From bd20873648a0d07535f491706c58e7ba482ea6c3 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 28 Feb 2025 18:23:21 -0500 Subject: [PATCH 01/64] Changes so that Commet builds and runs, and has libolm, on macOS --- commet/macos/Flutter/Flutter-Debug.xcconfig | 1 + commet/macos/Flutter/Flutter-Release.xcconfig | 1 + commet/macos/Podfile | 41 +++++ commet/macos/Podfile.lock | 168 ++++++++++++++++++ commet/macos/Runner.xcodeproj/project.pbxproj | 118 ++++++++++-- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- .../contents.xcworkspacedata | 3 + commet/macos/Runner/AppDelegate.swift | 2 +- commet/macos/Runner/DebugProfile.entitlements | 4 + commet/macos/Runner/Release.entitlements | 4 + 10 files changed, 325 insertions(+), 19 deletions(-) create mode 100644 commet/macos/Podfile create mode 100644 commet/macos/Podfile.lock diff --git a/commet/macos/Flutter/Flutter-Debug.xcconfig b/commet/macos/Flutter/Flutter-Debug.xcconfig index c2efd0b60..4b81f9b2d 100644 --- a/commet/macos/Flutter/Flutter-Debug.xcconfig +++ b/commet/macos/Flutter/Flutter-Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/commet/macos/Flutter/Flutter-Release.xcconfig b/commet/macos/Flutter/Flutter-Release.xcconfig index c2efd0b60..5caa9d157 100644 --- a/commet/macos/Flutter/Flutter-Release.xcconfig +++ b/commet/macos/Flutter/Flutter-Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/commet/macos/Podfile b/commet/macos/Podfile new file mode 100644 index 000000000..98fa9cc12 --- /dev/null +++ b/commet/macos/Podfile @@ -0,0 +1,41 @@ +platform :osx, '10.15' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + pod "OLMKit" +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/commet/macos/Podfile.lock b/commet/macos/Podfile.lock new file mode 100644 index 000000000..f8bd1e0f8 --- /dev/null +++ b/commet/macos/Podfile.lock @@ -0,0 +1,168 @@ +PODS: + - desktop_drop (0.0.1): + - FlutterMacOS + - device_info_plus (0.0.1): + - FlutterMacOS + - dynamic_color (0.0.2): + - FlutterMacOS + - flutter_local_notifications (0.0.1): + - FlutterMacOS + - flutter_web_auth_2 (3.0.0): + - FlutterMacOS + - FlutterMacOS (1.0.0) + - media_kit_libs_macos_video (1.0.4): + - FlutterMacOS + - media_kit_native_event_loop (1.0.0): + - FlutterMacOS + - media_kit_video (0.0.1): + - FlutterMacOS + - OLMKit (3.2.12): + - OLMKit/olmc (= 3.2.12) + - OLMKit/olmcpp (= 3.2.12) + - OLMKit/olmc (3.2.12) + - OLMKit/olmcpp (3.2.12) + - package_info_plus (0.0.1): + - FlutterMacOS + - pasteboard (0.0.1): + - FlutterMacOS + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - screen_brightness_macos (0.1.0): + - FlutterMacOS + - screen_retriever (0.0.1): + - FlutterMacOS + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + - sqflite_darwin (0.0.4): + - Flutter + - FlutterMacOS + - sqlite3 (3.47.2): + - sqlite3/common (= 3.47.2) + - sqlite3/common (3.47.2) + - sqlite3/dbstatvtab (3.47.2): + - sqlite3/common + - sqlite3/fts5 (3.47.2): + - sqlite3/common + - sqlite3/perf-threadsafe (3.47.2): + - sqlite3/common + - sqlite3/rtree (3.47.2): + - sqlite3/common + - sqlite3_flutter_libs (0.0.1): + - FlutterMacOS + - sqlite3 (~> 3.47.0) + - sqlite3/dbstatvtab + - sqlite3/fts5 + - sqlite3/perf-threadsafe + - sqlite3/rtree + - url_launcher_macos (0.0.1): + - FlutterMacOS + - wakelock_plus (0.0.1): + - FlutterMacOS + - window_manager (0.2.0): + - FlutterMacOS + - window_to_front (0.0.1): + - FlutterMacOS + +DEPENDENCIES: + - desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`) + - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) + - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`) + - flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`) + - flutter_web_auth_2 (from `Flutter/ephemeral/.symlinks/plugins/flutter_web_auth_2/macos`) + - FlutterMacOS (from `Flutter/ephemeral`) + - media_kit_libs_macos_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos`) + - media_kit_native_event_loop (from `Flutter/ephemeral/.symlinks/plugins/media_kit_native_event_loop/macos`) + - media_kit_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos`) + - OLMKit + - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) + - pasteboard (from `Flutter/ephemeral/.symlinks/plugins/pasteboard/macos`) + - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) + - screen_brightness_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_brightness_macos/macos`) + - screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`) + - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) + - sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`) + - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) + - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) + - wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`) + - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) + - window_to_front (from `Flutter/ephemeral/.symlinks/plugins/window_to_front/macos`) + +SPEC REPOS: + trunk: + - OLMKit + - sqlite3 + +EXTERNAL SOURCES: + desktop_drop: + :path: Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos + device_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos + dynamic_color: + :path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos + flutter_local_notifications: + :path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos + flutter_web_auth_2: + :path: Flutter/ephemeral/.symlinks/plugins/flutter_web_auth_2/macos + FlutterMacOS: + :path: Flutter/ephemeral + media_kit_libs_macos_video: + :path: Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos + media_kit_native_event_loop: + :path: Flutter/ephemeral/.symlinks/plugins/media_kit_native_event_loop/macos + media_kit_video: + :path: Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos + package_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos + pasteboard: + :path: Flutter/ephemeral/.symlinks/plugins/pasteboard/macos + path_provider_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin + screen_brightness_macos: + :path: Flutter/ephemeral/.symlinks/plugins/screen_brightness_macos/macos + screen_retriever: + :path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos + shared_preferences_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin + sqflite_darwin: + :path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin + sqlite3_flutter_libs: + :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos + url_launcher_macos: + :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos + wakelock_plus: + :path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos + window_manager: + :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos + window_to_front: + :path: Flutter/ephemeral/.symlinks/plugins/window_to_front/macos + +SPEC CHECKSUMS: + desktop_drop: e0b672a7d84c0a6cbc378595e82cdb15f2970a43 + device_info_plus: b0fafc687fb901e2af612763340f1b0d4352f8e5 + dynamic_color: b820c000cc68df65e7ba7ff177cb98404ce56651 + flutter_local_notifications: 13862b132e32eb858dea558a86d45d08daeacfe7 + flutter_web_auth_2: 62b08da29f15a20fa63f144234622a1488d45b65 + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + media_kit_libs_macos_video: 85a23e549b5f480e72cae3e5634b5514bc692f65 + media_kit_native_event_loop: a80d071c835c612fd80173e79390a50ec409f1b1 + media_kit_video: fa6564e3799a0a28bff39442334817088b7ca758 + OLMKit: da115f16582e47626616874e20f7bb92222c7a51 + package_info_plus: 8147fd5037235202932580f35ebe195f7a55e3cd + pasteboard: 278d8100149f940fb795d6b3a74f0720c890ecb7 + path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 + screen_brightness_macos: 2a3ee243f8051c340381e8e51bcedced8360f421 + screen_retriever: 4f97c103641aab8ce183fa5af3b87029df167936 + shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 + sqflite_darwin: 44bb54cc302bff1fbe5752293aba1820b157cf1c + sqlite3: 7559e33dae4c78538df563795af3a86fc887ee71 + sqlite3_flutter_libs: 7997a56aa96fdba2546e237664deb07f600768ac + url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673 + wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497 + window_manager: 1d01fa7ac65a6e6f83b965471b1a7fdd3f06166c + window_to_front: 9e76fd432e36700a197dac86a0011e49c89abe0a + +PODFILE CHECKSUM: acd442b0fa53a35b8a3f19d753304bc047ef6356 + +COCOAPODS: 1.16.2 diff --git a/commet/macos/Runner.xcodeproj/project.pbxproj b/commet/macos/Runner.xcodeproj/project.pbxproj index 83c675b80..034a4ca04 100644 --- a/commet/macos/Runner.xcodeproj/project.pbxproj +++ b/commet/macos/Runner.xcodeproj/project.pbxproj @@ -26,6 +26,8 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 60367AC52D723B8600EA0A89 /* OLMKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 60367AC42D723B8600EA0A89 /* OLMKit.framework */; }; + AC4192BA0488492D25D9E4A3 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 89C5F16CEF9F24CA598260E4 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -38,23 +40,13 @@ }; /* End PBXContainerItemProxy section */ -/* Begin PBXCopyFilesBuildPhase section */ - 33CC110E2044A8840003C045 /* Bundle Framework */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Bundle Framework"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - /* Begin PBXFileReference section */ + 15B0A6FC1C7284C778A19AA3 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 15E6C7095F45D47F4D59CBD9 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 293A9321CED3782F58B1C21B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* commet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "commet.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* commet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = commet.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -66,7 +58,10 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 60367AC42D723B8600EA0A89 /* OLMKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OLMKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 60E898A32D72337F00696429 /* OLMKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OLMKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 89C5F16CEF9F24CA598260E4 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ @@ -75,6 +70,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 60367AC52D723B8600EA0A89 /* OLMKit.framework in Frameworks */, + AC4192BA0488492D25D9E4A3 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -99,6 +96,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + 98839A8BA3B2B6F0EC91A84C /* Pods */, ); sourceTree = ""; }; @@ -145,9 +143,22 @@ path = Runner; sourceTree = ""; }; + 98839A8BA3B2B6F0EC91A84C /* Pods */ = { + isa = PBXGroup; + children = ( + 15B0A6FC1C7284C778A19AA3 /* Pods-Runner.debug.xcconfig */, + 15E6C7095F45D47F4D59CBD9 /* Pods-Runner.release.xcconfig */, + 293A9321CED3782F58B1C21B /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + 60367AC42D723B8600EA0A89 /* OLMKit.framework */, + 89C5F16CEF9F24CA598260E4 /* Pods_Runner.framework */, + 60E898A32D72337F00696429 /* OLMKit.framework */, ); name = Frameworks; sourceTree = ""; @@ -159,11 +170,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 4A3EC4A4E39DC40045050BEE /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, - 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 11C171EF4F711973987131AF /* [CP] Embed Pods Frameworks */, + 60367AC32D7239A000EA0A89 /* ShellScript */, ); buildRules = ( ); @@ -182,7 +195,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { @@ -233,6 +246,23 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 11C171EF4F711973987131AF /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -269,7 +299,46 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire\n"; + }; + 4A3EC4A4E39DC40045050BEE /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 60367AC32D7239A000EA0A89 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nframedir=${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}\nstartfile=$framedir/OLMKit.framework/Versions/Current/OLMKit\nendfile=$framedir/libolm.3.dylib\necho \"linking $startfile to $endfile\"\neval \"ln $startfile $endfile\"\necho \"Listing Frameworks Dir:\"\neval \"ls $framedir/\"\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -360,13 +429,18 @@ 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; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = J6B4LYQ6NB; INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; }; @@ -486,13 +560,18 @@ 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; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = J6B4LYQ6NB; INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -506,13 +585,18 @@ 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; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = J6B4LYQ6NB; INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; }; diff --git a/commet/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/commet/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index b0f960503..992df92a1 100644 --- a/commet/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/commet/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ + + diff --git a/commet/macos/Runner/AppDelegate.swift b/commet/macos/Runner/AppDelegate.swift index d53ef6437..8e02df288 100644 --- a/commet/macos/Runner/AppDelegate.swift +++ b/commet/macos/Runner/AppDelegate.swift @@ -1,7 +1,7 @@ import Cocoa import FlutterMacOS -@NSApplicationMain +@main class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true diff --git a/commet/macos/Runner/DebugProfile.entitlements b/commet/macos/Runner/DebugProfile.entitlements index dddb8a30c..b76b509ee 100644 --- a/commet/macos/Runner/DebugProfile.entitlements +++ b/commet/macos/Runner/DebugProfile.entitlements @@ -2,10 +2,14 @@ + com.apple.developer.aps-environment + development com.apple.security.app-sandbox com.apple.security.cs.allow-jit + com.apple.security.network.client + com.apple.security.network.server diff --git a/commet/macos/Runner/Release.entitlements b/commet/macos/Runner/Release.entitlements index 852fa1a47..39bde1896 100644 --- a/commet/macos/Runner/Release.entitlements +++ b/commet/macos/Runner/Release.entitlements @@ -2,7 +2,11 @@ + com.apple.developer.aps-environment + development com.apple.security.app-sandbox + com.apple.security.network.client + From 581db9a805863acc08b55a278cba1246308f4e0a Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 1 Mar 2025 10:06:47 -0500 Subject: [PATCH 02/64] Updated README --- README.md | 46 +++++++++++++++++++++++---- commet/ios/Runner/Runner.entitlements | 8 +++++ 2 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 commet/ios/Runner/Runner.entitlements diff --git a/README.md b/README.md index 6b5aa1047..cfdf43dfe 100644 --- a/README.md +++ b/README.md @@ -74,15 +74,15 @@ When building Commet, there are some additional command line arguments that must **Required** | **Argument** | **Valid Values** | **Description** | |--------------|---------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------| -| PLATFORM | 'desktop', 'mobile', 'linux', 'windows', 'macos', 'android', 'ios', 'web' | Defines which platform to build for | +| PLATFORM | 'desktop', 'mobile', 'linux', 'windows', 'macos', 'android', 'ios', 'web' | Defines which platform to build for | | BUILD_MODE | 'release', 'debug' | When building with 'debug' flag, additional debug information will be shown | **Optional** -| **Argument** | **Valid Values** | **Description** | -|--------------|---------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------| -| GIT_HASH | * | Supply the current git hash when building to show in info screen | -| VERSION_TAG | * | Supply the current build version, to display app version | -| BUILD_DETAIL | * | Can provide additional detail about the current build, for example if it was being built for Flatpak or Snap | +| **Argument** | **Valid Values** | **Description** | +|--------------|------------------|--------------------------------------------------------------------------------------------------------------| +| GIT_HASH | * | Supply the current git hash when building to show in info screen | +| VERSION_TAG | * | Supply the current build version, to display app version | +| BUILD_DETAIL | * | Can provide additional detail about the current build, for example if it was being built for Flatpak or Snap | **Example:** @@ -90,3 +90,37 @@ When building Commet, there are some additional command line arguments that must cd commet flutter run --dart-define BUILD_MODE=debug --dart-define PLATFORM=linux ``` + +## Building on macOS + +These are rough notes, based on the experience of getting Commet compiled and running for +macOS and iOS from a mac. + +- Install [Homebrew](https://brew.sh) +- Install ninja with `brew install ninja` + - Repeat for "gtk", "mpv", "ffmpeg", "libmpv", "mimalloc" +- If you want to run locally only (on a mac), you can install OLM with + `brew install libolm`. If you want to generate a universal binary, then the Commet + Xcode project for macOS includes a Cocoapods installation of "OLMKit" along with a shell + script to create an alias to the compiled library named "libolm.3.dylib", so that the + application can find it. +- For both macOS and iOS, open the Xcode projects by opening the ".xcworkspace" file + instead of the ".xcodeproj" file. + - In these files, set up code signing appropriately. You will need: + - An apple code signing certificate for iOS (and the same for macOS if you want to be + able to run the app non-locally) + - An Apple Push Services certificate for push notification support + - An Apple Identifier for your app bundle name (e.g. "chat.commet.app.WHATEVER") + - An Apple device profile for each device (mac or phone) you want to test on + - An Apple services key for push services (and your own Firebase set-up to go with it) + if you want to use push notifications outside of the main commet set-up + +The current set-up specifies the Podfile for both macOS and iOS (rather than having +Flutter generate it) because the generated Podfile both sets the wrong target OS versions +and includes a test target which is not actually present in the code. In addition, on +macOS, the pod install of 'OLMKit' *must* be done manually in the pod file because the +Flutter pod definition of OLMKit will only install it on iOS, and Homebrew will only +install the version of libolm that matches the system architecture on which it's running. +In addition, the Homebrew libolm is linked with the rest of the homebrew installation, and +thus the library may fail to work, even embedded in the app, if installed on a different +system. diff --git a/commet/ios/Runner/Runner.entitlements b/commet/ios/Runner/Runner.entitlements new file mode 100644 index 000000000..903def2af --- /dev/null +++ b/commet/ios/Runner/Runner.entitlements @@ -0,0 +1,8 @@ + + + + + aps-environment + development + + From b0d36108a2a1593864aa885fcc96eff11497a373 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 1 Mar 2025 10:08:43 -0500 Subject: [PATCH 03/64] iOS builds --- commet/ios/Flutter/AppFrameworkInfo.plist | 2 +- commet/ios/Flutter/Debug.xcconfig | 1 + commet/ios/Flutter/Release.xcconfig | 1 + commet/ios/Podfile | 41 ++++ commet/ios/Podfile.lock | 226 ++++++++++++++++++ commet/ios/Runner.xcodeproj/project.pbxproj | 111 ++++++++- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- .../contents.xcworkspacedata | 3 + commet/ios/Runner/AppDelegate.swift | 2 +- commet/ios/Runner/Info.plist | 13 +- 10 files changed, 388 insertions(+), 14 deletions(-) create mode 100644 commet/ios/Podfile create mode 100644 commet/ios/Podfile.lock diff --git a/commet/ios/Flutter/AppFrameworkInfo.plist b/commet/ios/Flutter/AppFrameworkInfo.plist index 9625e105d..7c5696400 100644 --- a/commet/ios/Flutter/AppFrameworkInfo.plist +++ b/commet/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/commet/ios/Flutter/Debug.xcconfig b/commet/ios/Flutter/Debug.xcconfig index 592ceee85..ec97fc6f3 100644 --- a/commet/ios/Flutter/Debug.xcconfig +++ b/commet/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/commet/ios/Flutter/Release.xcconfig b/commet/ios/Flutter/Release.xcconfig index 592ceee85..c4855bfe2 100644 --- a/commet/ios/Flutter/Release.xcconfig +++ b/commet/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/commet/ios/Podfile b/commet/ios/Podfile new file mode 100644 index 000000000..279576f38 --- /dev/null +++ b/commet/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '12.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/commet/ios/Podfile.lock b/commet/ios/Podfile.lock new file mode 100644 index 000000000..43e929f4b --- /dev/null +++ b/commet/ios/Podfile.lock @@ -0,0 +1,226 @@ +PODS: + - device_info_plus (0.0.1): + - Flutter + - DKImagePickerController/Core (4.3.9): + - DKImagePickerController/ImageDataManager + - DKImagePickerController/Resource + - DKImagePickerController/ImageDataManager (4.3.9) + - DKImagePickerController/PhotoGallery (4.3.9): + - DKImagePickerController/Core + - DKPhotoGallery + - DKImagePickerController/Resource (4.3.9) + - DKPhotoGallery (0.0.19): + - DKPhotoGallery/Core (= 0.0.19) + - DKPhotoGallery/Model (= 0.0.19) + - DKPhotoGallery/Preview (= 0.0.19) + - DKPhotoGallery/Resource (= 0.0.19) + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Core (0.0.19): + - DKPhotoGallery/Model + - DKPhotoGallery/Preview + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Model (0.0.19): + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Preview (0.0.19): + - DKPhotoGallery/Model + - DKPhotoGallery/Resource + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Resource (0.0.19): + - SDWebImage + - SwiftyGif + - file_picker (0.0.1): + - DKImagePickerController/PhotoGallery + - Flutter + - Flutter (1.0.0) + - flutter_background_service_ios (0.0.3): + - Flutter + - flutter_local_notifications (0.0.1): + - Flutter + - flutter_olm (3.2.15): + - Flutter + - flutter_openssl_crypto (0.0.1): + - Flutter + - OpenSSL-Universal + - flutter_shortcuts (0.0.1): + - Flutter + - flutter_web_auth_2 (3.0.0): + - Flutter + - integration_test (0.0.1): + - Flutter + - media_kit_libs_ios_video (1.0.4): + - Flutter + - media_kit_native_event_loop (1.0.0): + - Flutter + - media_kit_video (0.0.1): + - Flutter + - OpenSSL-Universal (3.3.2000) + - package_info_plus (0.4.5): + - Flutter + - pasteboard (0.0.1): + - Flutter + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - permission_handler_apple (9.3.0): + - Flutter + - screen_brightness_ios (0.1.0): + - Flutter + - SDWebImage (5.21.0): + - SDWebImage/Core (= 5.21.0) + - SDWebImage/Core (5.21.0) + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + - sqflite_darwin (0.0.4): + - Flutter + - FlutterMacOS + - sqlite3 (3.47.2): + - sqlite3/common (= 3.47.2) + - sqlite3/common (3.47.2) + - sqlite3/dbstatvtab (3.47.2): + - sqlite3/common + - sqlite3/fts5 (3.47.2): + - sqlite3/common + - sqlite3/perf-threadsafe (3.47.2): + - sqlite3/common + - sqlite3/rtree (3.47.2): + - sqlite3/common + - sqlite3_flutter_libs (0.0.1): + - Flutter + - sqlite3 (~> 3.47.0) + - sqlite3/dbstatvtab + - sqlite3/fts5 + - sqlite3/perf-threadsafe + - sqlite3/rtree + - SwiftyGif (5.4.5) + - url_launcher_ios (0.0.1): + - Flutter + - volume_controller (0.0.1): + - Flutter + - wakelock_plus (0.0.1): + - Flutter + +DEPENDENCIES: + - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) + - file_picker (from `.symlinks/plugins/file_picker/ios`) + - Flutter (from `Flutter`) + - flutter_background_service_ios (from `.symlinks/plugins/flutter_background_service_ios/ios`) + - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) + - flutter_olm (from `.symlinks/plugins/flutter_olm/ios`) + - flutter_openssl_crypto (from `.symlinks/plugins/flutter_openssl_crypto/ios`) + - flutter_shortcuts (from `.symlinks/plugins/flutter_shortcuts/ios`) + - flutter_web_auth_2 (from `.symlinks/plugins/flutter_web_auth_2/ios`) + - integration_test (from `.symlinks/plugins/integration_test/ios`) + - media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`) + - media_kit_native_event_loop (from `.symlinks/plugins/media_kit_native_event_loop/ios`) + - media_kit_video (from `.symlinks/plugins/media_kit_video/ios`) + - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) + - pasteboard (from `.symlinks/plugins/pasteboard/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) + - screen_brightness_ios (from `.symlinks/plugins/screen_brightness_ios/ios`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) + - sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) + - volume_controller (from `.symlinks/plugins/volume_controller/ios`) + - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`) + +SPEC REPOS: + trunk: + - DKImagePickerController + - DKPhotoGallery + - OpenSSL-Universal + - SDWebImage + - sqlite3 + - SwiftyGif + +EXTERNAL SOURCES: + device_info_plus: + :path: ".symlinks/plugins/device_info_plus/ios" + file_picker: + :path: ".symlinks/plugins/file_picker/ios" + Flutter: + :path: Flutter + flutter_background_service_ios: + :path: ".symlinks/plugins/flutter_background_service_ios/ios" + flutter_local_notifications: + :path: ".symlinks/plugins/flutter_local_notifications/ios" + flutter_olm: + :path: ".symlinks/plugins/flutter_olm/ios" + flutter_openssl_crypto: + :path: ".symlinks/plugins/flutter_openssl_crypto/ios" + flutter_shortcuts: + :path: ".symlinks/plugins/flutter_shortcuts/ios" + flutter_web_auth_2: + :path: ".symlinks/plugins/flutter_web_auth_2/ios" + integration_test: + :path: ".symlinks/plugins/integration_test/ios" + media_kit_libs_ios_video: + :path: ".symlinks/plugins/media_kit_libs_ios_video/ios" + media_kit_native_event_loop: + :path: ".symlinks/plugins/media_kit_native_event_loop/ios" + media_kit_video: + :path: ".symlinks/plugins/media_kit_video/ios" + package_info_plus: + :path: ".symlinks/plugins/package_info_plus/ios" + pasteboard: + :path: ".symlinks/plugins/pasteboard/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" + permission_handler_apple: + :path: ".symlinks/plugins/permission_handler_apple/ios" + screen_brightness_ios: + :path: ".symlinks/plugins/screen_brightness_ios/ios" + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + sqflite_darwin: + :path: ".symlinks/plugins/sqflite_darwin/darwin" + sqlite3_flutter_libs: + :path: ".symlinks/plugins/sqlite3_flutter_libs/ios" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" + volume_controller: + :path: ".symlinks/plugins/volume_controller/ios" + wakelock_plus: + :path: ".symlinks/plugins/wakelock_plus/ios" + +SPEC CHECKSUMS: + device_info_plus: 335f3ce08d2e174b9fdc3db3db0f4e3b1f66bd89 + DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c + DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 + file_picker: 5f42b9d5580e30b57b4863f9d94b448016b702e5 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + flutter_background_service_ios: 00d31bdff7b4bfe06d32375df358abe0329cf87e + flutter_local_notifications: 395056b3175ba4f08480a7c5de30cd36d69827e4 + flutter_olm: a557853f4d153f9553240fe1197c42e683abe4c7 + flutter_openssl_crypto: 73dcefff7611c3ac324d82726047d8335d0b6e57 + flutter_shortcuts: f9d9086904f3c2a03071c938165771cbb9171729 + flutter_web_auth_2: 3464a7c16dc6480b6194fc89913bae6e82f28405 + integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e + media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854 + media_kit_native_event_loop: 5fba1a849a6c87a34985f1e178a0de5bd444a0cf + media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474 + OpenSSL-Universal: b60a3702c9fea8b3145549d421fdb018e53ab7b4 + package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 + pasteboard: 49088aeb6119d51f976a421db60d8e1ab079b63c + path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 + permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d + screen_brightness_ios: 5ed898fa50fa82a26171c086ca5e28228f932576 + SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868 + shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 + sqflite_darwin: 44bb54cc302bff1fbe5752293aba1820b157cf1c + sqlite3: 7559e33dae4c78538df563795af3a86fc887ee71 + sqlite3_flutter_libs: 4dd5d78cb764bc095baa5af79dcee907d05a21a1 + SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 + url_launcher_ios: 694010445543906933d732453a59da0a173ae33d + volume_controller: ca1cde542ee70fad77d388f82e9616488110942b + wakelock_plus: fd58c82b1388f4afe3fe8aa2c856503a262a5b03 + +PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011 + +COCOAPODS: 1.16.2 diff --git a/commet/ios/Runner.xcodeproj/project.pbxproj b/commet/ios/Runner.xcodeproj/project.pbxproj index c6503b75e..e403ad97b 100644 --- a/commet/ios/Runner.xcodeproj/project.pbxproj +++ b/commet/ios/Runner.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 33094CB8717F20131D8A6C51 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF23A21167A1629A46938202 /* Pods_Runner.framework */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -29,9 +30,12 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0D317BE01B771C2F83770B29 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 57C41A2591C5EDD8E3475A60 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 603701A52D728005004FE230 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; @@ -42,6 +46,8 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DD5B2EEE2F68770E413E08AF /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + DF23A21167A1629A46938202 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -49,12 +55,21 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 33094CB8717F20131D8A6C51 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 5F731FA9B1EF6A5DF5DC817A /* Frameworks */ = { + isa = PBXGroup; + children = ( + DF23A21167A1629A46938202 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -72,6 +87,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, + AAF1D69EC431FC127C369128 /* Pods */, + 5F731FA9B1EF6A5DF5DC817A /* Frameworks */, ); sourceTree = ""; }; @@ -86,6 +103,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + 603701A52D728005004FE230 /* Runner.entitlements */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, @@ -98,6 +116,16 @@ path = Runner; sourceTree = ""; }; + AAF1D69EC431FC127C369128 /* Pods */ = { + isa = PBXGroup; + children = ( + 0D317BE01B771C2F83770B29 /* Pods-Runner.debug.xcconfig */, + DD5B2EEE2F68770E413E08AF /* Pods-Runner.release.xcconfig */, + 57C41A2591C5EDD8E3475A60 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -105,12 +133,15 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + A06759ECA63285C3A4F0528E /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + B7544AEBA57AB2081ADCD564 /* [CP] Embed Pods Frameworks */, + 006FB0C14E09DB927049DA3C /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -127,7 +158,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -169,6 +200,23 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 006FB0C14E09DB927049DA3C /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -176,6 +224,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -199,6 +248,45 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + A06759ECA63285C3A4F0528E /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + B7544AEBA57AB2081ADCD564 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -274,7 +362,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -289,14 +377,17 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = J6B4LYQ6NB; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp; + PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -351,7 +442,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -400,7 +491,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -417,14 +508,17 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = J6B4LYQ6NB; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp; + PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -439,14 +533,17 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = J6B4LYQ6NB; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp; + PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/commet/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/commet/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index c87d15a33..5e31d3d34 100644 --- a/commet/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/commet/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ + + diff --git a/commet/ios/Runner/AppDelegate.swift b/commet/ios/Runner/AppDelegate.swift index 70693e4a8..b63630348 100644 --- a/commet/ios/Runner/AppDelegate.swift +++ b/commet/ios/Runner/AppDelegate.swift @@ -1,7 +1,7 @@ import UIKit import Flutter -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, diff --git a/commet/ios/Runner/Info.plist b/commet/ios/Runner/Info.plist index 0fb038ed1..6f9509957 100644 --- a/commet/ios/Runner/Info.plist +++ b/commet/ios/Runner/Info.plist @@ -2,6 +2,8 @@ + CADisableMinimumFrameDurationOnPhone + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName @@ -24,6 +26,13 @@ $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS + UIApplicationSupportsIndirectInputEvents + + UIBackgroundModes + + fetch + remote-notification + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile @@ -43,9 +52,5 @@ UIViewControllerBasedStatusBarAppearance - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - From 20efec4b59210f193757723a580fab38ebb98f2b Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 1 Mar 2025 13:33:32 -0500 Subject: [PATCH 04/64] Build now passes beta review --- commet/ios/Runner/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/commet/ios/Runner/Info.plist b/commet/ios/Runner/Info.plist index 6f9509957..087bd5166 100644 --- a/commet/ios/Runner/Info.plist +++ b/commet/ios/Runner/Info.plist @@ -26,6 +26,8 @@ $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS + NSPhotoLibraryUsageDescription + Commet requests access to your photo library in order to allow you to share photos in your Matrix servers and rooms. UIApplicationSupportsIndirectInputEvents UIBackgroundModes From 508bb872e75243e1f0e8b384d4a77c3491ce971b Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 1 Mar 2025 17:16:54 -0500 Subject: [PATCH 05/64] Adding MacOS build action --- .github/workflows/build.yml | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 49b8f30e0..a2a91e03a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -162,4 +162,33 @@ jobs: - name: Build Web run: | cd $PROJECT_PATH - flutter build web --release --dart-define PLATFORM=web \ No newline at end of file + flutter build web --release --dart-define PLATFORM=web + + build-mac: + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: 'true' + + - name: Setup Flutter + uses: subosito/flutter-action@v2.8.0 + with: + flutter-version: '3.24.4' + channel: 'stable' + + - name: Setup Tools + uses: gerlero/brew-install@v1 + with: + packages: ninja gtk+3 mpv ffmpeg mimalloc + + - name: Code Generation + run: | + cd $PROJECT_PATH + dart run scripts/codegen.dart + + - name: Build Mac + run: | + cd $PROJECT_PATH + flutter build macos --release --dart-define PLATFORM=macos From bf1c2b4294c86d5364af0ab2bcf8ee95d07bb72b Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sun, 2 Mar 2025 10:26:13 -0500 Subject: [PATCH 06/64] Bumping iOS required version to 13 to support firebase --- commet/ios/Podfile | 2 +- commet/ios/Runner.xcodeproj/project.pbxproj | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/commet/ios/Podfile b/commet/ios/Podfile index 279576f38..e72e0b480 100644 --- a/commet/ios/Podfile +++ b/commet/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '12.0' +# platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/commet/ios/Runner.xcodeproj/project.pbxproj b/commet/ios/Runner.xcodeproj/project.pbxproj index e403ad97b..07a007315 100644 --- a/commet/ios/Runner.xcodeproj/project.pbxproj +++ b/commet/ios/Runner.xcodeproj/project.pbxproj @@ -383,6 +383,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -514,6 +515,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -539,6 +541,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", From 3053b4bbf226a9d49e0215513a2981ad0dbe6876 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sun, 2 Mar 2025 17:15:34 -0500 Subject: [PATCH 07/64] Updated benchmarking, and added ios push notification class --- .github/workflows/benchmark.yml | 2 +- .github/workflows/build.yml | 36 ++++ .github/workflows/integration-test.yml | 2 +- .../{android => }/firebase_push_notifier.dart | 20 +- .../push_notification/ios/ios_notifier.dart | 180 ++++++++++++++++++ .../notification_manager.dart | 6 +- commet/lib/config/platform_utils.dart | 5 + 7 files changed, 242 insertions(+), 9 deletions(-) rename commet/lib/client/components/push_notification/{android => }/firebase_push_notifier.dart (87%) create mode 100644 commet/lib/client/components/push_notification/ios/ios_notifier.dart diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 19124c991..a585e72a0 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -55,7 +55,7 @@ jobs: exit $INTEGRATION_TEST_EXIT_CODE - name: Upload Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: result.mkv path: commet/video.mkv diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a2a91e03a..378519b0f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -183,6 +183,36 @@ jobs: with: packages: ninja gtk+3 mpv ffmpeg mimalloc + - name: Setup Provisioning Profile + env: + BUILD_CERTIFICATE_BASE64: ${{ secrets.APPLE_SIGNING_P12 }} + P12_PASSWORD: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} + BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + run: | + # create variables + CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 + PP_PATH=$RUNNER_TEMP/build_pp.provisionprofile + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + + # import certificate and provisioning profile from secrets + echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH + echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH + + # create temporary keychain + security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security set-keychain-settings -lut 21600 $KEYCHAIN_PATH + security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + + # import certificate to keychain + security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security list-keychain -d user -s $KEYCHAIN_PATH + + # apply provisioning profile + mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles + cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles + - name: Code Generation run: | cd $PROJECT_PATH @@ -192,3 +222,9 @@ jobs: run: | cd $PROJECT_PATH flutter build macos --release --dart-define PLATFORM=macos + + - name: Clean up keychain and provisioning profile + if: ${{ always() }} + run: | + security delete-keychain $RUNNER_TEMP/app-signing.keychain-db + rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.provisionprofile \ No newline at end of file diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index ee7151acb..c63b4677f 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -67,7 +67,7 @@ jobs: - name: Upload Artifact if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: result.mkv path: commet/video.mkv diff --git a/commet/lib/client/components/push_notification/android/firebase_push_notifier.dart b/commet/lib/client/components/push_notification/firebase_push_notifier.dart similarity index 87% rename from commet/lib/client/components/push_notification/android/firebase_push_notifier.dart rename to commet/lib/client/components/push_notification/firebase_push_notifier.dart index 75e6f5bf9..af36b741f 100644 --- a/commet/lib/client/components/push_notification/android/firebase_push_notifier.dart +++ b/commet/lib/client/components/push_notification/firebase_push_notifier.dart @@ -4,20 +4,22 @@ import 'dart:async'; import 'package:commet/client/components/direct_messages/direct_message_component.dart'; import 'package:commet/client/components/push_notification/android/android_notifier.dart'; +import 'package:commet/client/components/push_notification/ios/ios_notifier.dart'; import 'package:commet/client/components/push_notification/notification_content.dart'; import 'package:commet/client/components/push_notification/notification_manager.dart'; import 'package:commet/client/components/push_notification/notifier.dart'; import 'package:commet/client/room.dart'; +import 'package:commet/config/platform_utils.dart'; import 'package:commet/debug/log.dart'; import 'package:commet/main.dart'; import 'package:commet/service/background_service.dart'; import 'package:commet/service/background_service_notifications/background_service_task_notification.dart'; // Manage these to enable / disable firebase -// import 'package:firebase_core/firebase_core.dart'; -// import 'package:firebase_messaging/firebase_messaging.dart'; -dynamic Firebase; -dynamic FirebaseMessaging; +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; +//dynamic Firebase; +//dynamic FirebaseMessaging; // -------- Future onForegroundMessage(dynamic message) async { @@ -65,7 +67,7 @@ Future _firebaseMessagingBackgroundHandler(dynamic message) async { } class FirebasePushNotifier implements Notifier { - late AndroidNotifier notifier; + late Notifier notifier; @override bool get hasPermission => notifier.hasPermission; @@ -74,7 +76,13 @@ class FirebasePushNotifier implements Notifier { bool get needsToken => true; FirebasePushNotifier() { - notifier = AndroidNotifier(); + if (PlatformUtils.isAndroid) { + notifier = AndroidNotifier(); + } else if (PlatformUtils.isIOS) { + notifier = IOSNotifier(); + } else { + notifier = AndroidNotifier(); + } } @override diff --git a/commet/lib/client/components/push_notification/ios/ios_notifier.dart b/commet/lib/client/components/push_notification/ios/ios_notifier.dart new file mode 100644 index 000000000..61b11df1e --- /dev/null +++ b/commet/lib/client/components/push_notification/ios/ios_notifier.dart @@ -0,0 +1,180 @@ +import 'dart:ui'; + +import 'package:commet/client/components/push_notification/notification_content.dart'; +import 'package:commet/client/components/push_notification/notifier.dart'; +import 'package:commet/client/room.dart'; +import 'package:commet/debug/log.dart'; +import 'package:commet/main.dart'; +import 'package:commet/utils/custom_uri.dart'; +import 'package:commet/utils/event_bus.dart'; +import 'package:commet/utils/image_utils.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; + +@pragma('vm:entry-point') +void onBackgroundResponse(NotificationResponse details) { + Log.i("Got a background notification response: $details"); +} + +class IOSNotifier implements Notifier { + @override + bool hasPermission = false; + + @override + bool get needsToken => false; + + FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin; + + @override + bool get enabled => true; + + @override + Future init() async { + flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); + + final DarwinInitializationSettings settings = DarwinInitializationSettings( + requestSoundPermission: false, + requestBadgePermission: false, + requestAlertPermission: false, + notificationCategories: [ + DarwinNotificationCategory( + 'plainCategory', + actions: [ + DarwinNotificationAction.plain( + 'id_1', + 'Action 1', + options: { + DarwinNotificationActionOption.foreground, + }, + ), + ], + options: { + DarwinNotificationCategoryOption.hiddenPreviewShowTitle, + }, + ) + ], + ); + + final initSettings = InitializationSettings(iOS: settings); + + await flutterLocalNotificationsPlugin?.initialize(initSettings, + onDidReceiveBackgroundNotificationResponse: onBackgroundResponse, + onDidReceiveNotificationResponse: onResponse); + + if (!isHeadless) { + checkPermission(); + } + } + + Future checkPermission() async { + var ios = flutterLocalNotificationsPlugin! + .resolvePlatformSpecificImplementation< + IOSFlutterLocalNotificationsPlugin>()!; + hasPermission = + await ios.requestPermissions(alert: true, badge: true, sound: true) ?? + false; + } + + @override + Future notify(NotificationContent notification) async { + switch (notification.runtimeType) { + case MessageNotificationContent: + return displayMessageNotification( + notification as MessageNotificationContent); + default: + } + } + + Future displayMessageNotification( + MessageNotificationContent content) async { + var client = clientManager?.getClient(content.clientId); + var room = client?.getRoom(content.roomId); + + if (room == null) { + return; + } + + if (flutterLocalNotificationsPlugin == null) { + Log.i( + "Flutter local notifications plugin was null. Something went wrong"); + return; + } + + if (shortcutsManager.loading != null) { + await shortcutsManager.loading; + } + + await Future.wait([ + shortcutsManager.createShortcutForRoom(room), + ]); + + var id = room.identifier.hashCode; + + var payload = + OpenRoomURI(roomId: content.roomId, clientId: content.clientId) + .toString(); + + const DarwinNotificationDetails details = + DarwinNotificationDetails(categoryIdentifier: 'plainCategory'); + + const NotificationDetails notificationDetails = + NotificationDetails(iOS: details); + await flutterLocalNotificationsPlugin?.show( + id, null, content.content, notificationDetails, + payload: payload); + } + + Future getImageBytes(ImageProvider? provider) async { + if (provider != null) { + var data = await ImageUtils.imageProviderToImage(provider); + var bytes = await data.toByteData(format: ImageByteFormat.png); + return bytes?.buffer.asUint8List(); + } + return null; + } + + @override + Future requestPermission() async { + return true; + } + + static void onResponse(NotificationResponse details) { + Log.i("Got a notification response: $details"); + + if (details.payload == null) return; + + var uri = CustomURI.parse(details.payload!); + + if (details.notificationResponseType == + NotificationResponseType.selectedNotification) { + if (uri is OpenRoomURI) { + EventBus.openRoom.add((uri.roomId, uri.clientId)); + } + } + } + + @override + Future getToken() async { + return null; + } + + @override + Map? extraRegistrationData() { + return null; + } + + @override + Future clearNotifications(Room room) async { + var notifications = + await flutterLocalNotificationsPlugin?.getActiveNotifications(); + + if (notifications == null) return; + + for (var noti in notifications) { + if (noti.groupKey == room.identifier) { + flutterLocalNotificationsPlugin?.cancel(noti.id!); + } + } + } +} diff --git a/commet/lib/client/components/push_notification/notification_manager.dart b/commet/lib/client/components/push_notification/notification_manager.dart index 641a429d7..e22f42711 100644 --- a/commet/lib/client/components/push_notification/notification_manager.dart +++ b/commet/lib/client/components/push_notification/notification_manager.dart @@ -1,7 +1,7 @@ import 'package:commet/client/alert.dart'; import 'package:commet/client/client.dart'; +import 'package:commet/client/components/push_notification/firebase_push_notifier.dart'; import 'package:commet/client/components/push_notification/android/android_notifier.dart'; -import 'package:commet/client/components/push_notification/android/firebase_push_notifier.dart'; import 'package:commet/client/components/push_notification/android/unified_push_notifier.dart'; import 'package:commet/client/components/push_notification/linux/linux_notifier.dart'; import 'package:commet/client/components/push_notification/modifiers/notification_modifiers.dart'; @@ -80,6 +80,10 @@ class NotificationManager { } } + if (PlatformUtils.isIOS) { + return FirebasePushNotifier(); + } + return null; } diff --git a/commet/lib/config/platform_utils.dart b/commet/lib/config/platform_utils.dart index bb788cf53..1c4734fd5 100644 --- a/commet/lib/config/platform_utils.dart +++ b/commet/lib/config/platform_utils.dart @@ -22,4 +22,9 @@ class PlatformUtils { static bool get isWeb { return kIsWeb; } + + static bool get isIOS { + if (kIsWeb) return false; + return Platform.isIOS; + } } From bb2e0439428f9d9ffb3ece83a0d5e97122f299b2 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sun, 2 Mar 2025 17:24:11 -0500 Subject: [PATCH 08/64] Updated pubspec to include firebase --- commet/pubspec.lock | 56 +++++++++++++++++++++++++++++++++++++++++++++ commet/pubspec.yaml | 4 ++-- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/commet/pubspec.lock b/commet/pubspec.lock index 683a02bb5..601f17428 100644 --- a/commet/pubspec.lock +++ b/commet/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "72.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "37a42d06068e2fe3deddb2da079a8c4d105f241225ba27b7122b37e9865fd8f7" + url: "https://pub.dev" + source: hosted + version: "1.3.35" _macros: dependency: transitive description: dart @@ -432,6 +440,54 @@ packages: url: "https://pub.dev" source: hosted version: "5.5.0" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "26de145bb9688a90962faec6f838247377b0b0d32cc0abecd9a4e43525fc856c" + url: "https://pub.dev" + source: hosted + version: "2.32.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: d7253d255ff10f85cfd2adaba9ac17bae878fa3ba577462451163bd9f1d1f0bf + url: "https://pub.dev" + source: hosted + version: "5.4.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: faa5a76f6380a9b90b53bc3bdcb85bc7926a382e0709b9b5edac9f7746651493 + url: "https://pub.dev" + source: hosted + version: "2.21.1" + firebase_messaging: + dependency: "direct main" + description: + name: firebase_messaging + sha256: "980259425fa5e2afc03e533f33723335731d21a56fd255611083bceebf4373a8" + url: "https://pub.dev" + source: hosted + version: "14.7.10" + firebase_messaging_platform_interface: + dependency: transitive + description: + name: firebase_messaging_platform_interface + sha256: "87c4a922cb6f811cfb7a889bdbb3622702443c52a0271636cbc90d813ceac147" + url: "https://pub.dev" + source: hosted + version: "4.5.37" + firebase_messaging_web: + dependency: transitive + description: + name: firebase_messaging_web + sha256: "90dc7ed885e90a24bb0e56d661d4d2b5f84429697fd2cbb9e5890a0ca370e6f4" + url: "https://pub.dev" + source: hosted + version: "3.5.18" fixnum: dependency: transitive description: diff --git a/commet/pubspec.yaml b/commet/pubspec.yaml index bcf0009f9..e723c1163 100644 --- a/commet/pubspec.yaml +++ b/commet/pubspec.yaml @@ -94,8 +94,8 @@ dependencies: ## ---- Putting some extra lines in here to help git with the diff ## ---- Probably good to keep this stuff at the bottom of the list ## Begin Google Services Dependencies - #firebase_core: ^2.30.0 - #firebase_messaging: ^14.7.10 + firebase_core: ^2.30.0 + firebase_messaging: ^14.7.10 ## End Google Services Dependencies ## ---- ## ---- From e6f8e15d9c07b2317f287b683e9431eaa294ad02 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sun, 2 Mar 2025 17:30:07 -0500 Subject: [PATCH 09/64] Since I moved the location of the plugin) --- commet/scripts/apply_google_services.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/commet/scripts/apply_google_services.patch b/commet/scripts/apply_google_services.patch index 3801541bc..0a715c6d6 100644 --- a/commet/scripts/apply_google_services.patch +++ b/commet/scripts/apply_google_services.patch @@ -24,10 +24,10 @@ index 7b03921..a059ce6 100644 } } -diff --git a/commet/lib/client/components/push_notification/android/firebase_push_notifier.dart b/commet/lib/client/components/push_notification/android/firebase_push_notifier.dart +diff --git a/commet/lib/client/components/push_notification/firebase_push_notifier.dart b/commet/lib/client/components/push_notification/firebase_push_notifier.dart index 67d69a7..beb0791 100644 ---- a/commet/lib/client/components/push_notification/android/firebase_push_notifier.dart -+++ b/commet/lib/client/components/push_notification/android/firebase_push_notifier.dart +--- a/commet/lib/client/components/push_notification/firebase_push_notifier.dart ++++ b/commet/lib/client/components/push_notification/firebase_push_notifier.dart @@ -12,10 +12,10 @@ import 'package:commet/service/background_service.dart'; import 'package:commet/service/background_service_notifications/background_service_task_notification.dart'; From 7fb547d4835ab887c10586a0ccb7a5f6aed6d7fd Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sun, 2 Mar 2025 17:54:20 -0500 Subject: [PATCH 10/64] Reverting pubspec for PR and repository --- commet/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commet/pubspec.yaml b/commet/pubspec.yaml index e723c1163..bcf0009f9 100644 --- a/commet/pubspec.yaml +++ b/commet/pubspec.yaml @@ -94,8 +94,8 @@ dependencies: ## ---- Putting some extra lines in here to help git with the diff ## ---- Probably good to keep this stuff at the bottom of the list ## Begin Google Services Dependencies - firebase_core: ^2.30.0 - firebase_messaging: ^14.7.10 + #firebase_core: ^2.30.0 + #firebase_messaging: ^14.7.10 ## End Google Services Dependencies ## ---- ## ---- From 1611d3ed3c2c683a00d654106bd1482d78fda737 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sun, 2 Mar 2025 18:20:20 -0500 Subject: [PATCH 11/64] Also reverting the base firebase push notifier code segment --- .../push_notification/firebase_push_notifier.dart | 8 ++++---- .../components/push_notification/ios/ios_notifier.dart | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/commet/lib/client/components/push_notification/firebase_push_notifier.dart b/commet/lib/client/components/push_notification/firebase_push_notifier.dart index af36b741f..5eabaea69 100644 --- a/commet/lib/client/components/push_notification/firebase_push_notifier.dart +++ b/commet/lib/client/components/push_notification/firebase_push_notifier.dart @@ -16,10 +16,10 @@ import 'package:commet/service/background_service.dart'; import 'package:commet/service/background_service_notifications/background_service_task_notification.dart'; // Manage these to enable / disable firebase -import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; -//dynamic Firebase; -//dynamic FirebaseMessaging; +// import 'package:firebase_core/firebase_core.dart'; +// import 'package:firebase_messaging/firebase_messaging.dart'; +dynamic Firebase; +dynamic FirebaseMessaging; // -------- Future onForegroundMessage(dynamic message) async { diff --git a/commet/lib/client/components/push_notification/ios/ios_notifier.dart b/commet/lib/client/components/push_notification/ios/ios_notifier.dart index 61b11df1e..72c412ad2 100644 --- a/commet/lib/client/components/push_notification/ios/ios_notifier.dart +++ b/commet/lib/client/components/push_notification/ios/ios_notifier.dart @@ -44,9 +44,9 @@ class IOSNotifier implements Notifier { DarwinNotificationAction.plain( 'id_1', 'Action 1', - options: { - DarwinNotificationActionOption.foreground, - }, +// options: { +// DarwinNotificationActionOption.foreground, +// }, ), ], options: { From 8637341223a0279f5e3ef01852d18f160703139c Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Mon, 3 Mar 2025 19:31:05 -0500 Subject: [PATCH 12/64] Naming everything correctly in the build profile --- .github/workflows/build.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 378519b0f..c04406d85 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -164,11 +164,14 @@ jobs: cd $PROJECT_PATH flutter build web --release --dart-define PLATFORM=web + build_with_signing: + runs-on: macos-latest + build-mac: runs-on: macos-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: 'true' @@ -183,16 +186,16 @@ jobs: with: packages: ninja gtk+3 mpv ffmpeg mimalloc - - name: Setup Provisioning Profile + - name: Install the Apple certificate and provisioning profile env: BUILD_CERTIFICATE_BASE64: ${{ secrets.APPLE_SIGNING_P12 }} P12_PASSWORD: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} - BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} + BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.APPLE_MACOS_PROVISIONING_BASE64 }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | # create variables CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 - PP_PATH=$RUNNER_TEMP/build_pp.provisionprofile + PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db # import certificate and provisioning profile from secrets From 82b3e762f86686223de62ca716b399291802d9cf Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Mon, 3 Mar 2025 19:35:09 -0500 Subject: [PATCH 13/64] And this time, not introducing any egregious errors into the YML file --- .github/workflows/build.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c04406d85..6ad71d205 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -164,9 +164,6 @@ jobs: cd $PROJECT_PATH flutter build web --release --dart-define PLATFORM=web - build_with_signing: - runs-on: macos-latest - build-mac: runs-on: macos-latest steps: @@ -186,7 +183,7 @@ jobs: with: packages: ninja gtk+3 mpv ffmpeg mimalloc - - name: Install the Apple certificate and provisioning profile + - name: Setup Provisioning Profile env: BUILD_CERTIFICATE_BASE64: ${{ secrets.APPLE_SIGNING_P12 }} P12_PASSWORD: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} @@ -195,11 +192,13 @@ jobs: run: | # create variables CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 - PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision + PP_PATH=$RUNNER_TEMP/build_pp.provisionprofile KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db # import certificate and provisioning profile from secrets + echo "Making Build Certificate" echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH + echo "Making Provisioning Profile" echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH # create temporary keychain From ca7503b30b4ca646b44af345a669941a34d69eca Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Wed, 5 Mar 2025 09:09:40 -0500 Subject: [PATCH 14/64] Added the ability to dismiss the keyboard --- commet/lib/ui/atoms/dismiss_keyboard.dart | 20 ++++++++++++++++++++ commet/lib/ui/atoms/keyboard_adaptor.dart | 10 ++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 commet/lib/ui/atoms/dismiss_keyboard.dart diff --git a/commet/lib/ui/atoms/dismiss_keyboard.dart b/commet/lib/ui/atoms/dismiss_keyboard.dart new file mode 100644 index 000000000..131b94825 --- /dev/null +++ b/commet/lib/ui/atoms/dismiss_keyboard.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; + +class DismissKeyboard extends StatelessWidget { + final Widget child; + const DismissKeyboard({Key? key, required this.child}) : super(key: key); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + FocusScopeNode currentFocus = FocusScope.of(context); + if (!currentFocus.hasPrimaryFocus && + currentFocus.focusedChild != null) { + FocusManager.instance.primaryFocus?.unfocus(); + } + }, + child: child, + ); + } +} diff --git a/commet/lib/ui/atoms/keyboard_adaptor.dart b/commet/lib/ui/atoms/keyboard_adaptor.dart index a47ac9f16..1c9169827 100644 --- a/commet/lib/ui/atoms/keyboard_adaptor.dart +++ b/commet/lib/ui/atoms/keyboard_adaptor.dart @@ -1,5 +1,6 @@ import 'dart:math'; +import 'package:commet/ui/atoms/dismiss_keyboard.dart'; import 'package:commet/ui/atoms/scaled_safe_area.dart'; import 'package:commet/utils/scaled_app.dart'; import 'package:flutter/material.dart'; @@ -14,9 +15,10 @@ class KeyboardAdaptor extends StatelessWidget { var scaledQuery = MediaQuery.of(context).scale(); var offset = max(scaledQuery.viewInsets.bottom, scaledQuery.padding.bottom); - return ScaledSafeArea( - bottom: false, - child: Padding( - padding: EdgeInsets.fromLTRB(0, 0, 0, offset), child: child)); + return DismissKeyboard( + child: ScaledSafeArea( + bottom: false, + child: Padding( + padding: EdgeInsets.fromLTRB(0, 0, 0, offset), child: child))); } } From 28b5f6d12afa0af658b12f5fd499e62d175b3af1 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 16:40:27 -0500 Subject: [PATCH 15/64] Changes to improve the chance of macos version building --- .github/workflows/build.yml | 10 +++ .../Flutter/GeneratedPluginRegistrant.swift | 48 ------------ commet/macos/Runner.xcodeproj/project.pbxproj | 45 ++++++++++- .../xcschemes/Runner Release.xcscheme | 78 +++++++++++++++++++ 4 files changed, 129 insertions(+), 52 deletions(-) delete mode 100644 commet/macos/Flutter/GeneratedPluginRegistrant.swift create mode 100644 commet/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner Release.xcscheme diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6ad71d205..b84b1baca 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -220,6 +220,16 @@ jobs: cd $PROJECT_PATH dart run scripts/codegen.dart + - name: Pre-run Xcodebuild + run: | + WORKSPACE: $PROJECT_PATH/macos/Runner.xcworkspace + cd $PROJECT_PATH + xcodebuild build -workspace $WORKSPACE \ + --scheme Runner \ + --configuration Release \ + --destination 'generic/platform=OS X' \ + --allowProvisioningUpdates + - name: Build Mac run: | cd $PROJECT_PATH diff --git a/commet/macos/Flutter/GeneratedPluginRegistrant.swift b/commet/macos/Flutter/GeneratedPluginRegistrant.swift deleted file mode 100644 index 213f26a95..000000000 --- a/commet/macos/Flutter/GeneratedPluginRegistrant.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// Generated file. Do not edit. -// - -import FlutterMacOS -import Foundation - -import desktop_drop -import device_info_plus -import dynamic_color -import flutter_local_notifications -import flutter_web_auth_2 -import media_kit_libs_macos_video -import media_kit_video -import package_info_plus -import pasteboard -import path_provider_foundation -import screen_brightness_macos -import screen_retriever -import shared_preferences_foundation -import sqflite_darwin -import sqlite3_flutter_libs -import url_launcher_macos -import wakelock_plus -import window_manager -import window_to_front - -func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin")) - DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) - DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) - FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) - FlutterWebAuth2Plugin.register(with: registry.registrar(forPlugin: "FlutterWebAuth2Plugin")) - MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin")) - MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin")) - FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) - PasteboardPlugin.register(with: registry.registrar(forPlugin: "PasteboardPlugin")) - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) - ScreenBrightnessMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenBrightnessMacosPlugin")) - ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin")) - SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) - SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) - Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) - UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) - WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) - WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) - WindowToFrontPlugin.register(with: registry.registrar(forPlugin: "WindowToFrontPlugin")) -} diff --git a/commet/macos/Runner.xcodeproj/project.pbxproj b/commet/macos/Runner.xcodeproj/project.pbxproj index 034a4ca04..ecfd2b91a 100644 --- a/commet/macos/Runner.xcodeproj/project.pbxproj +++ b/commet/macos/Runner.xcodeproj/project.pbxproj @@ -176,7 +176,8 @@ 33CC10EB2044A3C60003C045 /* Resources */, 3399D490228B24CF009A79C7 /* ShellScript */, 11C171EF4F711973987131AF /* [CP] Embed Pods Frameworks */, - 60367AC32D7239A000EA0A89 /* ShellScript */, + 6063DE702D7B737B00E5E1D0 /* ShellScript */, + D7E4758527804155CB687CDB /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -323,8 +324,9 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 60367AC32D7239A000EA0A89 /* ShellScript */ = { + 6063DE702D7B737B00E5E1D0 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -338,7 +340,24 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nframedir=${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}\nstartfile=$framedir/OLMKit.framework/Versions/Current/OLMKit\nendfile=$framedir/libolm.3.dylib\necho \"linking $startfile to $endfile\"\neval \"ln $startfile $endfile\"\necho \"Listing Frameworks Dir:\"\neval \"ls $framedir/\"\n"; + shellScript = "framedir=${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}\nln -s \"./OLMKit\" $framedir/OLMKit.framework/libolm.3.dylib\n"; + }; + D7E4758527804155CB687CDB /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -378,7 +397,7 @@ /* Begin XCBuildConfiguration section */ 338D0CE9231458BD00FA5F75 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + baseConfigurationReference = 333000ED22D3DE5D00554162 /* Warnings.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -439,6 +458,11 @@ "$(inherited)", "@executable_path/../Frameworks", ); + "LD_RUNPATH_SEARCH_PATHS[arch=*]" = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../Frameworks/OLMKit.framework", + ); MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -448,6 +472,7 @@ }; 338D0CEB231458BD00FA5F75 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */; buildSettings = { CODE_SIGN_STYLE = Manual; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -570,6 +595,11 @@ "$(inherited)", "@executable_path/../Frameworks", ); + "LD_RUNPATH_SEARCH_PATHS[arch=*]" = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../Frameworks/OLMKit.framework", + ); MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -595,6 +625,11 @@ "$(inherited)", "@executable_path/../Frameworks", ); + "LD_RUNPATH_SEARCH_PATHS[arch=*]" = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../Frameworks/OLMKit.framework", + ); MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -604,6 +639,7 @@ }; 33CC111C2044C6BA0003C045 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */; buildSettings = { CODE_SIGN_STYLE = Manual; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -612,6 +648,7 @@ }; 33CC111D2044C6BA0003C045 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */; buildSettings = { CODE_SIGN_STYLE = Automatic; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/commet/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner Release.xcscheme b/commet/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner Release.xcscheme new file mode 100644 index 000000000..10f772855 --- /dev/null +++ b/commet/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner Release.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 10b3addb93173701f43effdea3af29cf83fa1586 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 16:46:43 -0500 Subject: [PATCH 16/64] Fixed error in formatting --- .github/workflows/build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b84b1baca..7a0f3e674 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -222,9 +222,8 @@ jobs: - name: Pre-run Xcodebuild run: | - WORKSPACE: $PROJECT_PATH/macos/Runner.xcworkspace cd $PROJECT_PATH - xcodebuild build -workspace $WORKSPACE \ + xcodebuild build -workspace ./macos/Runner.xcworkspace \ --scheme Runner \ --configuration Release \ --destination 'generic/platform=OS X' \ From 1a8e810850d0b70cf4559787719f692afed362a4 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 16:53:32 -0500 Subject: [PATCH 17/64] Changed double-dashes to single-dashes --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7a0f3e674..7889a43db 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -224,10 +224,10 @@ jobs: run: | cd $PROJECT_PATH xcodebuild build -workspace ./macos/Runner.xcworkspace \ - --scheme Runner \ - --configuration Release \ - --destination 'generic/platform=OS X' \ - --allowProvisioningUpdates + -scheme Runner \ + -configuration Release \ + -destination 'generic/platform=OS X' \ + -allowProvisioningUpdates - name: Build Mac run: | From 9cb21b442da8b30617adc74a878dea5921073b0e Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 18:16:06 -0500 Subject: [PATCH 18/64] Trying with a different provisioning profile and no pre-build step --- .github/workflows/build.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7889a43db..1e732303b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -220,14 +220,14 @@ jobs: cd $PROJECT_PATH dart run scripts/codegen.dart - - name: Pre-run Xcodebuild - run: | - cd $PROJECT_PATH - xcodebuild build -workspace ./macos/Runner.xcworkspace \ - -scheme Runner \ - -configuration Release \ - -destination 'generic/platform=OS X' \ - -allowProvisioningUpdates +# - name: Pre-run Xcodebuild +# run: | +# cd $PROJECT_PATH +# xcodebuild build -workspace ./macos/Runner.xcworkspace \ +# -scheme Runner \ +# -configuration Release \ +# -destination 'generic/platform=OS X' \ +# -allowProvisioningUpdates - name: Build Mac run: | From 7e74c1d91c45921f71a7534aeed38541e68697e4 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 18:32:21 -0500 Subject: [PATCH 19/64] Trying a different build string --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1e732303b..2e656e4e1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -232,7 +232,7 @@ jobs: - name: Build Mac run: | cd $PROJECT_PATH - flutter build macos --release --dart-define PLATFORM=macos + flutter build macos --dart-define BUILD_MODE=release --dart-define PLATFORM=macos - name: Clean up keychain and provisioning profile if: ${{ always() }} From fd48c6fd4cdd48918e2f3a7e60b0464a72f7bc3c Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 18:44:24 -0500 Subject: [PATCH 20/64] Trying an action to install the provisioning profile --- .github/workflows/build.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2e656e4e1..7c8fe47bc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -220,14 +220,10 @@ jobs: cd $PROJECT_PATH dart run scripts/codegen.dart -# - name: Pre-run Xcodebuild -# run: | -# cd $PROJECT_PATH -# xcodebuild build -workspace ./macos/Runner.xcworkspace \ -# -scheme Runner \ -# -configuration Release \ -# -destination 'generic/platform=OS X' \ -# -allowProvisioningUpdates + - name: Install Provisioning Profile + uses: akiojin/install-provisioning-profile-github-action@v1.0 + with: + base64: ${{ secrets.APPLE_MACOS_PROVISIONING_BASE64 }} - name: Build Mac run: | From 2ac5d407bb7ea32836c7524780048faff72fea2d Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 19:29:17 -0500 Subject: [PATCH 21/64] Yet another attempt at provisioning --- .github/workflows/build.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7c8fe47bc..b72a85b3c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -220,10 +220,13 @@ jobs: cd $PROJECT_PATH dart run scripts/codegen.dart - - name: Install Provisioning Profile - uses: akiojin/install-provisioning-profile-github-action@v1.0 + - uses: nickwph/apple-provisioning-profile-action@v1 with: - base64: ${{ secrets.APPLE_MACOS_PROVISIONING_BASE64 }} + profile-base64: ${{ secrets.APPLE_MACOS_PROVISIONING_BASE64 }} + - uses: nickwph/apple-build-certificate-action@v1 # Optional: Recommend to use with apple-build-certificate-action + with: + certificate-base64: ${{ secrets.ADHOC_MACOS_J6B4LYQ6NB_SIGNING_P12 }} + certificate-password: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} - name: Build Mac run: | From b0cac9323fe141e8be743309a9651caee3297d6f Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 19:38:32 -0500 Subject: [PATCH 22/64] Trying a different combination --- .github/workflows/build.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b72a85b3c..d93c69697 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -185,7 +185,7 @@ jobs: - name: Setup Provisioning Profile env: - BUILD_CERTIFICATE_BASE64: ${{ secrets.APPLE_SIGNING_P12 }} + BUILD_CERTIFICATE_BASE64: ${{ secrets.ADHOC_MACOS_J6B4LYQ6NB_SIGNING_P12 }} P12_PASSWORD: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.APPLE_MACOS_PROVISIONING_BASE64 }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} @@ -220,13 +220,13 @@ jobs: cd $PROJECT_PATH dart run scripts/codegen.dart - - uses: nickwph/apple-provisioning-profile-action@v1 - with: - profile-base64: ${{ secrets.APPLE_MACOS_PROVISIONING_BASE64 }} - - uses: nickwph/apple-build-certificate-action@v1 # Optional: Recommend to use with apple-build-certificate-action - with: - certificate-base64: ${{ secrets.ADHOC_MACOS_J6B4LYQ6NB_SIGNING_P12 }} - certificate-password: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} +# - uses: nickwph/apple-provisioning-profile-action@v1 +# with: +# profile-base64: ${{ secrets.APPLE_MACOS_PROVISIONING_BASE64 }} +# - uses: nickwph/apple-build-certificate-action@v1 # Optional: Recommend to use with apple-build-certificate-action +# with: +# certificate-base64: ${{ secrets.ADHOC_MACOS_J6B4LYQ6NB_SIGNING_P12 }} +# certificate-password: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} - name: Build Mac run: | From dbc56ca2d6295d2476361fbe3e008150fcdd3f16 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 19:59:47 -0500 Subject: [PATCH 23/64] And another --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d93c69697..f58e88f95 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -187,7 +187,7 @@ jobs: env: BUILD_CERTIFICATE_BASE64: ${{ secrets.ADHOC_MACOS_J6B4LYQ6NB_SIGNING_P12 }} P12_PASSWORD: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} - BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.APPLE_MACOS_PROVISIONING_BASE64 }} + BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.MACOS_DEV_J6B4LYQ6NB_PROVISIONPROFILE }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | # create variables From 3953db936e56bce8c17c29d17b5f60ec4827acfa Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 20:39:03 -0500 Subject: [PATCH 24/64] And yet again --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f58e88f95..c13606a3a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -185,9 +185,9 @@ jobs: - name: Setup Provisioning Profile env: - BUILD_CERTIFICATE_BASE64: ${{ secrets.ADHOC_MACOS_J6B4LYQ6NB_SIGNING_P12 }} + BUILD_CERTIFICATE_BASE64: ${{ secrets.YORK_DEV_ID_APP_P12 }} P12_PASSWORD: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} - BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.MACOS_DEV_J6B4LYQ6NB_PROVISIONPROFILE }} + BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.COMMET_MACOS_PROFILE_PROVISIONPROFILE }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | # create variables From 74cb768aa7ebfe258a3310dcf3a47d240b904f1b Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 20:39:31 -0500 Subject: [PATCH 25/64] Trying with homebrew turned off --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c13606a3a..980c0efc8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -178,10 +178,10 @@ jobs: flutter-version: '3.24.4' channel: 'stable' - - name: Setup Tools - uses: gerlero/brew-install@v1 - with: - packages: ninja gtk+3 mpv ffmpeg mimalloc +# - name: Setup Tools +# uses: gerlero/brew-install@v1 +# with: +# packages: ninja gtk+3 mpv ffmpeg mimalloc - name: Setup Provisioning Profile env: From 7989a23d6d59d29cb44d03e7fc392077af45eb3a Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 20:52:12 -0500 Subject: [PATCH 26/64] And again --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 980c0efc8..df000a52c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -186,8 +186,8 @@ jobs: - name: Setup Provisioning Profile env: BUILD_CERTIFICATE_BASE64: ${{ secrets.YORK_DEV_ID_APP_P12 }} - P12_PASSWORD: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} - BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.COMMET_MACOS_PROFILE_PROVISIONPROFILE }} + P12_PASSWORD: ${{ secrets.BRIAN_MAC_DEV_P12 }} + BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BRIAN_MAC_DEVELOPMENT_PROFILE_PROVISIONPROFILE }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | # create variables From bd5ec648bb2d27eebf93f6f814269e6a83c38814 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 20:55:27 -0500 Subject: [PATCH 27/64] Let's put the right secrets in the right variables --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index df000a52c..7ca299fb1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -185,8 +185,8 @@ jobs: - name: Setup Provisioning Profile env: - BUILD_CERTIFICATE_BASE64: ${{ secrets.YORK_DEV_ID_APP_P12 }} - P12_PASSWORD: ${{ secrets.BRIAN_MAC_DEV_P12 }} + BUILD_CERTIFICATE_BASE64: ${{ secrets.BRIAN_MAC_DEV_P12 }} + P12_PASSWORD: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BRIAN_MAC_DEVELOPMENT_PROFILE_PROVISIONPROFILE }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | From 0ff7094d2855aa64d4704f250e64207702f9cb54 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 21:06:30 -0500 Subject: [PATCH 28/64] Apparently the provisioning profile search location changed and github didn't update its documentation --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7ca299fb1..2db56e1f2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -213,7 +213,7 @@ jobs: # apply provisioning profile mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles - cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles + cp $PP_PATH ~/Library/Developer/Xcode/UserData/Provisioning\ Profiles - name: Code Generation run: | From 5fde41b4d8db6c18beb9aea3d37ab1caeb094bb2 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 21:08:51 -0500 Subject: [PATCH 29/64] Apparently I also need to create the directory before copying something to it. Who would have guessed? --- .github/workflows/build.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2db56e1f2..b27cf077f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -212,7 +212,7 @@ jobs: security list-keychain -d user -s $KEYCHAIN_PATH # apply provisioning profile - mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles + mkdir -p ~/Library/Developer/Xcode/UserData/Provisioning\ Profiles cp $PP_PATH ~/Library/Developer/Xcode/UserData/Provisioning\ Profiles - name: Code Generation @@ -220,14 +220,6 @@ jobs: cd $PROJECT_PATH dart run scripts/codegen.dart -# - uses: nickwph/apple-provisioning-profile-action@v1 -# with: -# profile-base64: ${{ secrets.APPLE_MACOS_PROVISIONING_BASE64 }} -# - uses: nickwph/apple-build-certificate-action@v1 # Optional: Recommend to use with apple-build-certificate-action -# with: -# certificate-base64: ${{ secrets.ADHOC_MACOS_J6B4LYQ6NB_SIGNING_P12 }} -# certificate-password: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} - - name: Build Mac run: | cd $PROJECT_PATH From b5c970177735e4f4615dc73b5239e4ad6bd1dd64 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 21:15:08 -0500 Subject: [PATCH 30/64] Trying again --- .github/workflows/build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b27cf077f..b5d76253a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -212,8 +212,9 @@ jobs: security list-keychain -d user -s $KEYCHAIN_PATH # apply provisioning profile - mkdir -p ~/Library/Developer/Xcode/UserData/Provisioning\ Profiles - cp $PP_PATH ~/Library/Developer/Xcode/UserData/Provisioning\ Profiles + mkdir -p '~/Library/Developer/Xcode/UserData/Provisioning Profiles' + cp $PP_PATH '~/Library/Developer/Xcode/UserData/Provisioning Profiles' + ln -s '~/Library/Developer/Xcode/UserData/Provisioning Profiles' '~/Library/MobileDevice/Provisioning Profiles' - name: Code Generation run: | From cc8e459741735ad4477e5f3962568462280118f9 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 21:17:01 -0500 Subject: [PATCH 31/64] and again --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b5d76253a..7e5d68623 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -214,7 +214,7 @@ jobs: # apply provisioning profile mkdir -p '~/Library/Developer/Xcode/UserData/Provisioning Profiles' cp $PP_PATH '~/Library/Developer/Xcode/UserData/Provisioning Profiles' - ln -s '~/Library/Developer/Xcode/UserData/Provisioning Profiles' '~/Library/MobileDevice/Provisioning Profiles' + ln -s '~/Library/MobileDevice/Provisioning Profiles' '~/Library/Developer/Xcode/UserData/Provisioning Profiles' - name: Code Generation run: | From 3b5047e9342c0f337265a1a50bcbc34586314f8f Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 21:22:02 -0500 Subject: [PATCH 32/64] Another tweak --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7e5d68623..bdfc66bf8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -212,9 +212,9 @@ jobs: security list-keychain -d user -s $KEYCHAIN_PATH # apply provisioning profile - mkdir -p '~/Library/Developer/Xcode/UserData/Provisioning Profiles' - cp $PP_PATH '~/Library/Developer/Xcode/UserData/Provisioning Profiles' - ln -s '~/Library/MobileDevice/Provisioning Profiles' '~/Library/Developer/Xcode/UserData/Provisioning Profiles' + mkdir -p '~/Library/MobileDevice/Provisioning Profiles' + cp $PP_PATH '~/Library/MobileDevice/Provisioning Profiles/' + ln -s '~/Library/Developer/Xcode/UserData/Provisioning Profiles' '~/Library/MobileDevice/Provisioning Profiles' - name: Code Generation run: | From 5461ef5b3aefd072243225dd60268ce2a3f29c77 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Fri, 7 Mar 2025 21:41:27 -0500 Subject: [PATCH 33/64] And trying once again --- .github/workflows/build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bdfc66bf8..1c310fe0d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -185,9 +185,9 @@ jobs: - name: Setup Provisioning Profile env: - BUILD_CERTIFICATE_BASE64: ${{ secrets.BRIAN_MAC_DEV_P12 }} + BUILD_CERTIFICATE_BASE64: ${{ secrets.YORK_DEV_ID_APP_P12 }} P12_PASSWORD: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} - BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BRIAN_MAC_DEVELOPMENT_PROFILE_PROVISIONPROFILE }} + BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.COMMET_MACOS_PROFILE_PROVISIONPROFILE }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | # create variables @@ -215,6 +215,7 @@ jobs: mkdir -p '~/Library/MobileDevice/Provisioning Profiles' cp $PP_PATH '~/Library/MobileDevice/Provisioning Profiles/' ln -s '~/Library/Developer/Xcode/UserData/Provisioning Profiles' '~/Library/MobileDevice/Provisioning Profiles' + xcode-project use-profiles - name: Code Generation run: | From d1c7db60ff74b40ab049a3f97fe4ef8341137c1f Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 8 Mar 2025 10:32:20 -0500 Subject: [PATCH 34/64] With a hardware keyboard, shift-return will now enter a newline without sending --- commet/lib/ui/molecules/message_input.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/commet/lib/ui/molecules/message_input.dart b/commet/lib/ui/molecules/message_input.dart index 42922978b..28775caa3 100644 --- a/commet/lib/ui/molecules/message_input.dart +++ b/commet/lib/ui/molecules/message_input.dart @@ -315,6 +315,15 @@ class MessageInputState extends State { } if (HardwareKeyboard.instance.isShiftPressed) { + String text = controller.text; + TextSelection textSelection = controller.selection; + String newText = + text.replaceRange(textSelection.start, textSelection.end, "\n"); + controller.text = newText; + controller.selection = textSelection.copyWith( + baseOffset: textSelection.start + 1, + extentOffset: textSelection.start + 1, + ); return KeyEventResult.ignored; } From c2c34ed7cdf9698bff0acb2071de37b1da37d855 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 8 Mar 2025 22:56:29 -0500 Subject: [PATCH 35/64] Updated signing to not be automatic in github --- commet/macos/Runner.xcodeproj/project.pbxproj | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/commet/macos/Runner.xcodeproj/project.pbxproj b/commet/macos/Runner.xcodeproj/project.pbxproj index ecfd2b91a..e07ba140b 100644 --- a/commet/macos/Runner.xcodeproj/project.pbxproj +++ b/commet/macos/Runner.xcodeproj/project.pbxproj @@ -202,7 +202,6 @@ 33CC10EC2044A3C60003C045 = { CreatedOnToolsVersion = 9.2; LastSwiftMigration = 1100; - ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.Sandbox = { enabled = 1; @@ -448,10 +447,12 @@ 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 = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = J6B4LYQ6NB; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=macosx*]" = J6B4LYQ6NB; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; LD_RUNPATH_SEARCH_PATHS = ( @@ -466,6 +467,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = commet_macos_profile; SWIFT_VERSION = 5.0; }; name = Profile; @@ -585,10 +587,12 @@ 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 = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = J6B4LYQ6NB; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=macosx*]" = J6B4LYQ6NB; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; LD_RUNPATH_SEARCH_PATHS = ( @@ -603,6 +607,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = commet_macos_profile; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; @@ -615,10 +620,12 @@ 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 = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = J6B4LYQ6NB; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=macosx*]" = J6B4LYQ6NB; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; LD_RUNPATH_SEARCH_PATHS = ( @@ -633,6 +640,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = commet_macos_profile; SWIFT_VERSION = 5.0; }; name = Release; From d65edcda246b785be6d7e85aa55310028a1d4977 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 8 Mar 2025 22:59:45 -0500 Subject: [PATCH 36/64] Removing unfound command --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1c310fe0d..6563e1e0e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -215,7 +215,6 @@ jobs: mkdir -p '~/Library/MobileDevice/Provisioning Profiles' cp $PP_PATH '~/Library/MobileDevice/Provisioning Profiles/' ln -s '~/Library/Developer/Xcode/UserData/Provisioning Profiles' '~/Library/MobileDevice/Provisioning Profiles' - xcode-project use-profiles - name: Code Generation run: | From 7532c73e26c898058d539ad4edafa67c9eaca947 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 8 Mar 2025 23:07:08 -0500 Subject: [PATCH 37/64] Trying different naming --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6563e1e0e..d293f6d4c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -212,9 +212,9 @@ jobs: security list-keychain -d user -s $KEYCHAIN_PATH # apply provisioning profile - mkdir -p '~/Library/MobileDevice/Provisioning Profiles' - cp $PP_PATH '~/Library/MobileDevice/Provisioning Profiles/' - ln -s '~/Library/Developer/Xcode/UserData/Provisioning Profiles' '~/Library/MobileDevice/Provisioning Profiles' + mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles + cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles/ + ln -s ~/Library/Developer/Xcode/UserData/Provisioning\ Profiles ~/Library/MobileDevice/Provisioning\ Profiles - name: Code Generation run: | From 9509b2953cfcb78f0073699bb6e94edb7e003e44 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sun, 9 Mar 2025 12:51:25 -0400 Subject: [PATCH 38/64] Ready to start testing ios build action --- commet/ios/Podfile | 15 ++++++++++- commet/ios/Runner.xcodeproj/project.pbxproj | 28 ++++++++++++++++++--- commet/ios/Runner/AppDelegate.swift | 16 +++++++++++- commet/ios/Runner/Info.plist | 13 ++++++++++ commet/ios/export.plist | 27 ++++++++++++++++++++ 5 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 commet/ios/export.plist diff --git a/commet/ios/Podfile b/commet/ios/Podfile index e72e0b480..f5f04672b 100644 --- a/commet/ios/Podfile +++ b/commet/ios/Podfile @@ -37,5 +37,18 @@ end post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) + + target.build_configurations.each do |config| + # You can remove unused permissions here + # for more information: https://github.com/Baseflow/flutter-permission-handler/blob/main/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h + # e.g. when you don't need camera permission, just add 'PERMISSION_CAMERA=0' + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ + '$(inherited)', + + ## dart: PermissionGroup.notification + 'PERMISSION_NOTIFICATIONS=1', + ] + + end end -end +end \ No newline at end of file diff --git a/commet/ios/Runner.xcodeproj/project.pbxproj b/commet/ios/Runner.xcodeproj/project.pbxproj index 07a007315..2bcede9b4 100644 --- a/commet/ios/Runner.xcodeproj/project.pbxproj +++ b/commet/ios/Runner.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 33094CB8717F20131D8A6C51 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF23A21167A1629A46938202 /* Pods_Runner.framework */; }; + 3A96899877713ACC1DEF03C5 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2CFD958428D90851AE5EC32F /* GoogleService-Info.plist */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -33,6 +34,7 @@ 0D317BE01B771C2F83770B29 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 2CFD958428D90851AE5EC32F /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 57C41A2591C5EDD8E3475A60 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 603701A52D728005004FE230 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; @@ -89,6 +91,7 @@ 97C146EF1CF9000F007C117D /* Products */, AAF1D69EC431FC127C369128 /* Pods */, 5F731FA9B1EF6A5DF5DC817A /* Frameworks */, + 2CFD958428D90851AE5EC32F /* GoogleService-Info.plist */, ); sourceTree = ""; }; @@ -194,6 +197,7 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + 3A96899877713ACC1DEF03C5 /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -376,10 +380,14 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = J6B4LYQ6NB; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = J6B4LYQ6NB; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; @@ -390,6 +398,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = commet_ios_distribution; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -508,10 +518,14 @@ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = J6B4LYQ6NB; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = J6B4LYQ6NB; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; @@ -522,6 +536,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = commet_ios_distribution; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -534,10 +550,14 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = J6B4LYQ6NB; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = J6B4LYQ6NB; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; @@ -548,6 +568,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = commet_ios_distribution; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; diff --git a/commet/ios/Runner/AppDelegate.swift b/commet/ios/Runner/AppDelegate.swift index b63630348..f9d9203a0 100644 --- a/commet/ios/Runner/AppDelegate.swift +++ b/commet/ios/Runner/AppDelegate.swift @@ -1,5 +1,9 @@ import UIKit import Flutter +import Firebase +import FirebaseCore +import flutter_local_notifications +import flutter_background_service_ios @main @objc class AppDelegate: FlutterAppDelegate { @@ -8,6 +12,16 @@ import Flutter didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) + if #available(iOS 10.0, *) { + UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate + } + FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in + GeneratedPluginRegistrant.register(with: registry) + } + SwiftFlutterBackgroundServicePlugin.taskIdentifier = "dev.flutter.background.refresh" +// FirebaseApp.configure() +// GeneratedPluginRegistrant.register(with: self) + + return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } diff --git a/commet/ios/Runner/Info.plist b/commet/ios/Runner/Info.plist index 087bd5166..e701f920a 100644 --- a/commet/ios/Runner/Info.plist +++ b/commet/ios/Runner/Info.plist @@ -2,6 +2,14 @@ + BGTaskScheduler + + dev.flutter.background.refresh + + BGTaskSchedulerPermittedIdentifiers + + dev.flutter.background.refresh + CADisableMinimumFrameDurationOnPhone CFBundleDevelopmentRegion @@ -24,6 +32,10 @@ ???? CFBundleVersion $(FLUTTER_BUILD_NUMBER) + FirebaseAppDelegateProxyEnabled + + ITSAppUsesNonExemptEncryption + LSRequiresIPhoneOS NSPhotoLibraryUsageDescription @@ -34,6 +46,7 @@ fetch remote-notification + processing UILaunchStoryboardName LaunchScreen diff --git a/commet/ios/export.plist b/commet/ios/export.plist new file mode 100644 index 000000000..77a4f3855 --- /dev/null +++ b/commet/ios/export.plist @@ -0,0 +1,27 @@ + + + + + destination + export + manageAppVersionAndBuildNumber + + method + app-store-connect + provisioningProfiles + + chat.commet.commetapp.quirt + commet_ios_distribution + + signingCertificate + Apple Distribution + signingStyle + manual + stripSwiftSymbols + + teamID + J6B4LYQ6NB + uploadSymbols + + + From 97308304b67066d6c180f556f3e3cc766bf67394 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sun, 9 Mar 2025 21:03:35 -0400 Subject: [PATCH 39/64] First attempt at iOS build in runner --- .github/workflows/build.yml | 70 ++- commet/ios/Runner.xcodeproj/project.pbxproj | 4 - commet/ios/Runner/AppDelegate.swift | 89 ++- .../firebase_push_notifier.dart | 27 +- .../push_notification/ios/ios_notifier.dart | 572 +++++++++++++----- .../notification_manager.dart | 1 + .../matrix_push_notification_component.dart | 19 +- commet/lib/config/platform_utils.dart | 5 + .../categories/app/settings_category_app.dart | 2 +- .../developer/developer_settings_page.dart | 25 +- 10 files changed, 621 insertions(+), 193 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d293f6d4c..51cfad942 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -178,11 +178,6 @@ jobs: flutter-version: '3.24.4' channel: 'stable' -# - name: Setup Tools -# uses: gerlero/brew-install@v1 -# with: -# packages: ninja gtk+3 mpv ffmpeg mimalloc - - name: Setup Provisioning Profile env: BUILD_CERTIFICATE_BASE64: ${{ secrets.YORK_DEV_ID_APP_P12 }} @@ -230,4 +225,67 @@ jobs: if: ${{ always() }} run: | security delete-keychain $RUNNER_TEMP/app-signing.keychain-db - rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.provisionprofile \ No newline at end of file + rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.provisionprofile + + build-ios: + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: 'true' + + - name: Setup Flutter + uses: subosito/flutter-action@v2.8.0 + with: + flutter-version: '3.24.4' + channel: 'stable' + + - name: Setup Provisioning Profile + env: + BUILD_CERTIFICATE_BASE64: ${{ secrets.YORK_IOS_CERT_P12 }} + P12_PASSWORD: ${{ secrets.YORK_IOS_CERT_P12_PASSWORD }} + BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.COMMET_IOS_PROFILE_PROVISIONPROFILE }} + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + run: | + # create variables + CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 + PP_PATH=$RUNNER_TEMP/build_pp.provisionprofile + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + + # import certificate and provisioning profile from secrets + echo "Making Build Certificate" + echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH + echo "Making Provisioning Profile" + echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH + + # create temporary keychain + security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security set-keychain-settings -lut 21600 $KEYCHAIN_PATH + security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + + # import certificate to keychain + security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security list-keychain -d user -s $KEYCHAIN_PATH + + # apply provisioning profile + mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles + cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles/ +# ln -s ~/Library/Developer/Xcode/UserData/Provisioning\ Profiles ~/Library/MobileDevice/Provisioning\ Profiles + + - name: Code Generation + run: | + cd $PROJECT_PATH + dart run scripts/codegen.dart + + - name: Build Mac + run: | + cd $PROJECT_PATH + flutter build ipa --export-options-plist=ios/export.plist --dart-define BUILD_MODE=release --dart-define PLATFORM=ios + + - name: Clean up keychain and provisioning profile + if: ${{ always() }} + run: | + security delete-keychain $RUNNER_TEMP/app-signing.keychain-db + rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.provisionprofile diff --git a/commet/ios/Runner.xcodeproj/project.pbxproj b/commet/ios/Runner.xcodeproj/project.pbxproj index 2bcede9b4..e9e6714b2 100644 --- a/commet/ios/Runner.xcodeproj/project.pbxproj +++ b/commet/ios/Runner.xcodeproj/project.pbxproj @@ -9,7 +9,6 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 33094CB8717F20131D8A6C51 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF23A21167A1629A46938202 /* Pods_Runner.framework */; }; - 3A96899877713ACC1DEF03C5 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2CFD958428D90851AE5EC32F /* GoogleService-Info.plist */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -34,7 +33,6 @@ 0D317BE01B771C2F83770B29 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 2CFD958428D90851AE5EC32F /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 57C41A2591C5EDD8E3475A60 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 603701A52D728005004FE230 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; @@ -91,7 +89,6 @@ 97C146EF1CF9000F007C117D /* Products */, AAF1D69EC431FC127C369128 /* Pods */, 5F731FA9B1EF6A5DF5DC817A /* Frameworks */, - 2CFD958428D90851AE5EC32F /* GoogleService-Info.plist */, ); sourceTree = ""; }; @@ -197,7 +194,6 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - 3A96899877713ACC1DEF03C5 /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/commet/ios/Runner/AppDelegate.swift b/commet/ios/Runner/AppDelegate.swift index f9d9203a0..3feeef9a8 100644 --- a/commet/ios/Runner/AppDelegate.swift +++ b/commet/ios/Runner/AppDelegate.swift @@ -1,27 +1,98 @@ import UIKit import Flutter -import Firebase -import FirebaseCore -import flutter_local_notifications import flutter_background_service_ios +import UserNotifications @main @objc class AppDelegate: FlutterAppDelegate { + + let channelName : String = "PushNotificationChannel" + var deviceToken : String = "" + override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { - GeneratedPluginRegistrant.register(with: self) + let controller : FlutterViewController = window?.rootViewController as! FlutterViewController + let pushNotificationChannel = FlutterMethodChannel(name: channelName, binaryMessenger: controller.binaryMessenger) if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate } - FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in - GeneratedPluginRegistrant.register(with: registry) - } SwiftFlutterBackgroundServicePlugin.taskIdentifier = "dev.flutter.background.refresh" -// FirebaseApp.configure() -// GeneratedPluginRegistrant.register(with: self) + + pushNotificationChannel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) in + switch call.method { + case "requestNotificationPermissions": + self?.requestNotificationPermissions(result: result) + case "registerForPushNotifications": + self?.registerForPushNotifications(application: application, result: result) + case "retrieveDeviceToken": + self?.getDeviceToken(result: result) + default: + result(FlutterMethodNotImplemented) + } + } + + GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } + + override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { + let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) } + let token = tokenParts.joined() + self.deviceToken = token + } + + override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { + } + + + + private func requestNotificationPermissions(result: @escaping FlutterResult) { + UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in + if let error = error { + result(FlutterError(code: "PERMISSION_ERROR", message: "Failed to request permissions", details: error.localizedDescription)) + return + } + result(granted) + } + } + + private func registerForPushNotifications(application: UIApplication, result: @escaping FlutterResult) { + application.registerForRemoteNotifications() + result("Device Token registration initiated") + } + + private func getDeviceToken(result: @escaping FlutterResult) { + if(deviceToken.isEmpty){ + result(FlutterError(code: "UNAVAILABLE", message: "Device token not available", details: nil)) + } else{ + result(deviceToken) + } + } + + override func userNotificationCenter(_ center: UNUserNotificationCenter, + willPresent notification: UNNotification, + withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { + if #available(iOS 14.0, *) { + completionHandler([.banner, .list, .sound, .badge]) + } else { + completionHandler([.alert, .sound, .badge]) + } + } + + override func userNotificationCenter(_ center: UNUserNotificationCenter, + didReceive response: UNNotificationResponse, + withCompletionHandler completionHandler: @escaping () -> Void) { + let userInfo = response.notification.request.content.userInfo + handleNotification(userInfo: userInfo) + completionHandler() + } + + private func handleNotification(userInfo: [AnyHashable: Any]) { + let controller: FlutterViewController = window?.rootViewController as! FlutterViewController + let pushNotificationChannel = FlutterMethodChannel(name: channelName, binaryMessenger: controller.binaryMessenger) + pushNotificationChannel.invokeMethod("onPushNotification", arguments: userInfo) + } } diff --git a/commet/lib/client/components/push_notification/firebase_push_notifier.dart b/commet/lib/client/components/push_notification/firebase_push_notifier.dart index 5eabaea69..5e30ff698 100644 --- a/commet/lib/client/components/push_notification/firebase_push_notifier.dart +++ b/commet/lib/client/components/push_notification/firebase_push_notifier.dart @@ -16,10 +16,11 @@ import 'package:commet/service/background_service.dart'; import 'package:commet/service/background_service_notifications/background_service_task_notification.dart'; // Manage these to enable / disable firebase -// import 'package:firebase_core/firebase_core.dart'; -// import 'package:firebase_messaging/firebase_messaging.dart'; -dynamic Firebase; -dynamic FirebaseMessaging; +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:commet/firebase_options.dart'; +//dynamic Firebase; +//dynamic FirebaseMessaging; // -------- Future onForegroundMessage(dynamic message) async { @@ -95,8 +96,18 @@ class FirebasePushNotifier implements Notifier { Log.i("Initializing firebase push notifier"); await notifier.init(); - await Firebase.initializeApp(); + await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); Log.i("Initialized App"); + if (PlatformUtils.isIOS) { + var fb = FirebaseMessaging.instance; + var apns_token = await fb.getAPNSToken(); + Log.i("APNS token is $apns_token"); + await fb.setForegroundNotificationPresentationOptions( + alert: true, + badge: true, + sound: true, + ); + } FirebaseMessaging.instance.onTokenRefresh.listen((event) { token = event; Log.i("Got new token: $token"); @@ -122,11 +133,17 @@ class FirebasePushNotifier implements Notifier { @override Future getToken() async { + if (PlatformUtils.isIOS) { + return notifier.getToken(); + } return preferences.fcmKey; } @override Map? extraRegistrationData() { + if (PlatformUtils.isIOS) { + return notifier.extraRegistrationData(); + } return {"type": "fcm"}; } diff --git a/commet/lib/client/components/push_notification/ios/ios_notifier.dart b/commet/lib/client/components/push_notification/ios/ios_notifier.dart index 72c412ad2..0c25fa722 100644 --- a/commet/lib/client/components/push_notification/ios/ios_notifier.dart +++ b/commet/lib/client/components/push_notification/ios/ios_notifier.dart @@ -1,5 +1,5 @@ -import 'dart:ui'; - +//import 'package:commet/client/components/direct_messages/direct_message_component.dart'; +//import 'package:commet/client/components/push_notification/notification_manager.dart'; import 'package:commet/client/components/push_notification/notification_content.dart'; import 'package:commet/client/components/push_notification/notifier.dart'; import 'package:commet/client/room.dart'; @@ -7,174 +7,416 @@ import 'package:commet/debug/log.dart'; import 'package:commet/main.dart'; import 'package:commet/utils/custom_uri.dart'; import 'package:commet/utils/event_bus.dart'; -import 'package:commet/utils/image_utils.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; + import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +//import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; +//import 'package:commet/firebase_options.dart'; + +//@pragma('vm:entry-point') +//void onBackgroundResponse(NotificationResponse details) { +// Log.i("Got a background notification response: $details"); +//} +// +//Future onNotification(dynamic message) async { +// String? eventId = message.data['event_id']; +// String? roomId = message.data['room_id']; +// if (eventId == null || roomId == null) { +// return; +// } +// +// Log.i("Got firebase message: $message"); +// +// var client = +// clientManager!.clients.firstWhere((element) => element.hasRoom(roomId)); +// var room = client.getRoom(roomId); +// var event = await room!.getEvent(eventId); +// +// var user = await room.fetchMember(event!.senderId); +// +// Log.i("Dispatching notification"); +// +// bool isDirectMessage = client +// .getComponent() +// ?.isRoomDirectMessage(room) ?? +// false; +// +// NotificationManager.notify(MessageNotificationContent( +// senderName: user.displayName, +// senderId: user.identifier, +// roomName: room.displayName, +// content: event.plainTextBody, +// eventId: eventId, +// roomId: room.identifier, +// clientId: client.identifier, +// senderImage: user.avatar, +// roomImage: await room.getShortcutImage(), +// isDirectMessage: isDirectMessage)); +//} +// +//class IOSNotifier implements Notifier { +// @override +// bool get hasPermission => true; +// +// @override +// bool get needsToken => false; +// +// @override +// bool get enabled => true; +// +// FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin; +// +// String? token; +// +// @override +// Future init() async { +// Log.i("Initializing ios push notifier"); +// +// flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); +// +// final DarwinInitializationSettings settings = DarwinInitializationSettings( +// requestSoundPermission: false, +// requestBadgePermission: false, +// requestAlertPermission: false, +// notificationCategories: [ +// DarwinNotificationCategory( +// 'plainCategory', +// actions: [ +// DarwinNotificationAction.plain( +// 'id_1', +// 'Action 1', +// options: { +// DarwinNotificationActionOption.foreground, +// }, +// ), +// ], +// options: { +// DarwinNotificationCategoryOption.hiddenPreviewShowTitle, +// }, +// ) +// ], +// ); +// +// final initSettings = InitializationSettings(iOS: settings); +// +// await flutterLocalNotificationsPlugin?.initialize(initSettings, +// onDidReceiveBackgroundNotificationResponse: onBackgroundResponse, +// onDidReceiveNotificationResponse: onResponse); +// +// await NativePush.instance.initialize( +// firebaseOptions: { +// 'apiKey': DefaultFirebaseOptions.currentPlatform.apiKey, +// 'projectId': DefaultFirebaseOptions.currentPlatform.projectId, +// 'messagingSenderId': DefaultFirebaseOptions.currentPlatform.messagingSenderId, +// 'applicationId': DefaultFirebaseOptions.currentPlatform.appId, +// }, +// useDefaultNotificationChannel: true, +// ); +// +// await NativePush.instance.registerForRemoteNotification( +// options: [ +// NotificationOption.alert, +// NotificationOption.sound, +// NotificationOption.badge +// ], +// ); +// +// NativePush.instance.notificationStream.listen((notification) { +// onNotification(notification); +// Log.i('Received notification: $notification'); +// }); +// } +// +// static void onResponse(NotificationResponse details) { +// Log.i("Got a notification response: $details"); +// +// if (details.payload == null) return; +// +// var uri = CustomURI.parse(details.payload!); +// +// if (details.notificationResponseType == +// NotificationResponseType.selectedNotification) { +// if (uri is OpenRoomURI) { +// EventBus.openRoom.add((uri.roomId, uri.clientId)); +// } +// } +// } +// +// @override +// Future notify(NotificationContent notification) async { +// Log.i("Notifying $notification"); +// switch (notification.runtimeType) { +// case MessageNotificationContent: +// return displayMessageNotification( +// notification as MessageNotificationContent); +// default: +// } +// } +// +// Future displayMessageNotification( +// MessageNotificationContent content) async { +// var client = clientManager?.getClient(content.clientId); +// var room = client?.getRoom(content.roomId); +// +// Log.i("Displaying Message $content"); +// +// if (room == null) { +// return; +// } +// +// if (shortcutsManager.loading != null) { +// await shortcutsManager.loading; +// } +// +// await Future.wait([ +// shortcutsManager.createShortcutForRoom(room), +// ]); +// +// var id = room.identifier.hashCode; +// +// var payload = +// OpenRoomURI(roomId: content.roomId, clientId: content.clientId) +// .toString(); +// +// const DarwinNotificationDetails details = +// DarwinNotificationDetails( +// interruptionLevel: InterruptionLevel.active, +// categoryIdentifier: 'plainCategory' +// ); +// +// const NotificationDetails notificationDetails = +// NotificationDetails(iOS: details); +// await flutterLocalNotificationsPlugin?.show( +// id, null, content.content, notificationDetails, +// payload: payload); +// } +// +// @override +// Future getToken() async { +// final (service, token) = await NativePush.instance.notificationToken; +// return token; +// } +// +// @override +// Future requestPermission() async { +// return true; +// } +// +// @override +// Map? extraRegistrationData() { +// var extraData = { +// "type": "fcm", +// "default_payload": { +// "aps": { +// "alert": { +// "loc-args": [], +// "loc-key": "Notification", +// }, +// "mutable-content": 1, +// "content_available": 1, +// }, +// }, +// "data_message": "ios", +//// "content_available": 1, +//// "apns": {"payload": {"aps": {"mutable-content": 1, "content-available": 1}}}, +// }; +// return extraData; +// } +// +// @override +// Future clearNotifications(Room room) async { +// var notifications = +// await flutterLocalNotificationsPlugin?.getActiveNotifications(); +// +// if (notifications == null) return; +// +// for (var noti in notifications) { +// if (noti.groupKey == room.identifier) { +// flutterLocalNotificationsPlugin?.cancel(noti.id!); +// } +// } +// } +//} @pragma('vm:entry-point') void onBackgroundResponse(NotificationResponse details) { - Log.i("Got a background notification response: $details"); + Log.i("Got a background notification response: $details"); } class IOSNotifier implements Notifier { - @override - bool hasPermission = false; - - @override - bool get needsToken => false; - - FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin; - - @override - bool get enabled => true; - - @override - Future init() async { - flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); - - final DarwinInitializationSettings settings = DarwinInitializationSettings( - requestSoundPermission: false, - requestBadgePermission: false, - requestAlertPermission: false, - notificationCategories: [ - DarwinNotificationCategory( - 'plainCategory', - actions: [ - DarwinNotificationAction.plain( - 'id_1', - 'Action 1', -// options: { -// DarwinNotificationActionOption.foreground, -// }, - ), - ], - options: { - DarwinNotificationCategoryOption.hiddenPreviewShowTitle, - }, - ) - ], - ); - - final initSettings = InitializationSettings(iOS: settings); - - await flutterLocalNotificationsPlugin?.initialize(initSettings, - onDidReceiveBackgroundNotificationResponse: onBackgroundResponse, - onDidReceiveNotificationResponse: onResponse); - - if (!isHeadless) { - checkPermission(); - } - } - - Future checkPermission() async { - var ios = flutterLocalNotificationsPlugin! - .resolvePlatformSpecificImplementation< - IOSFlutterLocalNotificationsPlugin>()!; - hasPermission = - await ios.requestPermissions(alert: true, badge: true, sound: true) ?? - false; - } - - @override - Future notify(NotificationContent notification) async { - switch (notification.runtimeType) { - case MessageNotificationContent: - return displayMessageNotification( - notification as MessageNotificationContent); - default: - } - } - - Future displayMessageNotification( - MessageNotificationContent content) async { - var client = clientManager?.getClient(content.clientId); - var room = client?.getRoom(content.roomId); - - if (room == null) { - return; - } - - if (flutterLocalNotificationsPlugin == null) { - Log.i( - "Flutter local notifications plugin was null. Something went wrong"); - return; - } - - if (shortcutsManager.loading != null) { - await shortcutsManager.loading; - } - - await Future.wait([ - shortcutsManager.createShortcutForRoom(room), - ]); - - var id = room.identifier.hashCode; - - var payload = - OpenRoomURI(roomId: content.roomId, clientId: content.clientId) - .toString(); - - const DarwinNotificationDetails details = - DarwinNotificationDetails(categoryIdentifier: 'plainCategory'); - - const NotificationDetails notificationDetails = - NotificationDetails(iOS: details); - await flutterLocalNotificationsPlugin?.show( - id, null, content.content, notificationDetails, - payload: payload); - } - - Future getImageBytes(ImageProvider? provider) async { - if (provider != null) { - var data = await ImageUtils.imageProviderToImage(provider); - var bytes = await data.toByteData(format: ImageByteFormat.png); - return bytes?.buffer.asUint8List(); - } - return null; - } - - @override - Future requestPermission() async { - return true; - } - - static void onResponse(NotificationResponse details) { - Log.i("Got a notification response: $details"); - - if (details.payload == null) return; - - var uri = CustomURI.parse(details.payload!); - - if (details.notificationResponseType == - NotificationResponseType.selectedNotification) { - if (uri is OpenRoomURI) { - EventBus.openRoom.add((uri.roomId, uri.clientId)); - } - } - } - - @override - Future getToken() async { - return null; - } - - @override - Map? extraRegistrationData() { - return null; - } - - @override - Future clearNotifications(Room room) async { - var notifications = - await flutterLocalNotificationsPlugin?.getActiveNotifications(); - - if (notifications == null) return; - - for (var noti in notifications) { - if (noti.groupKey == room.identifier) { - flutterLocalNotificationsPlugin?.cancel(noti.id!); - } - } - } + @override + bool hasPermission = false; + + @override + bool get needsToken => true; + + FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin; + + @override + bool get enabled => true; + + @override + Future init() async { + flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); + + final DarwinInitializationSettings settings = DarwinInitializationSettings( + notificationCategories: [ + DarwinNotificationCategory( + 'plainCategory', + actions: [ + DarwinNotificationAction.plain( + 'id_1', + 'Action 1', + options: { + DarwinNotificationActionOption.foreground, + }, + ), + ], + options: { + DarwinNotificationCategoryOption.hiddenPreviewShowTitle, + }, + ) + ], + ); + + final initSettings = InitializationSettings(iOS: settings); + + await flutterLocalNotificationsPlugin?.initialize(initSettings, + onDidReceiveBackgroundNotificationResponse: onBackgroundResponse, + onDidReceiveNotificationResponse: onResponse); + + if (!isHeadless) { + checkPermission(); + } + } + + Future checkPermission() async { + var ios = flutterLocalNotificationsPlugin! + .resolvePlatformSpecificImplementation< + IOSFlutterLocalNotificationsPlugin>()!; + hasPermission = + await ios.requestPermissions(alert: true, badge: true, sound: true) ?? false; + } + + @override + Future notify(NotificationContent notification) async { + switch (notification.runtimeType) { + case MessageNotificationContent: + return displayMessageNotification( + notification as MessageNotificationContent); + default: + } + } + + Future displayMessageNotification( + MessageNotificationContent content) async { + var client = clientManager?.getClient(content.clientId); + var room = client?.getRoom(content.roomId); + + if (room == null) { + return; + } + + if (flutterLocalNotificationsPlugin == null) { + Log.i( + "Flutter local notifications plugin was null. Something went wrong"); + return; + } + + if (shortcutsManager.loading != null) { + await shortcutsManager.loading; + } + + await Future.wait([ + shortcutsManager.createShortcutForRoom(room), + ]); + + var id = room.identifier.hashCode; + + var payload = + OpenRoomURI(roomId: content.roomId, clientId: content.clientId) + .toString(); + + const DarwinNotificationDetails details = + DarwinNotificationDetails( + interruptionLevel: InterruptionLevel.active, + categoryIdentifier: 'plainCategory' + ); + + const NotificationDetails notificationDetails = + NotificationDetails(iOS: details); + await flutterLocalNotificationsPlugin?.show( + id, null, content.content, notificationDetails, + payload: payload); + } + + @override + Future requestPermission() async { + var ios = flutterLocalNotificationsPlugin! + .resolvePlatformSpecificImplementation< + IOSFlutterLocalNotificationsPlugin>()!; + hasPermission = + await ios.requestPermissions(alert: true, badge: true, sound: true) ?? false; + return hasPermission; + } + + static void onResponse(NotificationResponse details) { + Log.i("Got a notification response: $details"); + + if (details.payload == null) return; + + var uri = CustomURI.parse(details.payload!); + + if (details.notificationResponseType == + NotificationResponseType.selectedNotification) { + if (uri is OpenRoomURI) { + EventBus.openRoom.add((uri.roomId, uri.clientId)); + } + } + } + + @override + Future getToken() async { + var firebaseInstance = FirebaseMessaging.instance; + var apns = await firebaseInstance.getAPNSToken(); + Log.i('apns $apns '); + var firebase = await firebaseInstance.getToken(); + Log.i('token $firebase'); + return firebase; + } + + @override + Map? extraRegistrationData() { + var extraData = { + "type": "fcm", + "default_payload": { + "aps": { + "alert": { + "loc-args": [], + "loc-key": "Notification", + }, + "mutable-content": 1, + "content_available": 1, + }, + }, + "data_message": "ios", + "content_available": 1, + "apns": {"payload": {"aps": {"mutable-content": 1, "content-available": 1}}}, + }; + return extraData; + } + + @override + Future clearNotifications(Room room) async { + var notifications = + await flutterLocalNotificationsPlugin?.getActiveNotifications(); + + if (notifications == null) return; + + for (var noti in notifications) { + if (noti.groupKey == room.identifier) { + flutterLocalNotificationsPlugin?.cancel(noti.id!); + } + } + } } diff --git a/commet/lib/client/components/push_notification/notification_manager.dart b/commet/lib/client/components/push_notification/notification_manager.dart index e22f42711..c71122765 100644 --- a/commet/lib/client/components/push_notification/notification_manager.dart +++ b/commet/lib/client/components/push_notification/notification_manager.dart @@ -2,6 +2,7 @@ import 'package:commet/client/alert.dart'; import 'package:commet/client/client.dart'; import 'package:commet/client/components/push_notification/firebase_push_notifier.dart'; import 'package:commet/client/components/push_notification/android/android_notifier.dart'; +import 'package:commet/client/components/push_notification/ios/ios_notifier.dart'; import 'package:commet/client/components/push_notification/android/unified_push_notifier.dart'; import 'package:commet/client/components/push_notification/linux/linux_notifier.dart'; import 'package:commet/client/components/push_notification/modifiers/notification_modifiers.dart'; diff --git a/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart b/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart index 54515d5dd..7f2f677ea 100644 --- a/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart +++ b/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart @@ -2,6 +2,7 @@ import 'package:commet/client/components/push_notification/notification_manager. import 'package:commet/client/components/push_notification/push_notification_component.dart'; import 'package:commet/client/matrix/matrix_client.dart'; import 'package:commet/config/build_config.dart'; +import 'package:commet/config/platform_utils.dart'; import 'package:commet/debug/log.dart'; import 'package:commet/main.dart'; import 'package:matrix/matrix.dart'; @@ -27,9 +28,22 @@ class MatrixPushNotificationComponent pushers.any((element) => element.pushkey == pushKey)) { return; } + + var profileTag = ""; + var appId = "chat.commet.commetapp"; + if (PlatformUtils.isAndroid) { + appId = "chat.commet.commetapp.android"; + profileTag = "android"; + } else if (PlatformUtils.isIOS) { + appId = "chat.commet.commetapp.quirt"; + profileTag = "ios"; + } else if (PlatformUtils.isMacOS) { + appId = "chat.commet.commetapp.macos"; + profileTag = "macos"; + } var pusher = Pusher( - appId: "chat.commet.commetapp.android", + appId: appId, pushkey: pushKey, appDisplayName: BuildConfig.appName, data: PusherData( @@ -39,7 +53,8 @@ class MatrixPushNotificationComponent ), deviceDisplayName: deviceName, kind: "http", - lang: "en"); + lang: "en", + profileTag: profileTag); await matrixClient.postPusher(pusher, append: true); } diff --git a/commet/lib/config/platform_utils.dart b/commet/lib/config/platform_utils.dart index 1c4734fd5..287629c8e 100644 --- a/commet/lib/config/platform_utils.dart +++ b/commet/lib/config/platform_utils.dart @@ -27,4 +27,9 @@ class PlatformUtils { if (kIsWeb) return false; return Platform.isIOS; } + + static bool get isMacOS { + if (kIsWeb) return false; + return Platform.isMacOS; + } } diff --git a/commet/lib/ui/pages/settings/categories/app/settings_category_app.dart b/commet/lib/ui/pages/settings/categories/app/settings_category_app.dart index 90ef17a8e..9f89acda3 100644 --- a/commet/lib/ui/pages/settings/categories/app/settings_category_app.dart +++ b/commet/lib/ui/pages/settings/categories/app/settings_category_app.dart @@ -66,7 +66,7 @@ class SettingsCategoryApp implements SettingsCategory { return const WindowSettingsPage(); }), // We really only need to configure on unified push - if (BuildConfig.ANDROID && + if ((BuildConfig.ANDROID || BuildConfig.IOS) && (!BuildConfig.ENABLE_GOOGLE_SERVICES || preferences.developerMode)) SettingsTab( label: labelSettingsAppNotifications, diff --git a/commet/lib/ui/pages/settings/categories/developer/developer_settings_page.dart b/commet/lib/ui/pages/settings/categories/developer/developer_settings_page.dart index 3d2a793f2..75859fc0c 100644 --- a/commet/lib/ui/pages/settings/categories/developer/developer_settings_page.dart +++ b/commet/lib/ui/pages/settings/categories/developer/developer_settings_page.dart @@ -198,7 +198,30 @@ class _DeveloperSettingsPageState extends State { )); }, ), - ]) + ]), + Wrap(spacing: 8, runSpacing: 8, children: [ + tiamat.Button( + text: "Delayed Message Notification", + onTap: () async { + var client = clientManager!.clients.first; + var room = client.rooms.first; + var user = client.self!; + Future.delayed(const Duration(milliseconds: 5000), () { + NotificationManager.notify(MessageNotificationContent( + senderName: user.displayName, + senderImage: user.avatar, + senderId: user.identifier, + roomName: room.displayName, + roomId: room.identifier, + content: "Test Message!", + clientId: client.identifier, + eventId: "fake_event_id", + isDirectMessage: true, + )); + }); + }, + ), + ]), ], ); } From ce52bdf78520ba567b7b29dd2981b32b518127f0 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sun, 9 Mar 2025 21:12:12 -0400 Subject: [PATCH 40/64] Added all the changed files --- .github/workflows/build.yml | 3 +- commet/ios/Podfile.lock | 226 -------- .../firebase_push_notifier.dart | 37 +- .../push_notification/ios/ios_notifier.dart | 528 +++++++++++------- .../notification_manager.dart | 2 +- 5 files changed, 349 insertions(+), 447 deletions(-) delete mode 100644 commet/ios/Podfile.lock diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 51cfad942..efca04fd7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -209,7 +209,6 @@ jobs: # apply provisioning profile mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles/ - ln -s ~/Library/Developer/Xcode/UserData/Provisioning\ Profiles ~/Library/MobileDevice/Provisioning\ Profiles - name: Code Generation run: | @@ -279,7 +278,7 @@ jobs: cd $PROJECT_PATH dart run scripts/codegen.dart - - name: Build Mac + - name: Build iOS run: | cd $PROJECT_PATH flutter build ipa --export-options-plist=ios/export.plist --dart-define BUILD_MODE=release --dart-define PLATFORM=ios diff --git a/commet/ios/Podfile.lock b/commet/ios/Podfile.lock deleted file mode 100644 index 43e929f4b..000000000 --- a/commet/ios/Podfile.lock +++ /dev/null @@ -1,226 +0,0 @@ -PODS: - - device_info_plus (0.0.1): - - Flutter - - DKImagePickerController/Core (4.3.9): - - DKImagePickerController/ImageDataManager - - DKImagePickerController/Resource - - DKImagePickerController/ImageDataManager (4.3.9) - - DKImagePickerController/PhotoGallery (4.3.9): - - DKImagePickerController/Core - - DKPhotoGallery - - DKImagePickerController/Resource (4.3.9) - - DKPhotoGallery (0.0.19): - - DKPhotoGallery/Core (= 0.0.19) - - DKPhotoGallery/Model (= 0.0.19) - - DKPhotoGallery/Preview (= 0.0.19) - - DKPhotoGallery/Resource (= 0.0.19) - - SDWebImage - - SwiftyGif - - DKPhotoGallery/Core (0.0.19): - - DKPhotoGallery/Model - - DKPhotoGallery/Preview - - SDWebImage - - SwiftyGif - - DKPhotoGallery/Model (0.0.19): - - SDWebImage - - SwiftyGif - - DKPhotoGallery/Preview (0.0.19): - - DKPhotoGallery/Model - - DKPhotoGallery/Resource - - SDWebImage - - SwiftyGif - - DKPhotoGallery/Resource (0.0.19): - - SDWebImage - - SwiftyGif - - file_picker (0.0.1): - - DKImagePickerController/PhotoGallery - - Flutter - - Flutter (1.0.0) - - flutter_background_service_ios (0.0.3): - - Flutter - - flutter_local_notifications (0.0.1): - - Flutter - - flutter_olm (3.2.15): - - Flutter - - flutter_openssl_crypto (0.0.1): - - Flutter - - OpenSSL-Universal - - flutter_shortcuts (0.0.1): - - Flutter - - flutter_web_auth_2 (3.0.0): - - Flutter - - integration_test (0.0.1): - - Flutter - - media_kit_libs_ios_video (1.0.4): - - Flutter - - media_kit_native_event_loop (1.0.0): - - Flutter - - media_kit_video (0.0.1): - - Flutter - - OpenSSL-Universal (3.3.2000) - - package_info_plus (0.4.5): - - Flutter - - pasteboard (0.0.1): - - Flutter - - path_provider_foundation (0.0.1): - - Flutter - - FlutterMacOS - - permission_handler_apple (9.3.0): - - Flutter - - screen_brightness_ios (0.1.0): - - Flutter - - SDWebImage (5.21.0): - - SDWebImage/Core (= 5.21.0) - - SDWebImage/Core (5.21.0) - - shared_preferences_foundation (0.0.1): - - Flutter - - FlutterMacOS - - sqflite_darwin (0.0.4): - - Flutter - - FlutterMacOS - - sqlite3 (3.47.2): - - sqlite3/common (= 3.47.2) - - sqlite3/common (3.47.2) - - sqlite3/dbstatvtab (3.47.2): - - sqlite3/common - - sqlite3/fts5 (3.47.2): - - sqlite3/common - - sqlite3/perf-threadsafe (3.47.2): - - sqlite3/common - - sqlite3/rtree (3.47.2): - - sqlite3/common - - sqlite3_flutter_libs (0.0.1): - - Flutter - - sqlite3 (~> 3.47.0) - - sqlite3/dbstatvtab - - sqlite3/fts5 - - sqlite3/perf-threadsafe - - sqlite3/rtree - - SwiftyGif (5.4.5) - - url_launcher_ios (0.0.1): - - Flutter - - volume_controller (0.0.1): - - Flutter - - wakelock_plus (0.0.1): - - Flutter - -DEPENDENCIES: - - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - - file_picker (from `.symlinks/plugins/file_picker/ios`) - - Flutter (from `Flutter`) - - flutter_background_service_ios (from `.symlinks/plugins/flutter_background_service_ios/ios`) - - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - - flutter_olm (from `.symlinks/plugins/flutter_olm/ios`) - - flutter_openssl_crypto (from `.symlinks/plugins/flutter_openssl_crypto/ios`) - - flutter_shortcuts (from `.symlinks/plugins/flutter_shortcuts/ios`) - - flutter_web_auth_2 (from `.symlinks/plugins/flutter_web_auth_2/ios`) - - integration_test (from `.symlinks/plugins/integration_test/ios`) - - media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`) - - media_kit_native_event_loop (from `.symlinks/plugins/media_kit_native_event_loop/ios`) - - media_kit_video (from `.symlinks/plugins/media_kit_video/ios`) - - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - - pasteboard (from `.symlinks/plugins/pasteboard/ios`) - - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - - screen_brightness_ios (from `.symlinks/plugins/screen_brightness_ios/ios`) - - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) - - sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`) - - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - - volume_controller (from `.symlinks/plugins/volume_controller/ios`) - - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`) - -SPEC REPOS: - trunk: - - DKImagePickerController - - DKPhotoGallery - - OpenSSL-Universal - - SDWebImage - - sqlite3 - - SwiftyGif - -EXTERNAL SOURCES: - device_info_plus: - :path: ".symlinks/plugins/device_info_plus/ios" - file_picker: - :path: ".symlinks/plugins/file_picker/ios" - Flutter: - :path: Flutter - flutter_background_service_ios: - :path: ".symlinks/plugins/flutter_background_service_ios/ios" - flutter_local_notifications: - :path: ".symlinks/plugins/flutter_local_notifications/ios" - flutter_olm: - :path: ".symlinks/plugins/flutter_olm/ios" - flutter_openssl_crypto: - :path: ".symlinks/plugins/flutter_openssl_crypto/ios" - flutter_shortcuts: - :path: ".symlinks/plugins/flutter_shortcuts/ios" - flutter_web_auth_2: - :path: ".symlinks/plugins/flutter_web_auth_2/ios" - integration_test: - :path: ".symlinks/plugins/integration_test/ios" - media_kit_libs_ios_video: - :path: ".symlinks/plugins/media_kit_libs_ios_video/ios" - media_kit_native_event_loop: - :path: ".symlinks/plugins/media_kit_native_event_loop/ios" - media_kit_video: - :path: ".symlinks/plugins/media_kit_video/ios" - package_info_plus: - :path: ".symlinks/plugins/package_info_plus/ios" - pasteboard: - :path: ".symlinks/plugins/pasteboard/ios" - path_provider_foundation: - :path: ".symlinks/plugins/path_provider_foundation/darwin" - permission_handler_apple: - :path: ".symlinks/plugins/permission_handler_apple/ios" - screen_brightness_ios: - :path: ".symlinks/plugins/screen_brightness_ios/ios" - shared_preferences_foundation: - :path: ".symlinks/plugins/shared_preferences_foundation/darwin" - sqflite_darwin: - :path: ".symlinks/plugins/sqflite_darwin/darwin" - sqlite3_flutter_libs: - :path: ".symlinks/plugins/sqlite3_flutter_libs/ios" - url_launcher_ios: - :path: ".symlinks/plugins/url_launcher_ios/ios" - volume_controller: - :path: ".symlinks/plugins/volume_controller/ios" - wakelock_plus: - :path: ".symlinks/plugins/wakelock_plus/ios" - -SPEC CHECKSUMS: - device_info_plus: 335f3ce08d2e174b9fdc3db3db0f4e3b1f66bd89 - DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c - DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 - file_picker: 5f42b9d5580e30b57b4863f9d94b448016b702e5 - Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - flutter_background_service_ios: 00d31bdff7b4bfe06d32375df358abe0329cf87e - flutter_local_notifications: 395056b3175ba4f08480a7c5de30cd36d69827e4 - flutter_olm: a557853f4d153f9553240fe1197c42e683abe4c7 - flutter_openssl_crypto: 73dcefff7611c3ac324d82726047d8335d0b6e57 - flutter_shortcuts: f9d9086904f3c2a03071c938165771cbb9171729 - flutter_web_auth_2: 3464a7c16dc6480b6194fc89913bae6e82f28405 - integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e - media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854 - media_kit_native_event_loop: 5fba1a849a6c87a34985f1e178a0de5bd444a0cf - media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474 - OpenSSL-Universal: b60a3702c9fea8b3145549d421fdb018e53ab7b4 - package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 - pasteboard: 49088aeb6119d51f976a421db60d8e1ab079b63c - path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 - permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d - screen_brightness_ios: 5ed898fa50fa82a26171c086ca5e28228f932576 - SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868 - shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 - sqflite_darwin: 44bb54cc302bff1fbe5752293aba1820b157cf1c - sqlite3: 7559e33dae4c78538df563795af3a86fc887ee71 - sqlite3_flutter_libs: 4dd5d78cb764bc095baa5af79dcee907d05a21a1 - SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 - url_launcher_ios: 694010445543906933d732453a59da0a173ae33d - volume_controller: ca1cde542ee70fad77d388f82e9616488110942b - wakelock_plus: fd58c82b1388f4afe3fe8aa2c856503a262a5b03 - -PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011 - -COCOAPODS: 1.16.2 diff --git a/commet/lib/client/components/push_notification/firebase_push_notifier.dart b/commet/lib/client/components/push_notification/firebase_push_notifier.dart index 5e30ff698..3fb07f929 100644 --- a/commet/lib/client/components/push_notification/firebase_push_notifier.dart +++ b/commet/lib/client/components/push_notification/firebase_push_notifier.dart @@ -4,23 +4,20 @@ import 'dart:async'; import 'package:commet/client/components/direct_messages/direct_message_component.dart'; import 'package:commet/client/components/push_notification/android/android_notifier.dart'; -import 'package:commet/client/components/push_notification/ios/ios_notifier.dart'; import 'package:commet/client/components/push_notification/notification_content.dart'; import 'package:commet/client/components/push_notification/notification_manager.dart'; import 'package:commet/client/components/push_notification/notifier.dart'; import 'package:commet/client/room.dart'; -import 'package:commet/config/platform_utils.dart'; import 'package:commet/debug/log.dart'; import 'package:commet/main.dart'; import 'package:commet/service/background_service.dart'; import 'package:commet/service/background_service_notifications/background_service_task_notification.dart'; // Manage these to enable / disable firebase -import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:commet/firebase_options.dart'; -//dynamic Firebase; -//dynamic FirebaseMessaging; +// import 'package:firebase_core/firebase_core.dart'; +// import 'package:firebase_messaging/firebase_messaging.dart'; +dynamic Firebase; +dynamic FirebaseMessaging; // -------- Future onForegroundMessage(dynamic message) async { @@ -77,13 +74,7 @@ class FirebasePushNotifier implements Notifier { bool get needsToken => true; FirebasePushNotifier() { - if (PlatformUtils.isAndroid) { - notifier = AndroidNotifier(); - } else if (PlatformUtils.isIOS) { - notifier = IOSNotifier(); - } else { - notifier = AndroidNotifier(); - } + notifier = AndroidNotifier(); } @override @@ -96,18 +87,8 @@ class FirebasePushNotifier implements Notifier { Log.i("Initializing firebase push notifier"); await notifier.init(); - await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); + await Firebase.initializeApp(); Log.i("Initialized App"); - if (PlatformUtils.isIOS) { - var fb = FirebaseMessaging.instance; - var apns_token = await fb.getAPNSToken(); - Log.i("APNS token is $apns_token"); - await fb.setForegroundNotificationPresentationOptions( - alert: true, - badge: true, - sound: true, - ); - } FirebaseMessaging.instance.onTokenRefresh.listen((event) { token = event; Log.i("Got new token: $token"); @@ -133,17 +114,11 @@ class FirebasePushNotifier implements Notifier { @override Future getToken() async { - if (PlatformUtils.isIOS) { - return notifier.getToken(); - } return preferences.fcmKey; } @override Map? extraRegistrationData() { - if (PlatformUtils.isIOS) { - return notifier.extraRegistrationData(); - } return {"type": "fcm"}; } diff --git a/commet/lib/client/components/push_notification/ios/ios_notifier.dart b/commet/lib/client/components/push_notification/ios/ios_notifier.dart index 0c25fa722..dc3329ef6 100644 --- a/commet/lib/client/components/push_notification/ios/ios_notifier.dart +++ b/commet/lib/client/components/push_notification/ios/ios_notifier.dart @@ -1,5 +1,5 @@ -//import 'package:commet/client/components/direct_messages/direct_message_component.dart'; -//import 'package:commet/client/components/push_notification/notification_manager.dart'; +import 'package:commet/client/components/direct_messages/direct_message_component.dart'; +import 'package:commet/client/components/push_notification/notification_manager.dart'; import 'package:commet/client/components/push_notification/notification_content.dart'; import 'package:commet/client/components/push_notification/notifier.dart'; import 'package:commet/client/room.dart'; @@ -8,10 +8,164 @@ import 'package:commet/main.dart'; import 'package:commet/utils/custom_uri.dart'; import 'package:commet/utils/event_bus.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; -//import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; -//import 'package:commet/firebase_options.dart'; + +class IOSNotifier implements Notifier { + static const String _channelName = "PushNotificationChannel"; + static const MethodChannel _channel = MethodChannel(_channelName); + + @override + bool hasPermission = false; + + @override + bool get needsToken => true; + + @override + bool get enabled => true; + + @override + Future init() async { + await requestPermission().then((value) async { + await registerDevice(); + }); + } + + @override + Future notify(NotificationContent notification) async { + switch (notification.runtimeType) { + case MessageNotificationContent: + return displayMessageNotification( + notification as MessageNotificationContent); + default: + } + } + + Future displayMessageNotification( + MessageNotificationContent content) async { + var client = clientManager?.getClient(content.clientId); + var room = client?.getRoom(content.roomId); + + if (room == null) { + return; + } + + if (shortcutsManager.loading != null) { + await shortcutsManager.loading; + } + + await Future.wait([ + shortcutsManager.createShortcutForRoom(room), + ]); + + EventBus.openRoom.add((content.roomId, content.clientId)); + } + + @override + Future requestPermission() async { + try { + await _channel.invokeMethod("requestNotificationPermissions"); + return true; + } on PlatformException catch (e) { + Log.e("Error Getting Permission: $e.message"); + return false; + } + } + + static Future registerDevice() async { + try { + await _channel.invokeMethod("registerForPushNotifications"); + } on PlatformException catch (e) { + throw PlatformException(message: e.message, code: e.code); + } + } + + static void onResponse(NotificationResponse details) { + Log.i("Got a notification response: $details"); + + if (details.payload == null) return; + + var uri = CustomURI.parse(details.payload!); + + if (details.notificationResponseType == + NotificationResponseType.selectedNotification) { + if (uri is OpenRoomURI) { + EventBus.openRoom.add((uri.roomId, uri.clientId)); + } + } + } + + @override + Future getToken() async { + try { + String? token = await _channel.invokeMethod("retrieveDeviceToken"); + Log.i("APNS Device Token is $token"); + return token; + } on PlatformException catch (e) { + throw PlatformException(message: e.message, code: e.code); + } + } + + @override + Map? extraRegistrationData() { + var extraData = { + "default_payload": { + "aps": { + "alert": { + "loc-args": [], + "loc-key": "Notification", + }, + "mutable-content": 1, + "content_available": 1, + }, + }, + }; + return extraData; + } + + static handlerPushNotificationData({required BuildContext context}) async { + _channel.setMethodCallHandler((call) async { + if (call.method == "onPushNotification") { + final roomId = call.arguments.roomId as String?; + final eventId = call.arguments.eventId as String?; + + if (eventId == null || roomId == null) { + return; + } + + var client = + clientManager!.clients.firstWhere((element) => element.hasRoom(roomId)); + var room = client.getRoom(roomId); + var event = await room!.getEvent(eventId); + + var user = await room.fetchMember(event!.senderId); + + bool isDirectMessage = client + .getComponent() + ?.isRoomDirectMessage(room) ?? + false; + + NotificationManager.notify(MessageNotificationContent( + senderName: user.displayName, + senderId: user.identifier, + roomName: room.displayName, + content: event.plainTextBody, + eventId: eventId, + roomId: room.identifier, + clientId: client.identifier, + senderImage: user.avatar, + roomImage: await room.getShortcutImage(), + isDirectMessage: isDirectMessage)); + } + }); + } + + @override + Future clearNotifications(Room room) async { + return; + } +} //@pragma('vm:entry-point') //void onBackgroundResponse(NotificationResponse details) { @@ -238,185 +392,185 @@ import 'package:firebase_messaging/firebase_messaging.dart'; // } //} -@pragma('vm:entry-point') -void onBackgroundResponse(NotificationResponse details) { - Log.i("Got a background notification response: $details"); -} - -class IOSNotifier implements Notifier { - @override - bool hasPermission = false; - - @override - bool get needsToken => true; - - FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin; - - @override - bool get enabled => true; - - @override - Future init() async { - flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); - - final DarwinInitializationSettings settings = DarwinInitializationSettings( - notificationCategories: [ - DarwinNotificationCategory( - 'plainCategory', - actions: [ - DarwinNotificationAction.plain( - 'id_1', - 'Action 1', - options: { - DarwinNotificationActionOption.foreground, - }, - ), - ], - options: { - DarwinNotificationCategoryOption.hiddenPreviewShowTitle, - }, - ) - ], - ); - - final initSettings = InitializationSettings(iOS: settings); - - await flutterLocalNotificationsPlugin?.initialize(initSettings, - onDidReceiveBackgroundNotificationResponse: onBackgroundResponse, - onDidReceiveNotificationResponse: onResponse); - - if (!isHeadless) { - checkPermission(); - } - } - - Future checkPermission() async { - var ios = flutterLocalNotificationsPlugin! - .resolvePlatformSpecificImplementation< - IOSFlutterLocalNotificationsPlugin>()!; - hasPermission = - await ios.requestPermissions(alert: true, badge: true, sound: true) ?? false; - } - - @override - Future notify(NotificationContent notification) async { - switch (notification.runtimeType) { - case MessageNotificationContent: - return displayMessageNotification( - notification as MessageNotificationContent); - default: - } - } - - Future displayMessageNotification( - MessageNotificationContent content) async { - var client = clientManager?.getClient(content.clientId); - var room = client?.getRoom(content.roomId); - - if (room == null) { - return; - } - - if (flutterLocalNotificationsPlugin == null) { - Log.i( - "Flutter local notifications plugin was null. Something went wrong"); - return; - } - - if (shortcutsManager.loading != null) { - await shortcutsManager.loading; - } - - await Future.wait([ - shortcutsManager.createShortcutForRoom(room), - ]); - - var id = room.identifier.hashCode; - - var payload = - OpenRoomURI(roomId: content.roomId, clientId: content.clientId) - .toString(); - - const DarwinNotificationDetails details = - DarwinNotificationDetails( - interruptionLevel: InterruptionLevel.active, - categoryIdentifier: 'plainCategory' - ); - - const NotificationDetails notificationDetails = - NotificationDetails(iOS: details); - await flutterLocalNotificationsPlugin?.show( - id, null, content.content, notificationDetails, - payload: payload); - } - - @override - Future requestPermission() async { - var ios = flutterLocalNotificationsPlugin! - .resolvePlatformSpecificImplementation< - IOSFlutterLocalNotificationsPlugin>()!; - hasPermission = - await ios.requestPermissions(alert: true, badge: true, sound: true) ?? false; - return hasPermission; - } - - static void onResponse(NotificationResponse details) { - Log.i("Got a notification response: $details"); - - if (details.payload == null) return; - - var uri = CustomURI.parse(details.payload!); - - if (details.notificationResponseType == - NotificationResponseType.selectedNotification) { - if (uri is OpenRoomURI) { - EventBus.openRoom.add((uri.roomId, uri.clientId)); - } - } - } - - @override - Future getToken() async { - var firebaseInstance = FirebaseMessaging.instance; - var apns = await firebaseInstance.getAPNSToken(); - Log.i('apns $apns '); - var firebase = await firebaseInstance.getToken(); - Log.i('token $firebase'); - return firebase; - } - - @override - Map? extraRegistrationData() { - var extraData = { - "type": "fcm", - "default_payload": { - "aps": { - "alert": { - "loc-args": [], - "loc-key": "Notification", - }, - "mutable-content": 1, - "content_available": 1, - }, - }, - "data_message": "ios", - "content_available": 1, - "apns": {"payload": {"aps": {"mutable-content": 1, "content-available": 1}}}, - }; - return extraData; - } - - @override - Future clearNotifications(Room room) async { - var notifications = - await flutterLocalNotificationsPlugin?.getActiveNotifications(); - - if (notifications == null) return; - - for (var noti in notifications) { - if (noti.groupKey == room.identifier) { - flutterLocalNotificationsPlugin?.cancel(noti.id!); - } - } - } -} +//@pragma('vm:entry-point') +//void onBackgroundResponse(NotificationResponse details) { +// Log.i("Got a background notification response: $details"); +//} +// +//class IOSNotifier implements Notifier { +// @override +// bool hasPermission = false; +// +// @override +// bool get needsToken => true; +// +// FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin; +// +// @override +// bool get enabled => true; +// +// @override +// Future init() async { +// flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); +// +// final DarwinInitializationSettings settings = DarwinInitializationSettings( +// notificationCategories: [ +// DarwinNotificationCategory( +// 'plainCategory', +// actions: [ +// DarwinNotificationAction.plain( +// 'id_1', +// 'Action 1', +// options: { +// DarwinNotificationActionOption.foreground, +// }, +// ), +// ], +// options: { +// DarwinNotificationCategoryOption.hiddenPreviewShowTitle, +// }, +// ) +// ], +// ); +// +// final initSettings = InitializationSettings(iOS: settings); +// +// await flutterLocalNotificationsPlugin?.initialize(initSettings, +// onDidReceiveBackgroundNotificationResponse: onBackgroundResponse, +// onDidReceiveNotificationResponse: onResponse); +// +// if (!isHeadless) { +// checkPermission(); +// } +// } +// +// Future checkPermission() async { +// var ios = flutterLocalNotificationsPlugin! +// .resolvePlatformSpecificImplementation< +// IOSFlutterLocalNotificationsPlugin>()!; +// hasPermission = +// await ios.requestPermissions(alert: true, badge: true, sound: true) ?? false; +// } +// +// @override +// Future notify(NotificationContent notification) async { +// switch (notification.runtimeType) { +// case MessageNotificationContent: +// return displayMessageNotification( +// notification as MessageNotificationContent); +// default: +// } +// } +// +// Future displayMessageNotification( +// MessageNotificationContent content) async { +// var client = clientManager?.getClient(content.clientId); +// var room = client?.getRoom(content.roomId); +// +// if (room == null) { +// return; +// } +// +// if (flutterLocalNotificationsPlugin == null) { +// Log.i( +// "Flutter local notifications plugin was null. Something went wrong"); +// return; +// } +// +// if (shortcutsManager.loading != null) { +// await shortcutsManager.loading; +// } +// +// await Future.wait([ +// shortcutsManager.createShortcutForRoom(room), +// ]); +// +// var id = room.identifier.hashCode; +// +// var payload = +// OpenRoomURI(roomId: content.roomId, clientId: content.clientId) +// .toString(); +// +// const DarwinNotificationDetails details = +// DarwinNotificationDetails( +// interruptionLevel: InterruptionLevel.active, +// categoryIdentifier: 'plainCategory' +// ); +// +// const NotificationDetails notificationDetails = +// NotificationDetails(iOS: details); +// await flutterLocalNotificationsPlugin?.show( +// id, null, content.content, notificationDetails, +// payload: payload); +// } +// +// @override +// Future requestPermission() async { +// var ios = flutterLocalNotificationsPlugin! +// .resolvePlatformSpecificImplementation< +// IOSFlutterLocalNotificationsPlugin>()!; +// hasPermission = +// await ios.requestPermissions(alert: true, badge: true, sound: true) ?? false; +// return hasPermission; +// } +// +// static void onResponse(NotificationResponse details) { +// Log.i("Got a notification response: $details"); +// +// if (details.payload == null) return; +// +// var uri = CustomURI.parse(details.payload!); +// +// if (details.notificationResponseType == +// NotificationResponseType.selectedNotification) { +// if (uri is OpenRoomURI) { +// EventBus.openRoom.add((uri.roomId, uri.clientId)); +// } +// } +// } +// +// @override +// Future getToken() async { +// var firebaseInstance = FirebaseMessaging.instance; +// var apns = await firebaseInstance.getAPNSToken(); +// Log.i('apns $apns '); +// var firebase = await firebaseInstance.getToken(); +// Log.i('token $firebase'); +// return firebase; +// } +// +// @override +// Map? extraRegistrationData() { +// var extraData = { +// "type": "fcm", +// "default_payload": { +// "aps": { +// "alert": { +// "loc-args": [], +// "loc-key": "Notification", +// }, +// "mutable-content": 1, +// "content_available": true, +// }, +// }, +// "data_message": "ios", +// "content_available": true, +// "apns": {"payload": {"aps": {"mutable-content": 1, "content-available": true}}}, +// }; +// return extraData; +// } +// +// @override +// Future clearNotifications(Room room) async { +// var notifications = +// await flutterLocalNotificationsPlugin?.getActiveNotifications(); +// +// if (notifications == null) return; +// +// for (var noti in notifications) { +// if (noti.groupKey == room.identifier) { +// flutterLocalNotificationsPlugin?.cancel(noti.id!); +// } +// } +// } +//} diff --git a/commet/lib/client/components/push_notification/notification_manager.dart b/commet/lib/client/components/push_notification/notification_manager.dart index c71122765..5ecff0777 100644 --- a/commet/lib/client/components/push_notification/notification_manager.dart +++ b/commet/lib/client/components/push_notification/notification_manager.dart @@ -82,7 +82,7 @@ class NotificationManager { } if (PlatformUtils.isIOS) { - return FirebasePushNotifier(); + return IOSNotifier(); } return null; From d2968f008a06f16c1daae89813bfe14164dbac45 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sun, 9 Mar 2025 21:24:44 -0400 Subject: [PATCH 41/64] Dart formatting --- .../push_notification/ios/ios_notifier.dart | 107 +++++++++--------- .../matrix_push_notification_component.dart | 2 +- 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/commet/lib/client/components/push_notification/ios/ios_notifier.dart b/commet/lib/client/components/push_notification/ios/ios_notifier.dart index dc3329ef6..00dcbe41a 100644 --- a/commet/lib/client/components/push_notification/ios/ios_notifier.dart +++ b/commet/lib/client/components/push_notification/ios/ios_notifier.dart @@ -15,7 +15,7 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart'; class IOSNotifier implements Notifier { static const String _channelName = "PushNotificationChannel"; static const MethodChannel _channel = MethodChannel(_channelName); - + @override bool hasPermission = false; @@ -43,7 +43,7 @@ class IOSNotifier implements Notifier { } Future displayMessageNotification( - MessageNotificationContent content) async { + MessageNotificationContent content) async { var client = clientManager?.getClient(content.clientId); var room = client?.getRoom(content.roomId); @@ -60,7 +60,7 @@ class IOSNotifier implements Notifier { ]); EventBus.openRoom.add((content.roomId, content.clientId)); - } + } @override Future requestPermission() async { @@ -80,26 +80,27 @@ class IOSNotifier implements Notifier { throw PlatformException(message: e.message, code: e.code); } } - - static void onResponse(NotificationResponse details) { - Log.i("Got a notification response: $details"); - if (details.payload == null) return; + static void onResponse(NotificationResponse details) { + Log.i("Got a notification response: $details"); + + if (details.payload == null) return; - var uri = CustomURI.parse(details.payload!); + var uri = CustomURI.parse(details.payload!); - if (details.notificationResponseType == - NotificationResponseType.selectedNotification) { - if (uri is OpenRoomURI) { - EventBus.openRoom.add((uri.roomId, uri.clientId)); - } - } - } + if (details.notificationResponseType == + NotificationResponseType.selectedNotification) { + if (uri is OpenRoomURI) { + EventBus.openRoom.add((uri.roomId, uri.clientId)); + } + } + } @override Future getToken() async { try { - String? token = await _channel.invokeMethod("retrieveDeviceToken"); + String? token = + await _channel.invokeMethod("retrieveDeviceToken"); Log.i("APNS Device Token is $token"); return token; } on PlatformException catch (e) { @@ -107,22 +108,22 @@ class IOSNotifier implements Notifier { } } - @override - Map? extraRegistrationData() { - var extraData = { - "default_payload": { - "aps": { - "alert": { - "loc-args": [], - "loc-key": "Notification", - }, - "mutable-content": 1, - "content_available": 1, - }, - }, - }; - return extraData; - } + @override + Map? extraRegistrationData() { + var extraData = { + "default_payload": { + "aps": { + "alert": { + "loc-args": [], + "loc-key": "Notification", + }, + "mutable-content": 1, + "content_available": 1, + }, + }, + }; + return extraData; + } static handlerPushNotificationData({required BuildContext context}) async { _channel.setMethodCallHandler((call) async { @@ -134,37 +135,37 @@ class IOSNotifier implements Notifier { return; } - var client = - clientManager!.clients.firstWhere((element) => element.hasRoom(roomId)); + var client = clientManager!.clients + .firstWhere((element) => element.hasRoom(roomId)); var room = client.getRoom(roomId); var event = await room!.getEvent(eventId); var user = await room.fetchMember(event!.senderId); bool isDirectMessage = client - .getComponent() - ?.isRoomDirectMessage(room) ?? - false; + .getComponent() + ?.isRoomDirectMessage(room) ?? + false; NotificationManager.notify(MessageNotificationContent( - senderName: user.displayName, - senderId: user.identifier, - roomName: room.displayName, - content: event.plainTextBody, - eventId: eventId, - roomId: room.identifier, - clientId: client.identifier, - senderImage: user.avatar, - roomImage: await room.getShortcutImage(), - isDirectMessage: isDirectMessage)); + senderName: user.displayName, + senderId: user.identifier, + roomName: room.displayName, + content: event.plainTextBody, + eventId: eventId, + roomId: room.identifier, + clientId: client.identifier, + senderImage: user.avatar, + roomImage: await room.getShortcutImage(), + isDirectMessage: isDirectMessage)); } }); } - @override - Future clearNotifications(Room room) async { - return; - } + @override + Future clearNotifications(Room room) async { + return; + } } //@pragma('vm:entry-point') @@ -274,7 +275,7 @@ class IOSNotifier implements Notifier { // NotificationOption.badge // ], // ); -// +// // NativePush.instance.notificationStream.listen((notification) { // onNotification(notification); // Log.i('Received notification: $notification'); @@ -438,7 +439,7 @@ class IOSNotifier implements Notifier { // await flutterLocalNotificationsPlugin?.initialize(initSettings, // onDidReceiveBackgroundNotificationResponse: onBackgroundResponse, // onDidReceiveNotificationResponse: onResponse); -// +// // if (!isHeadless) { // checkPermission(); // } diff --git a/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart b/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart index 7f2f677ea..5efdb3370 100644 --- a/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart +++ b/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart @@ -28,7 +28,7 @@ class MatrixPushNotificationComponent pushers.any((element) => element.pushkey == pushKey)) { return; } - + var profileTag = ""; var appId = "chat.commet.commetapp"; if (PlatformUtils.isAndroid) { From d1abccf70ef306614e663b15e6b8b738428af0d0 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Tue, 11 Mar 2025 11:17:33 -0400 Subject: [PATCH 42/64] Version with combined local notifications and APNS swift --- commet/ios/Runner/AppDelegate.swift | 29 +- .../push_notification/ios/ios_notifier.dart | 621 +++++------------- .../matrix_push_notification_component.dart | 2 + 3 files changed, 183 insertions(+), 469 deletions(-) diff --git a/commet/ios/Runner/AppDelegate.swift b/commet/ios/Runner/AppDelegate.swift index 3feeef9a8..8f2e7056b 100644 --- a/commet/ios/Runner/AppDelegate.swift +++ b/commet/ios/Runner/AppDelegate.swift @@ -2,6 +2,7 @@ import UIKit import Flutter import flutter_background_service_ios import UserNotifications +import flutter_local_notifications @main @objc class AppDelegate: FlutterAppDelegate { @@ -19,6 +20,9 @@ import UserNotifications UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate } SwiftFlutterBackgroundServicePlugin.taskIdentifier = "dev.flutter.background.refresh" + FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in + GeneratedPluginRegistrant.register(with: registry) + } pushNotificationChannel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) in switch call.method { @@ -39,9 +43,11 @@ import UserNotifications } override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { - let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) } - let token = tokenParts.joined() - self.deviceToken = token + let deviceTokenString = deviceToken.reduce("", { $0 + String(format: "%02X", $1) }) + let controller: FlutterViewController = window?.rootViewController as! FlutterViewController + let pushNotificationChannel = FlutterMethodChannel(name: channelName, binaryMessenger: controller.binaryMessenger) + self.deviceToken = deviceTokenString + pushNotificationChannel.invokeMethod("didRegister", arguments: deviceTokenString) } override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { @@ -65,12 +71,19 @@ import UserNotifications } private func getDeviceToken(result: @escaping FlutterResult) { - if(deviceToken.isEmpty){ + if(deviceToken.isEmpty) { result(FlutterError(code: "UNAVAILABLE", message: "Device token not available", details: nil)) - } else{ + } else { result(deviceToken) } } + + override func application(_ application: UIApplication, + didReceiveRemoteNotification userInfo: [AnyHashable: Any], + fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { + handleNotification(methodName: "onBackgroundNotification", userInfo: userInfo) + completionHandler(UIBackgroundFetchResult.noData) + } override func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, @@ -86,13 +99,13 @@ import UserNotifications didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo - handleNotification(userInfo: userInfo) + handleNotification(methodName: "onPushNotification", userInfo: userInfo) completionHandler() } - private func handleNotification(userInfo: [AnyHashable: Any]) { + private func handleNotification(methodName: String, userInfo: [AnyHashable: Any]) { let controller: FlutterViewController = window?.rootViewController as! FlutterViewController let pushNotificationChannel = FlutterMethodChannel(name: channelName, binaryMessenger: controller.binaryMessenger) - pushNotificationChannel.invokeMethod("onPushNotification", arguments: userInfo) + pushNotificationChannel.invokeMethod(methodName, arguments: userInfo) } } diff --git a/commet/lib/client/components/push_notification/ios/ios_notifier.dart b/commet/lib/client/components/push_notification/ios/ios_notifier.dart index 00dcbe41a..8a22ac83c 100644 --- a/commet/lib/client/components/push_notification/ios/ios_notifier.dart +++ b/commet/lib/client/components/push_notification/ios/ios_notifier.dart @@ -12,10 +12,100 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +@pragma('vm:entry-point') +void notificationTapBackground(NotificationResponse notificationResponse) { + Log.i("in notificationTapBackground"); + Log.i("Got $notificationResponse"); + IOSNotifier.onResponse(notificationResponse); + // handle action +} + +@pragma('vm:entry-point') +void handlerPushNotificationData({required BuildContext context}) async { + Log.i("in handlerPushNotificationData()"); + IOSNotifier._channel.setMethodCallHandler((call) async { + Log.i("in setMethodCallHandler() with call $call"); + if (call.method == "onPushNotification()") { + Log.i("in onPushNotification"); + final roomId = call.arguments.roomId as String?; + final eventId = call.arguments.eventId as String?; + Log.i("roomID $roomId and eventID $eventId"); + + if (eventId == null || roomId == null) { + return; + } + + var client = clientManager!.clients + .firstWhere((element) => element.hasRoom(roomId)); + var room = client.getRoom(roomId); + var event = await room!.getEvent(eventId); + + var user = await room.fetchMember(event!.senderId); + + bool isDirectMessage = client + .getComponent() + ?.isRoomDirectMessage(room) ?? + false; + + NotificationManager.notify(MessageNotificationContent( + senderName: user.displayName, + senderId: user.identifier, + roomName: room.displayName, + content: event.plainTextBody, + eventId: eventId, + roomId: room.identifier, + clientId: client.identifier, + senderImage: user.avatar, + roomImage: await room.getShortcutImage(), + isDirectMessage: isDirectMessage)); + } else if (call.method == "didRegister") { + Log.i("in didRegister()"); + final deviceToken = call.arguments as String; + Log.i("Received token $deviceToken"); + } else if (call.method == "onBackgroundNotification") { + Log.i("in onBackgroundNotification()"); + final roomId = call.arguments.roomId as String?; + final eventId = call.arguments.eventId as String?; + Log.i("roomID $roomId and eventID $eventId"); + + if (eventId == null || roomId == null) { + return; + } + + var client = clientManager!.clients + .firstWhere((element) => element.hasRoom(roomId)); + var room = client.getRoom(roomId); + var event = await room!.getEvent(eventId); + + var user = await room.fetchMember(event!.senderId); + + bool isDirectMessage = client + .getComponent() + ?.isRoomDirectMessage(room) ?? + false; + + NotificationManager.notify(MessageNotificationContent( + senderName: user.displayName, + senderId: user.identifier, + roomName: room.displayName, + content: event.plainTextBody, + eventId: eventId, + roomId: room.identifier, + clientId: client.identifier, + senderImage: user.avatar, + roomImage: await room.getShortcutImage(), + isDirectMessage: isDirectMessage)); + } + }); +} + + class IOSNotifier implements Notifier { static const String _channelName = "PushNotificationChannel"; static const MethodChannel _channel = MethodChannel(_channelName); + FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin; + @override bool hasPermission = false; @@ -27,13 +117,26 @@ class IOSNotifier implements Notifier { @override Future init() async { + Log.i("in init()"); + preferences.setPushGateway("sygnal.spacebinoculars.matrix.town"); + flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); await requestPermission().then((value) async { - await registerDevice(); + Log.i("Got permission, registering"); + await registerDevice().then((_) async { + Log.i("Registered"); + }); }); + const DarwinInitializationSettings settings = DarwinInitializationSettings(); + const initSettings = InitializationSettings(iOS: settings); + await flutterLocalNotificationsPlugin?.initialize(initSettings, + onDidReceiveBackgroundNotificationResponse: notificationTapBackground, + onDidReceiveNotificationResponse: onResponse); } @override Future notify(NotificationContent notification) async { + Log.i("in notify()"); + Log.i("Notification: $notification"); switch (notification.runtimeType) { case MessageNotificationContent: return displayMessageNotification( @@ -46,11 +149,19 @@ class IOSNotifier implements Notifier { MessageNotificationContent content) async { var client = clientManager?.getClient(content.clientId); var room = client?.getRoom(content.roomId); + + Log.i("in displayMessage() with client $client and room $room"); if (room == null) { return; } + if (flutterLocalNotificationsPlugin == null) { + Log.i( + "Flutter local notifications plugin was null. Something went wrong"); + return; + } + if (shortcutsManager.loading != null) { await shortcutsManager.loading; } @@ -59,13 +170,33 @@ class IOSNotifier implements Notifier { shortcutsManager.createShortcutForRoom(room), ]); - EventBus.openRoom.add((content.roomId, content.clientId)); + var id = room.identifier.hashCode; + + var payload = + OpenRoomURI(roomId: content.roomId, clientId: content.clientId) + .toString(); + + await flutterLocalNotificationsPlugin?.show( + id, null, content.content, const NotificationDetails(), + payload: payload); + } + + static Future requestPushNotificationPermission() async { + Log.i("in requestPushNotificationPermission()"); + try { + await _channel.invokeMethod("requestNotificationPermissions"); + Log.i("Got Permission"); + } on PlatformException catch (e) { + Log.e("Failed to get permission with message $e.message"); + throw PlatformException(message: e.message, code: e.code); + } } @override Future requestPermission() async { + Log.i("in requestPermission()"); try { - await _channel.invokeMethod("requestNotificationPermissions"); + await IOSNotifier.requestPushNotificationPermission(); return true; } on PlatformException catch (e) { Log.e("Error Getting Permission: $e.message"); @@ -74,17 +205,22 @@ class IOSNotifier implements Notifier { } static Future registerDevice() async { + Log.i("in registerDevice()"); try { await _channel.invokeMethod("registerForPushNotifications"); - } on PlatformException catch (e) { - throw PlatformException(message: e.message, code: e.code); + Log.i("Registered"); + } on PlatformException { + return; } } static void onResponse(NotificationResponse details) { + Log.i("in onResponse()"); Log.i("Got a notification response: $details"); if (details.payload == null) return; + + Log.i("Payload is $details.payload"); var uri = CustomURI.parse(details.payload!); @@ -95,483 +231,46 @@ class IOSNotifier implements Notifier { } } } + + static Future retriveDeviceToken() async { + Log.i("in retrieveDeviceToken()"); + try { + String? token = await _channel.invokeMethod("retrieveDeviceToken"); + return token; + } on PlatformException catch (e) { + Log.e("Error on token retrieval: $e.message"); + throw PlatformException(message: e.message, code: e.code); + } + } @override Future getToken() async { + Log.i("in getToken()"); try { - String? token = - await _channel.invokeMethod("retrieveDeviceToken"); - Log.i("APNS Device Token is $token"); + String? token = await IOSNotifier.retriveDeviceToken(); return token; - } on PlatformException catch (e) { - throw PlatformException(message: e.message, code: e.code); + } on PlatformException { + return null; } } @override Map? extraRegistrationData() { + Log.i("in extraRegistrationData()"); var extraData = { "default_payload": { "aps": { - "alert": { - "loc-args": [], - "loc-key": "Notification", - }, "mutable-content": 1, - "content_available": 1, - }, + "content-available": 1, + "alert": {"loc-key": "SINGLE_UNREAD", "loc-args": []} + } }, }; return extraData; } - static handlerPushNotificationData({required BuildContext context}) async { - _channel.setMethodCallHandler((call) async { - if (call.method == "onPushNotification") { - final roomId = call.arguments.roomId as String?; - final eventId = call.arguments.eventId as String?; - - if (eventId == null || roomId == null) { - return; - } - - var client = clientManager!.clients - .firstWhere((element) => element.hasRoom(roomId)); - var room = client.getRoom(roomId); - var event = await room!.getEvent(eventId); - - var user = await room.fetchMember(event!.senderId); - - bool isDirectMessage = client - .getComponent() - ?.isRoomDirectMessage(room) ?? - false; - - NotificationManager.notify(MessageNotificationContent( - senderName: user.displayName, - senderId: user.identifier, - roomName: room.displayName, - content: event.plainTextBody, - eventId: eventId, - roomId: room.identifier, - clientId: client.identifier, - senderImage: user.avatar, - roomImage: await room.getShortcutImage(), - isDirectMessage: isDirectMessage)); - } - }); - } - @override Future clearNotifications(Room room) async { return; } } - -//@pragma('vm:entry-point') -//void onBackgroundResponse(NotificationResponse details) { -// Log.i("Got a background notification response: $details"); -//} -// -//Future onNotification(dynamic message) async { -// String? eventId = message.data['event_id']; -// String? roomId = message.data['room_id']; -// if (eventId == null || roomId == null) { -// return; -// } -// -// Log.i("Got firebase message: $message"); -// -// var client = -// clientManager!.clients.firstWhere((element) => element.hasRoom(roomId)); -// var room = client.getRoom(roomId); -// var event = await room!.getEvent(eventId); -// -// var user = await room.fetchMember(event!.senderId); -// -// Log.i("Dispatching notification"); -// -// bool isDirectMessage = client -// .getComponent() -// ?.isRoomDirectMessage(room) ?? -// false; -// -// NotificationManager.notify(MessageNotificationContent( -// senderName: user.displayName, -// senderId: user.identifier, -// roomName: room.displayName, -// content: event.plainTextBody, -// eventId: eventId, -// roomId: room.identifier, -// clientId: client.identifier, -// senderImage: user.avatar, -// roomImage: await room.getShortcutImage(), -// isDirectMessage: isDirectMessage)); -//} -// -//class IOSNotifier implements Notifier { -// @override -// bool get hasPermission => true; -// -// @override -// bool get needsToken => false; -// -// @override -// bool get enabled => true; -// -// FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin; -// -// String? token; -// -// @override -// Future init() async { -// Log.i("Initializing ios push notifier"); -// -// flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); -// -// final DarwinInitializationSettings settings = DarwinInitializationSettings( -// requestSoundPermission: false, -// requestBadgePermission: false, -// requestAlertPermission: false, -// notificationCategories: [ -// DarwinNotificationCategory( -// 'plainCategory', -// actions: [ -// DarwinNotificationAction.plain( -// 'id_1', -// 'Action 1', -// options: { -// DarwinNotificationActionOption.foreground, -// }, -// ), -// ], -// options: { -// DarwinNotificationCategoryOption.hiddenPreviewShowTitle, -// }, -// ) -// ], -// ); -// -// final initSettings = InitializationSettings(iOS: settings); -// -// await flutterLocalNotificationsPlugin?.initialize(initSettings, -// onDidReceiveBackgroundNotificationResponse: onBackgroundResponse, -// onDidReceiveNotificationResponse: onResponse); -// -// await NativePush.instance.initialize( -// firebaseOptions: { -// 'apiKey': DefaultFirebaseOptions.currentPlatform.apiKey, -// 'projectId': DefaultFirebaseOptions.currentPlatform.projectId, -// 'messagingSenderId': DefaultFirebaseOptions.currentPlatform.messagingSenderId, -// 'applicationId': DefaultFirebaseOptions.currentPlatform.appId, -// }, -// useDefaultNotificationChannel: true, -// ); -// -// await NativePush.instance.registerForRemoteNotification( -// options: [ -// NotificationOption.alert, -// NotificationOption.sound, -// NotificationOption.badge -// ], -// ); -// -// NativePush.instance.notificationStream.listen((notification) { -// onNotification(notification); -// Log.i('Received notification: $notification'); -// }); -// } -// -// static void onResponse(NotificationResponse details) { -// Log.i("Got a notification response: $details"); -// -// if (details.payload == null) return; -// -// var uri = CustomURI.parse(details.payload!); -// -// if (details.notificationResponseType == -// NotificationResponseType.selectedNotification) { -// if (uri is OpenRoomURI) { -// EventBus.openRoom.add((uri.roomId, uri.clientId)); -// } -// } -// } -// -// @override -// Future notify(NotificationContent notification) async { -// Log.i("Notifying $notification"); -// switch (notification.runtimeType) { -// case MessageNotificationContent: -// return displayMessageNotification( -// notification as MessageNotificationContent); -// default: -// } -// } -// -// Future displayMessageNotification( -// MessageNotificationContent content) async { -// var client = clientManager?.getClient(content.clientId); -// var room = client?.getRoom(content.roomId); -// -// Log.i("Displaying Message $content"); -// -// if (room == null) { -// return; -// } -// -// if (shortcutsManager.loading != null) { -// await shortcutsManager.loading; -// } -// -// await Future.wait([ -// shortcutsManager.createShortcutForRoom(room), -// ]); -// -// var id = room.identifier.hashCode; -// -// var payload = -// OpenRoomURI(roomId: content.roomId, clientId: content.clientId) -// .toString(); -// -// const DarwinNotificationDetails details = -// DarwinNotificationDetails( -// interruptionLevel: InterruptionLevel.active, -// categoryIdentifier: 'plainCategory' -// ); -// -// const NotificationDetails notificationDetails = -// NotificationDetails(iOS: details); -// await flutterLocalNotificationsPlugin?.show( -// id, null, content.content, notificationDetails, -// payload: payload); -// } -// -// @override -// Future getToken() async { -// final (service, token) = await NativePush.instance.notificationToken; -// return token; -// } -// -// @override -// Future requestPermission() async { -// return true; -// } -// -// @override -// Map? extraRegistrationData() { -// var extraData = { -// "type": "fcm", -// "default_payload": { -// "aps": { -// "alert": { -// "loc-args": [], -// "loc-key": "Notification", -// }, -// "mutable-content": 1, -// "content_available": 1, -// }, -// }, -// "data_message": "ios", -//// "content_available": 1, -//// "apns": {"payload": {"aps": {"mutable-content": 1, "content-available": 1}}}, -// }; -// return extraData; -// } -// -// @override -// Future clearNotifications(Room room) async { -// var notifications = -// await flutterLocalNotificationsPlugin?.getActiveNotifications(); -// -// if (notifications == null) return; -// -// for (var noti in notifications) { -// if (noti.groupKey == room.identifier) { -// flutterLocalNotificationsPlugin?.cancel(noti.id!); -// } -// } -// } -//} - -//@pragma('vm:entry-point') -//void onBackgroundResponse(NotificationResponse details) { -// Log.i("Got a background notification response: $details"); -//} -// -//class IOSNotifier implements Notifier { -// @override -// bool hasPermission = false; -// -// @override -// bool get needsToken => true; -// -// FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin; -// -// @override -// bool get enabled => true; -// -// @override -// Future init() async { -// flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); -// -// final DarwinInitializationSettings settings = DarwinInitializationSettings( -// notificationCategories: [ -// DarwinNotificationCategory( -// 'plainCategory', -// actions: [ -// DarwinNotificationAction.plain( -// 'id_1', -// 'Action 1', -// options: { -// DarwinNotificationActionOption.foreground, -// }, -// ), -// ], -// options: { -// DarwinNotificationCategoryOption.hiddenPreviewShowTitle, -// }, -// ) -// ], -// ); -// -// final initSettings = InitializationSettings(iOS: settings); -// -// await flutterLocalNotificationsPlugin?.initialize(initSettings, -// onDidReceiveBackgroundNotificationResponse: onBackgroundResponse, -// onDidReceiveNotificationResponse: onResponse); -// -// if (!isHeadless) { -// checkPermission(); -// } -// } -// -// Future checkPermission() async { -// var ios = flutterLocalNotificationsPlugin! -// .resolvePlatformSpecificImplementation< -// IOSFlutterLocalNotificationsPlugin>()!; -// hasPermission = -// await ios.requestPermissions(alert: true, badge: true, sound: true) ?? false; -// } -// -// @override -// Future notify(NotificationContent notification) async { -// switch (notification.runtimeType) { -// case MessageNotificationContent: -// return displayMessageNotification( -// notification as MessageNotificationContent); -// default: -// } -// } -// -// Future displayMessageNotification( -// MessageNotificationContent content) async { -// var client = clientManager?.getClient(content.clientId); -// var room = client?.getRoom(content.roomId); -// -// if (room == null) { -// return; -// } -// -// if (flutterLocalNotificationsPlugin == null) { -// Log.i( -// "Flutter local notifications plugin was null. Something went wrong"); -// return; -// } -// -// if (shortcutsManager.loading != null) { -// await shortcutsManager.loading; -// } -// -// await Future.wait([ -// shortcutsManager.createShortcutForRoom(room), -// ]); -// -// var id = room.identifier.hashCode; -// -// var payload = -// OpenRoomURI(roomId: content.roomId, clientId: content.clientId) -// .toString(); -// -// const DarwinNotificationDetails details = -// DarwinNotificationDetails( -// interruptionLevel: InterruptionLevel.active, -// categoryIdentifier: 'plainCategory' -// ); -// -// const NotificationDetails notificationDetails = -// NotificationDetails(iOS: details); -// await flutterLocalNotificationsPlugin?.show( -// id, null, content.content, notificationDetails, -// payload: payload); -// } -// -// @override -// Future requestPermission() async { -// var ios = flutterLocalNotificationsPlugin! -// .resolvePlatformSpecificImplementation< -// IOSFlutterLocalNotificationsPlugin>()!; -// hasPermission = -// await ios.requestPermissions(alert: true, badge: true, sound: true) ?? false; -// return hasPermission; -// } -// -// static void onResponse(NotificationResponse details) { -// Log.i("Got a notification response: $details"); -// -// if (details.payload == null) return; -// -// var uri = CustomURI.parse(details.payload!); -// -// if (details.notificationResponseType == -// NotificationResponseType.selectedNotification) { -// if (uri is OpenRoomURI) { -// EventBus.openRoom.add((uri.roomId, uri.clientId)); -// } -// } -// } -// -// @override -// Future getToken() async { -// var firebaseInstance = FirebaseMessaging.instance; -// var apns = await firebaseInstance.getAPNSToken(); -// Log.i('apns $apns '); -// var firebase = await firebaseInstance.getToken(); -// Log.i('token $firebase'); -// return firebase; -// } -// -// @override -// Map? extraRegistrationData() { -// var extraData = { -// "type": "fcm", -// "default_payload": { -// "aps": { -// "alert": { -// "loc-args": [], -// "loc-key": "Notification", -// }, -// "mutable-content": 1, -// "content_available": true, -// }, -// }, -// "data_message": "ios", -// "content_available": true, -// "apns": {"payload": {"aps": {"mutable-content": 1, "content-available": true}}}, -// }; -// return extraData; -// } -// -// @override -// Future clearNotifications(Room room) async { -// var notifications = -// await flutterLocalNotificationsPlugin?.getActiveNotifications(); -// -// if (notifications == null) return; -// -// for (var noti in notifications) { -// if (noti.groupKey == room.identifier) { -// flutterLocalNotificationsPlugin?.cancel(noti.id!); -// } -// } -// } -//} diff --git a/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart b/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart index 5efdb3370..37e4d40cd 100644 --- a/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart +++ b/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart @@ -78,6 +78,7 @@ class MatrixPushNotificationComponent @override Future updatePushers() async { + Log.i("in updatePushers()"); if (NotificationManager.notifierLoading != null) { await NotificationManager.notifierLoading; } @@ -101,6 +102,7 @@ class MatrixPushNotificationComponent await cleanOldPushers(key, name, uri); if (key == null) { + Log.w("Device key is null"); return; } From 386c819463110b07f278f97ec3e5836bbc2561ec Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Tue, 11 Mar 2025 12:12:27 -0400 Subject: [PATCH 43/64] Trying without local notifications --- .../push_notification/ios/ios_notifier.dart | 332 +++++++++++------- .../notification_content.dart | 2 + 2 files changed, 210 insertions(+), 124 deletions(-) diff --git a/commet/lib/client/components/push_notification/ios/ios_notifier.dart b/commet/lib/client/components/push_notification/ios/ios_notifier.dart index 8a22ac83c..f29452757 100644 --- a/commet/lib/client/components/push_notification/ios/ios_notifier.dart +++ b/commet/lib/client/components/push_notification/ios/ios_notifier.dart @@ -10,101 +10,100 @@ import 'package:commet/utils/event_bus.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; - -@pragma('vm:entry-point') -void notificationTapBackground(NotificationResponse notificationResponse) { - Log.i("in notificationTapBackground"); - Log.i("Got $notificationResponse"); - IOSNotifier.onResponse(notificationResponse); - // handle action -} - -@pragma('vm:entry-point') -void handlerPushNotificationData({required BuildContext context}) async { - Log.i("in handlerPushNotificationData()"); - IOSNotifier._channel.setMethodCallHandler((call) async { - Log.i("in setMethodCallHandler() with call $call"); - if (call.method == "onPushNotification()") { - Log.i("in onPushNotification"); - final roomId = call.arguments.roomId as String?; - final eventId = call.arguments.eventId as String?; - Log.i("roomID $roomId and eventID $eventId"); - - if (eventId == null || roomId == null) { - return; - } - - var client = clientManager!.clients - .firstWhere((element) => element.hasRoom(roomId)); - var room = client.getRoom(roomId); - var event = await room!.getEvent(eventId); - - var user = await room.fetchMember(event!.senderId); - - bool isDirectMessage = client - .getComponent() - ?.isRoomDirectMessage(room) ?? - false; - - NotificationManager.notify(MessageNotificationContent( - senderName: user.displayName, - senderId: user.identifier, - roomName: room.displayName, - content: event.plainTextBody, - eventId: eventId, - roomId: room.identifier, - clientId: client.identifier, - senderImage: user.avatar, - roomImage: await room.getShortcutImage(), - isDirectMessage: isDirectMessage)); - } else if (call.method == "didRegister") { - Log.i("in didRegister()"); - final deviceToken = call.arguments as String; - Log.i("Received token $deviceToken"); - } else if (call.method == "onBackgroundNotification") { - Log.i("in onBackgroundNotification()"); - final roomId = call.arguments.roomId as String?; - final eventId = call.arguments.eventId as String?; - Log.i("roomID $roomId and eventID $eventId"); - - if (eventId == null || roomId == null) { - return; - } - - var client = clientManager!.clients - .firstWhere((element) => element.hasRoom(roomId)); - var room = client.getRoom(roomId); - var event = await room!.getEvent(eventId); - - var user = await room.fetchMember(event!.senderId); - - bool isDirectMessage = client - .getComponent() - ?.isRoomDirectMessage(room) ?? - false; - - NotificationManager.notify(MessageNotificationContent( - senderName: user.displayName, - senderId: user.identifier, - roomName: room.displayName, - content: event.plainTextBody, - eventId: eventId, - roomId: room.identifier, - clientId: client.identifier, - senderImage: user.avatar, - roomImage: await room.getShortcutImage(), - isDirectMessage: isDirectMessage)); - } - }); -} - +//import 'package:flutter_local_notifications/flutter_local_notifications.dart'; + +//@pragma('vm:entry-point') +//void notificationTapBackground(NotificationResponse notificationResponse) { +// Log.i("in notificationTapBackground"); +// Log.i("Got $notificationResponse"); +// IOSNotifier.onResponse(notificationResponse); +// // handle action +//} + +//@pragma('vm:entry-point') +//void handlerPushNotificationData({required BuildContext context}) async { +// Log.i("in handlerPushNotificationData()"); +// IOSNotifier._channel.setMethodCallHandler((call) async { +// Log.i("in setMethodCallHandler() with call $call"); +// if (call.method == "onPushNotification()") { +// Log.i("in onPushNotification"); +// final roomId = call.arguments.roomId as String?; +// final eventId = call.arguments.eventId as String?; +// Log.i("roomID $roomId and eventID $eventId"); +// +// if (eventId == null || roomId == null) { +// return; +// } +// +// var client = clientManager!.clients +// .firstWhere((element) => element.hasRoom(roomId)); +// var room = client.getRoom(roomId); +// var event = await room!.getEvent(eventId); +// +// var user = await room.fetchMember(event!.senderId); +// +// bool isDirectMessage = client +// .getComponent() +// ?.isRoomDirectMessage(room) ?? +// false; +// +// NotificationManager.notify(MessageNotificationContent( +// senderName: user.displayName, +// senderId: user.identifier, +// roomName: room.displayName, +// content: event.plainTextBody, +// eventId: eventId, +// roomId: room.identifier, +// clientId: client.identifier, +// senderImage: user.avatar, +// roomImage: await room.getShortcutImage(), +// isDirectMessage: isDirectMessage)); +// } else if (call.method == "didRegister") { +// Log.i("in didRegister()"); +// final deviceToken = call.arguments as String; +// Log.i("Received token $deviceToken"); +// } else if (call.method == "onBackgroundNotification") { +// Log.i("in onBackgroundNotification()"); +// final roomId = call.arguments.roomId as String?; +// final eventId = call.arguments.eventId as String?; +// Log.i("roomID $roomId and eventID $eventId"); +// +// if (eventId == null || roomId == null) { +// return; +// } +// +// var client = clientManager!.clients +// .firstWhere((element) => element.hasRoom(roomId)); +// var room = client.getRoom(roomId); +// var event = await room!.getEvent(eventId); +// +// var user = await room.fetchMember(event!.senderId); +// +// bool isDirectMessage = client +// .getComponent() +// ?.isRoomDirectMessage(room) ?? +// false; +// +// NotificationManager.notify(MessageNotificationContent( +// senderName: user.displayName, +// senderId: user.identifier, +// roomName: room.displayName, +// content: event.plainTextBody, +// eventId: eventId, +// roomId: room.identifier, +// clientId: client.identifier, +// senderImage: user.avatar, +// roomImage: await room.getShortcutImage(), +// isDirectMessage: isDirectMessage)); +// } +// }); +//} class IOSNotifier implements Notifier { static const String _channelName = "PushNotificationChannel"; static const MethodChannel _channel = MethodChannel(_channelName); - FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin; +// FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin; @override bool hasPermission = false; @@ -119,18 +118,18 @@ class IOSNotifier implements Notifier { Future init() async { Log.i("in init()"); preferences.setPushGateway("sygnal.spacebinoculars.matrix.town"); - flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); +// flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); await requestPermission().then((value) async { Log.i("Got permission, registering"); await registerDevice().then((_) async { Log.i("Registered"); }); }); - const DarwinInitializationSettings settings = DarwinInitializationSettings(); - const initSettings = InitializationSettings(iOS: settings); - await flutterLocalNotificationsPlugin?.initialize(initSettings, - onDidReceiveBackgroundNotificationResponse: notificationTapBackground, - onDidReceiveNotificationResponse: onResponse); +// const DarwinInitializationSettings settings = DarwinInitializationSettings(); +// const initSettings = InitializationSettings(iOS: settings); +// await flutterLocalNotificationsPlugin?.initialize(initSettings, +// onDidReceiveBackgroundNotificationResponse: notificationTapBackground, +// onDidReceiveNotificationResponse: onResponse); } @override @@ -149,18 +148,20 @@ class IOSNotifier implements Notifier { MessageNotificationContent content) async { var client = clientManager?.getClient(content.clientId); var room = client?.getRoom(content.roomId); - - Log.i("in displayMessage() with client $client and room $room"); + var source = content.source; + + Log.i( + "in displayMessage() with client $client and room $room from source $source"); if (room == null) { return; } - if (flutterLocalNotificationsPlugin == null) { - Log.i( - "Flutter local notifications plugin was null. Something went wrong"); - return; - } +// if (flutterLocalNotificationsPlugin == null) { +// Log.i( +// "Flutter local notifications plugin was null. Something went wrong"); +// return; +// } if (shortcutsManager.loading != null) { await shortcutsManager.loading; @@ -176,9 +177,11 @@ class IOSNotifier implements Notifier { OpenRoomURI(roomId: content.roomId, clientId: content.clientId) .toString(); - await flutterLocalNotificationsPlugin?.show( - id, null, content.content, const NotificationDetails(), - payload: payload); + Log.i("Notify with ID $id and payload $payload"); + +// await flutterLocalNotificationsPlugin?.show( +// id, null, content.content, const NotificationDetails(), +// payload: payload); } static Future requestPushNotificationPermission() async { @@ -214,28 +217,29 @@ class IOSNotifier implements Notifier { } } - static void onResponse(NotificationResponse details) { - Log.i("in onResponse()"); - Log.i("Got a notification response: $details"); +// static void onResponse(NotificationResponse details) { +// Log.i("in onResponse()"); +// Log.i("Got a notification response: $details"); +// +// if (details.payload == null) return; +// +// Log.i("Payload is $details.payload"); +// +// var uri = CustomURI.parse(details.payload!); +// +// if (details.notificationResponseType == +// NotificationResponseType.selectedNotification) { +// if (uri is OpenRoomURI) { +// EventBus.openRoom.add((uri.roomId, uri.clientId)); +// } +// } +// } - if (details.payload == null) return; - - Log.i("Payload is $details.payload"); - - var uri = CustomURI.parse(details.payload!); - - if (details.notificationResponseType == - NotificationResponseType.selectedNotification) { - if (uri is OpenRoomURI) { - EventBus.openRoom.add((uri.roomId, uri.clientId)); - } - } - } - static Future retriveDeviceToken() async { Log.i("in retrieveDeviceToken()"); try { - String? token = await _channel.invokeMethod("retrieveDeviceToken"); + String? token = + await _channel.invokeMethod("retrieveDeviceToken"); return token; } on PlatformException catch (e) { Log.e("Error on token retrieval: $e.message"); @@ -269,6 +273,86 @@ class IOSNotifier implements Notifier { return extraData; } + void handlerPushNotificationData({required BuildContext context}) async { + Log.i("in handlerPushNotificationData()"); + _channel.setMethodCallHandler((call) async { + Log.i("in setMethodCallHandler() with call $call"); + if (call.method == "onPushNotification()") { + Log.i("in onPushNotification"); + final roomId = call.arguments.roomId as String?; + final eventId = call.arguments.eventId as String?; + Log.i("roomID $roomId and eventID $eventId"); + + if (eventId == null || roomId == null) { + return; + } + + var client = clientManager!.clients + .firstWhere((element) => element.hasRoom(roomId)); + var room = client.getRoom(roomId); + var event = await room!.getEvent(eventId); + + var user = await room.fetchMember(event!.senderId); + + bool isDirectMessage = client + .getComponent() + ?.isRoomDirectMessage(room) ?? + false; + + NotificationManager.notify(MessageNotificationContent( + senderName: user.displayName, + senderId: user.identifier, + roomName: room.displayName, + content: event.plainTextBody, + eventId: eventId, + roomId: room.identifier, + clientId: client.identifier, + senderImage: user.avatar, + roomImage: await room.getShortcutImage(), + isDirectMessage: isDirectMessage, + source: "onPushNotification")); + } else if (call.method == "didRegister") { + Log.i("in didRegister()"); + final deviceToken = call.arguments as String; + Log.i("Received token $deviceToken"); + } else if (call.method == "onBackgroundNotification") { + Log.i("in onBackgroundNotification()"); + final roomId = call.arguments.roomId as String?; + final eventId = call.arguments.eventId as String?; + Log.i("roomID $roomId and eventID $eventId"); + + if (eventId == null || roomId == null) { + return; + } + + var client = clientManager!.clients + .firstWhere((element) => element.hasRoom(roomId)); + var room = client.getRoom(roomId); + var event = await room!.getEvent(eventId); + + var user = await room.fetchMember(event!.senderId); + + bool isDirectMessage = client + .getComponent() + ?.isRoomDirectMessage(room) ?? + false; + + NotificationManager.notify(MessageNotificationContent( + senderName: user.displayName, + senderId: user.identifier, + roomName: room.displayName, + content: event.plainTextBody, + eventId: eventId, + roomId: room.identifier, + clientId: client.identifier, + senderImage: user.avatar, + roomImage: await room.getShortcutImage(), + isDirectMessage: isDirectMessage, + source: "onBackgroundNotification")); + } + }); + } + @override Future clearNotifications(Room room) async { return; diff --git a/commet/lib/client/components/push_notification/notification_content.dart b/commet/lib/client/components/push_notification/notification_content.dart index f6e3a12b2..30182cc4c 100644 --- a/commet/lib/client/components/push_notification/notification_content.dart +++ b/commet/lib/client/components/push_notification/notification_content.dart @@ -20,6 +20,7 @@ class MessageNotificationContent extends NotificationContent { String roomId; String clientId; String roomName; + String? source; bool isDirectMessage; ImageProvider? roomImage; ImageProvider? senderImage; @@ -37,5 +38,6 @@ class MessageNotificationContent extends NotificationContent { this.roomImage, this.senderImage, this.attachedImage, + this.source, }) : super(title: senderName, content: content); } From 3a253220d0d448d12e7c9f6b5bf8b973928f0002 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Wed, 19 Mar 2025 11:30:41 -0400 Subject: [PATCH 44/64] Resolved conflict --- commet/ios/Podfile | 4 + commet/ios/Runner.xcodeproj/project.pbxproj | 286 ++++++++++++++++- commet/ios/Runner/AppDelegate.swift | 6 - commet/ios/Runner/Runner.entitlements | 4 + commet/ios/export.plist | 4 +- commet/ios/servicer/Info.plist | 13 + commet/ios/servicer/NotificationService.swift | 69 +++++ commet/ios/servicer/servicer.entitlements | 10 + .../ios/ios_mutable_notifier.dart | 75 +++++ .../push_notification/ios/ios_notifier.dart | 288 +++--------------- .../macos/macos_notifier.dart | 161 ++++++++++ .../notification_manager.dart | 5 + .../matrix_push_notification_component.dart | 39 ++- commet/lib/client/matrix/matrix_room.dart | 2 +- commet/lib/config/platform_utils.dart | 11 + commet/lib/main.dart | 34 +++ commet/macos/Podfile.lock | 168 ---------- commet/macos/Runner.xcodeproj/project.pbxproj | 24 +- commet/macos/Runner/AppDelegate.swift | 94 +++++- commet/macos/Runner/MainFlutterWindow.swift | 18 +- commet/pubspec.lock | 122 +++++--- commet/pubspec.yaml | 2 + 22 files changed, 923 insertions(+), 516 deletions(-) create mode 100644 commet/ios/servicer/Info.plist create mode 100644 commet/ios/servicer/NotificationService.swift create mode 100644 commet/ios/servicer/servicer.entitlements create mode 100644 commet/lib/client/components/push_notification/ios/ios_mutable_notifier.dart create mode 100644 commet/lib/client/components/push_notification/macos/macos_notifier.dart delete mode 100644 commet/macos/Podfile.lock diff --git a/commet/ios/Podfile b/commet/ios/Podfile index f5f04672b..7f5d97b79 100644 --- a/commet/ios/Podfile +++ b/commet/ios/Podfile @@ -51,4 +51,8 @@ post_install do |installer| end end +end + +target 'servicer' do + use_frameworks! end \ No newline at end of file diff --git a/commet/ios/Runner.xcodeproj/project.pbxproj b/commet/ios/Runner.xcodeproj/project.pbxproj index e9e6714b2..5ccbe909e 100644 --- a/commet/ios/Runner.xcodeproj/project.pbxproj +++ b/commet/ios/Runner.xcodeproj/project.pbxproj @@ -10,13 +10,37 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 33094CB8717F20131D8A6C51 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF23A21167A1629A46938202 /* Pods_Runner.framework */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 551640AA994276376E608141 /* Pods_servicer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBEB167536972A2246629187 /* Pods_servicer.framework */; }; + 600D31212D83386000F738D9 /* Flutter.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 600D31202D83386000F738D9 /* Flutter.xcframework */; }; + 6021A3252D828F45001F0660 /* servicer.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 6021A31E2D828F45001F0660 /* servicer.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 6021A3232D828F45001F0660 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6021A31D2D828F45001F0660; + remoteInfo = servicer; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXCopyFilesBuildPhase section */ + 6021A3262D828F45001F0660 /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 6021A3252D828F45001F0660 /* servicer.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -35,7 +59,10 @@ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 57C41A2591C5EDD8E3475A60 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 600D31202D83386000F738D9 /* Flutter.xcframework */ = {isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:S8QB4VV633:FLUTTER.IO LLC"; lastKnownFileType = wrapper.xcframework; name = Flutter.xcframework; path = "../../../flutter-sdk/bin/cache/artifacts/engine/ios/extension_safe/Flutter.xcframework"; sourceTree = ""; }; + 6021A31E2D828F45001F0660 /* servicer.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = servicer.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 603701A52D728005004FE230 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; + 6F71ADEFB749D97791F21965 /* Pods-servicer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-servicer.debug.xcconfig"; path = "Target Support Files/Pods-servicer/Pods-servicer.debug.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; @@ -46,11 +73,44 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + ABF91C8D62261D1B58A78884 /* Pods-servicer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-servicer.release.xcconfig"; path = "Target Support Files/Pods-servicer/Pods-servicer.release.xcconfig"; sourceTree = ""; }; + D0E55B5F3A40F501ACD4023C /* Pods-servicer.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-servicer.profile.xcconfig"; path = "Target Support Files/Pods-servicer/Pods-servicer.profile.xcconfig"; sourceTree = ""; }; DD5B2EEE2F68770E413E08AF /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; DF23A21167A1629A46938202 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + EBEB167536972A2246629187 /* Pods_servicer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_servicer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + 6021A32A2D828F45001F0660 /* Exceptions for "servicer" folder in "servicer" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = 6021A31D2D828F45001F0660 /* servicer */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 6021A31F2D828F45001F0660 /* servicer */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + 6021A32A2D828F45001F0660 /* Exceptions for "servicer" folder in "servicer" target */, + ); + path = servicer; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + /* Begin PBXFrameworksBuildPhase section */ + 6021A31B2D828F45001F0660 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 600D31212D83386000F738D9 /* Flutter.xcframework in Frameworks */, + 551640AA994276376E608141 /* Pods_servicer.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -65,7 +125,9 @@ 5F731FA9B1EF6A5DF5DC817A /* Frameworks */ = { isa = PBXGroup; children = ( + 600D31202D83386000F738D9 /* Flutter.xcframework */, DF23A21167A1629A46938202 /* Pods_Runner.framework */, + EBEB167536972A2246629187 /* Pods_servicer.framework */, ); name = Frameworks; sourceTree = ""; @@ -86,6 +148,7 @@ children = ( 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, + 6021A31F2D828F45001F0660 /* servicer */, 97C146EF1CF9000F007C117D /* Products */, AAF1D69EC431FC127C369128 /* Pods */, 5F731FA9B1EF6A5DF5DC817A /* Frameworks */, @@ -96,6 +159,7 @@ isa = PBXGroup; children = ( 97C146EE1CF9000F007C117D /* Runner.app */, + 6021A31E2D828F45001F0660 /* servicer.appex */, ); name = Products; sourceTree = ""; @@ -122,6 +186,9 @@ 0D317BE01B771C2F83770B29 /* Pods-Runner.debug.xcconfig */, DD5B2EEE2F68770E413E08AF /* Pods-Runner.release.xcconfig */, 57C41A2591C5EDD8E3475A60 /* Pods-Runner.profile.xcconfig */, + 6F71ADEFB749D97791F21965 /* Pods-servicer.debug.xcconfig */, + ABF91C8D62261D1B58A78884 /* Pods-servicer.release.xcconfig */, + D0E55B5F3A40F501ACD4023C /* Pods-servicer.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -129,6 +196,27 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 6021A31D2D828F45001F0660 /* servicer */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6021A32B2D828F45001F0660 /* Build configuration list for PBXNativeTarget "servicer" */; + buildPhases = ( + 260232A55682F40F430C8857 /* [CP] Check Pods Manifest.lock */, + 6021A31A2D828F45001F0660 /* Sources */, + 6021A31B2D828F45001F0660 /* Frameworks */, + 6021A31C2D828F45001F0660 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 6021A31F2D828F45001F0660 /* servicer */, + ); + name = servicer; + productName = servicer; + productReference = 6021A31E2D828F45001F0660 /* servicer.appex */; + productType = "com.apple.product-type.app-extension"; + }; 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; @@ -139,6 +227,7 @@ 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, + 6021A3262D828F45001F0660 /* Embed Foundation Extensions */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, B7544AEBA57AB2081ADCD564 /* [CP] Embed Pods Frameworks */, 006FB0C14E09DB927049DA3C /* [CP] Copy Pods Resources */, @@ -146,6 +235,7 @@ buildRules = ( ); dependencies = ( + 6021A3242D828F45001F0660 /* PBXTargetDependency */, ); name = Runner; productName = Runner; @@ -158,9 +248,13 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 1620; LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { + 6021A31D2D828F45001F0660 = { + CreatedOnToolsVersion = 16.2; + }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 1100; @@ -168,7 +262,6 @@ }; }; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -176,16 +269,25 @@ Base, ); mainGroup = 97C146E51CF9000F007C117D; + preferredProjectObjectVersion = 77; productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, + 6021A31D2D828F45001F0660 /* servicer */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 6021A31C2D828F45001F0660 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -217,6 +319,28 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; showEnvVarsInLog = 0; }; + 260232A55682F40F430C8857 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-servicer-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -290,6 +414,13 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 6021A31A2D828F45001F0660 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -301,6 +432,14 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 6021A3242D828F45001F0660 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6021A31D2D828F45001F0660 /* servicer */; + targetProxy = 6021A3232D828F45001F0660 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ 97C146FA1CF9000F007C117D /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -402,6 +541,141 @@ }; name = Profile; }; + 6021A3272D828F45001F0660 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6F71ADEFB749D97791F21965 /* Pods-servicer.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = "$(inherited)"; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = servicer/servicer.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = J6B4LYQ6NB; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = servicer/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = servicer; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt.notificationservice; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = commet_ios_extension_distribution; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 6021A3282D828F45001F0660 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = ABF91C8D62261D1B58A78884 /* Pods-servicer.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = "$(inherited)"; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = servicer/servicer.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = J6B4LYQ6NB; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = servicer/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = servicer; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt.notificationservice; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = commet_ios_extension_distribution; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 6021A3292D828F45001F0660 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D0E55B5F3A40F501ACD4023C /* Pods-servicer.profile.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = "$(inherited)"; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = servicer/servicer.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = J6B4LYQ6NB; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = servicer/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = servicer; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt.notificationservice; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = commet_ios_extension_distribution; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Profile; + }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -575,6 +849,16 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 6021A32B2D828F45001F0660 /* Build configuration list for PBXNativeTarget "servicer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6021A3272D828F45001F0660 /* Debug */, + 6021A3282D828F45001F0660 /* Release */, + 6021A3292D828F45001F0660 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/commet/ios/Runner/AppDelegate.swift b/commet/ios/Runner/AppDelegate.swift index 8f2e7056b..f0e7131ee 100644 --- a/commet/ios/Runner/AppDelegate.swift +++ b/commet/ios/Runner/AppDelegate.swift @@ -1,8 +1,6 @@ import UIKit import Flutter -import flutter_background_service_ios import UserNotifications -import flutter_local_notifications @main @objc class AppDelegate: FlutterAppDelegate { @@ -19,10 +17,6 @@ import flutter_local_notifications if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate } - SwiftFlutterBackgroundServicePlugin.taskIdentifier = "dev.flutter.background.refresh" - FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in - GeneratedPluginRegistrant.register(with: registry) - } pushNotificationChannel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) in switch call.method { diff --git a/commet/ios/Runner/Runner.entitlements b/commet/ios/Runner/Runner.entitlements index 903def2af..fb5eb5be7 100644 --- a/commet/ios/Runner/Runner.entitlements +++ b/commet/ios/Runner/Runner.entitlements @@ -4,5 +4,9 @@ aps-environment development + com.apple.security.application-groups + + group.commet.ios + diff --git a/commet/ios/export.plist b/commet/ios/export.plist index 77a4f3855..dfb03d584 100644 --- a/commet/ios/export.plist +++ b/commet/ios/export.plist @@ -5,13 +5,15 @@ destination export manageAppVersionAndBuildNumber - + method app-store-connect provisioningProfiles chat.commet.commetapp.quirt commet_ios_distribution + chat.commet.commetapp.quirt.notificationservice + commet_ios_extension_distribution signingCertificate Apple Distribution diff --git a/commet/ios/servicer/Info.plist b/commet/ios/servicer/Info.plist new file mode 100644 index 000000000..57421ebf9 --- /dev/null +++ b/commet/ios/servicer/Info.plist @@ -0,0 +1,13 @@ + + + + + NSExtension + + NSExtensionPointIdentifier + com.apple.usernotifications.service + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).NotificationService + + + diff --git a/commet/ios/servicer/NotificationService.swift b/commet/ios/servicer/NotificationService.swift new file mode 100644 index 000000000..526b2ebd3 --- /dev/null +++ b/commet/ios/servicer/NotificationService.swift @@ -0,0 +1,69 @@ +// +// NotificationService.swift +// servicer +// +// Created by Brian Quirt on 3/12/25. +// + +import UserNotifications +import Flutter + +let channelName : String = "PushServiceChannel" + +class NotificationService: UNNotificationServiceExtension { + + var contentHandler: ((UNNotificationContent) -> Void)? + var bestAttemptContent: UNMutableNotificationContent? + + override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { + self.contentHandler = contentHandler + bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) + var flutterEngine : FlutterEngine? = FlutterEngine(name: "notification_service_engine", project: nil, allowHeadlessExecution: true) + let decodeChannel = FlutterMethodChannel(name: channelName, binaryMessenger: flutterEngine!.binaryMessenger) + + if let bestAttemptContent = bestAttemptContent { + var displayRoom : String = "" + let roomId = bestAttemptContent.userInfo["room_id"] as! String + if roomId.contains(":") { + let roomCode = roomId.lastIndex(of:":")! + displayRoom = String(roomId[roomCode...]) + } else { + displayRoom = roomId + } + let unreadCount = bestAttemptContent.userInfo["unread_count"] as! Int + + bestAttemptContent.title = "\(displayRoom)" + bestAttemptContent.subtitle = "\(unreadCount) new message(s)" + bestAttemptContent.body = "Tap on this message to be taken to the room where it happened™️" + +// do { +// flutterEngine!.run(withEntrypoint: "notificationMutationService") +// DispatchQueue.main.sync() { +// +// decodeChannel.invokeMethod("notificationReceived", arguments: bestAttemptContent.userInfo, result:{(result) -> () in +// let result = result as! NSDictionary +// +// bestAttemptContent.title = result["title"] as! String +// bestAttemptContent.subtitle = result["subtitle"] as! String +// bestAttemptContent.body = result["body"] as! String +// }) +// +// } +// } catch let error { +// bestAttemptContent.subtitle = "Error: \(error)" +// } + contentHandler(bestAttemptContent) + } + } + + override func serviceExtensionTimeWillExpire() { + // Called just before the extension will be terminated by the system. + // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. + if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { + bestAttemptContent.title = "New Matrix Message" + bestAttemptContent.body = "Tap on this message to be taken to the room where it happened™️" + contentHandler(bestAttemptContent) + } + } + +} diff --git a/commet/ios/servicer/servicer.entitlements b/commet/ios/servicer/servicer.entitlements new file mode 100644 index 000000000..476981528 --- /dev/null +++ b/commet/ios/servicer/servicer.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + group.commet.ios + + + diff --git a/commet/lib/client/components/push_notification/ios/ios_mutable_notifier.dart b/commet/lib/client/components/push_notification/ios/ios_mutable_notifier.dart new file mode 100644 index 000000000..e40b6503f --- /dev/null +++ b/commet/lib/client/components/push_notification/ios/ios_mutable_notifier.dart @@ -0,0 +1,75 @@ +import 'dart:async'; + +import 'package:commet/cache/file_cache.dart'; +import 'package:commet/client/client_manager.dart'; +import 'package:commet/client/member.dart'; +import 'package:commet/client/timeline_events/timeline_event_encrypted.dart'; +import 'package:commet/debug/log.dart'; +import 'package:commet/main.dart'; + +class IOSNotificationMutator { + Completer completer; + + IOSNotificationMutator(this.completer); + + Future init() async { + isHeadless = true; + + if (fileCache == null) { + fileCache = FileCache.getFileCacheInstance(); + + if (fileCache != null) { + await fileCache?.init(); + } + } + + shortcutsManager.init(); + + clientManager = await ClientManager.init(isBackgroundService: true); + } + + Future> handleMessage(Map? data) async { + if (data == null) { + completer.complete(); + return { + "title": "New Message", + "subtitle": "", + "body": "Received Message" + }; + } + + var roomId = data["room_id"] as String; + var eventId = data["event_id"] as String; + + var client = + clientManager!.clients.firstWhere((element) => element.hasRoom(roomId)); + + Log.i("Found client: ${client.identifier}"); + var room = client.getRoom(roomId); + Log.i("Found room: ${room?.displayName}"); + + var event = await room!.getEvent(eventId); + Member? user = await room.fetchMember(event!.senderId); + + Log.i("Got user: $user ($user)"); + + if (event is TimelineEventEncrypted) { + var decrypted = await event.attemptDecrypt(room); + event = decrypted ?? event; + } + + var content = { + "title": user.displayName, + "subtitle": room.displayName, + "body": event.plainTextBody + }; + completer.complete(); + return content; + } + + void channelHandler({channel}) async { + channel.setMethodCallHandler((call) async { + handleMessage(call.arguments); + }); + } +} diff --git a/commet/lib/client/components/push_notification/ios/ios_notifier.dart b/commet/lib/client/components/push_notification/ios/ios_notifier.dart index f29452757..240cb9603 100644 --- a/commet/lib/client/components/push_notification/ios/ios_notifier.dart +++ b/commet/lib/client/components/push_notification/ios/ios_notifier.dart @@ -1,109 +1,28 @@ -import 'package:commet/client/components/direct_messages/direct_message_component.dart'; -import 'package:commet/client/components/push_notification/notification_manager.dart'; +import 'dart:convert'; + import 'package:commet/client/components/push_notification/notification_content.dart'; import 'package:commet/client/components/push_notification/notifier.dart'; +import 'package:commet/client/components/push_notification/push_notification_component.dart'; import 'package:commet/client/room.dart'; import 'package:commet/debug/log.dart'; import 'package:commet/main.dart'; -import 'package:commet/utils/custom_uri.dart'; import 'package:commet/utils/event_bus.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; -//import 'package:flutter_local_notifications/flutter_local_notifications.dart'; - -//@pragma('vm:entry-point') -//void notificationTapBackground(NotificationResponse notificationResponse) { -// Log.i("in notificationTapBackground"); -// Log.i("Got $notificationResponse"); -// IOSNotifier.onResponse(notificationResponse); -// // handle action -//} - -//@pragma('vm:entry-point') -//void handlerPushNotificationData({required BuildContext context}) async { -// Log.i("in handlerPushNotificationData()"); -// IOSNotifier._channel.setMethodCallHandler((call) async { -// Log.i("in setMethodCallHandler() with call $call"); -// if (call.method == "onPushNotification()") { -// Log.i("in onPushNotification"); -// final roomId = call.arguments.roomId as String?; -// final eventId = call.arguments.eventId as String?; -// Log.i("roomID $roomId and eventID $eventId"); -// -// if (eventId == null || roomId == null) { -// return; -// } -// -// var client = clientManager!.clients -// .firstWhere((element) => element.hasRoom(roomId)); -// var room = client.getRoom(roomId); -// var event = await room!.getEvent(eventId); -// -// var user = await room.fetchMember(event!.senderId); -// -// bool isDirectMessage = client -// .getComponent() -// ?.isRoomDirectMessage(room) ?? -// false; -// -// NotificationManager.notify(MessageNotificationContent( -// senderName: user.displayName, -// senderId: user.identifier, -// roomName: room.displayName, -// content: event.plainTextBody, -// eventId: eventId, -// roomId: room.identifier, -// clientId: client.identifier, -// senderImage: user.avatar, -// roomImage: await room.getShortcutImage(), -// isDirectMessage: isDirectMessage)); -// } else if (call.method == "didRegister") { -// Log.i("in didRegister()"); -// final deviceToken = call.arguments as String; -// Log.i("Received token $deviceToken"); -// } else if (call.method == "onBackgroundNotification") { -// Log.i("in onBackgroundNotification()"); -// final roomId = call.arguments.roomId as String?; -// final eventId = call.arguments.eventId as String?; -// Log.i("roomID $roomId and eventID $eventId"); -// -// if (eventId == null || roomId == null) { -// return; -// } -// -// var client = clientManager!.clients -// .firstWhere((element) => element.hasRoom(roomId)); -// var room = client.getRoom(roomId); -// var event = await room!.getEvent(eventId); -// -// var user = await room.fetchMember(event!.senderId); -// -// bool isDirectMessage = client -// .getComponent() -// ?.isRoomDirectMessage(room) ?? -// false; -// -// NotificationManager.notify(MessageNotificationContent( -// senderName: user.displayName, -// senderId: user.identifier, -// roomName: room.displayName, -// content: event.plainTextBody, -// eventId: eventId, -// roomId: room.identifier, -// clientId: client.identifier, -// senderImage: user.avatar, -// roomImage: await room.getShortcutImage(), -// isDirectMessage: isDirectMessage)); -// } -// }); -//} +import 'package:convert/convert.dart'; class IOSNotifier implements Notifier { static const String _channelName = "PushNotificationChannel"; static const MethodChannel _channel = MethodChannel(_channelName); -// FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin; + static String? deviceToken; + static String? hexDeviceTokenUpper; + static String? hexDeviceTokenLower; + static String? base64DeviceToken; + static const String pushGateway = + "https://sygnal.spacebinoculars.matrix.town"; + static const bool deviceTokenIsHex = false; @override bool hasPermission = false; @@ -116,79 +35,18 @@ class IOSNotifier implements Notifier { @override Future init() async { - Log.i("in init()"); - preferences.setPushGateway("sygnal.spacebinoculars.matrix.town"); -// flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); + preferences.setPushGateway(pushGateway); await requestPermission().then((value) async { - Log.i("Got permission, registering"); - await registerDevice().then((_) async { - Log.i("Registered"); - }); + await registerDevice().then((_) async {}); }); -// const DarwinInitializationSettings settings = DarwinInitializationSettings(); -// const initSettings = InitializationSettings(iOS: settings); -// await flutterLocalNotificationsPlugin?.initialize(initSettings, -// onDidReceiveBackgroundNotificationResponse: notificationTapBackground, -// onDidReceiveNotificationResponse: onResponse); } @override - Future notify(NotificationContent notification) async { - Log.i("in notify()"); - Log.i("Notification: $notification"); - switch (notification.runtimeType) { - case MessageNotificationContent: - return displayMessageNotification( - notification as MessageNotificationContent); - default: - } - } - - Future displayMessageNotification( - MessageNotificationContent content) async { - var client = clientManager?.getClient(content.clientId); - var room = client?.getRoom(content.roomId); - var source = content.source; - - Log.i( - "in displayMessage() with client $client and room $room from source $source"); - - if (room == null) { - return; - } - -// if (flutterLocalNotificationsPlugin == null) { -// Log.i( -// "Flutter local notifications plugin was null. Something went wrong"); -// return; -// } - - if (shortcutsManager.loading != null) { - await shortcutsManager.loading; - } - - await Future.wait([ - shortcutsManager.createShortcutForRoom(room), - ]); - - var id = room.identifier.hashCode; - - var payload = - OpenRoomURI(roomId: content.roomId, clientId: content.clientId) - .toString(); - - Log.i("Notify with ID $id and payload $payload"); - -// await flutterLocalNotificationsPlugin?.show( -// id, null, content.content, const NotificationDetails(), -// payload: payload); - } + Future notify(NotificationContent notification) async {} static Future requestPushNotificationPermission() async { - Log.i("in requestPushNotificationPermission()"); try { await _channel.invokeMethod("requestNotificationPermissions"); - Log.i("Got Permission"); } on PlatformException catch (e) { Log.e("Failed to get permission with message $e.message"); throw PlatformException(message: e.message, code: e.code); @@ -197,7 +55,6 @@ class IOSNotifier implements Notifier { @override Future requestPermission() async { - Log.i("in requestPermission()"); try { await IOSNotifier.requestPushNotificationPermission(); return true; @@ -208,35 +65,14 @@ class IOSNotifier implements Notifier { } static Future registerDevice() async { - Log.i("in registerDevice()"); try { await _channel.invokeMethod("registerForPushNotifications"); - Log.i("Registered"); } on PlatformException { return; } } -// static void onResponse(NotificationResponse details) { -// Log.i("in onResponse()"); -// Log.i("Got a notification response: $details"); -// -// if (details.payload == null) return; -// -// Log.i("Payload is $details.payload"); -// -// var uri = CustomURI.parse(details.payload!); -// -// if (details.notificationResponseType == -// NotificationResponseType.selectedNotification) { -// if (uri is OpenRoomURI) { -// EventBus.openRoom.add((uri.roomId, uri.clientId)); -// } -// } -// } - static Future retriveDeviceToken() async { - Log.i("in retrieveDeviceToken()"); try { String? token = await _channel.invokeMethod("retrieveDeviceToken"); @@ -249,39 +85,42 @@ class IOSNotifier implements Notifier { @override Future getToken() async { - Log.i("in getToken()"); try { String? token = await IOSNotifier.retriveDeviceToken(); - return token; + if (deviceTokenIsHex) { + return token!.toLowerCase(); + } + return base64.encode(hex.decode(token!)); } on PlatformException { - return null; + Log.i("Failed to get token, device token is $deviceToken"); + if (deviceTokenIsHex) { + return hexDeviceTokenLower; + } + return base64DeviceToken; } } @override Map? extraRegistrationData() { - Log.i("in extraRegistrationData()"); var extraData = { "default_payload": { "aps": { "mutable-content": 1, "content-available": 1, "alert": {"loc-key": "SINGLE_UNREAD", "loc-args": []} - } + }, + "hex_device_token": hexDeviceTokenLower, }, }; return extraData; } - void handlerPushNotificationData({required BuildContext context}) async { - Log.i("in handlerPushNotificationData()"); + static handlerPushNotificationData({required BuildContext context}) async { _channel.setMethodCallHandler((call) async { - Log.i("in setMethodCallHandler() with call $call"); - if (call.method == "onPushNotification()") { + if (call.method == "onPushNotification") { Log.i("in onPushNotification"); - final roomId = call.arguments.roomId as String?; - final eventId = call.arguments.eventId as String?; - Log.i("roomID $roomId and eventID $eventId"); + final eventId = call.arguments['event_id']; + final roomId = call.arguments['room_id']; if (eventId == null || roomId == null) { return; @@ -289,66 +128,23 @@ class IOSNotifier implements Notifier { var client = clientManager!.clients .firstWhere((element) => element.hasRoom(roomId)); - var room = client.getRoom(roomId); - var event = await room!.getEvent(eventId); - var user = await room.fetchMember(event!.senderId); - - bool isDirectMessage = client - .getComponent() - ?.isRoomDirectMessage(room) ?? - false; - - NotificationManager.notify(MessageNotificationContent( - senderName: user.displayName, - senderId: user.identifier, - roomName: room.displayName, - content: event.plainTextBody, - eventId: eventId, - roomId: room.identifier, - clientId: client.identifier, - senderImage: user.avatar, - roomImage: await room.getShortcutImage(), - isDirectMessage: isDirectMessage, - source: "onPushNotification")); + EventBus.openRoom.add((roomId, client.identifier)); } else if (call.method == "didRegister") { - Log.i("in didRegister()"); - final deviceToken = call.arguments as String; - Log.i("Received token $deviceToken"); + Log.i("Registration Finished"); + hexDeviceTokenUpper = call.arguments as String; + base64DeviceToken = base64.encode(hex.decode(hexDeviceTokenUpper!)); + hexDeviceTokenLower = hexDeviceTokenUpper!.toLowerCase(); + if (deviceTokenIsHex) { + deviceToken = hexDeviceTokenLower; + } else { + deviceToken = base64DeviceToken; + } + await PushNotificationComponent.updateAllPushers(); } else if (call.method == "onBackgroundNotification") { Log.i("in onBackgroundNotification()"); - final roomId = call.arguments.roomId as String?; - final eventId = call.arguments.eventId as String?; - Log.i("roomID $roomId and eventID $eventId"); - - if (eventId == null || roomId == null) { - return; - } - - var client = clientManager!.clients - .firstWhere((element) => element.hasRoom(roomId)); - var room = client.getRoom(roomId); - var event = await room!.getEvent(eventId); - - var user = await room.fetchMember(event!.senderId); - - bool isDirectMessage = client - .getComponent() - ?.isRoomDirectMessage(room) ?? - false; - - NotificationManager.notify(MessageNotificationContent( - senderName: user.displayName, - senderId: user.identifier, - roomName: room.displayName, - content: event.plainTextBody, - eventId: eventId, - roomId: room.identifier, - clientId: client.identifier, - senderImage: user.avatar, - roomImage: await room.getShortcutImage(), - isDirectMessage: isDirectMessage, - source: "onBackgroundNotification")); + var callArguments = call.arguments; + Log.i("Message Arguments: $callArguments"); } }); } diff --git a/commet/lib/client/components/push_notification/macos/macos_notifier.dart b/commet/lib/client/components/push_notification/macos/macos_notifier.dart new file mode 100644 index 000000000..c50f77c7b --- /dev/null +++ b/commet/lib/client/components/push_notification/macos/macos_notifier.dart @@ -0,0 +1,161 @@ +import 'dart:convert'; + +import 'package:commet/client/components/push_notification/notification_content.dart'; +import 'package:commet/client/components/push_notification/notifier.dart'; +import 'package:commet/client/components/push_notification/push_notification_component.dart'; +import 'package:commet/client/room.dart'; +import 'package:commet/debug/log.dart'; +import 'package:commet/main.dart'; +import 'package:commet/utils/event_bus.dart'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; +import 'package:convert/convert.dart'; + +class MacosNotifier implements Notifier { + static const String _channelName = "PushNotificationChannel"; + static const MethodChannel _channel = MethodChannel(_channelName); + + static String? deviceToken; + static String? hexDeviceTokenUpper; + static String? hexDeviceTokenLower; + static String? base64DeviceToken; + static const String pushGateway = + "https://sygnal.spacebinoculars.matrix.town"; + static const bool deviceTokenIsHex = false; + + @override + bool hasPermission = false; + + @override + bool get needsToken => true; + + @override + bool get enabled => true; + + @override + Future init() async { + preferences.setPushGateway(pushGateway); + await requestPermission().then((value) async { + await registerDevice().then((_) async {}); + }); + } + + @override + Future notify(NotificationContent notification) async {} + + static Future requestPushNotificationPermission() async { + try { + await _channel.invokeMethod("requestNotificationPermissions"); + } on PlatformException catch (e) { + Log.e("Failed to get permission with message $e.message"); + throw PlatformException(message: e.message, code: e.code); + } + } + + @override + Future requestPermission() async { + try { + await MacosNotifier.requestPushNotificationPermission(); + return true; + } on PlatformException catch (e) { + Log.e("Error Getting Permission: $e.message"); + return false; + } + } + + static Future registerDevice() async { + try { + await _channel.invokeMethod("registerForPushNotifications"); + } on PlatformException { + return; + } + } + + static Future retriveDeviceToken() async { + try { + String? token = + await _channel.invokeMethod("retrieveDeviceToken"); + return token; + } on PlatformException catch (e) { + Log.e("Error on token retrieval: $e.message"); + throw PlatformException(message: e.message, code: e.code); + } + } + + @override + Future getToken() async { + try { + String? token = await MacosNotifier.retriveDeviceToken(); + if (deviceTokenIsHex) { + return token!.toLowerCase(); + } + return base64.encode(hex.decode(token!)); + } on PlatformException { + Log.i("Failed to get token, device token is $deviceToken"); + if (deviceTokenIsHex) { + return hexDeviceTokenLower; + } + return base64DeviceToken; + } + } + + @override + Map? extraRegistrationData() { + var extraData = { + "default_payload": { + "aps": { + "mutable-content": 1, + "content-available": 1, + "alert": {"loc-key": "SINGLE_UNREAD", "loc-args": []} + }, + "hex_device_token": hexDeviceTokenLower, + }, + }; + return extraData; + } + + static handlerPushNotificationData({required BuildContext context}) async { + _channel.setMethodCallHandler((call) async { + var callMethod = call.method; + Log.i("Channel Called with method $callMethod"); + if (call.method == "onPushNotification") { + Log.i("in onPushNotification"); + final eventId = call.arguments['event_id']; + final roomId = call.arguments['room_id']; + + if (eventId == null || roomId == null) { + return; + } + + var client = clientManager!.clients + .firstWhere((element) => element.hasRoom(roomId)); + + EventBus.openRoom.add((roomId, client.identifier)); + } else if (call.method == "didRegister") { + Log.i("Registered"); + hexDeviceTokenUpper = call.arguments as String; + Log.i("Received token $hexDeviceTokenUpper"); + base64DeviceToken = base64.encode(hex.decode(hexDeviceTokenUpper!)); + Log.i("Base64-encoded token is $base64DeviceToken"); + hexDeviceTokenLower = hexDeviceTokenUpper!.toLowerCase(); + Log.i("Lowercase Token is $hexDeviceTokenLower"); + if (deviceTokenIsHex) { + deviceToken = hexDeviceTokenLower; + } else { + deviceToken = base64DeviceToken; + } + await PushNotificationComponent.updateAllPushers(); + } else if (call.method == "onBackgroundNotification") { + Log.i("in onBackgroundNotification()"); + var callArguments = call.arguments; + Log.i("Message Arguments: $callArguments"); + } + }); + } + + @override + Future clearNotifications(Room room) async { + return; + } +} diff --git a/commet/lib/client/components/push_notification/notification_manager.dart b/commet/lib/client/components/push_notification/notification_manager.dart index 5ecff0777..73c16f8a9 100644 --- a/commet/lib/client/components/push_notification/notification_manager.dart +++ b/commet/lib/client/components/push_notification/notification_manager.dart @@ -5,6 +5,7 @@ import 'package:commet/client/components/push_notification/android/android_notif import 'package:commet/client/components/push_notification/ios/ios_notifier.dart'; import 'package:commet/client/components/push_notification/android/unified_push_notifier.dart'; import 'package:commet/client/components/push_notification/linux/linux_notifier.dart'; +import 'package:commet/client/components/push_notification/macos/macos_notifier.dart'; import 'package:commet/client/components/push_notification/modifiers/notification_modifiers.dart'; import 'package:commet/client/components/push_notification/modifiers/suppress_active_room.dart'; import 'package:commet/client/components/push_notification/modifiers/suppress_other_device_active.dart'; @@ -85,6 +86,10 @@ class NotificationManager { return IOSNotifier(); } + if (PlatformUtils.isMacOS) { + return MacosNotifier(); + } + return null; } diff --git a/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart b/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart index 37e4d40cd..1449404a6 100644 --- a/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart +++ b/commet/lib/client/matrix/components/push_notifications/matrix_push_notification_component.dart @@ -20,8 +20,6 @@ class MatrixPushNotificationComponent {Map? extraData}) async { var matrixClient = client.getMatrixClient(); - Log.i("Current push key: $pushKey"); - var pushers = await matrixClient.getPushers(); if (pushers != null && @@ -29,18 +27,7 @@ class MatrixPushNotificationComponent return; } - var profileTag = ""; - var appId = "chat.commet.commetapp"; - if (PlatformUtils.isAndroid) { - appId = "chat.commet.commetapp.android"; - profileTag = "android"; - } else if (PlatformUtils.isIOS) { - appId = "chat.commet.commetapp.quirt"; - profileTag = "ios"; - } else if (PlatformUtils.isMacOS) { - appId = "chat.commet.commetapp.macos"; - profileTag = "macos"; - } + var appId = PlatformUtils.appID; var pusher = Pusher( appId: appId, @@ -53,8 +40,7 @@ class MatrixPushNotificationComponent ), deviceDisplayName: deviceName, kind: "http", - lang: "en", - profileTag: profileTag); + lang: "en"); await matrixClient.postPusher(pusher, append: true); } @@ -67,9 +53,18 @@ class MatrixPushNotificationComponent // Check for stale pushers if (pushers != null) { for (var pusher in pushers) { - if (pusher.deviceDisplayName == deviceName && - (pusher.pushkey != currentPushKey || - pusher.data.url != pushGateway)) { + if (pusher.appId == PlatformUtils.appID && + ((pusher.deviceDisplayName != deviceName && + pusher.pushkey == currentPushKey) || + (pusher.deviceDisplayName == deviceName && + (pusher.pushkey != currentPushKey || + pusher.data.url != pushGateway)))) { + // 2 cases here: + // - existing pusher with the same key (i.e. same device for + // receiving notifications) but different device name, so + // a change of some sort has happened. + // - Same name but different key or different gateway + // But always we only want to remove the commet pushers. await matrixClient.deletePusher(pusher); } } @@ -78,7 +73,6 @@ class MatrixPushNotificationComponent @override Future updatePushers() async { - Log.i("in updatePushers()"); if (NotificationManager.notifierLoading != null) { await NotificationManager.notifierLoading; } @@ -88,6 +82,10 @@ class MatrixPushNotificationComponent var extraData = notifier?.extraRegistrationData(); var name = mxClient.clientName; + if (PlatformUtils.isIOS) { + name = "iPhone"; + } + var uri = Uri.parse(preferences.pushGateway); if (uri.hasScheme == false) { uri = Uri.https(preferences.pushGateway); @@ -106,6 +104,7 @@ class MatrixPushNotificationComponent return; } + Log.i("Registering pusher"); await ensurePushNotificationsRegistered(key, uri, name, extraData: extraData); } diff --git a/commet/lib/client/matrix/matrix_room.dart b/commet/lib/client/matrix/matrix_room.dart index 7ff5aa8f4..d70febf73 100644 --- a/commet/lib/client/matrix/matrix_room.dart +++ b/commet/lib/client/matrix/matrix_room.dart @@ -229,7 +229,7 @@ class MatrixRoom extends Room { } // let push notifications handle it - if (BuildConfig.ANDROID) { + if (BuildConfig.ANDROID || BuildConfig.IOS) { return; } diff --git a/commet/lib/config/platform_utils.dart b/commet/lib/config/platform_utils.dart index 287629c8e..245af6bc9 100644 --- a/commet/lib/config/platform_utils.dart +++ b/commet/lib/config/platform_utils.dart @@ -32,4 +32,15 @@ class PlatformUtils { if (kIsWeb) return false; return Platform.isMacOS; } + + static String get appID { + if (Platform.isIOS) { + return "chat.commet.commetapp.quirt"; + } else if (Platform.isMacOS) { + return "chat.commet.commetapp.macos"; + } else if (Platform.isAndroid) { + return "chat.commet.commetapp.android"; + } + return "chat.commet.commetapp"; + } } diff --git a/commet/lib/main.dart b/commet/lib/main.dart index 0ed6424b4..c93fba86e 100644 --- a/commet/lib/main.dart +++ b/commet/lib/main.dart @@ -1,9 +1,13 @@ import 'dart:async'; +import 'dart:ui'; import 'package:commet/cache/file_cache.dart'; import 'package:commet/client/client_manager.dart'; import 'package:commet/client/components/component.dart'; import 'package:commet/client/components/push_notification/notification_manager.dart'; +import 'package:commet/client/components/push_notification/ios/ios_notifier.dart'; +import 'package:commet/client/components/push_notification/ios/ios_mutable_notifier.dart'; +import 'package:commet/client/components/push_notification/macos/macos_notifier.dart'; import 'package:commet/config/build_config.dart'; import 'package:commet/config/global_config.dart'; import 'package:commet/config/layout_config.dart'; @@ -39,6 +43,7 @@ import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:tiamat/config/style/theme_changer.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:tiamat/config/style/theme_dark.dart'; +import 'package:flutter_background_service/flutter_background_service.dart'; final GlobalKey navigator = GlobalKey(); FileCache? fileCache; @@ -96,6 +101,30 @@ void bubble() async { ))); } +@pragma('vm:entry-point') +void notificationMutationService() async { + DartPluginRegistrant.ensureInitialized(); + Log.prefix = "notification-mutation-service"; + Log.i("Starting notification mutation service"); + final Completer completer = Completer(); + if (!preferences.isInit) { + await preferences.init(); + } + Log.i("Preferences initialized"); + + const String channelName = "PushServiceChannel"; + const MethodChannel channel = MethodChannel(channelName); + + var notificationMutator = IOSNotificationMutator(completer); + await notificationMutator.init(); + Log.i("Initialized mutator class"); + + notificationMutator.channelHandler(channel: channel); + Log.i("listening"); + await completer.future; + Log.i("done"); +} + void main() async { runZonedGuarded(appMain, Log.onError, zoneSpecification: Log.spec); } @@ -254,6 +283,11 @@ class App extends StatelessWidget { @override Widget build(BuildContext context) { + if (PlatformUtils.isIOS) { + IOSNotifier.handlerPushNotificationData(context: context); + } else if (PlatformUtils.isMacOS) { + MacosNotifier.handlerPushNotificationData(context: context); + } return ThemeChanger( shouldFollowSystemTheme: () => preferences.shouldFollowSystemTheme, getDarkTheme: () { diff --git a/commet/macos/Podfile.lock b/commet/macos/Podfile.lock deleted file mode 100644 index f8bd1e0f8..000000000 --- a/commet/macos/Podfile.lock +++ /dev/null @@ -1,168 +0,0 @@ -PODS: - - desktop_drop (0.0.1): - - FlutterMacOS - - device_info_plus (0.0.1): - - FlutterMacOS - - dynamic_color (0.0.2): - - FlutterMacOS - - flutter_local_notifications (0.0.1): - - FlutterMacOS - - flutter_web_auth_2 (3.0.0): - - FlutterMacOS - - FlutterMacOS (1.0.0) - - media_kit_libs_macos_video (1.0.4): - - FlutterMacOS - - media_kit_native_event_loop (1.0.0): - - FlutterMacOS - - media_kit_video (0.0.1): - - FlutterMacOS - - OLMKit (3.2.12): - - OLMKit/olmc (= 3.2.12) - - OLMKit/olmcpp (= 3.2.12) - - OLMKit/olmc (3.2.12) - - OLMKit/olmcpp (3.2.12) - - package_info_plus (0.0.1): - - FlutterMacOS - - pasteboard (0.0.1): - - FlutterMacOS - - path_provider_foundation (0.0.1): - - Flutter - - FlutterMacOS - - screen_brightness_macos (0.1.0): - - FlutterMacOS - - screen_retriever (0.0.1): - - FlutterMacOS - - shared_preferences_foundation (0.0.1): - - Flutter - - FlutterMacOS - - sqflite_darwin (0.0.4): - - Flutter - - FlutterMacOS - - sqlite3 (3.47.2): - - sqlite3/common (= 3.47.2) - - sqlite3/common (3.47.2) - - sqlite3/dbstatvtab (3.47.2): - - sqlite3/common - - sqlite3/fts5 (3.47.2): - - sqlite3/common - - sqlite3/perf-threadsafe (3.47.2): - - sqlite3/common - - sqlite3/rtree (3.47.2): - - sqlite3/common - - sqlite3_flutter_libs (0.0.1): - - FlutterMacOS - - sqlite3 (~> 3.47.0) - - sqlite3/dbstatvtab - - sqlite3/fts5 - - sqlite3/perf-threadsafe - - sqlite3/rtree - - url_launcher_macos (0.0.1): - - FlutterMacOS - - wakelock_plus (0.0.1): - - FlutterMacOS - - window_manager (0.2.0): - - FlutterMacOS - - window_to_front (0.0.1): - - FlutterMacOS - -DEPENDENCIES: - - desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`) - - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`) - - flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`) - - flutter_web_auth_2 (from `Flutter/ephemeral/.symlinks/plugins/flutter_web_auth_2/macos`) - - FlutterMacOS (from `Flutter/ephemeral`) - - media_kit_libs_macos_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos`) - - media_kit_native_event_loop (from `Flutter/ephemeral/.symlinks/plugins/media_kit_native_event_loop/macos`) - - media_kit_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos`) - - OLMKit - - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - - pasteboard (from `Flutter/ephemeral/.symlinks/plugins/pasteboard/macos`) - - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - - screen_brightness_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_brightness_macos/macos`) - - screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`) - - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - - sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`) - - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) - - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - - wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`) - - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) - - window_to_front (from `Flutter/ephemeral/.symlinks/plugins/window_to_front/macos`) - -SPEC REPOS: - trunk: - - OLMKit - - sqlite3 - -EXTERNAL SOURCES: - desktop_drop: - :path: Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos - device_info_plus: - :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos - dynamic_color: - :path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos - flutter_local_notifications: - :path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos - flutter_web_auth_2: - :path: Flutter/ephemeral/.symlinks/plugins/flutter_web_auth_2/macos - FlutterMacOS: - :path: Flutter/ephemeral - media_kit_libs_macos_video: - :path: Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos - media_kit_native_event_loop: - :path: Flutter/ephemeral/.symlinks/plugins/media_kit_native_event_loop/macos - media_kit_video: - :path: Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos - package_info_plus: - :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos - pasteboard: - :path: Flutter/ephemeral/.symlinks/plugins/pasteboard/macos - path_provider_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin - screen_brightness_macos: - :path: Flutter/ephemeral/.symlinks/plugins/screen_brightness_macos/macos - screen_retriever: - :path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos - shared_preferences_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin - sqflite_darwin: - :path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin - sqlite3_flutter_libs: - :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos - url_launcher_macos: - :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos - wakelock_plus: - :path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos - window_manager: - :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos - window_to_front: - :path: Flutter/ephemeral/.symlinks/plugins/window_to_front/macos - -SPEC CHECKSUMS: - desktop_drop: e0b672a7d84c0a6cbc378595e82cdb15f2970a43 - device_info_plus: b0fafc687fb901e2af612763340f1b0d4352f8e5 - dynamic_color: b820c000cc68df65e7ba7ff177cb98404ce56651 - flutter_local_notifications: 13862b132e32eb858dea558a86d45d08daeacfe7 - flutter_web_auth_2: 62b08da29f15a20fa63f144234622a1488d45b65 - FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - media_kit_libs_macos_video: 85a23e549b5f480e72cae3e5634b5514bc692f65 - media_kit_native_event_loop: a80d071c835c612fd80173e79390a50ec409f1b1 - media_kit_video: fa6564e3799a0a28bff39442334817088b7ca758 - OLMKit: da115f16582e47626616874e20f7bb92222c7a51 - package_info_plus: 8147fd5037235202932580f35ebe195f7a55e3cd - pasteboard: 278d8100149f940fb795d6b3a74f0720c890ecb7 - path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 - screen_brightness_macos: 2a3ee243f8051c340381e8e51bcedced8360f421 - screen_retriever: 4f97c103641aab8ce183fa5af3b87029df167936 - shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 - sqflite_darwin: 44bb54cc302bff1fbe5752293aba1820b157cf1c - sqlite3: 7559e33dae4c78538df563795af3a86fc887ee71 - sqlite3_flutter_libs: 7997a56aa96fdba2546e237664deb07f600768ac - url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673 - wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497 - window_manager: 1d01fa7ac65a6e6f83b965471b1a7fdd3f06166c - window_to_front: 9e76fd432e36700a197dac86a0011e49c89abe0a - -PODFILE CHECKSUM: acd442b0fa53a35b8a3f19d753304bc047ef6356 - -COCOAPODS: 1.16.2 diff --git a/commet/macos/Runner.xcodeproj/project.pbxproj b/commet/macos/Runner.xcodeproj/project.pbxproj index e07ba140b..497c066fd 100644 --- a/commet/macos/Runner.xcodeproj/project.pbxproj +++ b/commet/macos/Runner.xcodeproj/project.pbxproj @@ -177,7 +177,6 @@ 3399D490228B24CF009A79C7 /* ShellScript */, 11C171EF4F711973987131AF /* [CP] Embed Pods Frameworks */, 6063DE702D7B737B00E5E1D0 /* ShellScript */, - D7E4758527804155CB687CDB /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -341,23 +340,6 @@ shellPath = /bin/sh; shellScript = "framedir=${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}\nln -s \"./OLMKit\" $framedir/OLMKit.framework/libolm.3.dylib\n"; }; - D7E4758527804155CB687CDB /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -464,7 +446,7 @@ "@executable_path/../Frameworks", "@executable_path/../Frameworks/OLMKit.framework", ); - MACOSX_DEPLOYMENT_TARGET = 10.15; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = commet_macos_profile; @@ -604,7 +586,7 @@ "@executable_path/../Frameworks", "@executable_path/../Frameworks/OLMKit.framework", ); - MACOSX_DEPLOYMENT_TARGET = 10.15; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = commet_macos_profile; @@ -637,7 +619,7 @@ "@executable_path/../Frameworks", "@executable_path/../Frameworks/OLMKit.framework", ); - MACOSX_DEPLOYMENT_TARGET = 10.15; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = commet_macos_profile; diff --git a/commet/macos/Runner/AppDelegate.swift b/commet/macos/Runner/AppDelegate.swift index 8e02df288..d0da9135b 100644 --- a/commet/macos/Runner/AppDelegate.swift +++ b/commet/macos/Runner/AppDelegate.swift @@ -1,9 +1,97 @@ import Cocoa import FlutterMacOS +import OSLog +import UserNotifications @main class AppDelegate: FlutterAppDelegate { - override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { - return true - } + let channelName : String = "PushNotificationChannel" + var deviceToken : String = "" + + + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } + + override func applicationDidFinishLaunching(_ aNotification: Notification) { + let controller : FlutterViewController = mainFlutterWindow?.contentViewController as! FlutterViewController + let pushNotificationChannel : FlutterMethodChannel = FlutterMethodChannel.init(name: self.channelName, binaryMessenger: controller.engine.binaryMessenger) + + UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate + + pushNotificationChannel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) in + switch call.method { + case "requestNotificationPermissions": + self?.requestNotificationPermissions(result: result) + case "registerForPushNotifications": + self?.registerForPushNotifications(application: aNotification.object as! NSApplication, result: result) + case "retrieveDeviceToken": + self?.getDeviceToken(result: result) + default: + result(FlutterMethodNotImplemented) + } + } + + super.applicationDidFinishLaunching(aNotification) + } + + override func application(_ application: NSApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { + let tokenParts = deviceToken.map { data -> String in + return String(format: "%02.2hhx", data) + } + let token = tokenParts.joined() + let controller : FlutterViewController = mainFlutterWindow?.contentViewController as! FlutterViewController + let pushNotificationChannel = FlutterMethodChannel(name: channelName, binaryMessenger: controller.engine.binaryMessenger) + self.deviceToken = token + + let logger = Logger() + logger.notice("Registered for remote notifications with token: \(tokenParts)") + + pushNotificationChannel.invokeMethod("didRegister", arguments: token) + } + + private func requestNotificationPermissions(result: @escaping FlutterResult) { + UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in + if let error = error { + result(FlutterError(code: "PERMISSION_ERROR", message: "Failed to request permissions", details: error.localizedDescription)) + return + } + result(granted) + } + } + + private func registerForPushNotifications(application: NSApplication, result: @escaping FlutterResult) { + application.registerForRemoteNotifications() + result("Device Token registration initiated") + } + + private func getDeviceToken(result: @escaping FlutterResult) { + if(deviceToken.isEmpty) { + result(FlutterError(code: "UNAVAILABLE", message: "Device token not available", details: nil)) + } else { + result(deviceToken) + } + } + + override func application(_ application: NSApplication, didReceiveRemoteNotification userInfo: [String : Any]) { + let controller : FlutterViewController = mainFlutterWindow?.contentViewController as! FlutterViewController + let pushNotificationChannel = FlutterMethodChannel(name: channelName, binaryMessenger: controller.engine.binaryMessenger) + pushNotificationChannel.invokeMethod("onBackgroundNotification", arguments: userInfo) + } + + func usernotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { + if #available(macOS 11.0, *) { + completionHandler([.banner, .list, .badge, .sound]) + } else { + completionHandler([.alert, .badge, .sound]) + } + + } + + func usernotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { + let controller : FlutterViewController = mainFlutterWindow?.contentViewController as! FlutterViewController + let pushNotificationChannel = FlutterMethodChannel(name: channelName, binaryMessenger: controller.engine.binaryMessenger) + pushNotificationChannel.invokeMethod("onPushNotification", arguments: response.notification.request.content.userInfo) + completionHandler() + } } diff --git a/commet/macos/Runner/MainFlutterWindow.swift b/commet/macos/Runner/MainFlutterWindow.swift index 2722837ec..844cdbaca 100644 --- a/commet/macos/Runner/MainFlutterWindow.swift +++ b/commet/macos/Runner/MainFlutterWindow.swift @@ -2,14 +2,16 @@ import Cocoa import FlutterMacOS class MainFlutterWindow: NSWindow { - override func awakeFromNib() { - let flutterViewController = FlutterViewController.init() - let windowFrame = self.frame - self.contentViewController = flutterViewController - self.setFrame(windowFrame, display: true) - RegisterGeneratedPlugins(registry: flutterViewController) + override func awakeFromNib() { + let flutterViewController = FlutterViewController.init() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } - super.awakeFromNib() - } } diff --git a/commet/pubspec.lock b/commet/pubspec.lock index c669d68fc..a3fafbc64 100644 --- a/commet/pubspec.lock +++ b/commet/pubspec.lock @@ -9,14 +9,6 @@ packages: url: "https://pub.dev" source: hosted version: "72.0.0" - _flutterfire_internals: - dependency: transitive - description: - name: _flutterfire_internals - sha256: "37a42d06068e2fe3deddb2da079a8c4d105f241225ba27b7122b37e9865fd8f7" - url: "https://pub.dev" - source: hosted - version: "1.3.35" _macros: dependency: transitive description: dart @@ -239,7 +231,7 @@ packages: source: hosted version: "4.1.0" convert: - dependency: transitive + dependency: "direct main" description: name: convert sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 @@ -440,54 +432,38 @@ packages: url: "https://pub.dev" source: hosted version: "5.5.0" - firebase_core: - dependency: "direct main" - description: - name: firebase_core - sha256: "26de145bb9688a90962faec6f838247377b0b0d32cc0abecd9a4e43525fc856c" - url: "https://pub.dev" - source: hosted - version: "2.32.0" - firebase_core_platform_interface: + file_selector_linux: dependency: transitive description: - name: firebase_core_platform_interface - sha256: d7253d255ff10f85cfd2adaba9ac17bae878fa3ba577462451163bd9f1d1f0bf + name: file_selector_linux + sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" url: "https://pub.dev" source: hosted - version: "5.4.0" - firebase_core_web: + version: "0.9.3+2" + file_selector_macos: dependency: transitive description: - name: firebase_core_web - sha256: faa5a76f6380a9b90b53bc3bdcb85bc7926a382e0709b9b5edac9f7746651493 - url: "https://pub.dev" - source: hosted - version: "2.21.1" - firebase_messaging: - dependency: "direct main" - description: - name: firebase_messaging - sha256: "980259425fa5e2afc03e533f33723335731d21a56fd255611083bceebf4373a8" + name: file_selector_macos + sha256: "271ab9986df0c135d45c3cdb6bd0faa5db6f4976d3e4b437cf7d0f258d941bfc" url: "https://pub.dev" source: hosted - version: "14.7.10" - firebase_messaging_platform_interface: + version: "0.9.4+2" + file_selector_platform_interface: dependency: transitive description: - name: firebase_messaging_platform_interface - sha256: "87c4a922cb6f811cfb7a889bdbb3622702443c52a0271636cbc90d813ceac147" + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b url: "https://pub.dev" source: hosted - version: "4.5.37" - firebase_messaging_web: + version: "2.6.2" + file_selector_windows: dependency: transitive description: - name: firebase_messaging_web - sha256: "90dc7ed885e90a24bb0e56d661d4d2b5f84429697fd2cbb9e5890a0ca370e6f4" + name: file_selector_windows + sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" url: "https://pub.dev" source: hosted - version: "3.5.18" + version: "0.9.3+4" fixnum: dependency: transitive description: @@ -810,6 +786,70 @@ packages: url: "https://pub.dev" source: hosted version: "4.3.0" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "82652a75e3dd667a91187769a6a2cc81bd8c111bbead698d8e938d2b63e5e89a" + url: "https://pub.dev" + source: hosted + version: "0.8.12+21" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100" + url: "https://pub.dev" + source: hosted + version: "0.8.12+2" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0" + url: "https://pub.dev" + source: hosted + version: "2.10.1" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" implicitly_animated_list: dependency: "direct main" description: diff --git a/commet/pubspec.yaml b/commet/pubspec.yaml index 6fea80dcd..3ad516d25 100644 --- a/commet/pubspec.yaml +++ b/commet/pubspec.yaml @@ -91,6 +91,8 @@ dependencies: exif: ^3.3.0 image: ^4.2.0 reflectable: ^4.0.10 + convert: ^3.0.0 + image_picker: ^1.1.2 ## ---- Putting some extra lines in here to help git with the diff ## ---- Probably good to keep this stuff at the bottom of the list From 76b3ab36074dc65b0fb6e7d33ddd321aad7dd7e0 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Wed, 19 Mar 2025 18:59:17 -0400 Subject: [PATCH 45/64] iOS change to make AppInfo.xcconfig into the parameters file --- .github/workflows/build.yml | 9 +++- commet/ios/AppInfo.xcconfig | 26 +++++++++ commet/ios/Podfile | 59 +++++++++++++++++++-- commet/ios/Runner.xcodeproj/project.pbxproj | 30 +++++++---- commet/ios/Runner/Configs/AppInfo.xcconfig | 20 +++++++ commet/ios/export.plist | 29 ---------- 6 files changed, 127 insertions(+), 46 deletions(-) create mode 100644 commet/ios/AppInfo.xcconfig create mode 100644 commet/ios/Runner/Configs/AppInfo.xcconfig delete mode 100644 commet/ios/export.plist diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index efca04fd7..e9214ed22 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -245,11 +245,13 @@ jobs: BUILD_CERTIFICATE_BASE64: ${{ secrets.YORK_IOS_CERT_P12 }} P12_PASSWORD: ${{ secrets.YORK_IOS_CERT_P12_PASSWORD }} BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.COMMET_IOS_PROFILE_PROVISIONPROFILE }} + BUILD_EXTENSION_PROVISION_PROFILE_BASE64: ${{ secrets.COMMET_IOS_EXTENSION_MOBILEPROVISION }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | # create variables CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 - PP_PATH=$RUNNER_TEMP/build_pp.provisionprofile + PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision + PP_EXT_PATH=$RUNNER_TEMP/build_ext_pp.mobileprovision KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db # import certificate and provisioning profile from secrets @@ -257,6 +259,8 @@ jobs: echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH echo "Making Provisioning Profile" echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH + echo "Making Extension Provisioning Profile" + echo -n "$BUILD_EXTENSION_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_EXT_PATH # create temporary keychain security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH @@ -271,12 +275,13 @@ jobs: # apply provisioning profile mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles/ -# ln -s ~/Library/Developer/Xcode/UserData/Provisioning\ Profiles ~/Library/MobileDevice/Provisioning\ Profiles + cp $PP_EXT_PATH ~/Library/MobileDevice/Provisioning\ Profiles/ - name: Code Generation run: | cd $PROJECT_PATH dart run scripts/codegen.dart + gem install plist_lite - name: Build iOS run: | diff --git a/commet/ios/AppInfo.xcconfig b/commet/ios/AppInfo.xcconfig new file mode 100644 index 000000000..bbbb06c3f --- /dev/null +++ b/commet/ios/AppInfo.xcconfig @@ -0,0 +1,26 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME=commet + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER=chat.commet.commetapp.quirt + +// The application's service bundle identifier +PRODUCT_SERVICE_BUNDLE_IDENTIFIER=chat.commet.commetapp.quirt.notificationservice + +// The copyright displayed in application information +PRODUCT_COPYRIGHT=Copyright © 2023 commet.chat. All rights reserved. + +// The product team +PRODUCT_TEAM=J6B4LYQ6NB + +// The provisioning profile for the app +PRODUCT_PROFILE=commet_ios_distribution + +// The provisioning profile for the service extension +PRODUCT_SERVICE_PROFILE=commet_ios_extension_distribution diff --git a/commet/ios/Podfile b/commet/ios/Podfile index 7f5d97b79..010f452b1 100644 --- a/commet/ios/Podfile +++ b/commet/ios/Podfile @@ -4,6 +4,8 @@ # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' +require 'plist_lite' + project 'Runner', { 'Debug' => :debug, 'Profile' => :release, @@ -34,6 +36,10 @@ target 'Runner' do flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) end +target 'servicer' do + use_frameworks! +end + post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) @@ -48,11 +54,54 @@ post_install do |installer| ## dart: PermissionGroup.notification 'PERMISSION_NOTIFICATIONS=1', ] - + end end + + work_dir = Dir.pwd + app_id = "" + app_profile = "" + service_id = "" + service_profile = "" + team_id = "" + env_path = "#{work_dir}/Appinfo.xcconfig" + File.foreach( env_path ) do |line| + items = line.split("=") + if ("#{items[0]}" == "PRODUCT_SERVICE_BUNDLE_IDENTIFIER") then + service_id = items[1].strip! + elsif ("#{items[0]}" == "PRODUCT_BUNDLE_IDENTIFIER") then + app_id = items[1].strip! + elsif ("#{items[0]}" == "PRODUCT_TEAM") then + team_id = items[1].strip! + elsif ("#{items[0]}" == "PRODUCT_PROFILE") then + app_profile = items[1].strip! + elsif ("#{items[0]}" == "PRODUCT_SERVICE_PROFILE") then + service_profile = items[1].strip! + end + end + Dir.glob("Pods/Target Support Files/Pods-servicer/*.xcconfig") do |xc_config_filename| + full_path_name = "#{work_dir}/#{xc_config_filename}" + if (File.exist?(full_path_name)) + new_text = "PRODUCT_BUNDLE_IDENTIFIER = #{service_id}\n" + end + File.write(full_path_name, new_text, File.size(full_path_name), mode: 'a') + end + export_path = File.expand_path(File.join('..', "export.plist"), __FILE__) + puts "Export file path is #{export_path}" + provisioning_profiles={app_id => app_profile, service_id => service_profile} + plist = { + "destination" => "export", + "manageAppVersionAndBuildNumber" => true, + "method" => "app-store-connect", + "provisioningProfiles" => provisioning_profiles, + "signingCertificate" => "Apple Distribution", + "signingStyle" => "manual", + "stripSwiftSymbols" => true, + "teamID" => team_id, + "uploadSymbols" => true + } + puts plist + plist_text = PlistLite.dump(plist) + puts plist_text + File.open(export_path, "w") {|file| file.puts PlistLite.dump(plist) } end - -target 'servicer' do - use_frameworks! -end \ No newline at end of file diff --git a/commet/ios/Runner.xcodeproj/project.pbxproj b/commet/ios/Runner.xcodeproj/project.pbxproj index 5ccbe909e..29cf45f96 100644 --- a/commet/ios/Runner.xcodeproj/project.pbxproj +++ b/commet/ios/Runner.xcodeproj/project.pbxproj @@ -10,13 +10,14 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 33094CB8717F20131D8A6C51 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF23A21167A1629A46938202 /* Pods_Runner.framework */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 551640AA994276376E608141 /* Pods_servicer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBEB167536972A2246629187 /* Pods_servicer.framework */; }; + 600CAF462D8B2821002E12F6 /* AppInfo.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 600CAF452D8B2821002E12F6 /* AppInfo.xcconfig */; }; 600D31212D83386000F738D9 /* Flutter.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 600D31202D83386000F738D9 /* Flutter.xcframework */; }; 6021A3252D828F45001F0660 /* servicer.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 6021A31E2D828F45001F0660 /* servicer.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + F0DC56CC087774C439052C75 /* Pods_servicer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182DFD5CBE07ACC7F7E761BC /* Pods_servicer.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -57,8 +58,10 @@ 0D317BE01B771C2F83770B29 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 182DFD5CBE07ACC7F7E761BC /* Pods_servicer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_servicer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 57C41A2591C5EDD8E3475A60 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 600CAF452D8B2821002E12F6 /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; 600D31202D83386000F738D9 /* Flutter.xcframework */ = {isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:S8QB4VV633:FLUTTER.IO LLC"; lastKnownFileType = wrapper.xcframework; name = Flutter.xcframework; path = "../../../flutter-sdk/bin/cache/artifacts/engine/ios/extension_safe/Flutter.xcframework"; sourceTree = ""; }; 6021A31E2D828F45001F0660 /* servicer.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = servicer.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 603701A52D728005004FE230 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; @@ -77,7 +80,6 @@ D0E55B5F3A40F501ACD4023C /* Pods-servicer.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-servicer.profile.xcconfig"; path = "Target Support Files/Pods-servicer/Pods-servicer.profile.xcconfig"; sourceTree = ""; }; DD5B2EEE2F68770E413E08AF /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; DF23A21167A1629A46938202 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - EBEB167536972A2246629187 /* Pods_servicer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_servicer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ @@ -107,7 +109,7 @@ buildActionMask = 2147483647; files = ( 600D31212D83386000F738D9 /* Flutter.xcframework in Frameworks */, - 551640AA994276376E608141 /* Pods_servicer.framework in Frameworks */, + F0DC56CC087774C439052C75 /* Pods_servicer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -127,7 +129,7 @@ children = ( 600D31202D83386000F738D9 /* Flutter.xcframework */, DF23A21167A1629A46938202 /* Pods_Runner.framework */, - EBEB167536972A2246629187 /* Pods_servicer.framework */, + 182DFD5CBE07ACC7F7E761BC /* Pods_servicer.framework */, ); name = Frameworks; sourceTree = ""; @@ -152,6 +154,7 @@ 97C146EF1CF9000F007C117D /* Products */, AAF1D69EC431FC127C369128 /* Pods */, 5F731FA9B1EF6A5DF5DC817A /* Frameworks */, + 600CAF452D8B2821002E12F6 /* AppInfo.xcconfig */, ); sourceTree = ""; }; @@ -200,7 +203,7 @@ isa = PBXNativeTarget; buildConfigurationList = 6021A32B2D828F45001F0660 /* Build configuration list for PBXNativeTarget "servicer" */; buildPhases = ( - 260232A55682F40F430C8857 /* [CP] Check Pods Manifest.lock */, + 0B5A74AC87AAFB82FC770C06 /* [CP] Check Pods Manifest.lock */, 6021A31A2D828F45001F0660 /* Sources */, 6021A31B2D828F45001F0660 /* Frameworks */, 6021A31C2D828F45001F0660 /* Resources */, @@ -285,6 +288,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 600CAF462D8B2821002E12F6 /* AppInfo.xcconfig in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -319,7 +323,7 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 260232A55682F40F430C8857 /* [CP] Check Pods Manifest.lock */ = { + 0B5A74AC87AAFB82FC770C06 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -462,6 +466,7 @@ /* Begin XCBuildConfiguration section */ 249021D3217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 600CAF452D8B2821002E12F6 /* AppInfo.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -544,6 +549,8 @@ 6021A3272D828F45001F0660 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 6F71ADEFB749D97791F21965 /* Pods-servicer.debug.xcconfig */; + baseConfigurationReferenceAnchor = 6021A31F2D828F45001F0660 /* servicer */; + baseConfigurationReferenceRelativePath = "extension-debug.xcconfig"; buildSettings = { ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -575,7 +582,6 @@ MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt.notificationservice; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = commet_ios_extension_distribution; @@ -591,6 +597,8 @@ 6021A3282D828F45001F0660 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = ABF91C8D62261D1B58A78884 /* Pods-servicer.release.xcconfig */; + baseConfigurationReferenceAnchor = 6021A31F2D828F45001F0660 /* servicer */; + baseConfigurationReferenceRelativePath = extension.xcconfig; buildSettings = { ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -621,7 +629,6 @@ LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt.notificationservice; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = commet_ios_extension_distribution; @@ -635,6 +642,8 @@ 6021A3292D828F45001F0660 /* Profile */ = { isa = XCBuildConfiguration; baseConfigurationReference = D0E55B5F3A40F501ACD4023C /* Pods-servicer.profile.xcconfig */; + baseConfigurationReferenceAnchor = 6021A31F2D828F45001F0660 /* servicer */; + baseConfigurationReferenceRelativePath = "extension-profile.xcconfig"; buildSettings = { ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -665,7 +674,6 @@ LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt.notificationservice; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = commet_ios_extension_distribution; @@ -678,6 +686,7 @@ }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 600CAF452D8B2821002E12F6 /* AppInfo.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -733,6 +742,7 @@ }; 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 600CAF452D8B2821002E12F6 /* AppInfo.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -804,7 +814,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt; + PRODUCT_BUNDLE_IDENTIFIER = "--PRODUCT-BUNDLE-IDENTIFIER-"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = commet_ios_distribution; diff --git a/commet/ios/Runner/Configs/AppInfo.xcconfig b/commet/ios/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 000000000..7cbddb880 --- /dev/null +++ b/commet/ios/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,20 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = commet + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt + +// The application's service bundle identifier +PRODUCT_SERVICE_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt.notificationservice + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2023 commet.chat. All rights reserved. + +// The product team +PRODUCT_TEAM = J6B4LYQ6NB \ No newline at end of file diff --git a/commet/ios/export.plist b/commet/ios/export.plist deleted file mode 100644 index dfb03d584..000000000 --- a/commet/ios/export.plist +++ /dev/null @@ -1,29 +0,0 @@ - - - - - destination - export - manageAppVersionAndBuildNumber - - method - app-store-connect - provisioningProfiles - - chat.commet.commetapp.quirt - commet_ios_distribution - chat.commet.commetapp.quirt.notificationservice - commet_ios_extension_distribution - - signingCertificate - Apple Distribution - signingStyle - manual - stripSwiftSymbols - - teamID - J6B4LYQ6NB - uploadSymbols - - - From 9cc51d48b83b42753808027987a230aa12fe2086 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Wed, 19 Mar 2025 19:10:08 -0400 Subject: [PATCH 46/64] Building pods before running flutter --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e9214ed22..aaf35e6a5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -286,6 +286,9 @@ jobs: - name: Build iOS run: | cd $PROJECT_PATH + cd ios + pod install + cd .. flutter build ipa --export-options-plist=ios/export.plist --dart-define BUILD_MODE=release --dart-define PLATFORM=ios - name: Clean up keychain and provisioning profile From 883ca8a34738327e80cc118f1993308886e079a4 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Wed, 19 Mar 2025 20:43:33 -0400 Subject: [PATCH 47/64] Trying another updated build --- .github/workflows/build.yml | 9 ++++----- commet/ios/Podfile | 4 ++++ commet/ios/Runner/Configs/AppInfo.xcconfig | 20 -------------------- 3 files changed, 8 insertions(+), 25 deletions(-) delete mode 100644 commet/ios/Runner/Configs/AppInfo.xcconfig diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aaf35e6a5..9c61404f4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -280,19 +280,18 @@ jobs: - name: Code Generation run: | cd $PROJECT_PATH - dart run scripts/codegen.dart gem install plist_lite + dart run scripts/codegen.dart + cd ios + pod install - name: Build iOS run: | cd $PROJECT_PATH - cd ios - pod install - cd .. flutter build ipa --export-options-plist=ios/export.plist --dart-define BUILD_MODE=release --dart-define PLATFORM=ios - name: Clean up keychain and provisioning profile if: ${{ always() }} run: | security delete-keychain $RUNNER_TEMP/app-signing.keychain-db - rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.provisionprofile + rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.mobileprovision diff --git a/commet/ios/Podfile b/commet/ios/Podfile index 010f452b1..cc4b2a397 100644 --- a/commet/ios/Podfile +++ b/commet/ios/Podfile @@ -105,3 +105,7 @@ post_install do |installer| puts plist_text File.open(export_path, "w") {|file| file.puts PlistLite.dump(plist) } end + +target 'servicer' do + use_frameworks! +end diff --git a/commet/ios/Runner/Configs/AppInfo.xcconfig b/commet/ios/Runner/Configs/AppInfo.xcconfig deleted file mode 100644 index 7cbddb880..000000000 --- a/commet/ios/Runner/Configs/AppInfo.xcconfig +++ /dev/null @@ -1,20 +0,0 @@ -// Application-level settings for the Runner target. -// -// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the -// future. If not, the values below would default to using the project name when this becomes a -// 'flutter create' template. - -// The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = commet - -// The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt - -// The application's service bundle identifier -PRODUCT_SERVICE_BUNDLE_IDENTIFIER = chat.commet.commetapp.quirt.notificationservice - -// The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2023 commet.chat. All rights reserved. - -// The product team -PRODUCT_TEAM = J6B4LYQ6NB \ No newline at end of file From 7c2aa014712230686f9e8df9c16161bca395b66f Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Wed, 19 Mar 2025 22:27:21 -0400 Subject: [PATCH 48/64] Removed redundant servicer build target --- commet/ios/Podfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/commet/ios/Podfile b/commet/ios/Podfile index cc4b2a397..7e6138aa8 100644 --- a/commet/ios/Podfile +++ b/commet/ios/Podfile @@ -36,10 +36,6 @@ target 'Runner' do flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) end -target 'servicer' do - use_frameworks! -end - post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) From 7744b839360e56b1f992ef06ca55bb168e4f4a59 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Wed, 19 Mar 2025 22:46:12 -0400 Subject: [PATCH 49/64] Changed settings to hopefully avoid strange error --- commet/ios/Runner.xcodeproj/project.pbxproj | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/commet/ios/Runner.xcodeproj/project.pbxproj b/commet/ios/Runner.xcodeproj/project.pbxproj index 29cf45f96..263db14c8 100644 --- a/commet/ios/Runner.xcodeproj/project.pbxproj +++ b/commet/ios/Runner.xcodeproj/project.pbxproj @@ -272,6 +272,7 @@ Base, ); mainGroup = 97C146E51CF9000F007C117D; + minimizedProjectReferenceProxies = 1; preferredProjectObjectVersion = 77; productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; @@ -549,8 +550,6 @@ 6021A3272D828F45001F0660 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 6F71ADEFB749D97791F21965 /* Pods-servicer.debug.xcconfig */; - baseConfigurationReferenceAnchor = 6021A31F2D828F45001F0660 /* servicer */; - baseConfigurationReferenceRelativePath = "extension-debug.xcconfig"; buildSettings = { ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -597,8 +596,6 @@ 6021A3282D828F45001F0660 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = ABF91C8D62261D1B58A78884 /* Pods-servicer.release.xcconfig */; - baseConfigurationReferenceAnchor = 6021A31F2D828F45001F0660 /* servicer */; - baseConfigurationReferenceRelativePath = extension.xcconfig; buildSettings = { ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -642,8 +639,6 @@ 6021A3292D828F45001F0660 /* Profile */ = { isa = XCBuildConfiguration; baseConfigurationReference = D0E55B5F3A40F501ACD4023C /* Pods-servicer.profile.xcconfig */; - baseConfigurationReferenceAnchor = 6021A31F2D828F45001F0660 /* servicer */; - baseConfigurationReferenceRelativePath = "extension-profile.xcconfig"; buildSettings = { ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; From 5eec5329664ea4b8d454dc6c16174b4796cb87a2 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 22 Mar 2025 12:02:33 -0400 Subject: [PATCH 50/64] Trying to do a straight ios build instead of ipa --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9c61404f4..79987f5bf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -288,7 +288,7 @@ jobs: - name: Build iOS run: | cd $PROJECT_PATH - flutter build ipa --export-options-plist=ios/export.plist --dart-define BUILD_MODE=release --dart-define PLATFORM=ios + flutter build ios --dart-define BUILD_MODE=release --dart-define PLATFORM=ios - name: Clean up keychain and provisioning profile if: ${{ always() }} From ce4e9360b6578e1052caeb3cfa5e7a39535729a4 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 22 Mar 2025 12:21:02 -0400 Subject: [PATCH 51/64] Creating App Profile within build action --- .github/workflows/build.yml | 13 +++++++++++++ commet/ios/AppInfo.xcconfig | 26 -------------------------- 2 files changed, 13 insertions(+), 26 deletions(-) delete mode 100644 commet/ios/AppInfo.xcconfig diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 79987f5bf..b2f3eceb9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -277,6 +277,19 @@ jobs: cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles/ cp $PP_EXT_PATH ~/Library/MobileDevice/Provisioning\ Profiles/ + - name: Create Configuration + env: + run: | + cd $PROJECT_PATH/ios + touch AppInfo.xcconfig + echo PRODUCT_NAME=commet >> AppInfo.xcconfig + echo PRODUCT_BUNDLE_IDENTIFIER=${{ vars.BUNDLE_ID }} >> AppInfo.xcconfig + echo PRODUCT_SERVICE_BUNDLE_IDENTIFIER=${{ vars.BUNDLE_SERVICER_ID }} >> AppInfo.xcconfig + echo PRODUCT_COPYRIGHT="Copyright © 2023 commet.chat. All rights reserved." >> AppInfo.xcconfig + echo PRODUCT_TEAM=${{ secrets.DEV_TEAM_ID }} >> AppInfo.xcconfig + echo PRODUCT_PROFILE=${{ secrets.IOS_PROVISIONING_PROFILE_NAME }} >> AppInfo.xcconfig + echo PRODUCT_SERVICE_PROFILE=${{ secrets.IOS_EXTENSION_PROVISIONING_PROFILE_NAME }} >> AppInfo.xcconfig + - name: Code Generation run: | cd $PROJECT_PATH diff --git a/commet/ios/AppInfo.xcconfig b/commet/ios/AppInfo.xcconfig deleted file mode 100644 index bbbb06c3f..000000000 --- a/commet/ios/AppInfo.xcconfig +++ /dev/null @@ -1,26 +0,0 @@ -// Application-level settings for the Runner target. -// -// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the -// future. If not, the values below would default to using the project name when this becomes a -// 'flutter create' template. - -// The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME=commet - -// The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER=chat.commet.commetapp.quirt - -// The application's service bundle identifier -PRODUCT_SERVICE_BUNDLE_IDENTIFIER=chat.commet.commetapp.quirt.notificationservice - -// The copyright displayed in application information -PRODUCT_COPYRIGHT=Copyright © 2023 commet.chat. All rights reserved. - -// The product team -PRODUCT_TEAM=J6B4LYQ6NB - -// The provisioning profile for the app -PRODUCT_PROFILE=commet_ios_distribution - -// The provisioning profile for the service extension -PRODUCT_SERVICE_PROFILE=commet_ios_extension_distribution From 1c96f6a614f40c9928884c7eb063e927947216ac Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 22 Mar 2025 12:38:34 -0400 Subject: [PATCH 52/64] Renamed iOS certificates and profiles --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b2f3eceb9..88f2b190f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -242,9 +242,9 @@ jobs: - name: Setup Provisioning Profile env: - BUILD_CERTIFICATE_BASE64: ${{ secrets.YORK_IOS_CERT_P12 }} - P12_PASSWORD: ${{ secrets.YORK_IOS_CERT_P12_PASSWORD }} - BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.COMMET_IOS_PROFILE_PROVISIONPROFILE }} + BUILD_CERTIFICATE_BASE64: ${{ secrets.IOS_SIGNING_P12 }} + P12_PASSWORD: ${{ secrets.IOS_SIGNING_P12_PASSWORD }} + BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.COMMET_IOS_MOBILEPROVISION }} BUILD_EXTENSION_PROVISION_PROFILE_BASE64: ${{ secrets.COMMET_IOS_EXTENSION_MOBILEPROVISION }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | From b296f93d36d2e2b671f0838b6be7a1c12c468e22 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 22 Mar 2025 12:46:25 -0400 Subject: [PATCH 53/64] Possibly yml syntax error --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 88f2b190f..2238ca1e1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -278,7 +278,6 @@ jobs: cp $PP_EXT_PATH ~/Library/MobileDevice/Provisioning\ Profiles/ - name: Create Configuration - env: run: | cd $PROJECT_PATH/ios touch AppInfo.xcconfig From 8087a0ec462765aaf693ae6a7155ac7989d491f0 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 22 Mar 2025 13:30:34 -0400 Subject: [PATCH 54/64] Changed extension servicer to a group --- commet/ios/Runner.xcodeproj/project.pbxproj | 55 +++++++++++---------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/commet/ios/Runner.xcodeproj/project.pbxproj b/commet/ios/Runner.xcodeproj/project.pbxproj index 263db14c8..9a4ade275 100644 --- a/commet/ios/Runner.xcodeproj/project.pbxproj +++ b/commet/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 77; objects = { /* Begin PBXBuildFile section */ @@ -11,6 +11,10 @@ 33094CB8717F20131D8A6C51 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF23A21167A1629A46938202 /* Pods_Runner.framework */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 600CAF462D8B2821002E12F6 /* AppInfo.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 600CAF452D8B2821002E12F6 /* AppInfo.xcconfig */; }; + 600CB1462D8F2B0A002E12F6 /* extension.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 600CB13F2D8F2B0A002E12F6 /* extension.xcconfig */; }; + 600CB1472D8F2B0A002E12F6 /* extension-debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 600CB1402D8F2B0A002E12F6 /* extension-debug.xcconfig */; }; + 600CB1482D8F2B0A002E12F6 /* extension-profile.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 600CB1412D8F2B0A002E12F6 /* extension-profile.xcconfig */; }; + 600CB14A2D8F2B0A002E12F6 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 600CB1432D8F2B0A002E12F6 /* NotificationService.swift */; }; 600D31212D83386000F738D9 /* Flutter.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 600D31202D83386000F738D9 /* Flutter.xcframework */; }; 6021A3252D828F45001F0660 /* servicer.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 6021A31E2D828F45001F0660 /* servicer.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; @@ -62,6 +66,12 @@ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 57C41A2591C5EDD8E3475A60 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 600CAF452D8B2821002E12F6 /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 600CB13F2D8F2B0A002E12F6 /* extension.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = extension.xcconfig; sourceTree = ""; }; + 600CB1402D8F2B0A002E12F6 /* extension-debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "extension-debug.xcconfig"; sourceTree = ""; }; + 600CB1412D8F2B0A002E12F6 /* extension-profile.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "extension-profile.xcconfig"; sourceTree = ""; }; + 600CB1422D8F2B0A002E12F6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 600CB1432D8F2B0A002E12F6 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; + 600CB1442D8F2B0A002E12F6 /* servicer.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = servicer.entitlements; sourceTree = ""; }; 600D31202D83386000F738D9 /* Flutter.xcframework */ = {isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:S8QB4VV633:FLUTTER.IO LLC"; lastKnownFileType = wrapper.xcframework; name = Flutter.xcframework; path = "../../../flutter-sdk/bin/cache/artifacts/engine/ios/extension_safe/Flutter.xcframework"; sourceTree = ""; }; 6021A31E2D828F45001F0660 /* servicer.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = servicer.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 603701A52D728005004FE230 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; @@ -82,27 +92,6 @@ DF23A21167A1629A46938202 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ -/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ - 6021A32A2D828F45001F0660 /* Exceptions for "servicer" folder in "servicer" target */ = { - isa = PBXFileSystemSynchronizedBuildFileExceptionSet; - membershipExceptions = ( - Info.plist, - ); - target = 6021A31D2D828F45001F0660 /* servicer */; - }; -/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ - -/* Begin PBXFileSystemSynchronizedRootGroup section */ - 6021A31F2D828F45001F0660 /* servicer */ = { - isa = PBXFileSystemSynchronizedRootGroup; - exceptions = ( - 6021A32A2D828F45001F0660 /* Exceptions for "servicer" folder in "servicer" target */, - ); - path = servicer; - sourceTree = ""; - }; -/* End PBXFileSystemSynchronizedRootGroup section */ - /* Begin PBXFrameworksBuildPhase section */ 6021A31B2D828F45001F0660 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; @@ -134,6 +123,19 @@ name = Frameworks; sourceTree = ""; }; + 600CB1452D8F2B0A002E12F6 /* servicer */ = { + isa = PBXGroup; + children = ( + 600CB13F2D8F2B0A002E12F6 /* extension.xcconfig */, + 600CB1402D8F2B0A002E12F6 /* extension-debug.xcconfig */, + 600CB1412D8F2B0A002E12F6 /* extension-profile.xcconfig */, + 600CB1422D8F2B0A002E12F6 /* Info.plist */, + 600CB1432D8F2B0A002E12F6 /* NotificationService.swift */, + 600CB1442D8F2B0A002E12F6 /* servicer.entitlements */, + ); + path = servicer; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -150,7 +152,7 @@ children = ( 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, - 6021A31F2D828F45001F0660 /* servicer */, + 600CB1452D8F2B0A002E12F6 /* servicer */, 97C146EF1CF9000F007C117D /* Products */, AAF1D69EC431FC127C369128 /* Pods */, 5F731FA9B1EF6A5DF5DC817A /* Frameworks */, @@ -212,9 +214,6 @@ ); dependencies = ( ); - fileSystemSynchronizedGroups = ( - 6021A31F2D828F45001F0660 /* servicer */, - ); name = servicer; productName = servicer; productReference = 6021A31E2D828F45001F0660 /* servicer.appex */; @@ -289,6 +288,9 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 600CB1462D8F2B0A002E12F6 /* extension.xcconfig in Resources */, + 600CB1472D8F2B0A002E12F6 /* extension-debug.xcconfig in Resources */, + 600CB1482D8F2B0A002E12F6 /* extension-profile.xcconfig in Resources */, 600CAF462D8B2821002E12F6 /* AppInfo.xcconfig in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -423,6 +425,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 600CB14A2D8F2B0A002E12F6 /* NotificationService.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From e72515be2fbf9be67d055ced4d28f57184e05ca3 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 22 Mar 2025 13:37:47 -0400 Subject: [PATCH 55/64] Changed xcode version hopefully --- commet/ios/Runner.xcodeproj/project.pbxproj | 1 - 1 file changed, 1 deletion(-) diff --git a/commet/ios/Runner.xcodeproj/project.pbxproj b/commet/ios/Runner.xcodeproj/project.pbxproj index 9a4ade275..8dd565e66 100644 --- a/commet/ios/Runner.xcodeproj/project.pbxproj +++ b/commet/ios/Runner.xcodeproj/project.pbxproj @@ -271,7 +271,6 @@ Base, ); mainGroup = 97C146E51CF9000F007C117D; - minimizedProjectReferenceProxies = 1; preferredProjectObjectVersion = 77; productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; From fd848d6a784c3822885467f4af212e3fd5b5ce53 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 22 Mar 2025 14:34:08 -0400 Subject: [PATCH 56/64] Changed xcode version hopefully --- commet/ios/Runner.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commet/ios/Runner.xcodeproj/project.pbxproj b/commet/ios/Runner.xcodeproj/project.pbxproj index 8dd565e66..3b4b59f9d 100644 --- a/commet/ios/Runner.xcodeproj/project.pbxproj +++ b/commet/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 77; + objectVersion = 63; objects = { /* Begin PBXBuildFile section */ @@ -264,6 +264,7 @@ }; }; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 15.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -271,7 +272,6 @@ Base, ); mainGroup = 97C146E51CF9000F007C117D; - preferredProjectObjectVersion = 77; productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; projectRoot = ""; From 497a057be007f69ab88b193a856f7bbceac36da1 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 22 Mar 2025 15:10:35 -0400 Subject: [PATCH 57/64] Removed flutter framework from extension --- commet/ios/Runner.xcodeproj/project.pbxproj | 4 +--- commet/ios/servicer/NotificationService.swift | 21 ------------------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/commet/ios/Runner.xcodeproj/project.pbxproj b/commet/ios/Runner.xcodeproj/project.pbxproj index 3b4b59f9d..6e4dce37d 100644 --- a/commet/ios/Runner.xcodeproj/project.pbxproj +++ b/commet/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 63; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -15,7 +15,6 @@ 600CB1472D8F2B0A002E12F6 /* extension-debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 600CB1402D8F2B0A002E12F6 /* extension-debug.xcconfig */; }; 600CB1482D8F2B0A002E12F6 /* extension-profile.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 600CB1412D8F2B0A002E12F6 /* extension-profile.xcconfig */; }; 600CB14A2D8F2B0A002E12F6 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 600CB1432D8F2B0A002E12F6 /* NotificationService.swift */; }; - 600D31212D83386000F738D9 /* Flutter.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 600D31202D83386000F738D9 /* Flutter.xcframework */; }; 6021A3252D828F45001F0660 /* servicer.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 6021A31E2D828F45001F0660 /* servicer.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -97,7 +96,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 600D31212D83386000F738D9 /* Flutter.xcframework in Frameworks */, F0DC56CC087774C439052C75 /* Pods_servicer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/commet/ios/servicer/NotificationService.swift b/commet/ios/servicer/NotificationService.swift index 526b2ebd3..f1ed58445 100644 --- a/commet/ios/servicer/NotificationService.swift +++ b/commet/ios/servicer/NotificationService.swift @@ -6,9 +6,6 @@ // import UserNotifications -import Flutter - -let channelName : String = "PushServiceChannel" class NotificationService: UNNotificationServiceExtension { @@ -18,8 +15,6 @@ class NotificationService: UNNotificationServiceExtension { override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) - var flutterEngine : FlutterEngine? = FlutterEngine(name: "notification_service_engine", project: nil, allowHeadlessExecution: true) - let decodeChannel = FlutterMethodChannel(name: channelName, binaryMessenger: flutterEngine!.binaryMessenger) if let bestAttemptContent = bestAttemptContent { var displayRoom : String = "" @@ -36,22 +31,6 @@ class NotificationService: UNNotificationServiceExtension { bestAttemptContent.subtitle = "\(unreadCount) new message(s)" bestAttemptContent.body = "Tap on this message to be taken to the room where it happened™️" -// do { -// flutterEngine!.run(withEntrypoint: "notificationMutationService") -// DispatchQueue.main.sync() { -// -// decodeChannel.invokeMethod("notificationReceived", arguments: bestAttemptContent.userInfo, result:{(result) -> () in -// let result = result as! NSDictionary -// -// bestAttemptContent.title = result["title"] as! String -// bestAttemptContent.subtitle = result["subtitle"] as! String -// bestAttemptContent.body = result["body"] as! String -// }) -// -// } -// } catch let error { -// bestAttemptContent.subtitle = "Error: \(error)" -// } contentHandler(bestAttemptContent) } } From 8e67af89df372d966231bd7e6877044056483a02 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 22 Mar 2025 15:19:19 -0400 Subject: [PATCH 58/64] Returned to building ipa and removed unneeded extension profiles from extension --- .github/workflows/build.yml | 2 +- commet/ios/Runner.xcodeproj/project.pbxproj | 14 +------------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2238ca1e1..1caaed928 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -300,7 +300,7 @@ jobs: - name: Build iOS run: | cd $PROJECT_PATH - flutter build ios --dart-define BUILD_MODE=release --dart-define PLATFORM=ios + flutter build ipa --export-options-plist=ios/export.plist --dart-define BUILD_MODE=release --dart-define PLATFORM=ios - name: Clean up keychain and provisioning profile if: ${{ always() }} diff --git a/commet/ios/Runner.xcodeproj/project.pbxproj b/commet/ios/Runner.xcodeproj/project.pbxproj index 6e4dce37d..5cafe174d 100644 --- a/commet/ios/Runner.xcodeproj/project.pbxproj +++ b/commet/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 63; objects = { /* Begin PBXBuildFile section */ @@ -11,9 +11,6 @@ 33094CB8717F20131D8A6C51 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF23A21167A1629A46938202 /* Pods_Runner.framework */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 600CAF462D8B2821002E12F6 /* AppInfo.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 600CAF452D8B2821002E12F6 /* AppInfo.xcconfig */; }; - 600CB1462D8F2B0A002E12F6 /* extension.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 600CB13F2D8F2B0A002E12F6 /* extension.xcconfig */; }; - 600CB1472D8F2B0A002E12F6 /* extension-debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 600CB1402D8F2B0A002E12F6 /* extension-debug.xcconfig */; }; - 600CB1482D8F2B0A002E12F6 /* extension-profile.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 600CB1412D8F2B0A002E12F6 /* extension-profile.xcconfig */; }; 600CB14A2D8F2B0A002E12F6 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 600CB1432D8F2B0A002E12F6 /* NotificationService.swift */; }; 6021A3252D828F45001F0660 /* servicer.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 6021A31E2D828F45001F0660 /* servicer.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; @@ -65,9 +62,6 @@ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 57C41A2591C5EDD8E3475A60 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 600CAF452D8B2821002E12F6 /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 600CB13F2D8F2B0A002E12F6 /* extension.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = extension.xcconfig; sourceTree = ""; }; - 600CB1402D8F2B0A002E12F6 /* extension-debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "extension-debug.xcconfig"; sourceTree = ""; }; - 600CB1412D8F2B0A002E12F6 /* extension-profile.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "extension-profile.xcconfig"; sourceTree = ""; }; 600CB1422D8F2B0A002E12F6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 600CB1432D8F2B0A002E12F6 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; 600CB1442D8F2B0A002E12F6 /* servicer.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = servicer.entitlements; sourceTree = ""; }; @@ -124,9 +118,6 @@ 600CB1452D8F2B0A002E12F6 /* servicer */ = { isa = PBXGroup; children = ( - 600CB13F2D8F2B0A002E12F6 /* extension.xcconfig */, - 600CB1402D8F2B0A002E12F6 /* extension-debug.xcconfig */, - 600CB1412D8F2B0A002E12F6 /* extension-profile.xcconfig */, 600CB1422D8F2B0A002E12F6 /* Info.plist */, 600CB1432D8F2B0A002E12F6 /* NotificationService.swift */, 600CB1442D8F2B0A002E12F6 /* servicer.entitlements */, @@ -285,9 +276,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 600CB1462D8F2B0A002E12F6 /* extension.xcconfig in Resources */, - 600CB1472D8F2B0A002E12F6 /* extension-debug.xcconfig in Resources */, - 600CB1482D8F2B0A002E12F6 /* extension-profile.xcconfig in Resources */, 600CAF462D8B2821002E12F6 /* AppInfo.xcconfig in Resources */, ); runOnlyForDeploymentPostprocessing = 0; From 264aa56aaecc0ae75819d74a5ae3f32f08f2bdcb Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Sat, 22 Mar 2025 17:41:33 -0400 Subject: [PATCH 59/64] Made macOS build configurable --- .github/workflows/build.yml | 22 ++++++++++++++----- commet/macos/Runner.xcodeproj/project.pbxproj | 11 ++++------ commet/macos/Runner/Configs/AppInfo.xcconfig | 14 ------------ 3 files changed, 20 insertions(+), 27 deletions(-) delete mode 100644 commet/macos/Runner/Configs/AppInfo.xcconfig diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1caaed928..16f14f487 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -177,12 +177,12 @@ jobs: with: flutter-version: '3.24.4' channel: 'stable' - + - name: Setup Provisioning Profile env: - BUILD_CERTIFICATE_BASE64: ${{ secrets.YORK_DEV_ID_APP_P12 }} - P12_PASSWORD: ${{ secrets.APPLE_SIGNING_P12_PASSWORD }} - BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.COMMET_MACOS_PROFILE_PROVISIONPROFILE }} + BUILD_CERTIFICATE_BASE64: ${{ secrets.MACOS_SIGNING_P12 }} + P12_PASSWORD: ${{ secrets.MACOS_SIGNING_P12_PASSWORD }} + BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.COMMET_MACOS_PROVISIONPROFILE }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | # create variables @@ -210,6 +210,16 @@ jobs: mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles/ + - name: Create Configuration + run: | + cd $PROJECT_PATH/macos/Runner/Configs + touch AppInfo.xcconfig + echo PRODUCT_NAME=commet >> AppInfo.xcconfig + echo PRODUCT_BUNDLE_IDENTIFIER=${{ vars.MACOS_BUNDLE_ID }} >> AppInfo.xcconfig + echo PRODUCT_COPYRIGHT="Copyright © 2023 commet.chat. All rights reserved." >> AppInfo.xcconfig + echo PRODUCT_TEAM=${{ secrets.DEV_TEAM_ID }} >> AppInfo.xcconfig + echo PRODUCT_PROFILE=${{ secrets.MACOS_PROVISIONING_PROFILE_NAME }} >> AppInfo.xcconfig + - name: Code Generation run: | cd $PROJECT_PATH @@ -282,8 +292,8 @@ jobs: cd $PROJECT_PATH/ios touch AppInfo.xcconfig echo PRODUCT_NAME=commet >> AppInfo.xcconfig - echo PRODUCT_BUNDLE_IDENTIFIER=${{ vars.BUNDLE_ID }} >> AppInfo.xcconfig - echo PRODUCT_SERVICE_BUNDLE_IDENTIFIER=${{ vars.BUNDLE_SERVICER_ID }} >> AppInfo.xcconfig + echo PRODUCT_BUNDLE_IDENTIFIER=${{ vars.IOS_BUNDLE_ID }} >> AppInfo.xcconfig + echo PRODUCT_SERVICE_BUNDLE_IDENTIFIER=${{ vars.IOS_BUNDLE_SERVICER_ID }} >> AppInfo.xcconfig echo PRODUCT_COPYRIGHT="Copyright © 2023 commet.chat. All rights reserved." >> AppInfo.xcconfig echo PRODUCT_TEAM=${{ secrets.DEV_TEAM_ID }} >> AppInfo.xcconfig echo PRODUCT_PROFILE=${{ secrets.IOS_PROVISIONING_PROFILE_NAME }} >> AppInfo.xcconfig diff --git a/commet/macos/Runner.xcodeproj/project.pbxproj b/commet/macos/Runner.xcodeproj/project.pbxproj index 497c066fd..739092232 100644 --- a/commet/macos/Runner.xcodeproj/project.pbxproj +++ b/commet/macos/Runner.xcodeproj/project.pbxproj @@ -46,7 +46,7 @@ 293A9321CED3782F58B1C21B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* commet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = commet.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* .app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = .app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -103,7 +103,7 @@ 33CC10EE2044A3C60003C045 /* Products */ = { isa = PBXGroup; children = ( - 33CC10ED2044A3C60003C045 /* commet.app */, + 33CC10ED2044A3C60003C045 /* .app */, ); name = Products; sourceTree = ""; @@ -185,7 +185,7 @@ ); name = Runner; productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* commet.app */; + productReference = 33CC10ED2044A3C60003C045 /* .app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -378,7 +378,7 @@ /* Begin XCBuildConfiguration section */ 338D0CE9231458BD00FA5F75 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 333000ED22D3DE5D00554162 /* Warnings.xcconfig */; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -447,7 +447,6 @@ "@executable_path/../Frameworks/OLMKit.framework", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = commet_macos_profile; SWIFT_VERSION = 5.0; @@ -587,7 +586,6 @@ "@executable_path/../Frameworks/OLMKit.framework", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = commet_macos_profile; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -620,7 +618,6 @@ "@executable_path/../Frameworks/OLMKit.framework", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp.macos; PROVISIONING_PROFILE_SPECIFIER = ""; "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = commet_macos_profile; SWIFT_VERSION = 5.0; diff --git a/commet/macos/Runner/Configs/AppInfo.xcconfig b/commet/macos/Runner/Configs/AppInfo.xcconfig deleted file mode 100644 index 95b7695cf..000000000 --- a/commet/macos/Runner/Configs/AppInfo.xcconfig +++ /dev/null @@ -1,14 +0,0 @@ -// Application-level settings for the Runner target. -// -// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the -// future. If not, the values below would default to using the project name when this becomes a -// 'flutter create' template. - -// The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = commet - -// The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = chat.commet.commetapp - -// The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2023 commet.chat. All rights reserved. From 08797f829b1947600abb52d73e0f00f95dbb1e6c Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Wed, 2 Apr 2025 13:25:42 -0400 Subject: [PATCH 60/64] Make push gateway settable at build --- .../push_notification/ios/ios_notifier.dart | 11 +++++++++-- commet/lib/config/build_config.dart | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/commet/lib/client/components/push_notification/ios/ios_notifier.dart b/commet/lib/client/components/push_notification/ios/ios_notifier.dart index 240cb9603..2dd39a7ad 100644 --- a/commet/lib/client/components/push_notification/ios/ios_notifier.dart +++ b/commet/lib/client/components/push_notification/ios/ios_notifier.dart @@ -4,6 +4,7 @@ import 'package:commet/client/components/push_notification/notification_content. import 'package:commet/client/components/push_notification/notifier.dart'; import 'package:commet/client/components/push_notification/push_notification_component.dart'; import 'package:commet/client/room.dart'; +import 'package:commet/config/build_config.dart'; import 'package:commet/debug/log.dart'; import 'package:commet/main.dart'; import 'package:commet/utils/event_bus.dart'; @@ -20,8 +21,7 @@ class IOSNotifier implements Notifier { static String? hexDeviceTokenUpper; static String? hexDeviceTokenLower; static String? base64DeviceToken; - static const String pushGateway = - "https://sygnal.spacebinoculars.matrix.town"; + static String pushGateway = ""; static const bool deviceTokenIsHex = false; @override @@ -35,6 +35,13 @@ class IOSNotifier implements Notifier { @override Future init() async { + if (BuildConfig.PUSH_GATEWAY == "binocs") { + pushGateway = "https://sygnal.spacebinoculars.matrix.town"; + } else if (BuildConfig.PUSH_GATEWAY != "unset") { + pushGateway = BuildConfig.PUSH_GATEWAY; + } else { + pushGateway = "push.commet.chat"; + } preferences.setPushGateway(pushGateway); await requestPermission().then((value) async { await registerDevice().then((_) async {}); diff --git a/commet/lib/config/build_config.dart b/commet/lib/config/build_config.dart index ea2fdad30..219cfbd55 100644 --- a/commet/lib/config/build_config.dart +++ b/commet/lib/config/build_config.dart @@ -22,6 +22,9 @@ class BuildConfig { static const bool ENABLE_GOOGLE_SERVICES = bool.fromEnvironment("ENABLE_GOOGLE_SERVICES", defaultValue: false); + static const String PUSH_GATEWAY = + String.fromEnvironment('PUSH_GATEWAY', defaultValue: "unset"); + static const bool DEBUG = _buildMode == _Constants._debug; static const bool RELEASE = _buildMode == _Constants.release; From 5df9fd3524439ca2081d72f75d331197c50fe5a8 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Wed, 2 Apr 2025 13:29:43 -0400 Subject: [PATCH 61/64] Now get push gateway from environment variable --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 16f14f487..bba3ba1cb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -308,9 +308,11 @@ jobs: pod install - name: Build iOS + env: + GATEWAY: ${{ vars.IOS_BUNDLE_ID }} run: | cd $PROJECT_PATH - flutter build ipa --export-options-plist=ios/export.plist --dart-define BUILD_MODE=release --dart-define PLATFORM=ios + flutter build ipa --export-options-plist=ios/export.plist --dart-define BUILD_MODE=release --dart-define PLATFORM=ios --dart-define PUSH_GATEWAY=$GATEWAY - name: Clean up keychain and provisioning profile if: ${{ always() }} From 01da98d01bc94570bae41b0965eb015b5413c93b Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Wed, 2 Apr 2025 13:34:42 -0400 Subject: [PATCH 62/64] Changed the push gateway configuration to actually use its own variable --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bba3ba1cb..c3c7766bd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -309,7 +309,7 @@ jobs: - name: Build iOS env: - GATEWAY: ${{ vars.IOS_BUNDLE_ID }} + GATEWAY: ${{ vars.IOS_PUSH_GATEWAY }} run: | cd $PROJECT_PATH flutter build ipa --export-options-plist=ios/export.plist --dart-define BUILD_MODE=release --dart-define PLATFORM=ios --dart-define PUSH_GATEWAY=$GATEWAY From 39d88e7884e8072511b7f3e1d3409674a2449672 Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Wed, 2 Apr 2025 13:40:12 -0400 Subject: [PATCH 63/64] Fix patch for re-ordering of build config --- commet/scripts/apply_google_services.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commet/scripts/apply_google_services.patch b/commet/scripts/apply_google_services.patch index 0a715c6d6..4fda46520 100644 --- a/commet/scripts/apply_google_services.patch +++ b/commet/scripts/apply_google_services.patch @@ -54,8 +54,8 @@ index 5134142..417a061 100644 - bool.fromEnvironment("ENABLE_GOOGLE_SERVICES", defaultValue: false); + bool.fromEnvironment("ENABLE_GOOGLE_SERVICES", defaultValue: true); - static const bool DEBUG = _buildMode == _Constants._debug; - + static const String PUSH_GATEWAY = + String.fromEnvironment('PUSH_GATEWAY', defaultValue: "unset"); diff --git a/commet/pubspec.yaml b/commet/pubspec.yaml index 8163da0..e3bb1c5 100644 --- a/commet/pubspec.yaml From 84676eec854645cf0d1a3a52d0af3acbdb60571d Mon Sep 17 00:00:00 2001 From: Brian Quirt Date: Wed, 2 Apr 2025 13:57:21 -0400 Subject: [PATCH 64/64] Trying to restore the android build patch working --- commet/lib/config/build_config.dart | 8 ++++---- commet/scripts/apply_google_services.patch | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/commet/lib/config/build_config.dart b/commet/lib/config/build_config.dart index 219cfbd55..d22ed7209 100644 --- a/commet/lib/config/build_config.dart +++ b/commet/lib/config/build_config.dart @@ -22,13 +22,13 @@ class BuildConfig { static const bool ENABLE_GOOGLE_SERVICES = bool.fromEnvironment("ENABLE_GOOGLE_SERVICES", defaultValue: false); - static const String PUSH_GATEWAY = - String.fromEnvironment('PUSH_GATEWAY', defaultValue: "unset"); - static const bool DEBUG = _buildMode == _Constants._debug; static const bool RELEASE = _buildMode == _Constants.release; + static const String PUSH_GATEWAY = + String.fromEnvironment('PUSH_GATEWAY', defaultValue: "unset"); + static const bool DESKTOP = PLATFORM == _Constants._desktop || PLATFORM == _Constants._linux || PLATFORM == _Constants._windows || @@ -94,4 +94,4 @@ class _Constants { static const String _mobile = "mobile"; static const String _web = "web"; -} +} \ No newline at end of file diff --git a/commet/scripts/apply_google_services.patch b/commet/scripts/apply_google_services.patch index 4fda46520..0a715c6d6 100644 --- a/commet/scripts/apply_google_services.patch +++ b/commet/scripts/apply_google_services.patch @@ -54,8 +54,8 @@ index 5134142..417a061 100644 - bool.fromEnvironment("ENABLE_GOOGLE_SERVICES", defaultValue: false); + bool.fromEnvironment("ENABLE_GOOGLE_SERVICES", defaultValue: true); - static const String PUSH_GATEWAY = - String.fromEnvironment('PUSH_GATEWAY', defaultValue: "unset"); + static const bool DEBUG = _buildMode == _Constants._debug; + diff --git a/commet/pubspec.yaml b/commet/pubspec.yaml index 8163da0..e3bb1c5 100644 --- a/commet/pubspec.yaml