From 6a004c7dde5208d0fba5885fd6fc17fc58b57748 Mon Sep 17 00:00:00 2001 From: Delta Date: Sun, 23 Nov 2025 14:02:14 -0800 Subject: [PATCH 01/29] Set AppImage file name --- AppImageBuilder.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/AppImageBuilder.yml b/AppImageBuilder.yml index ba08637..577ca1d 100644 --- a/AppImageBuilder.yml +++ b/AppImageBuilder.yml @@ -26,3 +26,4 @@ AppDir: AppImage: arch: x86_64 update-information: guess + file_name: "recon-linux.AppImage" \ No newline at end of file From b1816e745f6ef8599ec74709ec9da502004cc5ff Mon Sep 17 00:00:00 2001 From: Delta Date: Sun, 23 Nov 2025 14:10:47 -0800 Subject: [PATCH 02/29] Enable cache on setup-flutter --- .github/workflows/create_release_from_builds.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/create_release_from_builds.yml b/.github/workflows/create_release_from_builds.yml index 76c0e92..2393f8f 100644 --- a/.github/workflows/create_release_from_builds.yml +++ b/.github/workflows/create_release_from_builds.yml @@ -19,6 +19,7 @@ jobs: with: channel: stable version: 3.35.7 + cache: true - name: Install dependencies run: flutter pub get @@ -78,6 +79,7 @@ jobs: with: channel: stable version: 3.35.7 + cache: true - name: Install flutter dependencies run: flutter pub get @@ -114,6 +116,7 @@ jobs: with: channel: stable version: 3.35.7 + cache: true - name: Decode Keystore run: | From d2a8161b0a99b9b3c24dfe39731cf0ee057af3e8 Mon Sep 17 00:00:00 2001 From: Nutcake Date: Tue, 2 Dec 2025 20:52:19 +0100 Subject: [PATCH 03/29] Add devtools_options.yaml --- devtools_options.yaml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 devtools_options.yaml diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: From cf3000f29948f3870dae06bc0abd756c0a0c9e98 Mon Sep 17 00:00:00 2001 From: Taylor Date: Sun, 1 Feb 2026 16:38:02 +0000 Subject: [PATCH 04/29] Fix building on iOS by bumping targeted version to iOS 15.6 I think you might be able to get away with 14.0 - but the version of Xcode I have only supports 15.6+ --- .gitignore | 2 + ios/Flutter/AppFrameworkInfo.plist | 2 +- ios/Podfile | 4 +- ios/Podfile.lock | 101 +++++++----------- ios/Runner.xcodeproj/project.pbxproj | 41 +++++-- .../xcshareddata/xcschemes/Runner.xcscheme | 3 +- ios/Runner/AppDelegate.swift | 2 +- 7 files changed, 80 insertions(+), 75 deletions(-) diff --git a/.gitignore b/.gitignore index efd1511..90a7628 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 9625e10..1dc6cf7 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 13.0 diff --git a/ios/Podfile b/ios/Podfile index 9a3af86..6aeaf16 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '13.0' +platform :ios, '15.6' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -41,7 +41,7 @@ post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0' + config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET' end end end diff --git a/ios/Podfile.lock b/ios/Podfile.lock index e2eacb0..50ca428 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -36,13 +36,6 @@ PODS: - DKPhotoGallery/Resource (0.0.17): - SDWebImage - SwiftyGif - - ffmpeg-kit-ios-audio (6.0) - - ffmpeg_kit_flutter_audio (6.0.3): - - ffmpeg_kit_flutter_audio/audio (= 6.0.3) - - Flutter - - ffmpeg_kit_flutter_audio/audio (6.0.3): - - ffmpeg-kit-ios-audio (= 6.0) - - Flutter - file_picker (0.0.1): - DKImagePickerController/PhotoGallery - Flutter @@ -51,63 +44,56 @@ PODS: - Flutter - flutter_secure_storage (6.0.0): - Flutter - - FMDB (2.7.9): - - FMDB/standard (= 2.7.9) - - FMDB/standard (2.7.9) - image_picker_ios (0.0.1): - Flutter - just_audio (0.0.1): - Flutter - - package_info_plus (0.4.5): + - FlutterMacOS + - objective_c (0.0.1): - Flutter - - path_provider_foundation (0.0.1): + - package_info_plus (0.4.5): - Flutter - - FlutterMacOS - - permission_handler_apple (9.1.1): + - permission_handler_apple (9.3.0): - Flutter - - record_darwin (1.0.0): + - record_ios (1.1.0): - Flutter - - FlutterMacOS - SDWebImage (5.19.0): - SDWebImage/Core (= 5.19.0) - SDWebImage/Core (5.19.0) - share_plus (0.0.1): - Flutter - - sqflite (0.0.3): + - sqflite_darwin (0.0.4): - Flutter - - FMDB (>= 2.7.5) + - FlutterMacOS - SwiftyGif (5.4.4) - url_launcher_ios (0.0.1): - Flutter - - workmanager (0.0.1): + - workmanager_apple (0.0.1): - Flutter DEPENDENCIES: - audio_session (from `.symlinks/plugins/audio_session/ios`) - background_downloader (from `.symlinks/plugins/background_downloader/ios`) - camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`) - - ffmpeg_kit_flutter_audio (from `.symlinks/plugins/ffmpeg_kit_flutter_audio/ios`) - file_picker (from `.symlinks/plugins/file_picker/ios`) - Flutter (from `Flutter`) - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - - just_audio (from `.symlinks/plugins/just_audio/ios`) + - just_audio (from `.symlinks/plugins/just_audio/darwin`) + - objective_c (from `.symlinks/plugins/objective_c/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - - record_darwin (from `.symlinks/plugins/record_darwin/ios`) + - record_ios (from `.symlinks/plugins/record_ios/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - - sqflite (from `.symlinks/plugins/sqflite/ios`) + - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - - workmanager (from `.symlinks/plugins/workmanager/ios`) + - workmanager_apple (from `.symlinks/plugins/workmanager_apple/ios`) SPEC REPOS: trunk: - DKImagePickerController - DKPhotoGallery - - ffmpeg-kit-ios-audio - - FMDB - SDWebImage - SwiftyGif @@ -118,8 +104,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/background_downloader/ios" camera_avfoundation: :path: ".symlinks/plugins/camera_avfoundation/ios" - ffmpeg_kit_flutter_audio: - :path: ".symlinks/plugins/ffmpeg_kit_flutter_audio/ios" file_picker: :path: ".symlinks/plugins/file_picker/ios" Flutter: @@ -131,50 +115,47 @@ EXTERNAL SOURCES: image_picker_ios: :path: ".symlinks/plugins/image_picker_ios/ios" just_audio: - :path: ".symlinks/plugins/just_audio/ios" + :path: ".symlinks/plugins/just_audio/darwin" + objective_c: + :path: ".symlinks/plugins/objective_c/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" - path_provider_foundation: - :path: ".symlinks/plugins/path_provider_foundation/darwin" permission_handler_apple: :path: ".symlinks/plugins/permission_handler_apple/ios" - record_darwin: - :path: ".symlinks/plugins/record_darwin/ios" + record_ios: + :path: ".symlinks/plugins/record_ios/ios" share_plus: :path: ".symlinks/plugins/share_plus/ios" - sqflite: - :path: ".symlinks/plugins/sqflite/ios" + sqflite_darwin: + :path: ".symlinks/plugins/sqflite_darwin/darwin" url_launcher_ios: :path: ".symlinks/plugins/url_launcher_ios/ios" - workmanager: - :path: ".symlinks/plugins/workmanager/ios" + workmanager_apple: + :path: ".symlinks/plugins/workmanager_apple/ios" SPEC CHECKSUMS: - audio_session: 4f3e461722055d21515cf3261b64c973c062f345 - background_downloader: 6f55e5548875be2ad4bb91b542558b5be22f339a - camera_avfoundation: 3125e8cd1a4387f6f31c6c63abb8a55892a9eeeb + audio_session: 9bb7f6c970f21241b19f5a3658097ae459681ba0 + background_downloader: 50e91d979067b82081aba359d7d916b3ba5fadad + camera_avfoundation: 5675ca25298b6f81fa0a325188e7df62cc217741 DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 - ffmpeg-kit-ios-audio: 9fa9953fc197280a69e59c603c7fa7690df7190c - ffmpeg_kit_flutter_audio: 9b107d9902e16804c90637cd7f42106a5447a9e6 - file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 - flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743 - flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be - FMDB: aa44149f6fb634b1ac54f64f47064bb0d0c5a032 - image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5 - just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa - package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 - path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 - permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 - record_darwin: 1f6619f2abac4d1ca91d3eeab038c980d76f1517 + file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be + Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 + flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb + flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13 + image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326 + just_audio: 4e391f57b79cad2b0674030a00453ca5ce817eed + objective_c: 89e720c30d716b036faf9c9684022048eee1eee2 + package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 + permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d + record_ios: f75fa1d57f840012775c0e93a38a7f3ceea1a374 SDWebImage: 981fd7e860af070920f249fd092420006014c3eb - share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5 - sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a + share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a + sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f - url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86 - workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6 + url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b + workmanager_apple: 904529ae31e97fc5be632cf628507652294a0778 -PODFILE CHECKSUM: 0a7d5b7d0e53420cb0284f7b2f171f93843b94d2 +PODFILE CHECKSUM: c1c473ba3f42a95a9bcd1b205addac0938789a41 -COCOAPODS: 1.14.3 +COCOAPODS: 1.16.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index e9429ac..d9b6a3b 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -188,6 +188,7 @@ 97C146EC1CF9000F007C117D /* Resources */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 3E67E7F8ECF942FF5AF50545 /* [CP] Embed Pods Frameworks */, + 4013DB8F26C08B20860E0600 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -205,7 +206,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1530; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 331C8080294A63A400263BE5 = { @@ -292,6 +293,23 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; + 4013DB8F26C08B20860E0600 /* [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; + }; 690A3B0A6C07C9F2F97916FF /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -472,18 +490,19 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = P9AV4LPNLL; ENABLE_BITCODE = NO; - FLUTTER_BUILD_NAME = 0.11.2; + FLUTTER_BUILD_NAME = "$(FLUTTER_BUILD_NAME)"; + FLUTTER_BUILD_NUMBER = "$(FLUTTER_BUILD_NUMBER)"; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = ReCon; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 0.11.2; PRODUCT_BUNDLE_IDENTIFIER = ch.isota.recon; + MARKETING_VERSION = 0.12.1; PRODUCT_NAME = ReCon; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -680,18 +699,19 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = P9AV4LPNLL; ENABLE_BITCODE = NO; - FLUTTER_BUILD_NAME = 0.11.2; + FLUTTER_BUILD_NAME = "$(FLUTTER_BUILD_NAME)"; + FLUTTER_BUILD_NUMBER = "$(FLUTTER_BUILD_NUMBER)"; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = ReCon; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 0.11.2; PRODUCT_BUNDLE_IDENTIFIER = ch.isota.recon; + MARKETING_VERSION = 0.12.1; PRODUCT_NAME = ReCon; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -710,18 +730,19 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = P9AV4LPNLL; ENABLE_BITCODE = NO; - FLUTTER_BUILD_NAME = 0.11.2; + FLUTTER_BUILD_NAME = "$(FLUTTER_BUILD_NAME)"; + FLUTTER_BUILD_NUMBER = "$(FLUTTER_BUILD_NUMBER)"; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = ReCon; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 0.11.2; PRODUCT_BUNDLE_IDENTIFIER = ch.isota.recon; + MARKETING_VERSION = 0.12.1; PRODUCT_NAME = ReCon; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index cc26a5c..a8636a0 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 70693e4..b636303 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -1,7 +1,7 @@ import UIKit import Flutter -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, From 0f10293064fc152d117743affc6c53bed6433f02 Mon Sep 17 00:00:00 2001 From: RetrowaveHyena Date: Wed, 22 Apr 2026 19:33:13 -0400 Subject: [PATCH 05/29] fix linux audio messages not working --- lib/main.dart | 4 +-- pubspec.lock | 88 ++++++++++++++++++++++++++++++++++++++++++++++----- pubspec.yaml | 3 +- 3 files changed, 84 insertions(+), 11 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 869313b..7dc122e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -24,12 +24,12 @@ import 'package:recon/models/sem_ver.dart'; import 'package:recon/widgets/homepage.dart'; import 'package:recon/widgets/login_screen.dart'; import 'package:recon/widgets/update_notifier.dart'; - +import 'package:just_audio_media_kit/just_audio_media_kit.dart'; import 'models/authentication_data.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); - + JustAudioMediaKit.ensureInitialized(linux: true); SystemChrome.setSystemUIOverlayStyle( const SystemUiOverlayStyle( systemStatusBarContrastEnforced: true, diff --git a/pubspec.lock b/pubspec.lock index a580888..cf061db 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + archive: + dependency: transitive + description: + name: archive + sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff + url: "https://pub.dev" + source: hosted + version: "4.0.9" args: dependency: transitive description: @@ -109,10 +117,10 @@ packages: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" clock: dependency: transitive description: @@ -424,6 +432,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.2" + image: + dependency: transitive + description: + name: image + sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce + url: "https://pub.dev" + source: hosted + version: "4.8.0" image_picker: dependency: "direct main" description: @@ -512,6 +528,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.10.5" + just_audio_media_kit: + dependency: "direct main" + description: + name: just_audio_media_kit + sha256: f3cf04c3a50339709e87e90b4e841eef4364ab4be2bdbac0c54cc48679f84d23 + url: "https://pub.dev" + source: hosted + version: "2.1.0" just_audio_platform_interface: dependency: transitive description: @@ -572,18 +596,34 @@ packages: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.19" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" + url: "https://pub.dev" + source: hosted + version: "0.13.0" + media_kit: + dependency: transitive + description: + name: media_kit + sha256: ae9e79597500c7ad6083a3c7b7b7544ddabfceacce7ae5c9709b0ec16a5d6643 + url: "https://pub.dev" + source: hosted + version: "1.2.6" + media_kit_libs_linux: + dependency: "direct main" + description: + name: media_kit_libs_linux + sha256: "2b473399a49ec94452c4d4ae51cfc0f6585074398d74216092bf3d54aac37ecf" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "1.2.1" meta: dependency: transitive description: @@ -776,6 +816,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + posix: + dependency: transitive + description: + name: posix + sha256: "185ef7606574f789b40f289c233efa52e96dead518aed988e040a10737febb07" + url: "https://pub.dev" + source: hosted + version: "6.5.0" provider: dependency: "direct main" description: @@ -864,6 +912,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.28.0" + safe_local_storage: + dependency: transitive + description: + name: safe_local_storage + sha256: "287ea1f667c0b93cdc127dccc707158e2d81ee59fba0459c31a0c7da4d09c755" + url: "https://pub.dev" + source: hosted + version: "2.0.3" share_plus: dependency: "direct main" description: @@ -985,10 +1041,10 @@ packages: dependency: transitive description: name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" url: "https://pub.dev" source: hosted - version: "0.7.7" + version: "0.7.10" timezone: dependency: transitive description: @@ -1005,6 +1061,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + universal_platform: + dependency: transitive + description: + name: universal_platform + sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + uri_parser: + dependency: transitive + description: + name: uri_parser + sha256: "051c62e5f693de98ca9f130ee707f8916e2266945565926be3ff20659f7853ce" + url: "https://pub.dev" + source: hosted + version: "3.0.2" url_launcher: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 296e32b..903032e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,7 +64,8 @@ dependencies: flutter_cube: ^0.1.1 share_plus: ^12.0.1 background_downloader: ^9.3.0 - + just_audio_media_kit: ^2.1.0 + media_kit_libs_linux: any dev_dependencies: flutter_test: sdk: flutter From 509d3d2e5b4361fe888fa0970fc5801725111107 Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 09:23:59 -0700 Subject: [PATCH 06/29] Update FilePicker --- lib/widgets/inventory/inventory_browser_app_bar.dart | 2 +- lib/widgets/messages/message_input_bar.dart | 4 ++-- pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/widgets/inventory/inventory_browser_app_bar.dart b/lib/widgets/inventory/inventory_browser_app_bar.dart index 74800e0..861ebba 100644 --- a/lib/widgets/inventory/inventory_browser_app_bar.dart +++ b/lib/widgets/inventory/inventory_browser_app_bar.dart @@ -193,7 +193,7 @@ class _InventoryBrowserAppBarState extends State { ); if (selectedUris == null) return; - final directory = await FilePicker.platform.getDirectoryPath(dialogTitle: "Download to..."); + final directory = await FilePicker.getDirectoryPath(dialogTitle: "Download to..."); if (directory == null) { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( diff --git a/lib/widgets/messages/message_input_bar.dart b/lib/widgets/messages/message_input_bar.dart index 05fddd2..9b6d030 100644 --- a/lib/widgets/messages/message_input_bar.dart +++ b/lib/widgets/messages/message_input_bar.dart @@ -330,7 +330,7 @@ class _MessageInputBarState extends State { onPressed: _isSending ? null : () async { - final result = await FilePicker.platform.pickFiles(type: FileType.image, allowMultiple: true); + final result = await FilePicker.pickFiles(type: FileType.image, allowMultiple: true); if (result != null) { setState(() { _loadedFiles.addAll( @@ -371,7 +371,7 @@ class _MessageInputBarState extends State { onPressed: _isSending ? null : () async { - final result = await FilePicker.platform.pickFiles(type: FileType.any, allowMultiple: true); + final result = await FilePicker.pickFiles(type: FileType.any, allowMultiple: true); if (result != null) { setState(() { _loadedFiles.addAll( diff --git a/pubspec.yaml b/pubspec.yaml index 296e32b..6c5a620 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -54,9 +54,9 @@ dependencies: dynamic_color: ^1.8.1 hive: ^2.2.3 hive_flutter: ^1.1.0 - file_picker: ^10.3.6 record: ^6.1.2 camera: ^0.11.3 + file_picker: ^12.0.0-beta.7 path_provider: ^2.1.5 crypto: ^3.0.7 image_picker: ^1.2.1 From 371fa1d4f5967c325c5eb45d952a138b3d7bd19a Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 09:43:16 -0700 Subject: [PATCH 07/29] FilePicker --- lib/widgets/messages/message_attachment_list.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/widgets/messages/message_attachment_list.dart b/lib/widgets/messages/message_attachment_list.dart index 2ee00b8..bae2f88 100644 --- a/lib/widgets/messages/message_attachment_list.dart +++ b/lib/widgets/messages/message_attachment_list.dart @@ -158,7 +158,7 @@ class _MessageAttachmentListState extends State { ), padding: EdgeInsets.zero, onPressed: () async { - final result = await FilePicker.platform.pickFiles(type: FileType.image, allowMultiple: true); + final result = await FilePicker.pickFiles(type: FileType.image, allowMultiple: true); if (result != null) { setState(() { _loadedFiles.addAll( @@ -229,7 +229,7 @@ class _MessageAttachmentListState extends State { ), padding: EdgeInsets.zero, onPressed: () async { - final result = await FilePicker.platform.pickFiles(type: FileType.any, allowMultiple: true); + final result = await FilePicker.pickFiles(type: FileType.any, allowMultiple: true); if (result != null) { setState(() { _loadedFiles.addAll( From 386a3b1d5d329851315093dc5ea6c51229219544 Mon Sep 17 00:00:00 2001 From: Nutcake Date: Sat, 20 Jun 2026 19:12:50 +0200 Subject: [PATCH 08/29] Fix unhandled exception in message audio player --- .../messages/message_audio_player.dart | 44 +++++++------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/lib/widgets/messages/message_audio_player.dart b/lib/widgets/messages/message_audio_player.dart index f8e67f7..adcdefe 100644 --- a/lib/widgets/messages/message_audio_player.dart +++ b/lib/widgets/messages/message_audio_player.dart @@ -40,10 +40,14 @@ class _MessageAudioPlayerState extends State with WidgetsBin void didChangeDependencies() { super.didChangeDependencies(); final audioCache = Provider.of(context); - _audioFileFuture = audioCache - .cachedNetworkAudioFile(AudioClipContent.fromMap(jsonDecode(widget.message.content))) - .then((value) => _audioPlayer.setFilePath(value.path)) - .whenComplete(() => _audioPlayer.setLoopMode(LoopMode.off)); + _audioFileFuture = Future( + () async { + return audioCache + .cachedNetworkAudioFile(AudioClipContent.fromMap(jsonDecode(widget.message.content))) + .then((value) => _audioPlayer.setFilePath(value.path)) + .whenComplete(() => _audioPlayer.setLoopMode(LoopMode.off)); + }, + ); } @override @@ -51,9 +55,7 @@ class _MessageAudioPlayerState extends State with WidgetsBin super.didUpdateWidget(oldWidget); if (oldWidget.message.id == widget.message.id) return; final audioCache = Provider.of(context); - _audioFileFuture = audioCache - .cachedNetworkAudioFile(AudioClipContent.fromMap(jsonDecode(widget.message.content))) - .then((value) async { + _audioFileFuture = audioCache.cachedNetworkAudioFile(AudioClipContent.fromMap(jsonDecode(widget.message.content))).then((value) async { final path = _audioPlayer.setFilePath(value.path); await _audioPlayer.setLoopMode(LoopMode.off); await _audioPlayer.pause(); @@ -117,8 +119,7 @@ class _MessageAudioPlayerState extends State with WidgetsBin future: _audioFileFuture, builder: (context, fileSnapshot) { if (fileSnapshot.hasError) { - FlutterError.reportError( - FlutterErrorDetails(exception: fileSnapshot.error!, stack: fileSnapshot.stackTrace)); + FlutterError.reportError(FlutterErrorDetails(exception: fileSnapshot.error!, stack: fileSnapshot.stackTrace)); return const IconButton( icon: Icon(Icons.warning), tooltip: "Failed to load audio-message.", @@ -126,10 +127,7 @@ class _MessageAudioPlayerState extends State with WidgetsBin ); } return IconButton( - onPressed: fileSnapshot.hasData && - snapshot.hasData && - playerState != null && - playerState.processingState != ProcessingState.loading + onPressed: fileSnapshot.hasData && snapshot.hasData && playerState != null && playerState.processingState != ProcessingState.loading ? () { switch (playerState.processingState) { case ProcessingState.idle: @@ -152,9 +150,7 @@ class _MessageAudioPlayerState extends State with WidgetsBin : null, color: widget.foregroundColor, icon: Icon( - ((_audioPlayer.duration ?? const Duration(days: 9999)) - _audioPlayer.position) - .inMilliseconds < - 10 + ((_audioPlayer.duration ?? const Duration(days: 9999)) - _audioPlayer.position).inMilliseconds < 10 ? Icons.replay : ((playerState?.playing ?? false) ? Icons.pause : Icons.play_arrow), ), @@ -164,10 +160,7 @@ class _MessageAudioPlayerState extends State with WidgetsBin StreamBuilder( stream: _audioPlayer.positionStream, builder: (context, snapshot) { - _sliderValue = _audioPlayer.duration == null - ? 0 - : (_audioPlayer.position.inMilliseconds / (_audioPlayer.duration!.inMilliseconds)) - .clamp(0, 1); + _sliderValue = _audioPlayer.duration == null ? 0 : (_audioPlayer.position.inMilliseconds / (_audioPlayer.duration!.inMilliseconds)).clamp(0, 1); return StatefulBuilder( // Not sure if this makes sense here... builder: (context, setState) { @@ -181,11 +174,11 @@ class _MessageAudioPlayerState extends State with WidgetsBin min: 0.0, max: 1.0, onChanged: (value) async { - _audioPlayer.pause(); + await _audioPlayer.pause(); setState(() { _sliderValue = value; }); - _audioPlayer.seek( + await _audioPlayer.seek( Duration( milliseconds: (value * (_audioPlayer.duration?.inMilliseconds ?? 0)).round(), ), @@ -196,7 +189,7 @@ class _MessageAudioPlayerState extends State with WidgetsBin }, ); }, - ) + ), ], ), Row( @@ -211,10 +204,7 @@ class _MessageAudioPlayerState extends State with WidgetsBin builder: (context, snapshot) { return Text( "${snapshot.data?.format() ?? "??"}/${_audioPlayer.duration?.format() ?? "??"}", - style: Theme.of(context) - .textTheme - .bodySmall - ?.copyWith(color: widget.foregroundColor?.withAlpha(150)), + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: widget.foregroundColor?.withAlpha(150)), ); }, ), From 69d4f0abde843d3bc00c747574c6aa6495686d23 Mon Sep 17 00:00:00 2001 From: Nutcake Date: Sat, 20 Jun 2026 19:21:02 +0200 Subject: [PATCH 09/29] Fix visual issues with inkwell ripple on message items --- .../messages/message_audio_player.dart | 239 +++++++++--------- lib/widgets/messages/message_bubble.dart | 17 +- .../messages/message_invite_request.dart | 1 + .../messages/message_session_invite.dart | 117 ++++----- lib/widgets/messages/message_text.dart | 49 ++-- 5 files changed, 215 insertions(+), 208 deletions(-) diff --git a/lib/widgets/messages/message_audio_player.dart b/lib/widgets/messages/message_audio_player.dart index adcdefe..9941a16 100644 --- a/lib/widgets/messages/message_audio_player.dart +++ b/lib/widgets/messages/message_audio_player.dart @@ -98,126 +98,129 @@ class _MessageAudioPlayerState extends State with WidgetsBin @override Widget build(BuildContext context) { - return IntrinsicWidth( - child: StreamBuilder( - stream: _audioPlayer.playerStateStream, - builder: (context, snapshot) { - if (snapshot.hasError) { - FlutterError.reportError(FlutterErrorDetails(exception: snapshot.error!, stack: snapshot.stackTrace)); - return _createErrorWidget("Failed to load audio-message."); - } - final playerState = snapshot.data; - return Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - FutureBuilder( - future: _audioFileFuture, - builder: (context, fileSnapshot) { - if (fileSnapshot.hasError) { - FlutterError.reportError(FlutterErrorDetails(exception: fileSnapshot.error!, stack: fileSnapshot.stackTrace)); - return const IconButton( - icon: Icon(Icons.warning), - tooltip: "Failed to load audio-message.", - onPressed: null, - ); - } - return IconButton( - onPressed: fileSnapshot.hasData && snapshot.hasData && playerState != null && playerState.processingState != ProcessingState.loading - ? () { - switch (playerState.processingState) { - case ProcessingState.idle: - case ProcessingState.loading: - case ProcessingState.buffering: - break; - case ProcessingState.ready: - if (playerState.playing) { - _audioPlayer.pause(); - } else { + return Padding( + padding: const EdgeInsets.all(8.0), + child: IntrinsicWidth( + child: StreamBuilder( + stream: _audioPlayer.playerStateStream, + builder: (context, snapshot) { + if (snapshot.hasError) { + FlutterError.reportError(FlutterErrorDetails(exception: snapshot.error!, stack: snapshot.stackTrace)); + return _createErrorWidget("Failed to load audio-message."); + } + final playerState = snapshot.data; + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + FutureBuilder( + future: _audioFileFuture, + builder: (context, fileSnapshot) { + if (fileSnapshot.hasError) { + FlutterError.reportError(FlutterErrorDetails(exception: fileSnapshot.error!, stack: fileSnapshot.stackTrace)); + return const IconButton( + icon: Icon(Icons.warning), + tooltip: "Failed to load audio-message.", + onPressed: null, + ); + } + return IconButton( + onPressed: fileSnapshot.hasData && snapshot.hasData && playerState != null && playerState.processingState != ProcessingState.loading + ? () { + switch (playerState.processingState) { + case ProcessingState.idle: + case ProcessingState.loading: + case ProcessingState.buffering: + break; + case ProcessingState.ready: + if (playerState.playing) { + _audioPlayer.pause(); + } else { + _audioPlayer.play(); + } + break; + case ProcessingState.completed: + _audioPlayer.seek(Duration.zero); _audioPlayer.play(); - } - break; - case ProcessingState.completed: - _audioPlayer.seek(Duration.zero); - _audioPlayer.play(); - break; + break; + } } - } - : null, - color: widget.foregroundColor, - icon: Icon( - ((_audioPlayer.duration ?? const Duration(days: 9999)) - _audioPlayer.position).inMilliseconds < 10 - ? Icons.replay - : ((playerState?.playing ?? false) ? Icons.pause : Icons.play_arrow), - ), - ); - }, - ), - StreamBuilder( - stream: _audioPlayer.positionStream, - builder: (context, snapshot) { - _sliderValue = _audioPlayer.duration == null ? 0 : (_audioPlayer.position.inMilliseconds / (_audioPlayer.duration!.inMilliseconds)).clamp(0, 1); - return StatefulBuilder( - // Not sure if this makes sense here... - builder: (context, setState) { - return SliderTheme( - data: SliderThemeData( - inactiveTrackColor: widget.foregroundColor?.withAlpha(100), - ), - child: Slider( - thumbColor: widget.foregroundColor, - value: _sliderValue, - min: 0.0, - max: 1.0, - onChanged: (value) async { - await _audioPlayer.pause(); - setState(() { - _sliderValue = value; - }); - await _audioPlayer.seek( - Duration( - milliseconds: (value * (_audioPlayer.duration?.inMilliseconds ?? 0)).round(), - ), - ); - }, - ), - ); - }, - ); - }, - ), - ], - ), - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - const SizedBox( - width: 4, - ), - StreamBuilder( - stream: _audioPlayer.positionStream, - builder: (context, snapshot) { - return Text( - "${snapshot.data?.format() ?? "??"}/${_audioPlayer.duration?.format() ?? "??"}", - style: Theme.of(context).textTheme.bodySmall?.copyWith(color: widget.foregroundColor?.withAlpha(150)), - ); - }, - ), - const Spacer(), - MessageStateIndicator( - message: widget.message, - foregroundColor: widget.foregroundColor, - ), - ], - ), - ], - ); - }, + : null, + color: widget.foregroundColor, + icon: Icon( + ((_audioPlayer.duration ?? const Duration(days: 9999)) - _audioPlayer.position).inMilliseconds < 10 + ? Icons.replay + : ((playerState?.playing ?? false) ? Icons.pause : Icons.play_arrow), + ), + ); + }, + ), + StreamBuilder( + stream: _audioPlayer.positionStream, + builder: (context, snapshot) { + _sliderValue = _audioPlayer.duration == null ? 0 : (_audioPlayer.position.inMilliseconds / (_audioPlayer.duration!.inMilliseconds)).clamp(0, 1); + return StatefulBuilder( + // Not sure if this makes sense here... + builder: (context, setState) { + return SliderTheme( + data: SliderThemeData( + inactiveTrackColor: widget.foregroundColor?.withAlpha(100), + ), + child: Slider( + thumbColor: widget.foregroundColor, + value: _sliderValue, + min: 0.0, + max: 1.0, + onChanged: (value) async { + await _audioPlayer.pause(); + setState(() { + _sliderValue = value; + }); + await _audioPlayer.seek( + Duration( + milliseconds: (value * (_audioPlayer.duration?.inMilliseconds ?? 0)).round(), + ), + ); + }, + ), + ); + }, + ); + }, + ), + ], + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + const SizedBox( + width: 4, + ), + StreamBuilder( + stream: _audioPlayer.positionStream, + builder: (context, snapshot) { + return Text( + "${snapshot.data?.format() ?? "??"}/${_audioPlayer.duration?.format() ?? "??"}", + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: widget.foregroundColor?.withAlpha(150)), + ); + }, + ), + const Spacer(), + MessageStateIndicator( + message: widget.message, + foregroundColor: widget.foregroundColor, + ), + ], + ), + ], + ); + }, + ), ), ); } diff --git a/lib/widgets/messages/message_bubble.dart b/lib/widgets/messages/message_bubble.dart index 3cfaa05..77cbe73 100644 --- a/lib/widgets/messages/message_bubble.dart +++ b/lib/widgets/messages/message_bubble.dart @@ -27,16 +27,13 @@ class MessageBubble extends StatelessWidget { borderRadius: BorderRadius.circular(16), color: backgroundColor, textStyle: Theme.of(context).textTheme.bodySmall?.copyWith(color: foregroundColor), - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), - child: switch (message.type) { - MessageType.sessionInvite => MessageSessionInvite(message: message, foregroundColor: foregroundColor,), - MessageType.object => MessageAsset(message: message, foregroundColor: foregroundColor,), - MessageType.sound => MessageAudioPlayer(message: message, foregroundColor: foregroundColor,), - MessageType.inviteRequest => MessageInviteRequest(message: message, foregroundColor: foregroundColor,), - MessageType.unknown || MessageType.text => MessageText(message: message, foregroundColor: foregroundColor,) - }, - ), + child: switch (message.type) { + MessageType.sessionInvite => MessageSessionInvite(message: message, foregroundColor: foregroundColor,), + MessageType.object => MessageAsset(message: message, foregroundColor: foregroundColor,), + MessageType.sound => MessageAudioPlayer(message: message, foregroundColor: foregroundColor,), + MessageType.inviteRequest => MessageInviteRequest(message: message, foregroundColor: foregroundColor,), + MessageType.unknown || MessageType.text => MessageText(message: message, foregroundColor: foregroundColor,) + }, ), ], ), diff --git a/lib/widgets/messages/message_invite_request.dart b/lib/widgets/messages/message_invite_request.dart index 21ccc95..d592b5d 100644 --- a/lib/widgets/messages/message_invite_request.dart +++ b/lib/widgets/messages/message_invite_request.dart @@ -36,6 +36,7 @@ class MessageInviteRequest extends StatelessWidget { return Container( constraints: const BoxConstraints(maxWidth: 300), + padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ diff --git a/lib/widgets/messages/message_session_invite.dart b/lib/widgets/messages/message_session_invite.dart index f7f9d88..5bcaf03 100644 --- a/lib/widgets/messages/message_session_invite.dart +++ b/lib/widgets/messages/message_session_invite.dart @@ -20,68 +20,71 @@ class MessageSessionInvite extends StatelessWidget { final sessionInfo = Session.fromMap(jsonDecode(message.content)); return Container( constraints: const BoxConstraints(maxWidth: 300), - child: TextButton( - onPressed: () { + child: InkWell( + onTap: () { Navigator.of(context).push(MaterialPageRoute(builder: (context) => SessionView(session: sessionInfo))); }, - style: TextButton.styleFrom(padding: EdgeInsets.zero), - child: Container( - padding: const EdgeInsets.only(left: 4), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisSize: MainAxisSize.max, - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 4.0), - child: Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - GenericAvatar( - imageUri: Aux.resdbToHttp(sessionInfo.thumbnailUrl), - placeholderIcon: Icons.no_photography, - foregroundColor: foregroundColor, - ), - const SizedBox(height: 4,), - Text("${sessionInfo.sessionUsers.length.toString().padLeft(2, "0")}/${sessionInfo.maxUsers.toString().padLeft(2, "0")}", style: Theme + borderRadius: BorderRadius.all(Radius.circular(16)), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + padding: const EdgeInsets.only(left: 4), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GenericAvatar( + imageUri: Aux.resdbToHttp(sessionInfo.thumbnailUrl), + placeholderIcon: Icons.no_photography, + foregroundColor: foregroundColor, + ), + const SizedBox(height: 4,), + Text("${sessionInfo.sessionUsers.length.toString().padLeft(2, "0")}/${sessionInfo.maxUsers.toString().padLeft(2, "0")}", style: Theme + .of(context) + .textTheme + .bodyMedium + ?.copyWith(color: foregroundColor),) + ], + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.all(8), + child: FormattedText(sessionInfo.formattedName, maxLines: null, softWrap: true, textAlign: TextAlign.start, style: Theme .of(context) .textTheme - .bodyMedium - ?.copyWith(color: foregroundColor),) - ], - ), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.all(8), - child: FormattedText(sessionInfo.formattedName, maxLines: null, softWrap: true, textAlign: TextAlign.start, style: Theme - .of(context) - .textTheme - .titleMedium?.copyWith(color: foregroundColor),), + .titleMedium?.copyWith(color: foregroundColor),), + ), ), - ), - ], - ), - const SizedBox(height: 8,), - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text("Hosted by ${sessionInfo.hostUsername}", overflow: TextOverflow.ellipsis, style: Theme - .of(context) - .textTheme - .bodySmall - ?.copyWith(color: foregroundColor?.withAlpha(150)),), - MessageStateIndicator(message: message, foregroundColor: foregroundColor,), - ], - ) - ], + ], + ), + const SizedBox(height: 8,), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("Hosted by ${sessionInfo.hostUsername}", overflow: TextOverflow.ellipsis, style: Theme + .of(context) + .textTheme + .bodySmall + ?.copyWith(color: foregroundColor?.withAlpha(150)),), + MessageStateIndicator(message: message, foregroundColor: foregroundColor,), + ], + ) + ], + ), ), ), ), diff --git a/lib/widgets/messages/message_text.dart b/lib/widgets/messages/message_text.dart index 5587505..fd8eea0 100644 --- a/lib/widgets/messages/message_text.dart +++ b/lib/widgets/messages/message_text.dart @@ -39,30 +39,33 @@ class MessageText extends StatelessWidget { ); } }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Container( - constraints: const BoxConstraints(maxWidth: 300), - padding: const EdgeInsets.symmetric(horizontal: 8), - child: FormattedText( - message.formattedContent, - softWrap: true, - maxLines: null, - style: Theme.of(context).textTheme.bodyLarge?.copyWith(color: foregroundColor), - ), - ), - Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - MessageStateIndicator( - message: message, - foregroundColor: foregroundColor, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Container( + constraints: const BoxConstraints(maxWidth: 300), + padding: const EdgeInsets.symmetric(horizontal: 8), + child: FormattedText( + message.formattedContent, + softWrap: true, + maxLines: null, + style: Theme.of(context).textTheme.bodyLarge?.copyWith(color: foregroundColor), ), - ], - ), - ], + ), + Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + MessageStateIndicator( + message: message, + foregroundColor: foregroundColor, + ), + ], + ), + ], + ), ), ); } From 678efd1333b038d8f583792b4ef39cd410f271b9 Mon Sep 17 00:00:00 2001 From: Nutcake Date: Sat, 20 Jun 2026 19:23:51 +0200 Subject: [PATCH 10/29] Fix Session objects not handling null-values in sessionId field Closes #97 --- lib/clients/messaging_client.dart | 10 ++++++--- lib/models/session.dart | 4 ++-- lib/widgets/sessions/session_list.dart | 5 ++++- lib/widgets/sessions/session_view.dart | 31 +++++++++++++++----------- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/lib/clients/messaging_client.dart b/lib/clients/messaging_client.dart index 3ff4a68..28caca5 100644 --- a/lib/clients/messaging_client.dart +++ b/lib/clients/messaging_client.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:collection/collection.dart'; import 'package:flutter/widgets.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:logging/logging.dart'; @@ -57,7 +58,7 @@ class MessagingClient extends ChangeNotifier { Hive.openBox(_messageBoxKey).then((box) async { await box.delete(_lastUpdateKey); final sessions = await SessionApi.getSessions(_apiClient); - _sessionMap.addEntries(sessions.map((e) => MapEntry(e.id, e))); + _sessionMap.addEntries(sessions.whereNot((s) => s.id == null).map((s) => MapEntry(s.id!, s))); await _setupHub(); }); } @@ -369,7 +370,7 @@ class MessagingClient extends ChangeNotifier { } Map createSessionMap(String salt) { - return _sessionMap.map((key, value) => MapEntry(CryptoHelper.idHash(value.id + salt), value)); + return _sessionMap.map((key, value) => MapEntry(CryptoHelper.idHash(value.id! + salt), value)); } void _onMessageSent(List args) { @@ -427,7 +428,10 @@ class MessagingClient extends ChangeNotifier { void _onReceiveSessionUpdate(List args) { final sessionUpdate = args[0]; final session = Session.fromMap(sessionUpdate); - _sessionMap[session.id] = session; + if (session.id == null) { + return; + } + _sessionMap[session.id!] = session; notifyListeners(); } diff --git a/lib/models/session.dart b/lib/models/session.dart index afbff15..8de8ffb 100644 --- a/lib/models/session.dart +++ b/lib/models/session.dart @@ -6,7 +6,7 @@ class Session { final String description; final FormatNode formattedDescription; final List tags; - final String id; //sessionId + final String? id; //sessionId final String hostUserId; final String hostMachineId; final String hostUsername; @@ -69,7 +69,7 @@ class Session { name: "", description: "", tags: const [], - id: "", + id: null, hostUserId: "", hostMachineId: "", hostUsername: "", diff --git a/lib/widgets/sessions/session_list.dart b/lib/widgets/sessions/session_list.dart index 4794992..cb0c193 100644 --- a/lib/widgets/sessions/session_list.dart +++ b/lib/widgets/sessions/session_list.dart @@ -68,6 +68,9 @@ class _SessionListState extends State with AutomaticKeepAliveClient ), itemBuilder: (context, index) { final session = data[index]; + if (session.id == null) { + return SizedBox.shrink(); + } return Card( elevation: 0, shape: RoundedRectangleBorder( @@ -90,7 +93,7 @@ class _SessionListState extends State with AutomaticKeepAliveClient topRight: Radius.circular(16), ), child: Hero( - tag: session.id, + tag: session.id!, child: CachedNetworkImage( imageUrl: Aux.resdbToHttp(session.thumbnailUrl), fit: BoxFit.cover, diff --git a/lib/widgets/sessions/session_view.dart b/lib/widgets/sessions/session_view.dart index c2ef129..05b76d8 100644 --- a/lib/widgets/sessions/session_view.dart +++ b/lib/widgets/sessions/session_view.dart @@ -51,8 +51,11 @@ class _SessionViewState extends State { ), body: RefreshIndicator( onRefresh: () async { + if (session.id == null) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Session is no longer valid"))); + } setState(() { - _sessionFuture = SessionApi.getSession(ClientHolder.of(context).apiClient, sessionId: session.id); + _sessionFuture = SessionApi.getSession(ClientHolder.of(context).apiClient, sessionId: session.id!); }); await _sessionFuture; }, @@ -99,7 +102,7 @@ class _SessionViewState extends State { padding: EdgeInsets.all(16), child: Icon(Icons.panorama_photosphere), ), - ) + ), ], ), ), @@ -185,17 +188,19 @@ class _SessionViewState extends State { ), ] + session.sessionUsers - .map((user) => ListTile( - dense: true, - title: Text( - user.username, - textAlign: TextAlign.start, - ), - subtitle: Text( - user.isPresent ? "Active" : "Inactive", - textAlign: TextAlign.start, - ), - )) + .map( + (user) => ListTile( + dense: true, + title: Text( + user.username, + textAlign: TextAlign.start, + ), + subtitle: Text( + user.isPresent ? "Active" : "Inactive", + textAlign: TextAlign.start, + ), + ), + ) .toList(), ), ), From 89e78f63b2da8a9c31dfb3588a33d7dab2356620 Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 10:32:42 -0700 Subject: [PATCH 11/29] Update dart and flutter --- pubspec.lock | 4 ++-- pubspec.yaml | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index a580888..ed9cf60 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1174,5 +1174,5 @@ packages: source: hosted version: "6.6.1" sdks: - dart: ">=3.9.0 <4.0.0" - flutter: ">=3.35.0" + dart: ">=3.12.0 <4.0.0" + flutter: ">=3.44.0" diff --git a/pubspec.yaml b/pubspec.yaml index 6c5a620..92b1046 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -37,7 +37,7 @@ dependencies: uuid: any intl: any http_parser: ^4.1.2 - flutter_secure_storage: ^9.2.4 + flutter_secure_storage: ^10.3.1 logging: ^1.3.0 cached_network_image: ^3.4.1 web_socket_channel: ^3.0.3 @@ -46,24 +46,24 @@ dependencies: flutter_phoenix: ^1.1.1 url_launcher: ^6.3.2 workmanager: ^0.9.0+3 - flutter_local_notifications: ^19.5.0 - package_info_plus: ^9.0.0 provider: ^6.1.5+1 + flutter_local_notifications: ^22.0.1 + package_info_plus: ^10.1.0 photo_view: ^0.15.0 color: ^3.0.0 dynamic_color: ^1.8.1 hive: ^2.2.3 hive_flutter: ^1.1.0 - record: ^6.1.2 - camera: ^0.11.3 file_picker: ^12.0.0-beta.7 + record: ^7.1.0 + camera: ^0.12.0+1 path_provider: ^2.1.5 crypto: ^3.0.7 image_picker: ^1.2.1 - permission_handler: ^12.0.1 + permission_handler: ^12.0.3 flutter_cube: ^0.1.1 - share_plus: ^12.0.1 - background_downloader: ^9.3.0 + share_plus: ^13.1.0 + background_downloader: ^9.5.5 dev_dependencies: flutter_test: From 5ab858a8caa708e8efd9f0e227dbaff12028fd54 Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 10:53:00 -0700 Subject: [PATCH 12/29] update generated files --- .metadata | 25 +- linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 4 +- pubspec.lock | 352 +++++++++++------- windows/CMakeLists.txt | 9 +- windows/flutter/generated_plugins.cmake | 1 + windows/runner/Runner.rc | 4 +- windows/runner/runner.exe.manifest | 6 - windows/runner/utils.cpp | 9 +- windows/runner/win32_window.cpp | 2 +- windows/runner/win32_window.h | 2 +- 11 files changed, 234 insertions(+), 181 deletions(-) diff --git a/.metadata b/.metadata index acfc1cf..2393204 100644 --- a/.metadata +++ b/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: "6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e" + revision: "17025dd88227cd9532c33fa78f5250d548d87e9a" channel: "stable" project_type: app @@ -13,26 +13,11 @@ project_type: app migration: platforms: - platform: root - create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - - platform: android - create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - - platform: ios - create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - - platform: linux - create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - - platform: macos - create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - - platform: web - create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e + create_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a + base_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a - platform: windows - create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e + create_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a + base_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a # User provided section diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 8745386..ff47d84 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index cbb9bc8..15e34aa 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -10,7 +10,7 @@ import dynamic_color import file_picker import file_selector_macos import flutter_local_notifications -import flutter_secure_storage_macos +import flutter_secure_storage_darwin import just_audio import package_info_plus import record_macos @@ -24,7 +24,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) - FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) + FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin")) JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) RecordMacOsPlugin.register(with: registry.registrar(forPlugin: "RecordMacOsPlugin")) diff --git a/pubspec.lock b/pubspec.lock index ed9cf60..96a9c21 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,26 +13,26 @@ packages: dependency: transitive description: name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 url: "https://pub.dev" source: hosted - version: "2.13.0" + version: "2.13.1" audio_session: dependency: transitive description: name: audio_session - sha256: "8f96a7fecbb718cb093070f868b4cdcb8a9b1053dce342ff8ab2fde10eb9afb7" + sha256: "7217b229db57cc4dc577a8abb56b7429a5a212b978517a5be578704bfe5e568b" url: "https://pub.dev" source: hosted - version: "0.2.2" + version: "0.2.3" background_downloader: dependency: "direct main" description: name: background_downloader - sha256: a913b37cc47a656a225e9562b69576000d516f705482f392e2663500e6ff6032 + sha256: aceacec2b2a72ec3a8862ab5895fcbbc71ab33765f3619d57963f3110dd268e3 url: "https://pub.dev" source: hosted - version: "9.3.0" + version: "9.5.5" boolean_selector: dependency: transitive description: @@ -69,50 +69,50 @@ packages: dependency: "direct main" description: name: camera - sha256: eefad89f262a873f38d21e5eec853461737ea074d7c9ede39f3ceb135d201cab + sha256: "034c38cb8014d29698dcae6d20276688a1bf74e6487dfeb274d70ea05d5f7777" url: "https://pub.dev" source: hosted - version: "0.11.3" + version: "0.12.0+1" camera_android_camerax: dependency: transitive description: name: camera_android_camerax - sha256: d96bf774152dd2a0aee64c59ba6b914b5efb04ec5a25b56e17b7e898869cc07c + sha256: e20c1e92ce6797d9ae9b1db1e09a4c1039a04827d0b24985f5da3840b96948ac url: "https://pub.dev" source: hosted - version: "0.6.24+2" + version: "0.7.2+1" camera_avfoundation: dependency: transitive description: name: camera_avfoundation - sha256: "035b90c1e33c2efad7548f402572078f6e514d4f82be0a315cd6c6af7e855aa8" + sha256: "90e4cc3fde331581a3b2d35d83be41dbb7393af0ab857eb27b732174289cb96d" url: "https://pub.dev" source: hosted - version: "0.9.22+6" + version: "0.10.1" camera_platform_interface: dependency: transitive description: name: camera_platform_interface - sha256: "98cfc9357e04bad617671b4c1f78a597f25f08003089dd94050709ae54effc63" + sha256: "7ac852d77699acee79f0d438b793feee26721841e50973576419ff5c6d95e9b7" url: "https://pub.dev" source: hosted - version: "2.12.0" + version: "2.13.0" camera_web: dependency: transitive description: name: camera_web - sha256: "77e53acb64d9de8917424eeb32b5c7c73572d1e00954bbf54a1e609d79a751a2" + sha256: "1245a480a113437f8d46d19c0fb90cea9db921436d9cf2ba5fb11854a1312693" url: "https://pub.dev" source: hosted - version: "0.3.5+1" + version: "0.3.5+4" characters: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" clock: dependency: transitive description: @@ -121,6 +121,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8 + url: "https://pub.dev" + source: hosted + version: "1.2.1" collection: dependency: "direct main" description: @@ -141,10 +149,10 @@ packages: dependency: transitive description: name: cross_file - sha256: "701dcfc06da0882883a2657c445103380e53e647060ad8d9dfb710c100996608" + sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937" url: "https://pub.dev" source: hosted - version: "0.3.5+1" + version: "0.3.5+2" crypto: dependency: "direct main" description: @@ -165,10 +173,10 @@ packages: dependency: transitive description: name: dbus - sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" + sha256: "0ce9b0a839e6dee59a37a623d2fc26a35bbbe6404213e419b0d6411023d62645" url: "https://pub.dev" source: hosted - version: "0.7.11" + version: "0.7.14" dynamic_color: dependency: "direct main" description: @@ -189,10 +197,18 @@ packages: dependency: transitive description: name: ffi - sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" + ffi_leak_tracker: + dependency: transitive + description: + name: ffi_leak_tracker + sha256: "4093d4ef9ca06ffe2786e73bfb25e22aa92112b9bb4ec941f11e3e6b61489a97" + url: "https://pub.dev" + source: hosted + version: "0.1.2" file: dependency: transitive description: @@ -205,26 +221,26 @@ packages: dependency: "direct main" description: name: file_picker - sha256: f8f4ea435f791ab1f817b4e338ed958cb3d04ba43d6736ffc39958d950754967 + sha256: fdc6a37f715d19f35b131decf1ce39242eeed5ddae18c0818c3eccb731ab76be url: "https://pub.dev" source: hosted - version: "10.3.6" + version: "12.0.0-beta.7" file_selector_linux: dependency: transitive description: name: file_selector_linux - sha256: "80a877f5ec570c4fb3b40720a70b6f31e8bb1315a464b4d3e92fe82754d4b21a" + sha256: "2567f398e06ac72dcf2e98a0c95df2a9edd03c2c2e0cacd4780f20cdf56263a0" url: "https://pub.dev" source: hosted - version: "0.9.3+3" + version: "0.9.4" file_selector_macos: dependency: transitive description: name: file_selector_macos - sha256: "44f24d102e368370951b98ffe86c7325b38349e634578312976607d28cc6d747" + sha256: "5e0bbe9c312416f1787a68259ea1505b52f258c587f12920422671807c4d618a" url: "https://pub.dev" source: hosted - version: "0.9.4+6" + version: "0.9.5" file_selector_platform_interface: dependency: transitive description: @@ -282,34 +298,42 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: "19ffb0a8bb7407875555e5e98d7343a633bb73707bae6c6a5f37c90014077875" + sha256: a0d7141f14cabcee42967470a858dfc99dd6cfb70d3cab404bacfcafa9e84e70 url: "https://pub.dev" source: hosted - version: "19.5.0" + version: "22.0.1" flutter_local_notifications_linux: dependency: transitive description: name: flutter_local_notifications_linux - sha256: e3c277b2daab8e36ac5a6820536668d07e83851aeeb79c446e525a70710770a5 + sha256: "9ca97e63776f29ab1b955725c09999fc2c150523269db150c39274f2a43c5a8b" url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "8.0.1" flutter_local_notifications_platform_interface: dependency: transitive description: name: flutter_local_notifications_platform_interface - sha256: "277d25d960c15674ce78ca97f57d0bae2ee401c844b6ac80fcd972a9c99d09fe" + sha256: ff0013eae795e8dc8fad4a8992a209e64d3ba2fbd8bf5e43c36bf448f95bd814 + url: "https://pub.dev" + source: hosted + version: "12.0.0" + flutter_local_notifications_web: + dependency: transitive + description: + name: flutter_local_notifications_web + sha256: "516afaf97a2d1e67a036c6617321b00d205d72f7a67b6eccf936cd565f985878" url: "https://pub.dev" source: hosted - version: "9.1.0" + version: "1.0.0" flutter_local_notifications_windows: dependency: transitive description: name: flutter_local_notifications_windows - sha256: "8d658f0d367c48bd420e7cf2d26655e2d1130147bca1eea917e576ca76668aaf" + sha256: "6f43bdd03b171b7a90f22647506fea33e2bb12294b7c7c7a3d690e960a382945" url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "3.1.1" flutter_phoenix: dependency: "direct main" description: @@ -322,58 +346,58 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "306f0596590e077338312f38837f595c04f28d6cdeeac392d3d74df2f0003687" + sha256: "3854fe5e3bff0b113c658f260b90c95dea17c92db0f2addeac2e343dd9969785" url: "https://pub.dev" source: hosted - version: "2.0.32" + version: "2.0.35" flutter_secure_storage: dependency: "direct main" description: name: flutter_secure_storage - sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea" + sha256: "7686b1d6a29985dcbb808c59518226e603e3bfa7c0ddfd1a0d00e4cda77c868e" url: "https://pub.dev" source: hosted - version: "9.2.4" - flutter_secure_storage_linux: + version: "10.3.1" + flutter_secure_storage_darwin: dependency: transitive description: - name: flutter_secure_storage_linux - sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688 + name: flutter_secure_storage_darwin + sha256: "82329fa5cdf343773b1b6897dea959105a29f092454259edff92f9f6637e8149" url: "https://pub.dev" source: hosted - version: "1.2.3" - flutter_secure_storage_macos: + version: "0.3.2" + flutter_secure_storage_linux: dependency: transitive description: - name: flutter_secure_storage_macos - sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247" + name: flutter_secure_storage_linux + sha256: a5f35ddab43cf5c8215d2feb4ce1957851f28c5c37e6f04335066a0602087bf5 url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "3.0.1" flutter_secure_storage_platform_interface: dependency: transitive description: name: flutter_secure_storage_platform_interface - sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8 + sha256: "8ceea1223bee3c6ac1a22dabd8feefc550e4729b3675de4b5900f55afcb435d6" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "2.0.1" flutter_secure_storage_web: dependency: transitive description: name: flutter_secure_storage_web - sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9 + sha256: "073a62b3aeb866ab4ce795f960413948e51e5a42a9b0c8333b6daf5bb3208a1c" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "2.1.1" flutter_secure_storage_windows: dependency: transitive description: name: flutter_secure_storage_windows - sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709 + sha256: "471951813a97006d899db4948acc654a4f28c440083ea08178935ce20b173ec1" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "4.2.2" flutter_test: dependency: "direct dev" description: flutter @@ -400,6 +424,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + hooks: + dependency: transitive + description: + name: hooks + sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba" + url: "https://pub.dev" + source: hosted + version: "2.0.2" html: dependency: "direct main" description: @@ -428,18 +460,18 @@ packages: dependency: "direct main" description: name: image_picker - sha256: "784210112be18ea55f69d7076e2c656a4e24949fa9e76429fe53af0c0f4fa320" + sha256: "91c025426c2881c551100bce834e201c835a170151545f58d17da5180ca7d9ac" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" image_picker_android: dependency: transitive description: name: image_picker_android - sha256: "788167bcb578b13613b17c3b4a4efae911715f353e36bddc48a0b02a54a8de40" + sha256: "6f3a1995eafb000333174fae92202622033b0ee7fd917a6cd3730295264df84a" url: "https://pub.dev" source: hosted - version: "0.8.13+9" + version: "0.8.13+19" image_picker_for_web: dependency: transitive description: @@ -452,10 +484,10 @@ packages: dependency: transitive description: name: image_picker_ios - sha256: "997d100ce1dda5b1ba4085194c5e36c9f8a1fb7987f6a36ab677a344cd2dc986" + sha256: b9c4a438a9ff4f60808c9cf0039b93a42bb6c2211ef6ebb647394b2b3fa84588 url: "https://pub.dev" source: hosted - version: "0.8.13+2" + version: "0.8.13+6" image_picker_linux: dependency: transitive description: @@ -496,14 +528,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.20.2" - js: + jni: + dependency: transitive + description: + name: jni + sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f + url: "https://pub.dev" + source: hosted + version: "1.0.0" + jni_flutter: dependency: transitive description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + name: jni_flutter + sha256: "8b59e590786050b1cd866677dddaf76b1ade5e7bc751abe04b86e84d379d3ba6" url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "1.0.1" just_audio: dependency: "direct main" description: @@ -556,10 +596,10 @@ packages: dependency: transitive description: name: lints - sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "6.1.0" logging: dependency: "direct main" description: @@ -572,26 +612,26 @@ packages: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.19" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.18.0" mime: dependency: transitive description: @@ -612,10 +652,10 @@ packages: dependency: transitive description: name: objective_c - sha256: "1f81ed9e41909d44162d7ec8663b2c647c202317cc0b56d3d56f6a13146a0b64" + sha256: "6cb691c686fa2838c6deb34980d426145c2a5d537491cb83d463c33cdbc726ed" url: "https://pub.dev" source: hosted - version: "9.1.0" + version: "9.4.1" octo_image: dependency: transitive description: @@ -624,22 +664,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" package_info_plus: dependency: "direct main" description: name: package_info_plus - sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d + sha256: "4bf625947f6c7713ee242296a682e23e44823c09cf9d79e4f1238923c92db852" url: "https://pub.dev" source: hosted - version: "9.0.0" + version: "10.1.0" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" + sha256: db762cb2f4f25ee60fb6359773861b0f199e00b90d237bd85a76a1e806b46ef4 url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "4.1.0" path: dependency: "direct main" description: @@ -652,26 +700,26 @@ packages: dependency: "direct main" description: name: path_provider - sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + sha256: a7f4874f987173da295a61c181b8ee71dab59b332a486b391babf26a1b884825 url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.1.6" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "95c68a74d3cab950fd0ed8073d9fab15c1c06eb1f3eec68676e87aabc9ecee5a" + sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd" url: "https://pub.dev" source: hosted - version: "2.2.21" + version: "2.3.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "6192e477f34018ef1ea790c56fffc7302e3bc3efede9e798b934c252c8c105ba" + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.6.0" path_provider_linux: dependency: transitive description: @@ -684,10 +732,10 @@ packages: dependency: transitive description: name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + sha256: "484838772624c3a4b94f1e44a3e19897fee738f2d5c4ce448443b0417f7c9dda" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" path_provider_windows: dependency: transitive description: @@ -700,10 +748,10 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1 + sha256: fe54465bcc62a4564c6e4db337bbaded6c0c0fa6e10487414436d163114784f6 url: "https://pub.dev" source: hosted - version: "12.0.1" + version: "12.0.3" permission_handler_android: dependency: transitive description: @@ -716,10 +764,10 @@ packages: dependency: transitive description: name: permission_handler_apple - sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023 + sha256: "79dfa1df734798aa3cfdad166d3a3698c206d8813de13516ea1071b5d7e2f420" url: "https://pub.dev" source: hosted - version: "9.4.7" + version: "9.4.10" permission_handler_html: dependency: transitive description: @@ -748,10 +796,10 @@ packages: dependency: transitive description: name: petitparser - sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" url: "https://pub.dev" source: hosted - version: "7.0.1" + version: "7.0.2" photo_view: dependency: "direct main" description: @@ -796,66 +844,74 @@ packages: dependency: "direct main" description: name: record - sha256: "6bad72fb3ea6708d724cf8b6c97c4e236cf9f43a52259b654efeb6fd9b737f1f" + sha256: d28ec249ee4af6753a68a7a5077d6a2eee71e38dc61a241724aded53263274ba url: "https://pub.dev" source: hosted - version: "6.1.2" + version: "7.1.0" record_android: dependency: transitive description: name: record_android - sha256: "9aaf3f151e61399b09bd7c31eb5f78253d2962b3f57af019ac5a2d1a3afdcf71" + sha256: "6722be803d8b2a0945112d69cfbda1391970c5cff2cb53c16afd307a6b7ef0c4" url: "https://pub.dev" source: hosted - version: "1.4.5" + version: "2.1.1" record_ios: dependency: transitive description: name: record_ios - sha256: "69fcd37c6185834e90254573599a9165db18a2cbfa266b6d1e46ffffeb06a28c" + sha256: de6f660b02c2a909c963d5c3c929fdf100b03cea9e5552599d0e5ae1b7d1a89d url: "https://pub.dev" source: hosted - version: "1.1.5" + version: "2.1.0" record_linux: dependency: transitive description: name: record_linux - sha256: "235b1f1fb84e810f8149cc0c2c731d7d697f8d1c333b32cb820c449bf7bb72d8" + sha256: "305526af0560866a0cc4219aa3726ef8541f819e14bd5f65b73ffdb7dc5911be" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "2.1.0" record_macos: dependency: transitive description: name: record_macos - sha256: "842ea4b7e95f4dd237aacffc686d1b0ff4277e3e5357865f8d28cd28bc18ed95" + sha256: "9c29a7efdace0662db2aa7284873d49f8b48992432db3b5f0d38cbe2da8eecde" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "2.1.0" record_platform_interface: dependency: transitive description: name: record_platform_interface - sha256: b0065fdf1ec28f5a634d676724d388a77e43ce7646fb049949f58c69f3fcb4ed + sha256: d94b37cadb8fe203e64b0e9893271c0b71b34f2550ee7fb0c6105d650e00c1f5 url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "2.1.0" + record_use: + dependency: transitive + description: + name: record_use + sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed" + url: "https://pub.dev" + source: hosted + version: "0.6.0" record_web: dependency: transitive description: name: record_web - sha256: "3feeffbc0913af3021da9810bb8702a068db6bc9da52dde1d19b6ee7cb9edb51" + sha256: "9d2d43162afff63d8608eb09c2982b9c6898dd8fbf5b05395ca7d08305b6db40" url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "2.1.0" record_windows: dependency: transitive description: name: record_windows - sha256: "223258060a1d25c62bae18282c16783f28581ec19401d17e56b5205b9f039d78" + sha256: a1db1c0b996acd4161a93cc412b81a2a09a4fd7161c6353f32bf97683003b52f url: "https://pub.dev" source: hosted - version: "1.0.7" + version: "2.1.0" rxdart: dependency: transitive description: @@ -868,18 +924,18 @@ packages: dependency: "direct main" description: name: share_plus - sha256: "14c8860d4de93d3a7e53af51bff479598c4e999605290756bbbe45cf65b37840" + sha256: a857d8b1479250aff6b57a51b2c02d31ca05848d441817c43f1640c885c286c0 url: "https://pub.dev" source: hosted - version: "12.0.1" + version: "13.1.0" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface - sha256: "88023e53a13429bd65d8e85e11a9b484f49d4c190abbd96c7932b74d6927cc9a" + sha256: "7f7ae28cf400d13f811e297ff37742dba83b79e0a6f5dce14eec0248274e6ce9" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "7.1.0" sky_engine: dependency: transitive description: flutter @@ -889,50 +945,50 @@ packages: dependency: transitive description: name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" url: "https://pub.dev" source: hosted - version: "1.10.1" + version: "1.10.2" sqflite: dependency: transitive description: name: sqflite - sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03 + sha256: "58a799e6ac17dd32fbab93813d39ed835a75ccc0f8f85b8955fe318c6712b082" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.3" sqflite_android: dependency: transitive description: name: sqflite_android - sha256: ecd684501ebc2ae9a83536e8b15731642b9570dc8623e0073d227d0ee2bfea88 + sha256: d0548f9d7422a2dae99ec6f8b0a3074463b132d216fa5ba0d230eeefc901983b url: "https://pub.dev" source: hosted - version: "2.4.2+2" + version: "2.4.3" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6" + sha256: "5bf6a55c166e73bf651ba7ec3ed486e577620e3dc8f3a9c6a258a8031b624590" url: "https://pub.dev" source: hosted - version: "2.5.6" + version: "2.5.11" sqflite_darwin: dependency: transitive description: name: sqflite_darwin - sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3" + sha256: "164a5d73ab87a134566057219988bafde837029a64264e61f1f04376ef3cfcd2" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.3" sqflite_platform_interface: dependency: transitive description: name: sqflite_platform_interface - sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" + sha256: f84939f84350d92d04416f8bc4dc52d3896aec7716cc9e80cf0146342139dc50 url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" stack_trace: dependency: transitive description: @@ -969,10 +1025,10 @@ packages: dependency: transitive description: name: synchronized - sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 + sha256: "93b153dcb6a26dcddee6ca087dd634b53e38c10b5aa163e8e49501a776456153" url: "https://pub.dev" source: hosted - version: "3.4.0" + version: "3.4.1" term_glyph: dependency: transitive description: @@ -985,18 +1041,18 @@ packages: dependency: transitive description: name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" url: "https://pub.dev" source: hosted - version: "0.7.7" + version: "0.7.11" timezone: dependency: transitive description: name: timezone - sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1 + sha256: "784a5e34d2eb62e1326f24d6f600aaaee452eb8ca8ef2f384a59244e292d158b" url: "https://pub.dev" source: hosted - version: "0.10.1" + version: "0.11.0" typed_data: dependency: transitive description: @@ -1017,18 +1073,18 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "5387615091fb9bcacfe03e140437be22c3a3cd7ac53052ec9a16d2a6a370a994" + sha256: b413d49b73867ac08dd2f9890efd3cc11f2a0e577618d50843440a1fb3776c32 url: "https://pub.dev" source: hosted - version: "6.3.27" + version: "6.3.32" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: cfde38aa257dae62ffe79c87fab20165dfdf6988c1d31b58ebf59b9106062aad + sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0" url: "https://pub.dev" source: hosted - version: "6.3.6" + version: "6.4.1" url_launcher_linux: dependency: transitive description: @@ -1057,10 +1113,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" + sha256: "85c81589622fbc87c1c683aaea164d3604a7777495a79d91e39ffcdec39ddb34" url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.3" url_launcher_windows: dependency: transitive description: @@ -1073,10 +1129,10 @@ packages: dependency: "direct main" description: name: uuid - sha256: a11b666489b1954e01d992f3d601b1804a33937b5a8fe677bd26b8a9f96f96e8 + sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" url: "https://pub.dev" source: hosted - version: "4.5.2" + version: "4.5.3" vector_math: dependency: transitive description: @@ -1089,10 +1145,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360" url: "https://pub.dev" source: hosted - version: "15.0.2" + version: "15.2.0" web: dependency: transitive description: @@ -1121,10 +1177,10 @@ packages: dependency: transitive description: name: win32 - sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e + sha256: ba6f4bba816c8d7e3c1580e170f3786d216951cc6b94babc3b814c08d2cb2738 url: "https://pub.dev" source: hosted - version: "5.15.0" + version: "6.3.0" workmanager: dependency: "direct main" description: @@ -1173,6 +1229,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.6.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" sdks: dart: ">=3.12.0 <4.0.0" flutter: ">=3.44.0" diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 435e22d..13f5ab4 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -8,7 +8,7 @@ set(BINARY_NAME "recon") # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. -cmake_policy(SET CMP0063 NEW) +cmake_policy(VERSION 3.14...3.25) # Define build configuration option. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) @@ -52,6 +52,7 @@ add_subdirectory(${FLUTTER_MANAGED_DIR}) # Application build; see runner/CMakeLists.txt. add_subdirectory("runner") + # Generated plugin build rules, which manage building the plugins and adding # them to the application. include(flutter/generated_plugins.cmake) @@ -86,6 +87,12 @@ if(PLUGIN_BUNDLED_LIBRARIES) COMPONENT Runtime) endif() +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets") diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 946f230..63acf74 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -14,6 +14,7 @@ list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST flutter_local_notifications_windows + jni ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc index 18a0991..14898c8 100644 --- a/windows/runner/Runner.rc +++ b/windows/runner/Runner.rc @@ -89,11 +89,11 @@ BEGIN BEGIN BLOCK "040904e4" BEGIN - VALUE "CompanyName", "de.voidspace" "\0" + VALUE "CompanyName", "me.voidspace" "\0" VALUE "FileDescription", "recon" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "recon" "\0" - VALUE "LegalCopyright", "Copyright (C) 2023 de.voidspace. All rights reserved." "\0" + VALUE "LegalCopyright", "Copyright (C) 2026 me.voidspace. All rights reserved." "\0" VALUE "OriginalFilename", "recon.exe" "\0" VALUE "ProductName", "recon" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" diff --git a/windows/runner/runner.exe.manifest b/windows/runner/runner.exe.manifest index a42ea76..153653e 100644 --- a/windows/runner/runner.exe.manifest +++ b/windows/runner/runner.exe.manifest @@ -9,12 +9,6 @@ - - - - - - diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp index f5bf9fa..3a0b465 100644 --- a/windows/runner/utils.cpp +++ b/windows/runner/utils.cpp @@ -45,9 +45,11 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { if (utf16_string == nullptr) { return std::string(); } - int target_length = ::WideCharToMultiByte( + unsigned int target_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr); + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); std::string utf8_string; if (target_length == 0 || target_length > utf8_string.max_size()) { return utf8_string; @@ -55,8 +57,7 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { utf8_string.resize(target_length); int converted_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, utf8_string.data(), - target_length, nullptr, nullptr); + input_length, utf8_string.data(), target_length, nullptr, nullptr); if (converted_length == 0) { return std::string(); } diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index 041a385..60608d0 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -60,7 +60,7 @@ class WindowClassRegistrar { public: ~WindowClassRegistrar() = default; - // Returns the singleton registar instance. + // Returns the singleton registrar instance. static WindowClassRegistrar* GetInstance() { if (!instance_) { instance_ = new WindowClassRegistrar(); diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h index c86632d..e901dde 100644 --- a/windows/runner/win32_window.h +++ b/windows/runner/win32_window.h @@ -77,7 +77,7 @@ class Win32Window { // OS callback called by message pump. Handles the WM_NCCREATE message which // is passed when the non-client area is being created and enables automatic // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by + // responds to changes in DPI. All other messages are handled by // MessageHandler. static LRESULT CALLBACK WndProc(HWND const window, UINT const message, From 68f8b310150a216ed2031fd28d1d6182648f7be0 Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 10:58:36 -0700 Subject: [PATCH 13/29] media_kit_libs_linux generated --- linux/flutter/generated_plugin_registrant.cc | 4 ++++ linux/flutter/generated_plugins.cmake | 1 + 2 files changed, 5 insertions(+) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 6423c57..f75e949 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -22,6 +23,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); + g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin"); + media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar); g_autoptr(FlPluginRegistrar) record_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "RecordLinuxPlugin"); record_linux_plugin_register_with_registrar(record_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index ff47d84..a59a036 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color file_selector_linux flutter_secure_storage_linux + media_kit_libs_linux record_linux url_launcher_linux ) From 40b678683e58faf7afe1c99b1fdac2742913ad9f Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 11:05:32 -0700 Subject: [PATCH 14/29] sort --- lib/main.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 7dc122e..53c49f4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,6 +10,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_phoenix/flutter_phoenix.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:intl/intl.dart'; +import 'package:just_audio_media_kit/just_audio_media_kit.dart'; import 'package:logging/logging.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:provider/provider.dart'; @@ -24,7 +25,7 @@ import 'package:recon/models/sem_ver.dart'; import 'package:recon/widgets/homepage.dart'; import 'package:recon/widgets/login_screen.dart'; import 'package:recon/widgets/update_notifier.dart'; -import 'package:just_audio_media_kit/just_audio_media_kit.dart'; + import 'models/authentication_data.dart'; void main() async { From 9cb91383e23cb4c4f23ef715de9a128aaf54f32c Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 11:23:35 -0700 Subject: [PATCH 15/29] Suppress deprecation warning as error --- windows/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 13f5ab4..f504d91 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -32,6 +32,9 @@ set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") # Use Unicode for all projects. add_definitions(-DUNICODE -D_UNICODE) +# Ignore Coroutine Deprecation Warnings, Caused build error on windows with vs26 [permission_handler_windows] +add_definitions(-D_SILENCE_EXPERIMENTAL_COROUTINE_DEPRECATION_WARNINGS) + # Compilation settings that should be applied to most targets. # # Be cautious about adding new options here, as plugins use this function by From c431e9994d91ebedfacb4cfbe54460a447dd4434 Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 12:06:37 -0700 Subject: [PATCH 16/29] Windows notifications --- lib/clients/notification_client.dart | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/clients/notification_client.dart b/lib/clients/notification_client.dart index 6fb4511..7f803b6 100644 --- a/lib/clients/notification_client.dart +++ b/lib/clients/notification_client.dart @@ -23,7 +23,12 @@ class NotificationClient { ); final fln.FlutterLocalNotificationsPlugin _notifier = fln.FlutterLocalNotificationsPlugin() - ..initialize(const fln.InitializationSettings( + ..initialize(settings: const fln.InitializationSettings( + windows: fln.WindowsInitializationSettings( + appName: "ReCon", + appUserModelId: "me.voidspace.recon", + guid: 'a8100a1f-4794-4a6b-8ed6-c52efc766fc7', + ), android: fln.AndroidInitializationSettings("ic_notification"), iOS: fln.DarwinInitializationSettings(), macOS: fln.DarwinInitializationSettings(), @@ -38,10 +43,10 @@ class NotificationClient { for (final entry in bySender.entries) { final uname = entry.key.stripUid(); await _notifier.show( - uname.hashCode, - null, - null, - fln.NotificationDetails( + id: uname.hashCode, + title: null, + body: null, + notificationDetails: fln.NotificationDetails( android: fln.AndroidNotificationDetails( _messageChannel.id, _messageChannel.name, From 3e9b3050056fc26c254ae3067fdb7c8ef3788b0a Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 12:56:15 -0700 Subject: [PATCH 17/29] Set version for media_kit_libs_linux --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 717d08a..30f74fd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -65,7 +65,7 @@ dependencies: share_plus: ^13.1.0 background_downloader: ^9.5.5 just_audio_media_kit: ^2.1.0 - media_kit_libs_linux: any + media_kit_libs_linux: ^1.2.1 dev_dependencies: flutter_test: sdk: flutter From cca8ace37822355025bfcf84f8dcfe91a46c3718 Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 12:56:34 -0700 Subject: [PATCH 18/29] Add media_kit_libs_windows_audio --- pubspec.lock | 8 ++++++++ pubspec.yaml | 2 ++ 2 files changed, 10 insertions(+) diff --git a/pubspec.lock b/pubspec.lock index 079cc44..d366f2a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -664,6 +664,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" + media_kit_libs_windows_audio: + dependency: "direct main" + description: + name: media_kit_libs_windows_audio + sha256: c2fd558cc87b9d89a801141fcdffe02e338a3b21a41a18fbd63d5b221a1b8e53 + url: "https://pub.dev" + source: hosted + version: "1.0.9" meta: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 30f74fd..37454d1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -66,6 +66,8 @@ dependencies: background_downloader: ^9.5.5 just_audio_media_kit: ^2.1.0 media_kit_libs_linux: ^1.2.1 + media_kit_libs_windows_audio: ^1.0.9 + dev_dependencies: flutter_test: sdk: flutter From 7ac9666f96b00fa93ee6909426a37f28ebd199f6 Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 13:00:39 -0700 Subject: [PATCH 19/29] gen --- windows/flutter/generated_plugin_registrant.cc | 3 +++ windows/flutter/generated_plugins.cmake | 1 + 2 files changed, 4 insertions(+) diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 1610f0b..d109f5a 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("FileSelectorWindows")); FlutterSecureStorageWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); + MediaKitLibsWindowsAudioPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("MediaKitLibsWindowsAudioPluginCApi")); PermissionHandlerWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); RecordWindowsPluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 63acf74..385cb15 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color file_selector_windows flutter_secure_storage_windows + media_kit_libs_windows_audio permission_handler_windows record_windows share_plus From 1527bb10c6027d675fabf4ef4d90f27d2a2c243f Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 19:46:45 -0700 Subject: [PATCH 20/29] basic notification body --- lib/clients/notification_client.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/clients/notification_client.dart b/lib/clients/notification_client.dart index 7f803b6..9f7527c 100644 --- a/lib/clients/notification_client.dart +++ b/lib/clients/notification_client.dart @@ -45,7 +45,7 @@ class NotificationClient { await _notifier.show( id: uname.hashCode, title: null, - body: null, + body: "New message from $uname", notificationDetails: fln.NotificationDetails( android: fln.AndroidNotificationDetails( _messageChannel.id, From 0cc164ae2d92666838278f081a149bf0cefe0933 Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 20:19:35 -0700 Subject: [PATCH 21/29] try-catch for JustAudioMediaKit Initialization can throw an exception, also removed explicit parameter as linux and windows are enabled by default anyway --- lib/main.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 53c49f4..3f0bbbb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -30,7 +30,11 @@ import 'models/authentication_data.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); - JustAudioMediaKit.ensureInitialized(linux: true); + try { + JustAudioMediaKit.ensureInitialized(); // Windows and Linux are enabled by default. + } catch (e) { + log("Failed to initialize JustAudioMediaKit, audio features will be unavailable. Error: $e"); + } SystemChrome.setSystemUIOverlayStyle( const SystemUiOverlayStyle( systemStatusBarContrastEnforced: true, From 126e4acbcb775d7e8ae4e79939a4d3bbf1adf5e7 Mon Sep 17 00:00:00 2001 From: Delta Date: Thu, 17 Apr 2025 23:33:38 -0700 Subject: [PATCH 22/29] Granted and Adding contact messages --- lib/widgets/messages/message_invite_request.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/widgets/messages/message_invite_request.dart b/lib/widgets/messages/message_invite_request.dart index d592b5d..8e25ec2 100644 --- a/lib/widgets/messages/message_invite_request.dart +++ b/lib/widgets/messages/message_invite_request.dart @@ -25,6 +25,12 @@ class MessageInviteRequest extends StatelessWidget { } else if (fromSelf) { //Forwarded invite request text = '''Forwarded invite request from "${inviteInfo.usernameToInvite}" to session "${inviteInfo.forSessionName}"'''; + if(inviteInfo.response == "SendInvite") { + text = '''Granted "${inviteInfo.usernameToInvite}" invite to session "${inviteInfo.forSessionName}"'''; + } + if(inviteInfo.response == "AddAsContact") { + text = '''Adding ${inviteInfo.usernameToInvite} as a contact of the headless"'''; + } } else if (inviteInfo.forSessionName != null) { //Another user requested an invite from you. text = '''${inviteInfo.usernameToInvite} would like to join you in "${inviteInfo.forSessionName}"'''; From d13c02b95f16583ff9408ebcaa0aa22fe4f4456e Mon Sep 17 00:00:00 2001 From: Delta Date: Thu, 17 Apr 2025 23:34:22 -0700 Subject: [PATCH 23/29] User invite another user to session message --- lib/widgets/messages/message_invite_request.dart | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/widgets/messages/message_invite_request.dart b/lib/widgets/messages/message_invite_request.dart index 8e25ec2..9c64a59 100644 --- a/lib/widgets/messages/message_invite_request.dart +++ b/lib/widgets/messages/message_invite_request.dart @@ -32,8 +32,13 @@ class MessageInviteRequest extends StatelessWidget { text = '''Adding ${inviteInfo.usernameToInvite} as a contact of the headless"'''; } } else if (inviteInfo.forSessionName != null) { - //Another user requested an invite from you. - text = '''${inviteInfo.usernameToInvite} would like to join you in "${inviteInfo.forSessionName}"'''; + if (inviteInfo.requestingFromUsername != null) { + //User wants to invite user2 to world + text = '''"${inviteInfo.requestingFromUsername}" wants to invite "${inviteInfo.usernameToInvite}" to "${inviteInfo.forSessionName}"'''; + } else { + //Another user requested an invite from you. + text = '''${inviteInfo.usernameToInvite} would like to join you in "${inviteInfo.forSessionName}"'''; + } } else { text = '''${inviteInfo.usernameToInvite} would like to join you'''; } From 763475fdd634ae127e03cdfae350362bf829516d Mon Sep 17 00:00:00 2001 From: Delta Date: Sat, 20 Jun 2026 21:57:30 -0700 Subject: [PATCH 24/29] Handle unknown responses and empty username --- lib/widgets/messages/message_invite_request.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/widgets/messages/message_invite_request.dart b/lib/widgets/messages/message_invite_request.dart index 9c64a59..76de723 100644 --- a/lib/widgets/messages/message_invite_request.dart +++ b/lib/widgets/messages/message_invite_request.dart @@ -24,15 +24,17 @@ class MessageInviteRequest extends StatelessWidget { text ='''Requested invite'''; } else if (fromSelf) { //Forwarded invite request - text = '''Forwarded invite request from "${inviteInfo.usernameToInvite}" to session "${inviteInfo.forSessionName}"'''; if(inviteInfo.response == "SendInvite") { text = '''Granted "${inviteInfo.usernameToInvite}" invite to session "${inviteInfo.forSessionName}"'''; - } - if(inviteInfo.response == "AddAsContact") { + } else if(inviteInfo.response == "AddAsContact") { text = '''Adding ${inviteInfo.usernameToInvite} as a contact of the headless"'''; + } else { + //If new responses are added to the InviteRequestResponse enum. + text = '''Unknown response "${inviteInfo.response}" for invite request'''; } } else if (inviteInfo.forSessionName != null) { - if (inviteInfo.requestingFromUsername != null) { + //Another user requested an invite from you. + if (inviteInfo.requestingFromUsername.isNotEmpty) { //User wants to invite user2 to world text = '''"${inviteInfo.requestingFromUsername}" wants to invite "${inviteInfo.usernameToInvite}" to "${inviteInfo.forSessionName}"'''; } else { From e5268e123240e603f7da9f9553b2b1eabeab3d6f Mon Sep 17 00:00:00 2001 From: Nutcake Date: Sun, 21 Jun 2026 12:36:34 +0200 Subject: [PATCH 25/29] Fix username overflow in message view --- lib/widgets/messages/messages_list.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/widgets/messages/messages_list.dart b/lib/widgets/messages/messages_list.dart index 3bd8a66..28a5b44 100644 --- a/lib/widgets/messages/messages_list.dart +++ b/lib/widgets/messages/messages_list.dart @@ -68,7 +68,7 @@ class _MessagesListState extends State with SingleTickerProviderSt const SizedBox( width: 8, ), - Text(friend.contactUsername), + Expanded(child: Text(friend.contactUsername)), if (friend.isHeadless) Padding( padding: const EdgeInsets.only(left: 12), From 6d8ed650f8f5a35cc05e6997f36bc1bc45f75fef Mon Sep 17 00:00:00 2001 From: Nutcake Date: Sun, 21 Jun 2026 12:58:22 +0200 Subject: [PATCH 26/29] Improve memory usage of avatars --- .../friend_online_status_indicator.dart | 23 +++--- lib/widgets/generic_avatar.dart | 72 ++++++++++--------- 2 files changed, 49 insertions(+), 46 deletions(-) diff --git a/lib/widgets/friends/friend_online_status_indicator.dart b/lib/widgets/friends/friend_online_status_indicator.dart index 65e4d58..dc88e7b 100644 --- a/lib/widgets/friends/friend_online_status_indicator.dart +++ b/lib/widgets/friends/friend_online_status_indicator.dart @@ -1,7 +1,5 @@ import 'package:flutter/material.dart'; import 'package:recon/models/users/friend.dart'; -import 'package:recon/models/users/online_status.dart'; -import 'package:recon/models/users/user_status.dart'; class FriendOnlineStatusIndicator extends StatelessWidget { const FriendOnlineStatusIndicator({required this.friend, super.key}); @@ -10,17 +8,18 @@ class FriendOnlineStatusIndicator extends StatelessWidget { @override Widget build(BuildContext context) { - final UserStatus userStatus = friend.userStatus; - final OnlineStatus onlineStatus = userStatus.onlineStatus; + final userStatus = friend.userStatus; + final onlineStatus = userStatus.onlineStatus; return userStatus.appVersion.contains("ReCon") && friend.isOnline - ? SizedBox.square( - dimension: 10, - child: Image.asset( - "assets/images/logo-white.png", - color: onlineStatus.color(context), - filterQuality: FilterQuality.medium, - isAntiAlias: true, - ), + ? Image.asset( + "assets/images/logo-white.png", + color: onlineStatus.color(context), + filterQuality: FilterQuality.medium, + isAntiAlias: true, + width: 10, + height: 10, + cacheWidth: 25, + cacheHeight: 25, ) : Icon( friend.isOffline ? Icons.circle_outlined : Icons.circle, diff --git a/lib/widgets/generic_avatar.dart b/lib/widgets/generic_avatar.dart index 552b1cf..2dfe7b2 100644 --- a/lib/widgets/generic_avatar.dart +++ b/lib/widgets/generic_avatar.dart @@ -1,8 +1,7 @@ -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; class GenericAvatar extends StatelessWidget { - const GenericAvatar({this.imageUri="", super.key, this.placeholderIcon=Icons.person, this.radius, this.foregroundColor}); + const GenericAvatar({this.imageUri = "", super.key, this.placeholderIcon = Icons.person, this.radius, this.foregroundColor}); final String imageUri; final IconData placeholderIcon; @@ -11,39 +10,44 @@ class GenericAvatar extends StatelessWidget { @override Widget build(BuildContext context) { - return imageUri.isEmpty ? CircleAvatar( + final placeholder = CircleAvatar( + key: const ValueKey("avatar-placeholder"), radius: radius, - foregroundColor: foregroundColor ?? Theme.of(context).colorScheme.onPrimaryContainer, - backgroundColor: Theme.of(context).colorScheme.primaryContainer, - child: Icon(placeholderIcon, color: foregroundColor,), - ) : CachedNetworkImage( - imageBuilder: (context, imageProvider) { - return CircleAvatar( - foregroundImage: imageProvider, - foregroundColor: Colors.transparent, - backgroundColor: Colors.transparent, - radius: radius, - ); - }, - imageUrl: imageUri, - placeholder: (context, url) { - return CircleAvatar( - backgroundColor: Theme.of(context).colorScheme.primaryContainer, - foregroundColor: foregroundColor ?? Theme.of(context).colorScheme.onPrimaryContainer, - radius: radius, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: CircularProgressIndicator(color: foregroundColor ?? Theme.of(context).colorScheme.onPrimaryContainer, strokeWidth: 2), - ), - ); - }, - errorWidget: (context, error, what) => CircleAvatar( - radius: radius, - foregroundColor: foregroundColor ?? Theme.of(context).colorScheme.onPrimaryContainer, - backgroundColor: Theme.of(context).colorScheme.primaryContainer, - child: Icon(placeholderIcon, color: foregroundColor ?? Theme.of(context).colorScheme.onPrimaryContainer,), + foregroundColor: foregroundColor ?? Theme.of(context).colorScheme.onSecondaryContainer, + backgroundColor: Theme.of(context).colorScheme.secondaryContainer, + child: Icon( + placeholderIcon, + color: foregroundColor, ), ); + return imageUri.isEmpty + ? placeholder + : ClipRRect( + borderRadius: BorderRadiusGeometry.all(Radius.circular(64)), + child: Image.network( + imageUri, + width: 40, + height: 40, + cacheHeight: 40, + cacheWidth: 40, + frameBuilder: (context, child, frame, wasSynchronouslyLoaded) => AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + transitionBuilder: (child, animation) => FadeTransition( + opacity: animation, + child: child, + ), + child: frame == null + ? placeholder + : CircleAvatar( + key: const ValueKey("avatar-loaded"), + radius: radius, + foregroundColor: Colors.transparent, + backgroundColor: Colors.transparent, + child: child, + ), + ), + errorBuilder: (context, error, stackTrace) => placeholder, + ), + ); } - -} \ No newline at end of file +} From 1aa644f1cebbe0d3962c014c21ca803fe85cb04d Mon Sep 17 00:00:00 2001 From: Nutcake Date: Sun, 21 Jun 2026 12:58:40 +0200 Subject: [PATCH 27/29] Update gradle and kotlin --- android/gradle.properties | 4 ++++ android/gradle/wrapper/gradle-wrapper.properties | 2 +- android/settings.gradle | 5 +++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/android/gradle.properties b/android/gradle.properties index f018a61..475a628 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,3 +1,7 @@ org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true android.enableJetifier=true +# This builtInKotlin flag was added automatically by Flutter migrator +android.builtInKotlin=false +# This newDsl flag was added automatically by Flutter migrator +android.newDsl=false diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index efdcc4a..da80f8d 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-all.zip diff --git a/android/settings.gradle b/android/settings.gradle index 41ce158..bfc25ef 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -18,8 +18,9 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.9.1" apply false - id "org.jetbrains.kotlin.android" version "2.1.0" apply false + id "com.android.application" version "9.2.0" apply false + id 'com.android.library' version '9.2.0' apply false + id "org.jetbrains.kotlin.android" version "2.3.21" apply false } include ":app" \ No newline at end of file From 5f32f7c994a1dc704867e9d4482a59d0d6244b8c Mon Sep 17 00:00:00 2001 From: Nutcake Date: Sun, 21 Jun 2026 13:26:57 +0200 Subject: [PATCH 28/29] Reduce amount of widget updates caused by session updates --- lib/clients/messaging_client.dart | 5 +- lib/models/session.dart | 78 ++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/lib/clients/messaging_client.dart b/lib/clients/messaging_client.dart index 28caca5..ca9cb86 100644 --- a/lib/clients/messaging_client.dart +++ b/lib/clients/messaging_client.dart @@ -431,8 +431,11 @@ class MessagingClient extends ChangeNotifier { if (session.id == null) { return; } + final oldSession = _sessionMap[session.id!]; _sessionMap[session.id!] = session; - notifyListeners(); + if (oldSession != session) { + notifyListeners(); + } } void _onRemoveSession(List args) { diff --git a/lib/models/session.dart b/lib/models/session.dart index 8de8ffb..e46efa8 100644 --- a/lib/models/session.dart +++ b/lib/models/session.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:recon/string_formatter.dart'; class Session { @@ -28,6 +29,7 @@ class Session { final bool hideFromListing; final String broadcastKey; final bool awayKickEnabled; + //final Float awayKickMinutes; final bool hasEnded; final bool isValid; @@ -60,7 +62,6 @@ class Session { required this.awayKickEnabled, required this.hasEnded, required this.isValid, - }) : formattedName = FormatNode.fromText(name), formattedDescription = FormatNode.fromText(description); @@ -225,6 +226,68 @@ class Session { ); } + @override + bool operator ==(Object other) => + identical(this, other) || + other is Session && + runtimeType == other.runtimeType && + name == other.name && + description == other.description && + listEquals(tags, other.tags) && + id == other.id && + hostUserId == other.hostUserId && + hostMachineId == other.hostMachineId && + hostUsername == other.hostUsername && + universeId == other.universeId && + appVersion == other.appVersion && + headlessHost == other.headlessHost && + listEquals(sessionURLs, other.sessionURLs) && + listEquals(sessionUsers, other.sessionUsers) && + thumbnailUrl == other.thumbnailUrl && + joinedUsers == other.joinedUsers && + minActiveUsers == other.minActiveUsers && + totalJoinedUsers == other.totalJoinedUsers && + totalActiveUsers == other.totalActiveUsers && + maxUsers == other.maxUsers && + mobileFriendly == other.mobileFriendly && + sessionBeginTime == other.sessionBeginTime && + accessLevel == other.accessLevel && + hideFromListing == other.hideFromListing && + broadcastKey == other.broadcastKey && + awayKickEnabled == other.awayKickEnabled && + hasEnded == other.hasEnded && + isValid == other.isValid; + + @override + int get hashCode => Object.hashAll([ + name, + description, + tags, + id, + hostUserId, + hostMachineId, + hostUsername, + universeId, + appVersion, + headlessHost, + sessionURLs, + sessionUsers, + thumbnailUrl, + joinedUsers, + minActiveUsers, + totalJoinedUsers, + totalActiveUsers, + maxUsers, + mobileFriendly, + sessionBeginTime, + accessLevel, + hideFromListing, + broadcastKey, + awayKickEnabled, + hasEnded, + isValid, + ]); + bool get isLive => !hasEnded && isValid; } @@ -284,6 +347,19 @@ class SessionUser { "outputDevice": outputDevice, }; } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is SessionUser && + runtimeType == other.runtimeType && + id == other.id && + username == other.username && + isPresent == other.isPresent && + outputDevice == other.outputDevice; + + @override + int get hashCode => Object.hash(id, username, isPresent, outputDevice); } class SessionFilterSettings { From 7042da96b0713717b4ff68bcd5d1e91650eadc9e Mon Sep 17 00:00:00 2001 From: Nutcake Date: Sun, 21 Jun 2026 13:30:18 +0200 Subject: [PATCH 29/29] Bump version number --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 37454d1..d38f556 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.12.1-beta +version: 0.12.2-beta environment: sdk: ">=3.0.1"