diff --git a/apps/chanora_flutter/ios/Runner/Info.plist b/apps/chanora_flutter/ios/Runner/Info.plist
index 1bc9cef..b1ba0bb 100644
--- a/apps/chanora_flutter/ios/Runner/Info.plist
+++ b/apps/chanora_flutter/ios/Runner/Info.plist
@@ -26,6 +26,8 @@
$(FLUTTER_BUILD_NUMBER)
LSRequiresIPhoneOS
+ NSMicrophoneUsageDescription
+ Chanora needs microphone access so you can talk on your TeamSpeak-compatible voice server.
UIApplicationSceneManifest
UIApplicationSupportsMultipleScenes
@@ -49,6 +51,10 @@
UIApplicationSupportsIndirectInputEvents
+ UIBackgroundModes
+
+ audio
+
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
diff --git a/apps/chanora_flutter/macos/Runner.xcodeproj/project.pbxproj b/apps/chanora_flutter/macos/Runner.xcodeproj/project.pbxproj
index 5b7eddd..1998a6d 100644
--- a/apps/chanora_flutter/macos/Runner.xcodeproj/project.pbxproj
+++ b/apps/chanora_flutter/macos/Runner.xcodeproj/project.pbxproj
@@ -259,7 +259,7 @@
attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 0920;
- LastUpgradeCheck = 2650;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C80D4294CF70F00263BE5 = {
@@ -269,7 +269,6 @@
33CC10EC2044A3C60003C045 = {
CreatedOnToolsVersion = 9.2;
LastSwiftMigration = 1100;
- ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.Sandbox = {
enabled = 1;
@@ -390,14 +389,10 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
- inputPaths = (
- );
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
- outputPaths = (
- );
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
@@ -579,10 +574,11 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
- "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
- CODE_SIGN_STYLE = Automatic;
+ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
+ CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
- DEVELOPMENT_TEAM = 349G7M4TQQ;
+ DEVELOPMENT_TEAM = "";
+ "DEVELOPMENT_TEAM[sdk=macosx*]" = "";
ENABLE_APP_SANDBOX = YES;
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
@@ -728,10 +724,11 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
- "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
- CODE_SIGN_STYLE = Automatic;
+ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
+ CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
- DEVELOPMENT_TEAM = 349G7M4TQQ;
+ DEVELOPMENT_TEAM = "";
+ "DEVELOPMENT_TEAM[sdk=macosx*]" = "";
ENABLE_APP_SANDBOX = YES;
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
@@ -762,10 +759,11 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
- "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
- CODE_SIGN_STYLE = Automatic;
+ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
+ CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
- DEVELOPMENT_TEAM = 349G7M4TQQ;
+ DEVELOPMENT_TEAM = "";
+ "DEVELOPMENT_TEAM[sdk=macosx*]" = "";
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
diff --git a/apps/chanora_flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/apps/chanora_flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index 7aee463..132ce99 100644
--- a/apps/chanora_flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/apps/chanora_flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
+
com.apple.security.app-sandbox
com.apple.security.cs.allow-jit
com.apple.security.network.server
+
+ com.apple.security.network.client
+
+ com.apple.security.device.audio-input
+
diff --git a/apps/chanora_flutter/macos/Runner/Info.plist b/apps/chanora_flutter/macos/Runner/Info.plist
index 4789daa..e59169e 100644
--- a/apps/chanora_flutter/macos/Runner/Info.plist
+++ b/apps/chanora_flutter/macos/Runner/Info.plist
@@ -28,5 +28,13 @@
MainMenu
NSPrincipalClass
NSApplication
+
+ NSMicrophoneUsageDescription
+ Chanora needs microphone access so you can talk on your TeamSpeak-compatible voice server.
+ NSInputMonitoringUsageDescription
+ Chanora uses Input Monitoring so push-to-talk keys work even when other apps are focused. Chanora never records what you type — only the key you bound for talking.
diff --git a/apps/chanora_flutter/macos/Runner/Release.entitlements b/apps/chanora_flutter/macos/Runner/Release.entitlements
index 852fa1a..5d7d52f 100644
--- a/apps/chanora_flutter/macos/Runner/Release.entitlements
+++ b/apps/chanora_flutter/macos/Runner/Release.entitlements
@@ -2,7 +2,13 @@
+
com.apple.security.app-sandbox
+ com.apple.security.network.client
+
+ com.apple.security.device.audio-input
+
diff --git a/tools/macos-postbuild.sh b/tools/macos-postbuild.sh
new file mode 100755
index 0000000..3bd0a65
--- /dev/null
+++ b/tools/macos-postbuild.sh
@@ -0,0 +1,89 @@
+#!/usr/bin/env bash
+# Post-process the Flutter macOS Release bundle so it actually launches:
+#
+# 1. Wrap target/release/libchanora_bridge.dylib into a proper
+# chanora_bridge.framework bundle (Versions/A layout, Info.plist,
+# symlinks). FRB on macOS dlopen()s chanora_bridge.framework/
+# chanora_bridge — not the plain dylib.
+# 2. Rewrite the dylib's LC_ID_DYLIB so dyld resolves it as
+# @rpath/chanora_bridge.framework/chanora_bridge.
+# 3. Ad-hoc codesign the framework + the .app bundle.
+#
+# This is the macOS analogue of buildit.cmd on Windows. cocogkit /
+# corrosion-style auto-integration into the Xcode project is a P1
+# carryover — for now we run this script after `flutter build macos
+# --release`.
+#
+# Usage:
+# tools/macos-postbuild.sh [Release|Debug] (defaults to Release)
+
+set -euo pipefail
+
+CONFIG="${1:-Release}"
+REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
+APP="$REPO_ROOT/apps/chanora_flutter/build/macos/Build/Products/$CONFIG/chanora_flutter.app"
+DYLIB="$REPO_ROOT/target/release/libchanora_bridge.dylib"
+FW="$APP/Contents/Frameworks/chanora_bridge.framework"
+
+if [[ ! -d "$APP" ]]; then
+ echo "ERROR: app bundle not found at $APP" >&2
+ echo " run \`flutter build macos --$(echo "$CONFIG" | tr '[:upper:]' '[:lower:]')\` first" >&2
+ exit 1
+fi
+if [[ ! -f "$DYLIB" ]]; then
+ echo "ERROR: bridge dylib not found at $DYLIB" >&2
+ echo " run \`cargo build --release -p chanora_bridge\` first" >&2
+ exit 2
+fi
+
+# Step 1: build the chanora_bridge.framework layout.
+echo "[postbuild] wrapping bridge into chanora_bridge.framework"
+rm -rf "$FW"
+mkdir -p "$FW/Versions/A/Resources"
+cp "$DYLIB" "$FW/Versions/A/chanora_bridge"
+
+cat > "$FW/Versions/A/Resources/Info.plist" << 'PLIST'
+
+
+
+
+ CFBundleExecutable
+ chanora_bridge
+ CFBundleIdentifier
+ app.chanora.bridge
+ CFBundleName
+ chanora_bridge
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0.0
+ CFBundleVersion
+ 1
+
+
+PLIST
+
+ln -sf A "$FW/Versions/Current"
+ln -sf Versions/Current/chanora_bridge "$FW/chanora_bridge"
+ln -sf Versions/Current/Resources "$FW/Resources"
+
+# Step 2: rewrite install_name so dyld finds the bundled copy.
+echo "[postbuild] install_name_tool -id @rpath/chanora_bridge.framework/chanora_bridge"
+install_name_tool \
+ -id "@rpath/chanora_bridge.framework/chanora_bridge" \
+ "$FW/Versions/A/chanora_bridge"
+
+# Drop a stale plain dylib if a previous build left one alongside the
+# framework.
+rm -f "$APP/Contents/Frameworks/libchanora_bridge.dylib"
+
+# Step 3: codesign. Ad-hoc identity ('-') is sufficient for local
+# launches; replace with a real Developer ID when distributing.
+echo "[postbuild] codesigning framework + app (ad-hoc)"
+codesign --force -s - --timestamp=none "$FW/Versions/A/chanora_bridge"
+codesign --force -s - --timestamp=none "$FW"
+codesign --force --deep -s - --timestamp=none "$APP"
+
+codesign --verify --deep --strict "$APP"
+
+echo "[postbuild] OK: $APP is launchable"