neoagent 2.3.1-beta.4 → 2.3.1-beta.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. package/.env.example +45 -0
  2. package/docs/capabilities.md +2 -2
  3. package/docs/configuration.md +12 -5
  4. package/docs/hardware.md +1 -1
  5. package/docs/integrations.md +2 -3
  6. package/flutter_app/.metadata +42 -0
  7. package/flutter_app/README.md +21 -0
  8. package/flutter_app/analysis_options.yaml +32 -0
  9. package/flutter_app/android/app/build.gradle.kts +109 -0
  10. package/flutter_app/android/app/src/debug/AndroidManifest.xml +7 -0
  11. package/flutter_app/android/app/src/main/AndroidManifest.xml +147 -0
  12. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/MainActivity.kt +747 -0
  13. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthConnectGateway.kt +280 -0
  14. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncNotifications.kt +113 -0
  15. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncPayload.kt +57 -0
  16. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncScheduler.kt +78 -0
  17. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncWorker.kt +253 -0
  18. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/PermissionsRationaleActivity.kt +46 -0
  19. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingBootReceiver.kt +21 -0
  20. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingForegroundService.kt +586 -0
  21. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingStateStore.kt +78 -0
  22. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingUploadClient.kt +104 -0
  23. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/AiHomeWidgetProvider.kt +457 -0
  24. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/AiWidgetStore.kt +194 -0
  25. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/VoiceLaunchWidgetProvider.kt +67 -0
  26. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetConfigActivity.kt +228 -0
  27. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetSyncScheduler.kt +72 -0
  28. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetSyncWorker.kt +186 -0
  29. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetTaskRunWorker.kt +210 -0
  30. package/flutter_app/android/app/src/main/res/drawable/launch_background.xml +12 -0
  31. package/flutter_app/android/app/src/main/res/drawable/neoagent_ai_widget_bg.xml +11 -0
  32. package/flutter_app/android/app/src/main/res/drawable/neoagent_ai_widget_task_bg.xml +8 -0
  33. package/flutter_app/android/app/src/main/res/drawable-v21/launch_background.xml +12 -0
  34. package/flutter_app/android/app/src/main/res/layout/neoagent_ai_widget.xml +138 -0
  35. package/flutter_app/android/app/src/main/res/layout/neoagent_ai_widget_task_row.xml +52 -0
  36. package/flutter_app/android/app/src/main/res/layout/neoagent_voice_widget.xml +49 -0
  37. package/flutter_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  38. package/flutter_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  39. package/flutter_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  40. package/flutter_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  41. package/flutter_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  42. package/flutter_app/android/app/src/main/res/values/strings.xml +12 -0
  43. package/flutter_app/android/app/src/main/res/values/styles.xml +18 -0
  44. package/flutter_app/android/app/src/main/res/values-night/styles.xml +18 -0
  45. package/flutter_app/android/app/src/main/res/xml/file_paths.xml +6 -0
  46. package/flutter_app/android/app/src/main/res/xml/neoagent_ai_widget_info.xml +12 -0
  47. package/flutter_app/android/app/src/main/res/xml/neoagent_voice_widget_info.xml +12 -0
  48. package/flutter_app/android/app/src/profile/AndroidManifest.xml +7 -0
  49. package/flutter_app/android/build.gradle.kts +24 -0
  50. package/flutter_app/android/ci-release.keystore +0 -0
  51. package/flutter_app/android/gradle/wrapper/gradle-wrapper.properties +5 -0
  52. package/flutter_app/android/gradle.properties +3 -0
  53. package/flutter_app/android/key.properties +4 -0
  54. package/flutter_app/android/settings.gradle.kts +26 -0
  55. package/flutter_app/assets/branding/app_icon_1024.png +0 -0
  56. package/flutter_app/assets/branding/app_icon_128.png +0 -0
  57. package/flutter_app/assets/branding/app_icon_192.png +0 -0
  58. package/flutter_app/assets/branding/app_icon_256.png +0 -0
  59. package/flutter_app/assets/branding/app_icon_32.png +0 -0
  60. package/flutter_app/assets/branding/app_icon_512.png +0 -0
  61. package/flutter_app/assets/branding/app_icon_64.png +0 -0
  62. package/flutter_app/assets/branding/tray_icon_template.png +0 -0
  63. package/flutter_app/lib/features/location/location_service.dart +119 -0
  64. package/flutter_app/lib/features/notifications/notification_interceptor.dart +97 -0
  65. package/flutter_app/lib/main.dart +99 -0
  66. package/flutter_app/lib/main_account_settings.dart +1250 -0
  67. package/flutter_app/lib/main_admin.dart +886 -0
  68. package/flutter_app/lib/main_app_shell.dart +1682 -0
  69. package/flutter_app/lib/main_chat.dart +3352 -0
  70. package/flutter_app/lib/main_controller.dart +6781 -0
  71. package/flutter_app/lib/main_devices.dart +2301 -0
  72. package/flutter_app/lib/main_integrations.dart +1129 -0
  73. package/flutter_app/lib/main_launcher.dart +959 -0
  74. package/flutter_app/lib/main_launcher_entry.dart +5 -0
  75. package/flutter_app/lib/main_models.dart +3546 -0
  76. package/flutter_app/lib/main_navigation.dart +193 -0
  77. package/flutter_app/lib/main_operations.dart +4851 -0
  78. package/flutter_app/lib/main_recordings.dart +870 -0
  79. package/flutter_app/lib/main_runtime.dart +806 -0
  80. package/flutter_app/lib/main_settings.dart +2024 -0
  81. package/flutter_app/lib/main_shared.dart +2861 -0
  82. package/flutter_app/lib/main_theme.dart +204 -0
  83. package/flutter_app/lib/main_voice_assistant.dart +957 -0
  84. package/flutter_app/lib/src/android_apk_drop_zone.dart +32 -0
  85. package/flutter_app/lib/src/android_apk_drop_zone_stub.dart +16 -0
  86. package/flutter_app/lib/src/android_apk_drop_zone_web.dart +348 -0
  87. package/flutter_app/lib/src/android_app_installer.dart +22 -0
  88. package/flutter_app/lib/src/android_app_installer_io.dart +122 -0
  89. package/flutter_app/lib/src/android_app_installer_stub.dart +21 -0
  90. package/flutter_app/lib/src/android_launcher_bridge.dart +239 -0
  91. package/flutter_app/lib/src/app_launch_bridge.dart +29 -0
  92. package/flutter_app/lib/src/app_release_updater.dart +511 -0
  93. package/flutter_app/lib/src/backend_client.dart +1833 -0
  94. package/flutter_app/lib/src/desktop_companion.dart +2 -0
  95. package/flutter_app/lib/src/desktop_companion_actions.dart +586 -0
  96. package/flutter_app/lib/src/desktop_companion_io.dart +538 -0
  97. package/flutter_app/lib/src/desktop_companion_stub.dart +59 -0
  98. package/flutter_app/lib/src/desktop_native_bridge.dart +91 -0
  99. package/flutter_app/lib/src/desktop_screen_capture.dart +21 -0
  100. package/flutter_app/lib/src/desktop_screen_capture_io.dart +142 -0
  101. package/flutter_app/lib/src/desktop_screen_capture_stub.dart +12 -0
  102. package/flutter_app/lib/src/diagnostics_logger.dart +119 -0
  103. package/flutter_app/lib/src/health_bridge.dart +136 -0
  104. package/flutter_app/lib/src/live_voice_capture.dart +85 -0
  105. package/flutter_app/lib/src/messaging_access_summary.dart +46 -0
  106. package/flutter_app/lib/src/network/app_http_client.dart +53 -0
  107. package/flutter_app/lib/src/network/app_http_client_factory.dart +6 -0
  108. package/flutter_app/lib/src/network/app_http_client_io.dart +138 -0
  109. package/flutter_app/lib/src/network/app_http_client_stub.dart +3 -0
  110. package/flutter_app/lib/src/network/app_http_client_web.dart +94 -0
  111. package/flutter_app/lib/src/oauth_launcher.dart +33 -0
  112. package/flutter_app/lib/src/oauth_launcher_io.dart +77 -0
  113. package/flutter_app/lib/src/oauth_launcher_stub.dart +33 -0
  114. package/flutter_app/lib/src/oauth_launcher_web.dart +107 -0
  115. package/flutter_app/lib/src/recording_bridge.dart +232 -0
  116. package/flutter_app/lib/src/recording_bridge_io.dart +1019 -0
  117. package/flutter_app/lib/src/recording_bridge_stub.dart +120 -0
  118. package/flutter_app/lib/src/recording_bridge_web.dart +689 -0
  119. package/flutter_app/lib/src/recording_payloads.dart +86 -0
  120. package/flutter_app/lib/src/theme/palette.dart +81 -0
  121. package/flutter_app/lib/src/widget_bridge.dart +49 -0
  122. package/flutter_app/linux/CMakeLists.txt +128 -0
  123. package/flutter_app/linux/flutter/CMakeLists.txt +88 -0
  124. package/flutter_app/linux/flutter/generated_plugin_registrant.cc +43 -0
  125. package/flutter_app/linux/flutter/generated_plugin_registrant.h +15 -0
  126. package/flutter_app/linux/flutter/generated_plugins.cmake +31 -0
  127. package/flutter_app/linux/runner/CMakeLists.txt +26 -0
  128. package/flutter_app/linux/runner/main.cc +6 -0
  129. package/flutter_app/linux/runner/my_application.cc +144 -0
  130. package/flutter_app/linux/runner/my_application.h +18 -0
  131. package/flutter_app/linux/runner/resources/app_icon.png +0 -0
  132. package/flutter_app/macos/Flutter/Flutter-Debug.xcconfig +2 -0
  133. package/flutter_app/macos/Flutter/Flutter-Release.xcconfig +2 -0
  134. package/flutter_app/macos/Flutter/GeneratedPluginRegistrant.swift +40 -0
  135. package/flutter_app/macos/Podfile +42 -0
  136. package/flutter_app/macos/Podfile.lock +87 -0
  137. package/flutter_app/macos/Runner/AppDelegate.swift +576 -0
  138. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -0
  139. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
  140. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
  141. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
  142. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
  143. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
  144. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
  145. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
  146. package/flutter_app/macos/Runner/Base.lproj/MainMenu.xib +342 -0
  147. package/flutter_app/macos/Runner/Configs/AppInfo.xcconfig +14 -0
  148. package/flutter_app/macos/Runner/Configs/Debug.xcconfig +2 -0
  149. package/flutter_app/macos/Runner/Configs/Release.xcconfig +2 -0
  150. package/flutter_app/macos/Runner/Configs/Warnings.xcconfig +13 -0
  151. package/flutter_app/macos/Runner/DebugProfile.entitlements +16 -0
  152. package/flutter_app/macos/Runner/Info.plist +36 -0
  153. package/flutter_app/macos/Runner/MainFlutterWindow.swift +19 -0
  154. package/flutter_app/macos/Runner/Release.entitlements +12 -0
  155. package/flutter_app/macos/Runner.xcodeproj/project.pbxproj +801 -0
  156. package/flutter_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  157. package/flutter_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +99 -0
  158. package/flutter_app/macos/Runner.xcworkspace/contents.xcworkspacedata +10 -0
  159. package/flutter_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  160. package/flutter_app/macos/RunnerTests/RunnerTests.swift +12 -0
  161. package/flutter_app/patch_strings.py +12 -0
  162. package/flutter_app/pubspec.lock +1088 -0
  163. package/flutter_app/pubspec.yaml +53 -0
  164. package/flutter_app/test/messaging_access_summary_test.dart +22 -0
  165. package/flutter_app/test/recording_payloads_test.dart +53 -0
  166. package/flutter_app/third_party/desktop_audio_capture/LICENSE +21 -0
  167. package/flutter_app/third_party/desktop_audio_capture/README.md +262 -0
  168. package/flutter_app/third_party/desktop_audio_capture/lib/audio_capture.dart +65 -0
  169. package/flutter_app/third_party/desktop_audio_capture/lib/config/mic_audio_config.dart +153 -0
  170. package/flutter_app/third_party/desktop_audio_capture/lib/config/system_adudio_config.dart +110 -0
  171. package/flutter_app/third_party/desktop_audio_capture/lib/mic/mic_audio_capture.dart +461 -0
  172. package/flutter_app/third_party/desktop_audio_capture/lib/model/audio_status.dart +91 -0
  173. package/flutter_app/third_party/desktop_audio_capture/lib/model/decibel_data.dart +106 -0
  174. package/flutter_app/third_party/desktop_audio_capture/lib/model/input_device_type.dart +219 -0
  175. package/flutter_app/third_party/desktop_audio_capture/lib/system/system_audio_capture.dart +336 -0
  176. package/flutter_app/third_party/desktop_audio_capture/linux/CMakeLists.txt +101 -0
  177. package/flutter_app/third_party/desktop_audio_capture/linux/audio_capture_plugin.cc +692 -0
  178. package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/audio_capture_plugin.h +35 -0
  179. package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/mic_capture_plugin.h +36 -0
  180. package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/audio_capture_plugin.h +32 -0
  181. package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/mic_capture_plugin.h +32 -0
  182. package/flutter_app/third_party/desktop_audio_capture/linux/mic_capture_plugin.cc +878 -0
  183. package/flutter_app/third_party/desktop_audio_capture/macos/Classes/AudioCapturePlugin.swift +27 -0
  184. package/flutter_app/third_party/desktop_audio_capture/macos/Classes/MicCapturePlugin.swift +1172 -0
  185. package/flutter_app/third_party/desktop_audio_capture/macos/Classes/SystemCapturePlugin.swift +655 -0
  186. package/flutter_app/third_party/desktop_audio_capture/macos/Resources/PrivacyInfo.xcprivacy +12 -0
  187. package/flutter_app/third_party/desktop_audio_capture/macos/desktop_audio_capture.podspec +30 -0
  188. package/flutter_app/third_party/desktop_audio_capture/pubspec.yaml +87 -0
  189. package/flutter_app/third_party/desktop_audio_capture/windows/CMakeLists.txt +105 -0
  190. package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.cpp +80 -0
  191. package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.h +31 -0
  192. package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin_c_api.cpp +12 -0
  193. package/flutter_app/third_party/desktop_audio_capture/windows/include/audio_capture/audio_capture_plugin_c_api.h +23 -0
  194. package/flutter_app/third_party/desktop_audio_capture/windows/include/desktop_audio_capture/audio_capture_plugin.h +25 -0
  195. package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.cpp +1117 -0
  196. package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.h +115 -0
  197. package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.cpp +777 -0
  198. package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.h +87 -0
  199. package/flutter_app/third_party/flutter_secure_storage_linux/linux/CMakeLists.txt +30 -0
  200. package/flutter_app/third_party/flutter_secure_storage_linux/linux/flutter_secure_storage_linux_plugin.cc +215 -0
  201. package/flutter_app/third_party/flutter_secure_storage_linux/linux/include/flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h +27 -0
  202. package/flutter_app/third_party/flutter_secure_storage_linux/pubspec.yaml +20 -0
  203. package/flutter_app/tool/generate_desktop_branding.py +219 -0
  204. package/flutter_app/web/favicon.png +0 -0
  205. package/flutter_app/web/favicon.svg +12 -0
  206. package/flutter_app/web/icons/Icon-192.png +0 -0
  207. package/flutter_app/web/icons/Icon-512.png +0 -0
  208. package/flutter_app/web/icons/Icon-maskable-192.png +0 -0
  209. package/flutter_app/web/icons/Icon-maskable-512.png +0 -0
  210. package/flutter_app/web/index.html +39 -0
  211. package/flutter_app/web/manifest.json +35 -0
  212. package/flutter_app/windows/CMakeLists.txt +108 -0
  213. package/flutter_app/windows/flutter/CMakeLists.txt +109 -0
  214. package/flutter_app/windows/flutter/generated_plugin_registrant.cc +47 -0
  215. package/flutter_app/windows/flutter/generated_plugin_registrant.h +15 -0
  216. package/flutter_app/windows/flutter/generated_plugins.cmake +35 -0
  217. package/flutter_app/windows/runner/CMakeLists.txt +41 -0
  218. package/flutter_app/windows/runner/Runner.rc +121 -0
  219. package/flutter_app/windows/runner/flutter_window.cpp +533 -0
  220. package/flutter_app/windows/runner/flutter_window.h +37 -0
  221. package/flutter_app/windows/runner/main.cpp +53 -0
  222. package/flutter_app/windows/runner/resource.h +16 -0
  223. package/flutter_app/windows/runner/resources/app_icon.ico +0 -0
  224. package/flutter_app/windows/runner/runner.exe.manifest +14 -0
  225. package/flutter_app/windows/runner/utils.cpp +65 -0
  226. package/flutter_app/windows/runner/utils.h +19 -0
  227. package/flutter_app/windows/runner/win32_window.cpp +299 -0
  228. package/flutter_app/windows/runner/win32_window.h +102 -0
  229. package/lib/install_helpers.js +31 -0
  230. package/lib/manager.js +227 -6
  231. package/package.json +3 -1
  232. package/server/db/database.js +110 -0
  233. package/server/http/middleware.js +55 -2
  234. package/server/http/routes.js +1 -0
  235. package/server/index.js +3 -0
  236. package/server/public/.last_build_id +1 -1
  237. package/server/public/assets/NOTICES +1 -1
  238. package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
  239. package/server/public/canvaskit/wimp.wasm +0 -0
  240. package/server/public/flutter_bootstrap.js +2 -2
  241. package/server/public/main.dart.js +74324 -73132
  242. package/server/routes/integrations.js +108 -1
  243. package/server/routes/memory.js +11 -2
  244. package/server/{http/routes → routes}/screenHistory.js +2 -2
  245. package/server/routes/settings.js +75 -2
  246. package/server/{http/routes → routes}/triggers.js +2 -2
  247. package/server/routes/wearable.js +67 -0
  248. package/server/services/ai/models.js +30 -0
  249. package/server/services/ai/providers/githubCopilot.js +97 -0
  250. package/server/services/ai/providers/openai.js +2 -1
  251. package/server/services/ai/providers/openaiCodex.js +31 -0
  252. package/server/services/ai/settings.js +20 -0
  253. package/server/services/ai/toolSelector.js +14 -1
  254. package/server/services/ai/tools.js +77 -4
  255. package/server/services/desktop/screenRecorder.js +65 -9
  256. package/server/services/integrations/env.js +5 -0
  257. package/server/services/integrations/figma/provider.js +1 -0
  258. package/server/services/integrations/github/common.js +106 -0
  259. package/server/services/integrations/github/provider.js +499 -0
  260. package/server/services/integrations/github/repos.js +1124 -0
  261. package/server/services/integrations/google/provider.js +1 -0
  262. package/server/services/integrations/home_assistant/provider.js +325 -26
  263. package/server/services/integrations/manager.js +88 -12
  264. package/server/services/integrations/microsoft/provider.js +1 -0
  265. package/server/services/integrations/oauth_provider.js +25 -8
  266. package/server/services/integrations/provider_config_store.js +85 -0
  267. package/server/services/integrations/registry.js +4 -0
  268. package/server/services/integrations/spotify/provider.js +1 -0
  269. package/server/services/integrations/trello/provider.js +842 -0
  270. package/server/services/manager.js +46 -1
  271. package/server/services/mcp/client.js +120 -23
  272. package/server/services/memory/manager.js +39 -2
  273. package/server/services/messaging/access_policy.js +10 -0
  274. package/server/services/messaging/manager.js +49 -0
  275. package/server/services/messaging/meshtastic.js +260 -0
  276. package/server/services/messaging/meshtastic_env.js +100 -0
  277. package/server/services/messaging/meshtastic_protocol.js +476 -0
  278. package/server/services/messaging/meshtastic_tcp_transport.js +25 -0
  279. package/server/services/tasks/runtime.js +1 -1
  280. package/server/services/voice/openaiClient.js +4 -1
  281. package/server/services/voice/openaiSpeech.js +6 -1
  282. package/server/services/voice/providers.js +52 -12
  283. package/server/services/voice/runtimeManager.js +136 -19
  284. package/server/services/voice/turnRunner.js +29 -9
  285. package/server/services/wearable/firmware_manifest.js +370 -0
  286. package/server/services/wearable/gateway.js +350 -0
  287. package/server/services/wearable/protocol.js +45 -0
  288. package/server/services/wearable/service.js +244 -0
  289. package/server/utils/local_secrets.js +56 -0
  290. package/server/utils/logger.js +37 -9
@@ -0,0 +1,87 @@
1
+ #ifndef FLUTTER_PLUGIN_SYSTEM_AUDIO_CAPTURE_PLUGIN_H_
2
+ #define FLUTTER_PLUGIN_SYSTEM_AUDIO_CAPTURE_PLUGIN_H_
3
+
4
+ #include <flutter/event_channel.h>
5
+ #include <flutter/method_channel.h>
6
+ #include <flutter/plugin_registrar_windows.h>
7
+ #include <flutter/standard_method_codec.h>
8
+
9
+ #include <memory>
10
+ #include <mutex>
11
+ #include <thread>
12
+ #include <atomic>
13
+ #include <vector>
14
+
15
+ // Include Windows headers for WAVEFORMATEX
16
+ #include <mmsystem.h>
17
+
18
+ // Forward declarations for WASAPI interfaces
19
+ struct IAudioClient;
20
+ struct IAudioCaptureClient;
21
+ struct IMMDevice;
22
+
23
+ namespace audio_capture {
24
+
25
+ class SystemAudioCapturePlugin : public flutter::Plugin {
26
+ public:
27
+ static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar);
28
+
29
+ SystemAudioCapturePlugin(flutter::PluginRegistrarWindows *registrar);
30
+ ~SystemAudioCapturePlugin();
31
+
32
+ // Disallow copy and assign.
33
+ SystemAudioCapturePlugin(const SystemAudioCapturePlugin&) = delete;
34
+ SystemAudioCapturePlugin& operator=(const SystemAudioCapturePlugin&) = delete;
35
+
36
+ void HandleMethodCall(
37
+ const flutter::MethodCall<flutter::EncodableValue> &method_call,
38
+ std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
39
+
40
+ private:
41
+ bool StartCapture(const flutter::EncodableMap* args);
42
+ bool StopCapture();
43
+ void CaptureThread();
44
+ void SetThreadPriority();
45
+ double CalculateDecibel(const int16_t* samples, size_t sample_count);
46
+ void ApplyGainBoostAndConvertToMono(const int16_t* input, int16_t* output,
47
+ size_t frame_count, int input_channels,
48
+ float gain_boost);
49
+ void SendStatusUpdate(bool is_active);
50
+ void SendDecibelUpdate(double decibel);
51
+
52
+ flutter::PluginRegistrarWindows* registrar_;
53
+ std::unique_ptr<flutter::MethodChannel<flutter::EncodableValue>> method_channel_;
54
+ std::unique_ptr<flutter::EventChannel<flutter::EncodableValue>> event_channel_;
55
+ std::unique_ptr<flutter::EventChannel<flutter::EncodableValue>> status_event_channel_;
56
+ std::unique_ptr<flutter::EventChannel<flutter::EncodableValue>> decibel_event_channel_;
57
+
58
+ std::unique_ptr<flutter::EventSink<flutter::EncodableValue>> event_sink_;
59
+ std::unique_ptr<flutter::EventSink<flutter::EncodableValue>> status_event_sink_;
60
+ std::unique_ptr<flutter::EventSink<flutter::EncodableValue>> decibel_event_sink_;
61
+
62
+ std::mutex mutex_;
63
+ std::atomic<bool> is_capturing_;
64
+ std::atomic<bool> should_stop_;
65
+ std::thread capture_thread_;
66
+
67
+ // Audio configuration
68
+ int sample_rate_;
69
+ int channels_;
70
+ int bits_per_sample_;
71
+ int chunk_duration_ms_;
72
+ float gain_boost_;
73
+ float input_volume_;
74
+
75
+ // WASAPI interfaces
76
+ IAudioClient* audio_client_;
77
+ IAudioCaptureClient* capture_client_;
78
+ IMMDevice* device_;
79
+ WAVEFORMATEX* mix_format_;
80
+ UINT32 buffer_frame_count_;
81
+ bool com_initialized_; // Track if we initialized COM
82
+ };
83
+
84
+ } // namespace audio_capture
85
+
86
+ #endif // FLUTTER_PLUGIN_SYSTEM_AUDIO_CAPTURE_PLUGIN_H_
87
+
@@ -0,0 +1,30 @@
1
+ cmake_minimum_required(VERSION 3.10)
2
+ set(PROJECT_NAME "flutter_secure_storage_linux")
3
+ project(${PROJECT_NAME} LANGUAGES CXX)
4
+
5
+ set(PLUGIN_NAME "flutter_secure_storage_linux_plugin")
6
+
7
+ add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
8
+
9
+ add_library(${PLUGIN_NAME} SHARED
10
+ "flutter_secure_storage_linux_plugin.cc"
11
+ )
12
+
13
+ apply_standard_settings(${PLUGIN_NAME})
14
+
15
+ set_target_properties(${PLUGIN_NAME} PROPERTIES
16
+ CXX_VISIBILITY_PRESET hidden
17
+ )
18
+
19
+ target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
20
+ target_include_directories(${PLUGIN_NAME} INTERFACE
21
+ "${CMAKE_CURRENT_SOURCE_DIR}/include"
22
+ )
23
+
24
+ target_link_libraries(${PLUGIN_NAME} PRIVATE flutter)
25
+ target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK)
26
+
27
+ set(flutter_secure_storage_bundled_libraries
28
+ ""
29
+ PARENT_SCOPE
30
+ )
@@ -0,0 +1,215 @@
1
+ #include "include/flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h"
2
+
3
+ #include <flutter_linux/flutter_linux.h>
4
+ #include <glib.h>
5
+ #include <gtk/gtk.h>
6
+
7
+ #include <cstdio>
8
+ #include <string>
9
+
10
+ #define flutter_secure_storage_linux_plugin(obj) \
11
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), \
12
+ flutter_secure_storage_linux_plugin_get_type(), \
13
+ FlutterSecureStorageLinuxPlugin))
14
+
15
+ namespace {
16
+
17
+ constexpr const char *kChannelName =
18
+ "plugins.it_nomads.com/flutter_secure_storage";
19
+ constexpr const char *kGroupName = "secure_storage";
20
+
21
+ std::string GetStoragePath() {
22
+ const gchar *config_dir = g_get_user_config_dir();
23
+ gchar *directory = g_build_filename(config_dir, APPLICATION_ID, nullptr);
24
+ g_mkdir_with_parents(directory, 0700);
25
+ gchar *path = g_build_filename(directory, "flutter_secure_storage.ini", nullptr);
26
+ std::string result(path);
27
+ g_free(path);
28
+ g_free(directory);
29
+ return result;
30
+ }
31
+
32
+ GKeyFile *LoadKeyFile() {
33
+ GKeyFile *key_file = g_key_file_new();
34
+ const std::string path = GetStoragePath();
35
+ GError *error = nullptr;
36
+ g_key_file_load_from_file(
37
+ key_file,
38
+ path.c_str(),
39
+ static_cast<GKeyFileFlags>(G_KEY_FILE_KEEP_COMMENTS |
40
+ G_KEY_FILE_KEEP_TRANSLATIONS),
41
+ &error);
42
+ if (error != nullptr) {
43
+ g_error_free(error);
44
+ }
45
+ return key_file;
46
+ }
47
+
48
+ bool SaveKeyFile(GKeyFile *key_file, gchar **error_message) {
49
+ gsize length = 0;
50
+ GError *error = nullptr;
51
+ gchar *data = g_key_file_to_data(key_file, &length, &error);
52
+ if (error != nullptr) {
53
+ *error_message = g_strdup(error->message);
54
+ g_error_free(error);
55
+ return false;
56
+ }
57
+
58
+ const std::string path = GetStoragePath();
59
+ if (!g_file_set_contents(path.c_str(), data, static_cast<gssize>(length), &error)) {
60
+ *error_message = g_strdup(error->message);
61
+ g_error_free(error);
62
+ g_free(data);
63
+ return false;
64
+ }
65
+
66
+ g_free(data);
67
+ return true;
68
+ }
69
+
70
+ FlMethodResponse *BuildErrorResponse(const gchar *code, const gchar *message) {
71
+ return FL_METHOD_RESPONSE(
72
+ fl_method_error_response_new(code, message, nullptr));
73
+ }
74
+
75
+ } // namespace
76
+
77
+ struct _FlutterSecureStorageLinuxPlugin {
78
+ GObject parent_instance;
79
+ };
80
+
81
+ G_DEFINE_TYPE(FlutterSecureStorageLinuxPlugin,
82
+ flutter_secure_storage_linux_plugin,
83
+ g_object_get_type())
84
+
85
+ static void flutter_secure_storage_linux_plugin_handle_method_call(
86
+ FlutterSecureStorageLinuxPlugin *self,
87
+ FlMethodCall *method_call) {
88
+ g_autoptr(FlMethodResponse) response = nullptr;
89
+
90
+ const gchar *method = fl_method_call_get_name(method_call);
91
+ FlValue *args = fl_method_call_get_args(method_call);
92
+
93
+ if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
94
+ response = BuildErrorResponse("Bad arguments",
95
+ "args given to function is not a map");
96
+ fl_method_call_respond(method_call, response, nullptr);
97
+ return;
98
+ }
99
+
100
+ FlValue *key = fl_value_lookup_string(args, "key");
101
+ FlValue *value = fl_value_lookup_string(args, "value");
102
+ const gchar *key_string = key == nullptr ? nullptr : fl_value_get_string(key);
103
+ const gchar *value_string =
104
+ value == nullptr ? nullptr : fl_value_get_string(value);
105
+
106
+ g_autoptr(GKeyFile) key_file = LoadKeyFile();
107
+
108
+ if (strcmp(method, "write") == 0) {
109
+ if (key_string == nullptr || value_string == nullptr) {
110
+ response = BuildErrorResponse("Bad arguments", "Key or Value was null");
111
+ } else {
112
+ g_key_file_set_string(key_file, kGroupName, key_string, value_string);
113
+ gchar *error_message = nullptr;
114
+ if (!SaveKeyFile(key_file, &error_message)) {
115
+ response = BuildErrorResponse("Storage error", error_message);
116
+ g_free(error_message);
117
+ } else {
118
+ response = FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
119
+ }
120
+ }
121
+ } else if (strcmp(method, "read") == 0) {
122
+ if (key_string == nullptr) {
123
+ response = BuildErrorResponse("Bad arguments", "Key is null");
124
+ } else if (!g_key_file_has_key(key_file, kGroupName, key_string, nullptr)) {
125
+ response = FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
126
+ } else {
127
+ gchar *stored_value = g_key_file_get_string(key_file, kGroupName, key_string, nullptr);
128
+ g_autoptr(FlValue) result = fl_value_new_string(stored_value);
129
+ g_free(stored_value);
130
+ response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
131
+ }
132
+ } else if (strcmp(method, "readAll") == 0) {
133
+ gsize key_count = 0;
134
+ g_auto(GStrv) keys = g_key_file_get_keys(key_file, kGroupName, &key_count, nullptr);
135
+ g_autoptr(FlValue) result = fl_value_new_map();
136
+ for (gsize i = 0; i < key_count; ++i) {
137
+ gchar *stored_value = g_key_file_get_string(key_file, kGroupName, keys[i], nullptr);
138
+ fl_value_set_string_take(result, keys[i], fl_value_new_string(stored_value));
139
+ g_free(stored_value);
140
+ }
141
+ response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
142
+ } else if (strcmp(method, "delete") == 0) {
143
+ if (key_string == nullptr) {
144
+ response = BuildErrorResponse("Bad arguments", "Key is null");
145
+ } else {
146
+ g_key_file_remove_key(key_file, kGroupName, key_string, nullptr);
147
+ gchar *error_message = nullptr;
148
+ if (!SaveKeyFile(key_file, &error_message)) {
149
+ response = BuildErrorResponse("Storage error", error_message);
150
+ g_free(error_message);
151
+ } else {
152
+ response = FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
153
+ }
154
+ }
155
+ } else if (strcmp(method, "deleteAll") == 0) {
156
+ g_key_file_remove_group(key_file, kGroupName, nullptr);
157
+ gchar *error_message = nullptr;
158
+ if (!SaveKeyFile(key_file, &error_message)) {
159
+ response = BuildErrorResponse("Storage error", error_message);
160
+ g_free(error_message);
161
+ } else {
162
+ response = FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
163
+ }
164
+ } else if (strcmp(method, "containsKey") == 0) {
165
+ if (key_string == nullptr) {
166
+ response = BuildErrorResponse("Bad arguments", "Key is null");
167
+ } else {
168
+ g_autoptr(FlValue) result =
169
+ fl_value_new_bool(g_key_file_has_key(key_file, kGroupName, key_string, nullptr));
170
+ response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
171
+ }
172
+ } else {
173
+ response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
174
+ }
175
+
176
+ fl_method_call_respond(method_call, response, nullptr);
177
+ }
178
+
179
+ static void flutter_secure_storage_linux_plugin_dispose(GObject *object) {
180
+ G_OBJECT_CLASS(flutter_secure_storage_linux_plugin_parent_class)
181
+ ->dispose(object);
182
+ }
183
+
184
+ static void flutter_secure_storage_linux_plugin_class_init(
185
+ FlutterSecureStorageLinuxPluginClass *klass) {
186
+ G_OBJECT_CLASS(klass)->dispose =
187
+ flutter_secure_storage_linux_plugin_dispose;
188
+ }
189
+
190
+ static void flutter_secure_storage_linux_plugin_init(
191
+ FlutterSecureStorageLinuxPlugin *self) {}
192
+
193
+ static void method_call_cb(FlMethodChannel *channel,
194
+ FlMethodCall *method_call,
195
+ gpointer user_data) {
196
+ FlutterSecureStorageLinuxPlugin *plugin =
197
+ flutter_secure_storage_linux_plugin(user_data);
198
+ flutter_secure_storage_linux_plugin_handle_method_call(plugin, method_call);
199
+ }
200
+
201
+ void flutter_secure_storage_linux_plugin_register_with_registrar(
202
+ FlPluginRegistrar *registrar) {
203
+ FlutterSecureStorageLinuxPlugin *plugin =
204
+ flutter_secure_storage_linux_plugin(
205
+ g_object_new(flutter_secure_storage_linux_plugin_get_type(), nullptr));
206
+
207
+ g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
208
+ g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
209
+ fl_plugin_registrar_get_messenger(registrar),
210
+ kChannelName,
211
+ FL_METHOD_CODEC(codec));
212
+ fl_method_channel_set_method_call_handler(
213
+ channel, method_call_cb, g_object_ref(plugin), g_object_unref);
214
+ g_object_unref(plugin);
215
+ }
@@ -0,0 +1,27 @@
1
+ #ifndef FLUTTER_PLUGIN_FLUTTER_SECURE_STORAGE_LINUX_PLUGIN_H_
2
+ #define FLUTTER_PLUGIN_FLUTTER_SECURE_STORAGE_LINUX_PLUGIN_H_
3
+
4
+ #include <flutter_linux/flutter_linux.h>
5
+
6
+ G_BEGIN_DECLS
7
+
8
+ #ifdef FLUTTER_PLUGIN_IMPL
9
+ #define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default")))
10
+ #else
11
+ #define FLUTTER_PLUGIN_EXPORT
12
+ #endif
13
+
14
+ typedef struct _FlutterSecureStorageLinuxPlugin FlutterSecureStorageLinuxPlugin;
15
+ typedef struct {
16
+ GObjectClass parent_class;
17
+ } FlutterSecureStorageLinuxPluginClass;
18
+
19
+ FLUTTER_PLUGIN_EXPORT GType flutter_secure_storage_linux_plugin_get_type();
20
+
21
+ FLUTTER_PLUGIN_EXPORT void
22
+ flutter_secure_storage_linux_plugin_register_with_registrar(
23
+ FlPluginRegistrar *registrar);
24
+
25
+ G_END_DECLS
26
+
27
+ #endif
@@ -0,0 +1,20 @@
1
+ name: flutter_secure_storage_linux
2
+ description: Local Linux implementation of flutter_secure_storage without libsecret.
3
+ version: 1.2.3
4
+ publish_to: none
5
+
6
+ environment:
7
+ sdk: ">=3.0.0 <4.0.0"
8
+ flutter: ">=3.0.0"
9
+
10
+ dependencies:
11
+ flutter:
12
+ sdk: flutter
13
+ flutter_secure_storage_platform_interface: ^1.1.2
14
+
15
+ flutter:
16
+ plugin:
17
+ implements: flutter_secure_storage
18
+ platforms:
19
+ linux:
20
+ pluginClass: FlutterSecureStorageLinuxPlugin
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env python3
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ from pathlib import Path
7
+
8
+ from PIL import Image, ImageDraw, ImageFilter
9
+
10
+
11
+ ROOT = Path(__file__).resolve().parents[1]
12
+ BRANDING_DIR = ROOT / "assets" / "branding"
13
+ WEB_DIR = ROOT / "web"
14
+ WEB_ICONS_DIR = WEB_DIR / "icons"
15
+ MAC_ICON_DIR = ROOT / "macos" / "Runner" / "Assets.xcassets" / "AppIcon.appiconset"
16
+ WINDOWS_ICON_PATH = ROOT / "windows" / "runner" / "resources" / "app_icon.ico"
17
+ LINUX_ICON_DIR = ROOT / "linux" / "runner" / "resources"
18
+ ANDROID_RES_DIR = ROOT / "android" / "app" / "src" / "main" / "res"
19
+ SERVER_PUBLIC_DIR = ROOT.parent / "server" / "public"
20
+ SERVER_PUBLIC_ICONS_DIR = SERVER_PUBLIC_DIR / "icons"
21
+
22
+ ACCENT = (143, 109, 62)
23
+ ACCENT_ALT = (47, 125, 110)
24
+ WHITE = (255, 255, 255, 255)
25
+ TRANSPARENT = (0, 0, 0, 0)
26
+
27
+
28
+ def lerp(a: float, b: float, t: float) -> float:
29
+ return a + (b - a) * t
30
+
31
+
32
+ def gradient_background(size: int) -> Image.Image:
33
+ img = Image.new("RGBA", (size, size), TRANSPARENT)
34
+ px = img.load()
35
+ for y in range(size):
36
+ for x in range(size):
37
+ tx = x / max(size - 1, 1)
38
+ ty = y / max(size - 1, 1)
39
+ t = (tx + ty) / 2
40
+ px[x, y] = (
41
+ int(lerp(ACCENT[0], ACCENT_ALT[0], t)),
42
+ int(lerp(ACCENT[1], ACCENT_ALT[1], t)),
43
+ int(lerp(ACCENT[2], ACCENT_ALT[2], t)),
44
+ 255,
45
+ )
46
+ return img
47
+
48
+
49
+ def logo_paths(size: int, padding_ratio: float = 0.18):
50
+ pad = size * padding_ratio
51
+ inner = size - pad * 2
52
+ def point(x: float, y: float) -> tuple[float, float]:
53
+ return (pad + inner * x, pad + inner * y)
54
+
55
+ top = [point(0.5, 0.08), point(0.1, 0.3), point(0.5, 0.52), point(0.9, 0.3)]
56
+ middle = [point(0.1, 0.52), point(0.5, 0.74), point(0.9, 0.52)]
57
+ bottom = [point(0.1, 0.72), point(0.5, 0.94), point(0.9, 0.72)]
58
+ return top, middle, bottom, inner
59
+
60
+
61
+ def draw_logo(draw: ImageDraw.ImageDraw, size: int, color: tuple[int, int, int, int]) -> None:
62
+ top, middle, bottom, inner = logo_paths(size)
63
+ stroke = max(2, round(inner * 0.08))
64
+ draw.polygon(top, fill=color)
65
+ draw.line(middle, fill=color, width=stroke, joint="curve")
66
+ draw.line(bottom, fill=color, width=stroke, joint="curve")
67
+
68
+
69
+ def make_app_icon(size: int) -> Image.Image:
70
+ canvas = Image.new("RGBA", (size, size), TRANSPARENT)
71
+
72
+ shadow = Image.new("RGBA", (size, size), TRANSPARENT)
73
+ shadow_draw = ImageDraw.Draw(shadow)
74
+ offset_y = size * 0.02
75
+ corner = round(size * 0.34)
76
+ shadow_draw.rounded_rectangle(
77
+ (size * 0.07, size * 0.07 + offset_y, size * 0.93, size * 0.93 + offset_y),
78
+ radius=corner,
79
+ fill=(0, 0, 0, 72),
80
+ )
81
+ shadow = shadow.filter(ImageFilter.GaussianBlur(radius=max(2, size * 0.04)))
82
+ canvas.alpha_composite(shadow)
83
+
84
+ base_mask = Image.new("L", (size, size), 0)
85
+ mask_draw = ImageDraw.Draw(base_mask)
86
+ base_rect = (size * 0.08, size * 0.08, size * 0.92, size * 0.92)
87
+ mask_draw.rounded_rectangle(base_rect, radius=corner, fill=255)
88
+
89
+ base = gradient_background(size)
90
+ clipped = Image.new("RGBA", (size, size), TRANSPARENT)
91
+ clipped.paste(base, mask=base_mask)
92
+ canvas.alpha_composite(clipped)
93
+
94
+ ring = Image.new("RGBA", (size, size), TRANSPARENT)
95
+ ring_draw = ImageDraw.Draw(ring)
96
+ ring_draw.rounded_rectangle(
97
+ base_rect,
98
+ radius=corner,
99
+ outline=(255, 255, 255, 36),
100
+ width=max(1, round(size * 0.012)),
101
+ )
102
+ canvas.alpha_composite(ring)
103
+
104
+ glyph = Image.new("RGBA", (size, size), TRANSPARENT)
105
+ draw = ImageDraw.Draw(glyph)
106
+ draw_logo(draw, size, WHITE)
107
+ canvas.alpha_composite(glyph)
108
+ return canvas
109
+
110
+
111
+ def make_tray_template(size: int = 64) -> Image.Image:
112
+ img = Image.new("RGBA", (size, size), TRANSPARENT)
113
+ draw = ImageDraw.Draw(img)
114
+ draw_logo(draw, size, (0, 0, 0, 255))
115
+ return img
116
+
117
+
118
+ def ensure_dirs() -> None:
119
+ BRANDING_DIR.mkdir(parents=True, exist_ok=True)
120
+ WEB_ICONS_DIR.mkdir(parents=True, exist_ok=True)
121
+ MAC_ICON_DIR.mkdir(parents=True, exist_ok=True)
122
+ LINUX_ICON_DIR.mkdir(parents=True, exist_ok=True)
123
+ SERVER_PUBLIC_ICONS_DIR.mkdir(parents=True, exist_ok=True)
124
+
125
+
126
+ def write_text(path: Path, content: str) -> None:
127
+ path.write_text(content, encoding="utf-8")
128
+
129
+
130
+ def copy_png(image: Image.Image, path: Path, size: int) -> None:
131
+ path.parent.mkdir(parents=True, exist_ok=True)
132
+ save_png(image, path, size)
133
+
134
+
135
+ def write_favicon_svg(path: Path) -> None:
136
+ svg = f"""<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
137
+ <defs>
138
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
139
+ <stop offset="0%" stop-color="#{ACCENT[0]:02x}{ACCENT[1]:02x}{ACCENT[2]:02x}"/>
140
+ <stop offset="100%" stop-color="#{ACCENT_ALT[0]:02x}{ACCENT_ALT[1]:02x}{ACCENT_ALT[2]:02x}"/>
141
+ </linearGradient>
142
+ </defs>
143
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#bg)" stroke="#ffffff" stroke-opacity="0.16" stroke-width="1"/>
144
+ <polygon points="16,5.7 5.2,11.6 16,17.6 26.8,11.6" fill="white"/>
145
+ <polyline points="5.2,17.6 16,23.5 26.8,17.6" fill="none" stroke="white" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
146
+ <polyline points="5.2,22.7 16,28.1 26.8,22.7" fill="none" stroke="white" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
147
+ </svg>
148
+ """
149
+ write_text(path, svg)
150
+
151
+
152
+ def save_png(image: Image.Image, path: Path, size: int) -> None:
153
+ image.resize((size, size), Image.Resampling.LANCZOS).save(path, format="PNG")
154
+
155
+
156
+ def main() -> None:
157
+ ensure_dirs()
158
+ master = make_app_icon(1024)
159
+
160
+ save_png(master, BRANDING_DIR / "app_icon_1024.png", 1024)
161
+ save_png(master, BRANDING_DIR / "app_icon_512.png", 512)
162
+ save_png(master, BRANDING_DIR / "app_icon_256.png", 256)
163
+ save_png(master, BRANDING_DIR / "app_icon_192.png", 192)
164
+ save_png(master, BRANDING_DIR / "app_icon_128.png", 128)
165
+ save_png(master, BRANDING_DIR / "app_icon_64.png", 64)
166
+ save_png(master, BRANDING_DIR / "app_icon_32.png", 32)
167
+
168
+ tray = make_tray_template(64)
169
+ save_png(tray, BRANDING_DIR / "tray_icon_template.png", 64)
170
+
171
+ icon_sizes = {
172
+ 16: "app_icon_16.png",
173
+ 32: "app_icon_32.png",
174
+ 64: "app_icon_64.png",
175
+ 128: "app_icon_128.png",
176
+ 256: "app_icon_256.png",
177
+ 512: "app_icon_512.png",
178
+ 1024: "app_icon_1024.png",
179
+ }
180
+ for size, filename in icon_sizes.items():
181
+ save_png(master, MAC_ICON_DIR / filename, size)
182
+
183
+ save_png(master, LINUX_ICON_DIR / "app_icon.png", 256)
184
+
185
+ master_for_ico = master.resize((256, 256), Image.Resampling.LANCZOS)
186
+ master_for_ico.save(
187
+ WINDOWS_ICON_PATH,
188
+ format="ICO",
189
+ sizes=[(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)],
190
+ )
191
+
192
+ web_icon_sizes = {
193
+ 192: "Icon-192.png",
194
+ 512: "Icon-512.png",
195
+ }
196
+ for size, filename in web_icon_sizes.items():
197
+ copy_png(master, WEB_ICONS_DIR / filename, size)
198
+ copy_png(master, WEB_ICONS_DIR / filename.replace("Icon-", "Icon-maskable-"), size)
199
+ copy_png(master, SERVER_PUBLIC_ICONS_DIR / filename, size)
200
+ copy_png(master, SERVER_PUBLIC_ICONS_DIR / filename.replace("Icon-", "Icon-maskable-"), size)
201
+
202
+ copy_png(master, WEB_DIR / "favicon.png", 32)
203
+ copy_png(master, SERVER_PUBLIC_DIR / "favicon.png", 32)
204
+ write_favicon_svg(WEB_DIR / "favicon.svg")
205
+ write_favicon_svg(SERVER_PUBLIC_DIR / "favicon.svg")
206
+
207
+ android_icon_sizes = {
208
+ "mipmap-mdpi": 48,
209
+ "mipmap-hdpi": 72,
210
+ "mipmap-xhdpi": 96,
211
+ "mipmap-xxhdpi": 144,
212
+ "mipmap-xxxhdpi": 192,
213
+ }
214
+ for folder, size in android_icon_sizes.items():
215
+ copy_png(master, ANDROID_RES_DIR / folder / "ic_launcher.png", size)
216
+
217
+
218
+ if __name__ == "__main__":
219
+ main()
Binary file
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" stop-color="#8f6d3e"/>
5
+ <stop offset="100%" stop-color="#2f7d6e"/>
6
+ </linearGradient>
7
+ </defs>
8
+ <rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#bg)" stroke="#ffffff" stroke-opacity="0.16" stroke-width="1"/>
9
+ <polygon points="16,5.7 5.2,11.6 16,17.6 26.8,11.6" fill="white"/>
10
+ <polyline points="5.2,17.6 16,23.5 26.8,17.6" fill="none" stroke="white" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
11
+ <polyline points="5.2,22.7 16,28.1 26.8,22.7" fill="none" stroke="white" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
12
+ </svg>
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <!--
5
+ If you are serving your web app in a path other than the root, change the
6
+ href value below to reflect the base path you are serving from.
7
+
8
+ The path provided below has to start and end with a slash "/" in order for
9
+ it to work correctly.
10
+
11
+ For more details:
12
+ * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
13
+
14
+ This is a placeholder for base href that will be replaced by the value of
15
+ the `--base-href` argument provided to `flutter build`.
16
+ -->
17
+ <base href="$FLUTTER_BASE_HREF">
18
+
19
+ <meta charset="UTF-8">
20
+ <meta content="IE=Edge" http-equiv="X-UA-Compatible">
21
+ <meta name="description" content="NeoAgent Flutter client for web and Android.">
22
+
23
+ <!-- iOS meta tags & icons -->
24
+ <meta name="mobile-web-app-capable" content="yes">
25
+ <meta name="apple-mobile-web-app-status-bar-style" content="black">
26
+ <meta name="apple-mobile-web-app-title" content="NeoAgent">
27
+ <link rel="apple-touch-icon" href="icons/Icon-192.png">
28
+
29
+ <!-- Favicon -->
30
+ <link rel="icon" type="image/svg+xml" href="favicon.svg"/>
31
+ <link rel="icon" type="image/png" href="favicon.png"/>
32
+
33
+ <title>NeoAgent</title>
34
+ <link rel="manifest" href="manifest.json">
35
+ </head>
36
+ <body>
37
+ <script src="flutter_bootstrap.js" async></script>
38
+ </body>
39
+ </html>