neoagent 2.3.1-beta.2 → 2.3.1-beta.21
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.
- package/.env.example +39 -0
- package/README.md +2 -0
- package/docs/capabilities.md +2 -2
- package/docs/configuration.md +13 -5
- package/docs/integrations.md +4 -1
- package/flutter_app/.metadata +42 -0
- package/flutter_app/README.md +21 -0
- package/flutter_app/analysis_options.yaml +32 -0
- package/flutter_app/android/app/build.gradle.kts +109 -0
- package/flutter_app/android/app/src/debug/AndroidManifest.xml +7 -0
- package/flutter_app/android/app/src/main/AndroidManifest.xml +147 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/MainActivity.kt +747 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthConnectGateway.kt +280 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncNotifications.kt +113 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncPayload.kt +57 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncScheduler.kt +78 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/HealthSyncWorker.kt +253 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/health/PermissionsRationaleActivity.kt +46 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingBootReceiver.kt +21 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingForegroundService.kt +586 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingStateStore.kt +78 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/recording/RecordingUploadClient.kt +104 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/AiHomeWidgetProvider.kt +457 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/AiWidgetStore.kt +194 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/VoiceLaunchWidgetProvider.kt +67 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetConfigActivity.kt +228 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetSyncScheduler.kt +72 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetSyncWorker.kt +186 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/widgets/WidgetTaskRunWorker.kt +210 -0
- package/flutter_app/android/app/src/main/res/drawable/launch_background.xml +12 -0
- package/flutter_app/android/app/src/main/res/drawable/neoagent_ai_widget_bg.xml +11 -0
- package/flutter_app/android/app/src/main/res/drawable/neoagent_ai_widget_task_bg.xml +8 -0
- package/flutter_app/android/app/src/main/res/drawable-v21/launch_background.xml +12 -0
- package/flutter_app/android/app/src/main/res/layout/neoagent_ai_widget.xml +138 -0
- package/flutter_app/android/app/src/main/res/layout/neoagent_ai_widget_task_row.xml +52 -0
- package/flutter_app/android/app/src/main/res/layout/neoagent_voice_widget.xml +49 -0
- package/flutter_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/values/strings.xml +12 -0
- package/flutter_app/android/app/src/main/res/values/styles.xml +18 -0
- package/flutter_app/android/app/src/main/res/values-night/styles.xml +18 -0
- package/flutter_app/android/app/src/main/res/xml/file_paths.xml +6 -0
- package/flutter_app/android/app/src/main/res/xml/neoagent_ai_widget_info.xml +12 -0
- package/flutter_app/android/app/src/main/res/xml/neoagent_voice_widget_info.xml +12 -0
- package/flutter_app/android/app/src/profile/AndroidManifest.xml +7 -0
- package/flutter_app/android/build.gradle.kts +24 -0
- package/flutter_app/android/ci-release.keystore +0 -0
- package/flutter_app/android/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/flutter_app/android/gradle.properties +3 -0
- package/flutter_app/android/key.properties +4 -0
- package/flutter_app/android/settings.gradle.kts +26 -0
- package/flutter_app/assets/branding/app_icon_1024.png +0 -0
- package/flutter_app/assets/branding/app_icon_128.png +0 -0
- package/flutter_app/assets/branding/app_icon_192.png +0 -0
- package/flutter_app/assets/branding/app_icon_256.png +0 -0
- package/flutter_app/assets/branding/app_icon_32.png +0 -0
- package/flutter_app/assets/branding/app_icon_512.png +0 -0
- package/flutter_app/assets/branding/app_icon_64.png +0 -0
- package/flutter_app/assets/branding/tray_icon_template.png +0 -0
- package/flutter_app/lib/features/location/location_service.dart +119 -0
- package/flutter_app/lib/features/notifications/notification_interceptor.dart +97 -0
- package/flutter_app/lib/main.dart +23057 -0
- package/flutter_app/lib/main_app_shell.dart +1682 -0
- package/flutter_app/lib/main_integrations.dart +931 -0
- package/flutter_app/lib/main_launcher.dart +959 -0
- package/flutter_app/lib/main_launcher_entry.dart +5 -0
- package/flutter_app/lib/main_models.dart +3473 -0
- package/flutter_app/lib/main_shared.dart +2861 -0
- package/flutter_app/lib/main_theme.dart +204 -0
- package/flutter_app/lib/main_voice_assistant.dart +831 -0
- package/flutter_app/lib/src/android_apk_drop_zone.dart +32 -0
- package/flutter_app/lib/src/android_apk_drop_zone_stub.dart +16 -0
- package/flutter_app/lib/src/android_apk_drop_zone_web.dart +348 -0
- package/flutter_app/lib/src/android_app_installer.dart +22 -0
- package/flutter_app/lib/src/android_app_installer_io.dart +122 -0
- package/flutter_app/lib/src/android_app_installer_stub.dart +21 -0
- package/flutter_app/lib/src/android_launcher_bridge.dart +239 -0
- package/flutter_app/lib/src/app_launch_bridge.dart +29 -0
- package/flutter_app/lib/src/app_release_updater.dart +511 -0
- package/flutter_app/lib/src/backend_client.dart +1833 -0
- package/flutter_app/lib/src/desktop_companion.dart +2 -0
- package/flutter_app/lib/src/desktop_companion_actions.dart +586 -0
- package/flutter_app/lib/src/desktop_companion_io.dart +538 -0
- package/flutter_app/lib/src/desktop_companion_stub.dart +59 -0
- package/flutter_app/lib/src/desktop_native_bridge.dart +91 -0
- package/flutter_app/lib/src/desktop_screen_capture.dart +21 -0
- package/flutter_app/lib/src/desktop_screen_capture_io.dart +142 -0
- package/flutter_app/lib/src/desktop_screen_capture_stub.dart +12 -0
- package/flutter_app/lib/src/diagnostics_logger.dart +119 -0
- package/flutter_app/lib/src/health_bridge.dart +136 -0
- package/flutter_app/lib/src/live_voice_capture.dart +85 -0
- package/flutter_app/lib/src/messaging_access_summary.dart +46 -0
- package/flutter_app/lib/src/network/app_http_client.dart +53 -0
- package/flutter_app/lib/src/network/app_http_client_factory.dart +6 -0
- package/flutter_app/lib/src/network/app_http_client_io.dart +138 -0
- package/flutter_app/lib/src/network/app_http_client_stub.dart +3 -0
- package/flutter_app/lib/src/network/app_http_client_web.dart +94 -0
- package/flutter_app/lib/src/oauth_launcher.dart +33 -0
- package/flutter_app/lib/src/oauth_launcher_io.dart +77 -0
- package/flutter_app/lib/src/oauth_launcher_stub.dart +33 -0
- package/flutter_app/lib/src/oauth_launcher_web.dart +107 -0
- package/flutter_app/lib/src/recording_bridge.dart +232 -0
- package/flutter_app/lib/src/recording_bridge_io.dart +1019 -0
- package/flutter_app/lib/src/recording_bridge_stub.dart +120 -0
- package/flutter_app/lib/src/recording_bridge_web.dart +689 -0
- package/flutter_app/lib/src/recording_payloads.dart +86 -0
- package/flutter_app/lib/src/theme/palette.dart +81 -0
- package/flutter_app/lib/src/widget_bridge.dart +49 -0
- package/flutter_app/linux/CMakeLists.txt +128 -0
- package/flutter_app/linux/flutter/CMakeLists.txt +88 -0
- package/flutter_app/linux/flutter/generated_plugin_registrant.cc +43 -0
- package/flutter_app/linux/flutter/generated_plugin_registrant.h +15 -0
- package/flutter_app/linux/flutter/generated_plugins.cmake +31 -0
- package/flutter_app/linux/runner/CMakeLists.txt +26 -0
- package/flutter_app/linux/runner/main.cc +6 -0
- package/flutter_app/linux/runner/my_application.cc +144 -0
- package/flutter_app/linux/runner/my_application.h +18 -0
- package/flutter_app/linux/runner/resources/app_icon.png +0 -0
- package/flutter_app/macos/Flutter/Flutter-Debug.xcconfig +2 -0
- package/flutter_app/macos/Flutter/Flutter-Release.xcconfig +2 -0
- package/flutter_app/macos/Flutter/GeneratedPluginRegistrant.swift +40 -0
- package/flutter_app/macos/Podfile +42 -0
- package/flutter_app/macos/Podfile.lock +87 -0
- package/flutter_app/macos/Runner/AppDelegate.swift +576 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
- package/flutter_app/macos/Runner/Base.lproj/MainMenu.xib +342 -0
- package/flutter_app/macos/Runner/Configs/AppInfo.xcconfig +14 -0
- package/flutter_app/macos/Runner/Configs/Debug.xcconfig +2 -0
- package/flutter_app/macos/Runner/Configs/Release.xcconfig +2 -0
- package/flutter_app/macos/Runner/Configs/Warnings.xcconfig +13 -0
- package/flutter_app/macos/Runner/DebugProfile.entitlements +16 -0
- package/flutter_app/macos/Runner/Info.plist +36 -0
- package/flutter_app/macos/Runner/MainFlutterWindow.swift +19 -0
- package/flutter_app/macos/Runner/Release.entitlements +12 -0
- package/flutter_app/macos/Runner.xcodeproj/project.pbxproj +801 -0
- package/flutter_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/flutter_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +99 -0
- package/flutter_app/macos/Runner.xcworkspace/contents.xcworkspacedata +10 -0
- package/flutter_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/flutter_app/macos/RunnerTests/RunnerTests.swift +12 -0
- package/flutter_app/patch_strings.py +12 -0
- package/flutter_app/pubspec.lock +1088 -0
- package/flutter_app/pubspec.yaml +53 -0
- package/flutter_app/test/messaging_access_summary_test.dart +22 -0
- package/flutter_app/test/recording_payloads_test.dart +53 -0
- package/flutter_app/third_party/desktop_audio_capture/LICENSE +21 -0
- package/flutter_app/third_party/desktop_audio_capture/README.md +262 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/audio_capture.dart +65 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/config/mic_audio_config.dart +153 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/config/system_adudio_config.dart +110 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/mic/mic_audio_capture.dart +461 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/model/audio_status.dart +91 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/model/decibel_data.dart +106 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/model/input_device_type.dart +219 -0
- package/flutter_app/third_party/desktop_audio_capture/lib/system/system_audio_capture.dart +336 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/CMakeLists.txt +101 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/audio_capture_plugin.cc +692 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/audio_capture_plugin.h +35 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/include/audio_capture/mic_capture_plugin.h +36 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/audio_capture_plugin.h +32 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/include/desktop_audio_capture/mic_capture_plugin.h +32 -0
- package/flutter_app/third_party/desktop_audio_capture/linux/mic_capture_plugin.cc +878 -0
- package/flutter_app/third_party/desktop_audio_capture/macos/Classes/AudioCapturePlugin.swift +27 -0
- package/flutter_app/third_party/desktop_audio_capture/macos/Classes/MicCapturePlugin.swift +1172 -0
- package/flutter_app/third_party/desktop_audio_capture/macos/Classes/SystemCapturePlugin.swift +655 -0
- package/flutter_app/third_party/desktop_audio_capture/macos/Resources/PrivacyInfo.xcprivacy +12 -0
- package/flutter_app/third_party/desktop_audio_capture/macos/desktop_audio_capture.podspec +30 -0
- package/flutter_app/third_party/desktop_audio_capture/pubspec.yaml +87 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/CMakeLists.txt +105 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.cpp +80 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin.h +31 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/audio_capture_plugin_c_api.cpp +12 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/include/audio_capture/audio_capture_plugin_c_api.h +23 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/include/desktop_audio_capture/audio_capture_plugin.h +25 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.cpp +1117 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/mic_capture_plugin.h +115 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.cpp +777 -0
- package/flutter_app/third_party/desktop_audio_capture/windows/system_audio_capture_plugin.h +87 -0
- package/flutter_app/third_party/flutter_secure_storage_linux/linux/CMakeLists.txt +30 -0
- package/flutter_app/third_party/flutter_secure_storage_linux/linux/flutter_secure_storage_linux_plugin.cc +215 -0
- package/flutter_app/third_party/flutter_secure_storage_linux/linux/include/flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h +27 -0
- package/flutter_app/third_party/flutter_secure_storage_linux/pubspec.yaml +20 -0
- package/flutter_app/tool/generate_desktop_branding.py +219 -0
- package/flutter_app/web/favicon.png +0 -0
- package/flutter_app/web/favicon.svg +12 -0
- package/flutter_app/web/icons/Icon-192.png +0 -0
- package/flutter_app/web/icons/Icon-512.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-192.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-512.png +0 -0
- package/flutter_app/web/index.html +39 -0
- package/flutter_app/web/manifest.json +35 -0
- package/flutter_app/windows/CMakeLists.txt +108 -0
- package/flutter_app/windows/flutter/CMakeLists.txt +109 -0
- package/flutter_app/windows/flutter/generated_plugin_registrant.cc +47 -0
- package/flutter_app/windows/flutter/generated_plugin_registrant.h +15 -0
- package/flutter_app/windows/flutter/generated_plugins.cmake +35 -0
- package/flutter_app/windows/runner/CMakeLists.txt +41 -0
- package/flutter_app/windows/runner/Runner.rc +121 -0
- package/flutter_app/windows/runner/flutter_window.cpp +533 -0
- package/flutter_app/windows/runner/flutter_window.h +37 -0
- package/flutter_app/windows/runner/main.cpp +53 -0
- package/flutter_app/windows/runner/resource.h +16 -0
- package/flutter_app/windows/runner/resources/app_icon.ico +0 -0
- package/flutter_app/windows/runner/runner.exe.manifest +14 -0
- package/flutter_app/windows/runner/utils.cpp +65 -0
- package/flutter_app/windows/runner/utils.h +19 -0
- package/flutter_app/windows/runner/win32_window.cpp +299 -0
- package/flutter_app/windows/runner/win32_window.h +102 -0
- package/lib/manager.js +231 -7
- package/package.json +3 -1
- package/server/db/database.js +68 -0
- package/server/http/middleware.js +50 -0
- package/server/http/routes.js +3 -1
- package/server/index.js +1 -0
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/NOTICES +61 -0
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +65262 -64422
- package/server/routes/integrations.js +86 -0
- package/server/routes/memory.js +11 -2
- package/server/routes/screenHistory.js +46 -0
- package/server/routes/triggers.js +81 -0
- package/server/services/ai/models.js +30 -0
- package/server/services/ai/providers/githubCopilot.js +97 -0
- package/server/services/ai/providers/openai.js +2 -1
- package/server/services/ai/providers/openaiCodex.js +31 -0
- package/server/services/ai/settings.js +20 -0
- package/server/services/ai/systemPrompt.js +1 -1
- package/server/services/ai/tools.js +35 -6
- package/server/services/browser/controller.js +47 -3
- package/server/services/desktop/screenRecorder.js +172 -0
- package/server/services/integrations/env.js +5 -0
- package/server/services/integrations/github/common.js +106 -0
- package/server/services/integrations/github/provider.js +499 -0
- package/server/services/integrations/github/repos.js +1124 -0
- package/server/services/integrations/home_assistant/provider.js +306 -26
- package/server/services/integrations/manager.js +63 -7
- package/server/services/integrations/oauth_provider.js +13 -6
- package/server/services/integrations/provider_config_store.js +76 -0
- package/server/services/integrations/registry.js +4 -0
- package/server/services/integrations/trello/provider.js +744 -0
- package/server/services/integrations/whatsapp/provider.js +6 -2
- package/server/services/manager.js +22 -0
- package/server/services/memory/manager.js +39 -2
- package/server/services/skills/base_catalog.js +33 -0
- package/server/services/tasks/adapters/index.js +1 -0
- package/server/services/tasks/adapters/manual.js +12 -0
- package/server/services/tasks/runtime.js +1 -1
- package/server/services/voice/openaiClient.js +4 -1
- package/server/services/voice/providers.js +2 -1
- package/server/services/widgets/service.js +49 -4
- package/server/utils/local_secrets.js +56 -0
- 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>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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>
|