From ddf3829cda14dd52b1dbb504779d7abf3952ae5f Mon Sep 17 00:00:00 2001 From: Tristan Michael Date: Thu, 2 Apr 2026 08:10:30 -0700 Subject: [PATCH] remove flutter --- CLAUDE.md | 5 +- Cargo.toml | 1 - PLAN.md | 59 +- apps/flutter/.gitignore | 54 - apps/flutter/.metadata | 30 - apps/flutter/README.md | 17 - apps/flutter/analysis_options.yaml | 28 - apps/flutter/flutter_rust_bridge.yaml | 3 - apps/flutter/lib/main.dart | 227 -- apps/flutter/lib/src/rust/api.dart | 312 -- apps/flutter/lib/src/rust/frb_generated.dart | 1566 ---------- .../lib/src/rust/frb_generated.io.dart | 234 -- .../lib/src/rust/frb_generated.web.dart | 234 -- .../lib/src/screens/settings_screen.dart | 372 --- .../flutter/lib/src/screens/setup_screen.dart | 155 - .../flutter/lib/src/screens/tasks_screen.dart | 874 ------ apps/flutter/lib/src/state/app_state.dart | 322 -- apps/flutter/lib/src/theme.dart | 46 - .../lib/src/widgets/custom_title_bar.dart | 101 - .../lib/src/widgets/date_time_picker.dart | 209 -- .../lib/src/widgets/new_task_input.dart | 201 -- .../lib/src/widgets/task_detail_view.dart | 430 --- apps/flutter/lib/src/widgets/task_item.dart | 179 -- apps/flutter/linux/.gitignore | 1 - apps/flutter/linux/CMakeLists.txt | 155 - apps/flutter/linux/flutter/CMakeLists.txt | 88 - .../flutter/generated_plugin_registrant.cc | 19 - .../flutter/generated_plugin_registrant.h | 15 - .../linux/flutter/generated_plugins.cmake | 25 - apps/flutter/linux/runner/CMakeLists.txt | 26 - apps/flutter/linux/runner/main.cc | 6 - apps/flutter/linux/runner/my_application.cc | 130 - apps/flutter/linux/runner/my_application.h | 21 - apps/flutter/pubspec.lock | 538 ---- apps/flutter/pubspec.yaml | 24 - apps/flutter/rust/Cargo.lock | 2767 ----------------- apps/flutter/rust/Cargo.toml | 17 - apps/flutter/rust/src/api.rs | 422 --- apps/flutter/rust/src/frb_generated.rs | 1505 --------- apps/flutter/rust/src/lib.rs | 2 - apps/flutter/test/widget_test.dart | 30 - apps/flutter/windows/.gitignore | 17 - apps/flutter/windows/CMakeLists.txt | 108 - apps/flutter/windows/flutter/CMakeLists.txt | 109 - .../flutter/generated_plugin_registrant.cc | 17 - .../flutter/generated_plugin_registrant.h | 15 - .../windows/flutter/generated_plugins.cmake | 25 - apps/flutter/windows/runner/CMakeLists.txt | 40 - apps/flutter/windows/runner/Runner.rc | 121 - .../flutter/windows/runner/flutter_window.cpp | 71 - apps/flutter/windows/runner/flutter_window.h | 33 - apps/flutter/windows/runner/main.cpp | 43 - apps/flutter/windows/runner/resource.h | 16 - .../windows/runner/resources/app_icon.ico | Bin 33772 -> 0 bytes .../windows/runner/runner.exe.manifest | 14 - apps/flutter/windows/runner/utils.cpp | 65 - apps/flutter/windows/runner/utils.h | 19 - apps/flutter/windows/runner/win32_window.cpp | 288 -- apps/flutter/windows/runner/win32_window.h | 102 - 59 files changed, 5 insertions(+), 12548 deletions(-) delete mode 100644 apps/flutter/.gitignore delete mode 100644 apps/flutter/.metadata delete mode 100644 apps/flutter/README.md delete mode 100644 apps/flutter/analysis_options.yaml delete mode 100644 apps/flutter/flutter_rust_bridge.yaml delete mode 100644 apps/flutter/lib/main.dart delete mode 100644 apps/flutter/lib/src/rust/api.dart delete mode 100644 apps/flutter/lib/src/rust/frb_generated.dart delete mode 100644 apps/flutter/lib/src/rust/frb_generated.io.dart delete mode 100644 apps/flutter/lib/src/rust/frb_generated.web.dart delete mode 100644 apps/flutter/lib/src/screens/settings_screen.dart delete mode 100644 apps/flutter/lib/src/screens/setup_screen.dart delete mode 100644 apps/flutter/lib/src/screens/tasks_screen.dart delete mode 100644 apps/flutter/lib/src/state/app_state.dart delete mode 100644 apps/flutter/lib/src/theme.dart delete mode 100644 apps/flutter/lib/src/widgets/custom_title_bar.dart delete mode 100644 apps/flutter/lib/src/widgets/date_time_picker.dart delete mode 100644 apps/flutter/lib/src/widgets/new_task_input.dart delete mode 100644 apps/flutter/lib/src/widgets/task_detail_view.dart delete mode 100644 apps/flutter/lib/src/widgets/task_item.dart delete mode 100644 apps/flutter/linux/.gitignore delete mode 100644 apps/flutter/linux/CMakeLists.txt delete mode 100644 apps/flutter/linux/flutter/CMakeLists.txt delete mode 100644 apps/flutter/linux/flutter/generated_plugin_registrant.cc delete mode 100644 apps/flutter/linux/flutter/generated_plugin_registrant.h delete mode 100644 apps/flutter/linux/flutter/generated_plugins.cmake delete mode 100644 apps/flutter/linux/runner/CMakeLists.txt delete mode 100644 apps/flutter/linux/runner/main.cc delete mode 100644 apps/flutter/linux/runner/my_application.cc delete mode 100644 apps/flutter/linux/runner/my_application.h delete mode 100644 apps/flutter/pubspec.lock delete mode 100644 apps/flutter/pubspec.yaml delete mode 100644 apps/flutter/rust/Cargo.lock delete mode 100644 apps/flutter/rust/Cargo.toml delete mode 100644 apps/flutter/rust/src/api.rs delete mode 100644 apps/flutter/rust/src/frb_generated.rs delete mode 100644 apps/flutter/rust/src/lib.rs delete mode 100644 apps/flutter/test/widget_test.dart delete mode 100644 apps/flutter/windows/.gitignore delete mode 100644 apps/flutter/windows/CMakeLists.txt delete mode 100644 apps/flutter/windows/flutter/CMakeLists.txt delete mode 100644 apps/flutter/windows/flutter/generated_plugin_registrant.cc delete mode 100644 apps/flutter/windows/flutter/generated_plugin_registrant.h delete mode 100644 apps/flutter/windows/flutter/generated_plugins.cmake delete mode 100644 apps/flutter/windows/runner/CMakeLists.txt delete mode 100644 apps/flutter/windows/runner/Runner.rc delete mode 100644 apps/flutter/windows/runner/flutter_window.cpp delete mode 100644 apps/flutter/windows/runner/flutter_window.h delete mode 100644 apps/flutter/windows/runner/main.cpp delete mode 100644 apps/flutter/windows/runner/resource.h delete mode 100644 apps/flutter/windows/runner/resources/app_icon.ico delete mode 100644 apps/flutter/windows/runner/runner.exe.manifest delete mode 100644 apps/flutter/windows/runner/utils.cpp delete mode 100644 apps/flutter/windows/runner/utils.h delete mode 100644 apps/flutter/windows/runner/win32_window.cpp delete mode 100644 apps/flutter/windows/runner/win32_window.h diff --git a/CLAUDE.md b/CLAUDE.md index ae1093f..e49d19e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -32,8 +32,6 @@ Two-crate workspace (`resolver = "2"`, edition 2021) plus a Tauri app: - **onyx-core** — Pure Rust library. Storage trait with `FileSystemStorage` implementation, `TaskRepository` (main API), data models, config, error types. No CLI/UI dependencies. `keyring` feature-gated behind `keyring-storage` (default on) for Android compatibility. - **onyx-cli** — CLI frontend using clap. Commands are in `src/commands/` (init, workspace, list, task, group). Output formatting in `src/output.rs`. - **apps/tauri/** — Tauri v2 GUI. Svelte 5 frontend in `src/`, Rust backend in `src-tauri/` with Tauri commands that call into `onyx-core`. `notify` crate feature-gated for Android. -- **apps/flutter/** — Flutter GUI. Dart frontend in `lib/src/`, Rust backend in `rust/` via flutter_rust_bridge FFI into `onyx-core`. - ### Key patterns - **Storage trait** (`storage.rs`): Strategy pattern for task persistence. `FileSystemStorage` reads/writes markdown files with YAML frontmatter and JSON metadata files. @@ -62,7 +60,7 @@ The GUI uses Svelte 5 runes mode (`$state`, `$derived`, `$effect`, `$props()`). - **Phase 1** (Core + CLI): Complete - **Phase 2** (WebDAV sync): Backend done, CLI done, GUI wired (settings auto-populates credentials) -- **Phase 3** (GUI MVP): Complete — both Tauri and Flutter GUIs at feature parity +- **Phase 3** (GUI MVP): Complete - **Phase 4** (Mobile): Tauri Android cfg-gated, needs `tauri android init` + build ### GUI features done @@ -88,7 +86,6 @@ The GUI uses Svelte 5 runes mode (`$state`, `$derived`, `$effect`, `$props()`). - Sync status indicators (last-sync time + upload/download counts chip) - Push/pull/full sync mode selection (session-only, in settings) - Desktop packaging (Linux: AppImage + .deb) -- Flutter GUI at full parity with Tauri (WebDAV UI, has_time, sync status, sync mode) - Tauri desktop-only deps (notify, keyring) feature-gated for Android compilation - Subtask hierarchy: subtask count shown on parent tasks in list, subtask detail via three-panel slide navigation, inline add at top of subtask list (new subtasks prepend), collapsible completed subtasks section, cascade delete (parent deletion removes all subtasks with confirmation warning) - Custom confirmation dialogs (ConfirmDialog component replaces native confirm()) diff --git a/Cargo.toml b/Cargo.toml index 3eda0db..ff4f4c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ members = [ ] exclude = [ "apps/tauri/src-tauri", - "apps/flutter/rust", ] resolver = "2" diff --git a/PLAN.md b/PLAN.md index 437bd2a..b979b76 100644 --- a/PLAN.md +++ b/PLAN.md @@ -735,7 +735,6 @@ WorkspaceConfig { - [ ] Sub-300ms startup time (not yet measured/optimized) - [x] Clean, minimal UI - [ ] Feature parity with CLI -- [x] Flutter GUI at feature parity with Tauri (WebDAV, has_time, sync status, sync mode) ### Build & Release @@ -750,7 +749,7 @@ WorkspaceConfig { ## Phase 4: Mobile Basic Support -**Goal**: Get both GUIs building and running on Android and iOS, validate cross-platform architecture +**Goal**: Get the Tauri GUI building and running on Android and iOS, validate cross-platform architecture ### Why Early Mobile? - De-risk mobile builds early in development @@ -769,55 +768,7 @@ All Android work can be done locally on Linux. iOS must go through CI or a Mac. --- -### Flutter GUI (Priority Path) - -Flutter + flutter_rust_bridge was designed for mobile from the start and is the lower-risk path. - -#### Known Blockers - -**`window_manager` is desktop-only** (`pubspec.yaml` line 13). This package crashes or fails to compile on mobile. Must be gated behind `Platform.isDesktop` checks before any mobile build will succeed. - -**No platform directories exist yet.** `apps/flutter/android/` and `apps/flutter/ios/` have not been generated. Run `flutter create --platforms android,ios .` from `apps/flutter/` to scaffold them. - -#### Android Prerequisites - -1. Android Studio + NDK installed, `ANDROID_HOME` and `NDK_HOME` set -2. `cargo install cargo-ndk` -3. Rust Android targets: `rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android` - -flutter_rust_bridge invokes cargo-ndk automatically during `flutter build apk` — no manual cross-compilation step needed. - -#### Build Commands - -```bash -# Android -cd apps/flutter -flutter build apk # release APK -flutter build apk --debug # debug APK for sideloading - -# iOS (macOS CI only) -flutter build ios --no-codesign # unsigned build for simulator -flutter build ipa # signed IPA for TestFlight -``` - -#### Features - -- [ ] Gate `window_manager` behind `Platform.isDesktop` checks -- [ ] Generate Android platform (`flutter create --platforms android .`) -- [ ] Generate iOS platform (`flutter create --platforms ios .`) -- [ ] Install cargo-ndk + Android Rust targets (Android prereqs) -- [ ] Confirm `flutter build apk` succeeds locally -- [ ] Set up macOS CI for iOS builds -- [ ] Confirm `flutter build ios` succeeds on CI -- [ ] Basic smoke test: app launches, workspace setup, create a task - ---- - -### Tauri GUI - -Tauri v2 has mobile support but it's newer and less mature. Requires more code surgery than Flutter. - -#### Known Blockers +### Known Blockers **`notify` crate doesn't compile for mobile.** The file-watcher subsystem (`notify` + `notify-debouncer-mini` in `Cargo.toml`) does not support Android or iOS targets. The entire file-watcher initialization path must be gated behind `#[cfg(not(mobile))]` before cross-compilation will succeed. @@ -860,7 +811,7 @@ npm run tauri ios build --- -### Shared Mobile Adaptation (Both GUIs) +### Mobile Adaptation **Touch Support**: - Larger touch targets (44pt minimum) @@ -878,11 +829,9 @@ npm run tauri ios build ### Deliverables -- [ ] Flutter APK builds locally on Linux (Android) - [ ] Tauri APK builds locally on Linux (Android) -- [ ] Flutter iOS builds on macOS CI - [ ] Tauri iOS builds on macOS CI -- [ ] Basic task CRUD works on mobile (both GUIs) +- [ ] Basic task CRUD works on mobile - [ ] Validates cross-platform architecture ### Distribution diff --git a/apps/flutter/.gitignore b/apps/flutter/.gitignore deleted file mode 100644 index 89f241f..0000000 --- a/apps/flutter/.gitignore +++ /dev/null @@ -1,54 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ -/coverage/ - -# Generated plugin registrants -**/windows/flutter/generated_plugin_registrant.cc -**/windows/flutter/generated_plugin_registrant.h -**/windows/flutter/generated_plugins.cmake -**/linux/flutter/generated_plugin_registrant.cc -**/linux/flutter/generated_plugin_registrant.h -**/linux/flutter/generated_plugins.cmake - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release diff --git a/apps/flutter/.metadata b/apps/flutter/.metadata deleted file mode 100644 index 9b9642c..0000000 --- a/apps/flutter/.metadata +++ /dev/null @@ -1,30 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "ff37bef603469fb030f2b72995ab929ccfc227f0" - channel: "stable" - -project_type: app - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 - base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 - - platform: windows - create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 - base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/apps/flutter/README.md b/apps/flutter/README.md deleted file mode 100644 index 075c78a..0000000 --- a/apps/flutter/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# onyx - -A new Flutter project. - -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter) -- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. diff --git a/apps/flutter/analysis_options.yaml b/apps/flutter/analysis_options.yaml deleted file mode 100644 index 0d29021..0000000 --- a/apps/flutter/analysis_options.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/apps/flutter/flutter_rust_bridge.yaml b/apps/flutter/flutter_rust_bridge.yaml deleted file mode 100644 index c9690ba..0000000 --- a/apps/flutter/flutter_rust_bridge.yaml +++ /dev/null @@ -1,3 +0,0 @@ -rust_input: crate::api -rust_root: rust/ -dart_output: lib/src/rust diff --git a/apps/flutter/lib/main.dart b/apps/flutter/lib/main.dart deleted file mode 100644 index a9a5683..0000000 --- a/apps/flutter/lib/main.dart +++ /dev/null @@ -1,227 +0,0 @@ -import 'dart:io' show Platform; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:provider/provider.dart'; -import 'package:window_manager/window_manager.dart'; -import 'src/rust/frb_generated.dart'; -import 'src/theme.dart'; -import 'src/state/app_state.dart'; -import 'src/screens/setup_screen.dart'; -import 'src/screens/tasks_screen.dart'; -import 'src/screens/settings_screen.dart'; - -Future main() async { - WidgetsFlutterBinding.ensureInitialized(); - await RustLib.init(); - - await windowManager.ensureInitialized(); - await windowManager.waitUntilReadyToShow( - const WindowOptions( - size: Size(400, 700), - minimumSize: Size(320, 500), - titleBarStyle: TitleBarStyle.hidden, - ), - () async { - await windowManager.setBackgroundColor(Colors.transparent); - await windowManager.setResizable(true); - await windowManager.show(); - await windowManager.focus(); - }, - ); - - runApp( - ChangeNotifierProvider( - create: (_) => AppState()..loadConfig(), - child: const OnyxApp(), - ), - ); -} - -class OnyxApp extends StatelessWidget { - const OnyxApp({super.key}); - - @override - Widget build(BuildContext context) { - final state = context.watch(); - return MaterialApp( - title: 'Onyx', - debugShowCheckedModeBanner: false, - theme: AppTheme.light(), - darkTheme: AppTheme.dark(), - themeMode: state.darkMode ? ThemeMode.dark : ThemeMode.light, - home: const AppShell(), - ); - } -} - -class AppShell extends StatefulWidget { - const AppShell({super.key}); - - @override - State createState() => _AppShellState(); -} - -class _AppShellState extends State with SingleTickerProviderStateMixin { - static const _edge = 8.0; - late final AnimationController _settingsAnim; - late final Animation _settingsFade; - late final Animation _settingsScale; - bool _settingsVisible = false; - String? _prevScreen; - - @override - void initState() { - super.initState(); - _settingsAnim = AnimationController(vsync: this, duration: const Duration(milliseconds: 150)); - _settingsFade = CurvedAnimation(parent: _settingsAnim, curve: Curves.easeOut); - _settingsScale = Tween(begin: 0.95, end: 1.0) - .animate(CurvedAnimation(parent: _settingsAnim, curve: Curves.easeOut)); - } - - @override - void dispose() { - _settingsAnim.dispose(); - super.dispose(); - } - - void _onScreenChanged(String screen) { - if (screen == 'settings' && _prevScreen != 'settings') { - _settingsVisible = true; - _settingsAnim.forward(); - } else if (screen != 'settings' && _prevScreen == 'settings') { - _settingsAnim.reverse().then((_) { - if (mounted) setState(() => _settingsVisible = false); - }); - } - _prevScreen = screen; - } - - SystemMouseCursor _cursorFor(ResizeEdge? edge) => switch (edge) { - ResizeEdge.top || ResizeEdge.bottom => SystemMouseCursors.resizeUpDown, - ResizeEdge.left || ResizeEdge.right => SystemMouseCursors.resizeLeftRight, - ResizeEdge.topLeft || ResizeEdge.bottomRight => SystemMouseCursors.resizeUpLeftDownRight, - ResizeEdge.topRight || ResizeEdge.bottomLeft => SystemMouseCursors.resizeUpRightDownLeft, - _ => SystemMouseCursors.basic, - }; - - @override - Widget build(BuildContext context) { - final state = context.watch(); - final isDark = Theme.of(context).brightness == Brightness.dark; - final hasNativeBorder = Platform.isWindows; - - _onScreenChanged(state.screen); - - Widget content = Stack( - children: [ - if (state.screen == 'setup') - const SetupScreen() - else - const TasksScreen(), - if (state.error != null) - Positioned( - top: 0, left: 0, right: 0, - child: Material( - color: AppTheme.danger, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Row( - children: [ - Expanded( - child: Text(state.error!, style: const TextStyle(color: Colors.white, fontSize: 13)), - ), - GestureDetector( - onTap: state.clearError, - child: const Text('✕', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), - ), - ], - ), - ), - ), - ), - if (_settingsVisible) - FadeTransition( - opacity: _settingsFade, - child: ScaleTransition( - scale: _settingsScale, - child: const SettingsScreen(), - ), - ), - ], - ); - - if (hasNativeBorder) { - // Windows provides native border + shadow, just fill with surface color - return Scaffold( - backgroundColor: isDark ? AppTheme.surfaceDark : AppTheme.surfaceLight, - body: ClipRect(child: content), - ); - } - - // Linux/macOS: custom border, shadow, and resize zones - return Scaffold( - backgroundColor: Colors.transparent, - body: LayoutBuilder(builder: (context, constraints) { - return MouseRegion( - cursor: SystemMouseCursors.basic, - hitTestBehavior: HitTestBehavior.translucent, - child: Listener( - behavior: HitTestBehavior.translucent, - onPointerHover: (event) {}, - child: Stack( - children: [ - ..._buildResizeZones(constraints), - Padding( - padding: const EdgeInsets.all(_edge), - child: Container( - decoration: BoxDecoration( - color: isDark ? AppTheme.surfaceDark : AppTheme.surfaceLight, - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: isDark ? Colors.white.withValues(alpha: 0.15) : Colors.black.withValues(alpha: 0.15), - ), - boxShadow: [ - BoxShadow(color: Colors.black.withValues(alpha: 0.25), blurRadius: 8, offset: const Offset(0, 2)), - BoxShadow(color: Colors.black.withValues(alpha: 0.1), blurRadius: 2), - ], - ), - clipBehavior: Clip.antiAlias, - child: content, - ), - ), - ], - ), - ), - ); - }), - ); - } - - List _buildResizeZones(BoxConstraints constraints) { - final w = constraints.maxWidth; - final h = constraints.maxHeight; - Widget zone(ResizeEdge edge, {required double left, required double top, required double width, required double height}) { - return Positioned( - left: left, top: top, width: width, height: height, - child: MouseRegion( - cursor: _cursorFor(edge), - child: GestureDetector( - onPanStart: (_) => windowManager.startResizing(edge), - ), - ), - ); - } - return [ - // Corners (larger hit area) - zone(ResizeEdge.topLeft, left: 0, top: 0, width: _edge * 2, height: _edge * 2), - zone(ResizeEdge.topRight, left: w - _edge * 2, top: 0, width: _edge * 2, height: _edge * 2), - zone(ResizeEdge.bottomLeft, left: 0, top: h - _edge * 2, width: _edge * 2, height: _edge * 2), - zone(ResizeEdge.bottomRight, left: w - _edge * 2, top: h - _edge * 2, width: _edge * 2, height: _edge * 2), - // Edges - zone(ResizeEdge.top, left: _edge * 2, top: 0, width: w - _edge * 4, height: _edge), - zone(ResizeEdge.bottom, left: _edge * 2, top: h - _edge, width: w - _edge * 4, height: _edge), - zone(ResizeEdge.left, left: 0, top: _edge * 2, width: _edge, height: h - _edge * 4), - zone(ResizeEdge.right, left: w - _edge, top: _edge * 2, width: _edge, height: h - _edge * 4), - ]; - } -} diff --git a/apps/flutter/lib/src/rust/api.dart b/apps/flutter/lib/src/rust/api.dart deleted file mode 100644 index 2668c80..0000000 --- a/apps/flutter/lib/src/rust/api.dart +++ /dev/null @@ -1,312 +0,0 @@ -// This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. - -// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import - -import 'frb_generated.dart'; -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; - -// These functions are ignored because they are not marked as `pub`: `config_to_dto`, `ensure_repo`, `mute_watcher`, `task_to_dto` -// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `AppState` - -Future getConfig() => RustLib.instance.api.crateApiGetConfig(); - -Future initWorkspace({required String path}) => - RustLib.instance.api.crateApiInitWorkspace(path: path); - -Future addWorkspace({required String name, required String path}) => - RustLib.instance.api.crateApiAddWorkspace(name: name, path: path); - -Future setCurrentWorkspace({required String name}) => - RustLib.instance.api.crateApiSetCurrentWorkspace(name: name); - -Future removeWorkspace({required String name}) => - RustLib.instance.api.crateApiRemoveWorkspace(name: name); - -Future> getLists() => RustLib.instance.api.crateApiGetLists(); - -Future createList({required String name}) => - RustLib.instance.api.crateApiCreateList(name: name); - -Future deleteList({required String listId}) => - RustLib.instance.api.crateApiDeleteList(listId: listId); - -Future> listTasks({required String listId}) => - RustLib.instance.api.crateApiListTasks(listId: listId); - -Future createTask({ - required String listId, - required String title, - required String description, -}) => RustLib.instance.api.crateApiCreateTask( - listId: listId, - title: title, - description: description, -); - -Future updateTask({required String listId, required TaskDto task}) => - RustLib.instance.api.crateApiUpdateTask(listId: listId, task: task); - -Future deleteTask({required String listId, required String taskId}) => - RustLib.instance.api.crateApiDeleteTask(listId: listId, taskId: taskId); - -Future toggleTask({required String listId, required String taskId}) => - RustLib.instance.api.crateApiToggleTask(listId: listId, taskId: taskId); - -Future reorderTask({ - required String listId, - required String taskId, - required int newPosition, -}) => RustLib.instance.api.crateApiReorderTask( - listId: listId, - taskId: taskId, - newPosition: newPosition, -); - -Future moveTask({ - required String fromListId, - required String toListId, - required String taskId, -}) => RustLib.instance.api.crateApiMoveTask( - fromListId: fromListId, - toListId: toListId, - taskId: taskId, -); - -Future renameList({required String listId, required String newName}) => - RustLib.instance.api.crateApiRenameList(listId: listId, newName: newName); - -Future setGroupByDueDate({ - required String listId, - required bool enabled, -}) => RustLib.instance.api.crateApiSetGroupByDueDate( - listId: listId, - enabled: enabled, -); - -Future getGroupByDueDate({required String listId}) => - RustLib.instance.api.crateApiGetGroupByDueDate(listId: listId); - -Future storeCredentials({ - required String domain, - required String username, - required String password, -}) => RustLib.instance.api.crateApiStoreCredentials( - domain: domain, - username: username, - password: password, -); - -Future> loadCredentials({required String domain}) => - RustLib.instance.api.crateApiLoadCredentials(domain: domain); - -Future setWebdavConfig({ - required String workspaceName, - required String webdavUrl, -}) => RustLib.instance.api.crateApiSetWebdavConfig( - workspaceName: workspaceName, - webdavUrl: webdavUrl, -); - -Future testWebdavConnection({ - required String url, - required String username, - required String password, -}) => RustLib.instance.api.crateApiTestWebdavConnection( - url: url, - username: username, - password: password, -); - -Future syncWorkspaceCmd({ - required String workspaceName, - required String workspacePath, - required String webdavUrl, - required String username, - required String password, - required String mode, -}) => RustLib.instance.api.crateApiSyncWorkspaceCmd( - workspaceName: workspaceName, - workspacePath: workspacePath, - webdavUrl: webdavUrl, - username: username, - password: password, - mode: mode, -); - -Future> watchWorkspaceChanges({required String path}) => - RustLib.instance.api.crateApiWatchWorkspaceChanges(path: path); - -Future greet({required String name}) => - RustLib.instance.api.crateApiGreet(name: name); - -class AppConfigDto { - final List workspaces; - final String? currentWorkspace; - - const AppConfigDto({required this.workspaces, this.currentWorkspace}); - - @override - int get hashCode => workspaces.hashCode ^ currentWorkspace.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is AppConfigDto && - runtimeType == other.runtimeType && - workspaces == other.workspaces && - currentWorkspace == other.currentWorkspace; -} - -class SyncResultDto { - final int uploaded; - final int downloaded; - final int deletedLocal; - final int deletedRemote; - final int conflicts; - final List errors; - - const SyncResultDto({ - required this.uploaded, - required this.downloaded, - required this.deletedLocal, - required this.deletedRemote, - required this.conflicts, - required this.errors, - }); - - @override - int get hashCode => - uploaded.hashCode ^ - downloaded.hashCode ^ - deletedLocal.hashCode ^ - deletedRemote.hashCode ^ - conflicts.hashCode ^ - errors.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is SyncResultDto && - runtimeType == other.runtimeType && - uploaded == other.uploaded && - downloaded == other.downloaded && - deletedLocal == other.deletedLocal && - deletedRemote == other.deletedRemote && - conflicts == other.conflicts && - errors == other.errors; -} - -class TaskDto { - final String id; - final String title; - final String description; - final String status; - final String? dueDate; - final bool hasTime; - final String createdAt; - final String updatedAt; - final String? parentId; - - const TaskDto({ - required this.id, - required this.title, - required this.description, - required this.status, - this.dueDate, - required this.hasTime, - required this.createdAt, - required this.updatedAt, - this.parentId, - }); - - @override - int get hashCode => - id.hashCode ^ - title.hashCode ^ - description.hashCode ^ - status.hashCode ^ - dueDate.hashCode ^ - hasTime.hashCode ^ - createdAt.hashCode ^ - updatedAt.hashCode ^ - parentId.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is TaskDto && - runtimeType == other.runtimeType && - id == other.id && - title == other.title && - description == other.description && - status == other.status && - dueDate == other.dueDate && - hasTime == other.hasTime && - createdAt == other.createdAt && - updatedAt == other.updatedAt && - parentId == other.parentId; -} - -class TaskListDto { - final String id; - final String title; - final String createdAt; - final String updatedAt; - final bool groupByDueDate; - - const TaskListDto({ - required this.id, - required this.title, - required this.createdAt, - required this.updatedAt, - required this.groupByDueDate, - }); - - @override - int get hashCode => - id.hashCode ^ - title.hashCode ^ - createdAt.hashCode ^ - updatedAt.hashCode ^ - groupByDueDate.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is TaskListDto && - runtimeType == other.runtimeType && - id == other.id && - title == other.title && - createdAt == other.createdAt && - updatedAt == other.updatedAt && - groupByDueDate == other.groupByDueDate; -} - -class WorkspaceEntry { - final String name; - final String path; - final String? webdavUrl; - final String? lastSync; - - const WorkspaceEntry({ - required this.name, - required this.path, - this.webdavUrl, - this.lastSync, - }); - - @override - int get hashCode => - name.hashCode ^ path.hashCode ^ webdavUrl.hashCode ^ lastSync.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is WorkspaceEntry && - runtimeType == other.runtimeType && - name == other.name && - path == other.path && - webdavUrl == other.webdavUrl && - lastSync == other.lastSync; -} diff --git a/apps/flutter/lib/src/rust/frb_generated.dart b/apps/flutter/lib/src/rust/frb_generated.dart deleted file mode 100644 index 6aab38f..0000000 --- a/apps/flutter/lib/src/rust/frb_generated.dart +++ /dev/null @@ -1,1566 +0,0 @@ -// This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. - -// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field - -import 'api.dart'; -import 'dart:async'; -import 'dart:convert'; -import 'frb_generated.dart'; -import 'frb_generated.io.dart' - if (dart.library.js_interop) 'frb_generated.web.dart'; -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; - -/// Main entrypoint of the Rust API -class RustLib extends BaseEntrypoint { - @internal - static final instance = RustLib._(); - - RustLib._(); - - /// Initialize flutter_rust_bridge - static Future init({ - RustLibApi? api, - BaseHandler? handler, - ExternalLibrary? externalLibrary, - bool forceSameCodegenVersion = true, - }) async { - await instance.initImpl( - api: api, - handler: handler, - externalLibrary: externalLibrary, - forceSameCodegenVersion: forceSameCodegenVersion, - ); - } - - /// Initialize flutter_rust_bridge in mock mode. - /// No libraries for FFI are loaded. - static void initMock({required RustLibApi api}) { - instance.initMockImpl(api: api); - } - - /// Dispose flutter_rust_bridge - /// - /// The call to this function is optional, since flutter_rust_bridge (and everything else) - /// is automatically disposed when the app stops. - static void dispose() => instance.disposeImpl(); - - @override - ApiImplConstructor get apiImplConstructor => - RustLibApiImpl.new; - - @override - WireConstructor get wireConstructor => - RustLibWire.fromExternalLibrary; - - @override - Future executeRustInitializers() async {} - - @override - ExternalLibraryLoaderConfig get defaultExternalLibraryLoaderConfig => - kDefaultExternalLibraryLoaderConfig; - - @override - String get codegenVersion => '2.11.1'; - - @override - int get rustContentHash => -1094746925; - - static const kDefaultExternalLibraryLoaderConfig = - ExternalLibraryLoaderConfig( - stem: 'onyx_flutter', - ioDirectory: 'rust/target/release/', - webPrefix: 'pkg/', - ); -} - -abstract class RustLibApi extends BaseApi { - Future crateApiAddWorkspace({ - required String name, - required String path, - }); - - Future crateApiCreateList({required String name}); - - Future crateApiCreateTask({ - required String listId, - required String title, - required String description, - }); - - Future crateApiDeleteList({required String listId}); - - Future crateApiDeleteTask({ - required String listId, - required String taskId, - }); - - Future crateApiGetConfig(); - - Future crateApiGetGroupByDueDate({required String listId}); - - Future> crateApiGetLists(); - - Future crateApiGreet({required String name}); - - Future crateApiInitWorkspace({required String path}); - - Future> crateApiListTasks({required String listId}); - - Future> crateApiLoadCredentials({required String domain}); - - Future crateApiMoveTask({ - required String fromListId, - required String toListId, - required String taskId, - }); - - Future crateApiRemoveWorkspace({required String name}); - - Future crateApiRenameList({ - required String listId, - required String newName, - }); - - Future crateApiReorderTask({ - required String listId, - required String taskId, - required int newPosition, - }); - - Future crateApiSetCurrentWorkspace({required String name}); - - Future crateApiSetGroupByDueDate({ - required String listId, - required bool enabled, - }); - - Future crateApiSetWebdavConfig({ - required String workspaceName, - required String webdavUrl, - }); - - Future crateApiStoreCredentials({ - required String domain, - required String username, - required String password, - }); - - Future crateApiSyncWorkspaceCmd({ - required String workspaceName, - required String workspacePath, - required String webdavUrl, - required String username, - required String password, - required String mode, - }); - - Future crateApiTestWebdavConnection({ - required String url, - required String username, - required String password, - }); - - Future crateApiToggleTask({ - required String listId, - required String taskId, - }); - - Future crateApiUpdateTask({ - required String listId, - required TaskDto task, - }); - - Future> crateApiWatchWorkspaceChanges({required String path}); -} - -class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { - RustLibApiImpl({ - required super.handler, - required super.wire, - required super.generalizedFrbRustBinding, - required super.portManager, - }); - - @override - Future crateApiAddWorkspace({ - required String name, - required String path, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(name, serializer); - sse_encode_String(path, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 1, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiAddWorkspaceConstMeta, - argValues: [name, path], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAddWorkspaceConstMeta => const TaskConstMeta( - debugName: "add_workspace", - argNames: ["name", "path"], - ); - - @override - Future crateApiCreateList({required String name}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(name, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 2, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_task_list_dto, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiCreateListConstMeta, - argValues: [name], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiCreateListConstMeta => - const TaskConstMeta(debugName: "create_list", argNames: ["name"]); - - @override - Future crateApiCreateTask({ - required String listId, - required String title, - required String description, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(listId, serializer); - sse_encode_String(title, serializer); - sse_encode_String(description, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 3, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_task_dto, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiCreateTaskConstMeta, - argValues: [listId, title, description], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiCreateTaskConstMeta => const TaskConstMeta( - debugName: "create_task", - argNames: ["listId", "title", "description"], - ); - - @override - Future crateApiDeleteList({required String listId}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(listId, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 4, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiDeleteListConstMeta, - argValues: [listId], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiDeleteListConstMeta => - const TaskConstMeta(debugName: "delete_list", argNames: ["listId"]); - - @override - Future crateApiDeleteTask({ - required String listId, - required String taskId, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(listId, serializer); - sse_encode_String(taskId, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 5, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiDeleteTaskConstMeta, - argValues: [listId, taskId], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiDeleteTaskConstMeta => const TaskConstMeta( - debugName: "delete_task", - argNames: ["listId", "taskId"], - ); - - @override - Future crateApiGetConfig() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 6, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_app_config_dto, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiGetConfigConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiGetConfigConstMeta => - const TaskConstMeta(debugName: "get_config", argNames: []); - - @override - Future crateApiGetGroupByDueDate({required String listId}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(listId, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 7, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiGetGroupByDueDateConstMeta, - argValues: [listId], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiGetGroupByDueDateConstMeta => const TaskConstMeta( - debugName: "get_group_by_due_date", - argNames: ["listId"], - ); - - @override - Future> crateApiGetLists() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 8, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_task_list_dto, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiGetListsConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiGetListsConstMeta => - const TaskConstMeta(debugName: "get_lists", argNames: []); - - @override - Future crateApiGreet({required String name}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(name, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 9, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: null, - ), - constMeta: kCrateApiGreetConstMeta, - argValues: [name], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiGreetConstMeta => - const TaskConstMeta(debugName: "greet", argNames: ["name"]); - - @override - Future crateApiInitWorkspace({required String path}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(path, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 10, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiInitWorkspaceConstMeta, - argValues: [path], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiInitWorkspaceConstMeta => - const TaskConstMeta(debugName: "init_workspace", argNames: ["path"]); - - @override - Future> crateApiListTasks({required String listId}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(listId, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 11, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_task_dto, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiListTasksConstMeta, - argValues: [listId], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiListTasksConstMeta => - const TaskConstMeta(debugName: "list_tasks", argNames: ["listId"]); - - @override - Future> crateApiLoadCredentials({required String domain}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(domain, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 12, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_String, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiLoadCredentialsConstMeta, - argValues: [domain], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiLoadCredentialsConstMeta => - const TaskConstMeta(debugName: "load_credentials", argNames: ["domain"]); - - @override - Future crateApiMoveTask({ - required String fromListId, - required String toListId, - required String taskId, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(fromListId, serializer); - sse_encode_String(toListId, serializer); - sse_encode_String(taskId, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 13, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiMoveTaskConstMeta, - argValues: [fromListId, toListId, taskId], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiMoveTaskConstMeta => const TaskConstMeta( - debugName: "move_task", - argNames: ["fromListId", "toListId", "taskId"], - ); - - @override - Future crateApiRemoveWorkspace({required String name}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(name, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 14, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiRemoveWorkspaceConstMeta, - argValues: [name], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiRemoveWorkspaceConstMeta => - const TaskConstMeta(debugName: "remove_workspace", argNames: ["name"]); - - @override - Future crateApiRenameList({ - required String listId, - required String newName, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(listId, serializer); - sse_encode_String(newName, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 15, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiRenameListConstMeta, - argValues: [listId, newName], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiRenameListConstMeta => const TaskConstMeta( - debugName: "rename_list", - argNames: ["listId", "newName"], - ); - - @override - Future crateApiReorderTask({ - required String listId, - required String taskId, - required int newPosition, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(listId, serializer); - sse_encode_String(taskId, serializer); - sse_encode_u_32(newPosition, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 16, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiReorderTaskConstMeta, - argValues: [listId, taskId, newPosition], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiReorderTaskConstMeta => const TaskConstMeta( - debugName: "reorder_task", - argNames: ["listId", "taskId", "newPosition"], - ); - - @override - Future crateApiSetCurrentWorkspace({required String name}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(name, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 17, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiSetCurrentWorkspaceConstMeta, - argValues: [name], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiSetCurrentWorkspaceConstMeta => - const TaskConstMeta( - debugName: "set_current_workspace", - argNames: ["name"], - ); - - @override - Future crateApiSetGroupByDueDate({ - required String listId, - required bool enabled, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(listId, serializer); - sse_encode_bool(enabled, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 18, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiSetGroupByDueDateConstMeta, - argValues: [listId, enabled], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiSetGroupByDueDateConstMeta => const TaskConstMeta( - debugName: "set_group_by_due_date", - argNames: ["listId", "enabled"], - ); - - @override - Future crateApiSetWebdavConfig({ - required String workspaceName, - required String webdavUrl, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(workspaceName, serializer); - sse_encode_String(webdavUrl, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 19, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiSetWebdavConfigConstMeta, - argValues: [workspaceName, webdavUrl], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiSetWebdavConfigConstMeta => const TaskConstMeta( - debugName: "set_webdav_config", - argNames: ["workspaceName", "webdavUrl"], - ); - - @override - Future crateApiStoreCredentials({ - required String domain, - required String username, - required String password, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(domain, serializer); - sse_encode_String(username, serializer); - sse_encode_String(password, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 20, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiStoreCredentialsConstMeta, - argValues: [domain, username, password], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiStoreCredentialsConstMeta => const TaskConstMeta( - debugName: "store_credentials", - argNames: ["domain", "username", "password"], - ); - - @override - Future crateApiSyncWorkspaceCmd({ - required String workspaceName, - required String workspacePath, - required String webdavUrl, - required String username, - required String password, - required String mode, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(workspaceName, serializer); - sse_encode_String(workspacePath, serializer); - sse_encode_String(webdavUrl, serializer); - sse_encode_String(username, serializer); - sse_encode_String(password, serializer); - sse_encode_String(mode, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 21, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_sync_result_dto, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiSyncWorkspaceCmdConstMeta, - argValues: [ - workspaceName, - workspacePath, - webdavUrl, - username, - password, - mode, - ], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiSyncWorkspaceCmdConstMeta => const TaskConstMeta( - debugName: "sync_workspace_cmd", - argNames: [ - "workspaceName", - "workspacePath", - "webdavUrl", - "username", - "password", - "mode", - ], - ); - - @override - Future crateApiTestWebdavConnection({ - required String url, - required String username, - required String password, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(url, serializer); - sse_encode_String(username, serializer); - sse_encode_String(password, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 22, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiTestWebdavConnectionConstMeta, - argValues: [url, username, password], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiTestWebdavConnectionConstMeta => - const TaskConstMeta( - debugName: "test_webdav_connection", - argNames: ["url", "username", "password"], - ); - - @override - Future crateApiToggleTask({ - required String listId, - required String taskId, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(listId, serializer); - sse_encode_String(taskId, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 23, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_task_dto, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiToggleTaskConstMeta, - argValues: [listId, taskId], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiToggleTaskConstMeta => const TaskConstMeta( - debugName: "toggle_task", - argNames: ["listId", "taskId"], - ); - - @override - Future crateApiUpdateTask({ - required String listId, - required TaskDto task, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(listId, serializer); - sse_encode_box_autoadd_task_dto(task, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 24, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiUpdateTaskConstMeta, - argValues: [listId, task], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiUpdateTaskConstMeta => const TaskConstMeta( - debugName: "update_task", - argNames: ["listId", "task"], - ); - - @override - Future> crateApiWatchWorkspaceChanges({ - required String path, - }) async { - final sink = RustStreamSink(); - await handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(path, serializer); - sse_encode_StreamSink_unit_Sse(sink, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 25, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiWatchWorkspaceChangesConstMeta, - argValues: [path, sink], - apiImpl: this, - ), - ); - return sink.stream; - } - - TaskConstMeta get kCrateApiWatchWorkspaceChangesConstMeta => - const TaskConstMeta( - debugName: "watch_workspace_changes", - argNames: ["path", "sink"], - ); - - @protected - AnyhowException dco_decode_AnyhowException(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return AnyhowException(raw as String); - } - - @protected - RustStreamSink dco_decode_StreamSink_unit_Sse(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - throw UnimplementedError(); - } - - @protected - String dco_decode_String(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return raw as String; - } - - @protected - AppConfigDto dco_decode_app_config_dto(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - final arr = raw as List; - if (arr.length != 2) - throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); - return AppConfigDto( - workspaces: dco_decode_list_workspace_entry(arr[0]), - currentWorkspace: dco_decode_opt_String(arr[1]), - ); - } - - @protected - bool dco_decode_bool(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return raw as bool; - } - - @protected - TaskDto dco_decode_box_autoadd_task_dto(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return dco_decode_task_dto(raw); - } - - @protected - List dco_decode_list_String(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return (raw as List).map(dco_decode_String).toList(); - } - - @protected - Uint8List dco_decode_list_prim_u_8_strict(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return raw as Uint8List; - } - - @protected - List dco_decode_list_task_dto(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return (raw as List).map(dco_decode_task_dto).toList(); - } - - @protected - List dco_decode_list_task_list_dto(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return (raw as List).map(dco_decode_task_list_dto).toList(); - } - - @protected - List dco_decode_list_workspace_entry(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return (raw as List).map(dco_decode_workspace_entry).toList(); - } - - @protected - String? dco_decode_opt_String(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return raw == null ? null : dco_decode_String(raw); - } - - @protected - SyncResultDto dco_decode_sync_result_dto(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - final arr = raw as List; - if (arr.length != 6) - throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); - return SyncResultDto( - uploaded: dco_decode_u_32(arr[0]), - downloaded: dco_decode_u_32(arr[1]), - deletedLocal: dco_decode_u_32(arr[2]), - deletedRemote: dco_decode_u_32(arr[3]), - conflicts: dco_decode_u_32(arr[4]), - errors: dco_decode_list_String(arr[5]), - ); - } - - @protected - TaskDto dco_decode_task_dto(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - final arr = raw as List; - if (arr.length != 9) - throw Exception('unexpected arr length: expect 9 but see ${arr.length}'); - return TaskDto( - id: dco_decode_String(arr[0]), - title: dco_decode_String(arr[1]), - description: dco_decode_String(arr[2]), - status: dco_decode_String(arr[3]), - dueDate: dco_decode_opt_String(arr[4]), - hasTime: dco_decode_bool(arr[5]), - createdAt: dco_decode_String(arr[6]), - updatedAt: dco_decode_String(arr[7]), - parentId: dco_decode_opt_String(arr[8]), - ); - } - - @protected - TaskListDto dco_decode_task_list_dto(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - final arr = raw as List; - if (arr.length != 5) - throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); - return TaskListDto( - id: dco_decode_String(arr[0]), - title: dco_decode_String(arr[1]), - createdAt: dco_decode_String(arr[2]), - updatedAt: dco_decode_String(arr[3]), - groupByDueDate: dco_decode_bool(arr[4]), - ); - } - - @protected - int dco_decode_u_32(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return raw as int; - } - - @protected - int dco_decode_u_8(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return raw as int; - } - - @protected - void dco_decode_unit(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return; - } - - @protected - WorkspaceEntry dco_decode_workspace_entry(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - final arr = raw as List; - if (arr.length != 4) - throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); - return WorkspaceEntry( - name: dco_decode_String(arr[0]), - path: dco_decode_String(arr[1]), - webdavUrl: dco_decode_opt_String(arr[2]), - lastSync: dco_decode_opt_String(arr[3]), - ); - } - - @protected - AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var inner = sse_decode_String(deserializer); - return AnyhowException(inner); - } - - @protected - RustStreamSink sse_decode_StreamSink_unit_Sse( - SseDeserializer deserializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - throw UnimplementedError('Unreachable ()'); - } - - @protected - String sse_decode_String(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var inner = sse_decode_list_prim_u_8_strict(deserializer); - return utf8.decoder.convert(inner); - } - - @protected - AppConfigDto sse_decode_app_config_dto(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var var_workspaces = sse_decode_list_workspace_entry(deserializer); - var var_currentWorkspace = sse_decode_opt_String(deserializer); - return AppConfigDto( - workspaces: var_workspaces, - currentWorkspace: var_currentWorkspace, - ); - } - - @protected - bool sse_decode_bool(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - return deserializer.buffer.getUint8() != 0; - } - - @protected - TaskDto sse_decode_box_autoadd_task_dto(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - return (sse_decode_task_dto(deserializer)); - } - - @protected - List sse_decode_list_String(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - - var len_ = sse_decode_i_32(deserializer); - var ans_ = []; - for (var idx_ = 0; idx_ < len_; ++idx_) { - ans_.add(sse_decode_String(deserializer)); - } - return ans_; - } - - @protected - Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var len_ = sse_decode_i_32(deserializer); - return deserializer.buffer.getUint8List(len_); - } - - @protected - List sse_decode_list_task_dto(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - - var len_ = sse_decode_i_32(deserializer); - var ans_ = []; - for (var idx_ = 0; idx_ < len_; ++idx_) { - ans_.add(sse_decode_task_dto(deserializer)); - } - return ans_; - } - - @protected - List sse_decode_list_task_list_dto( - SseDeserializer deserializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - - var len_ = sse_decode_i_32(deserializer); - var ans_ = []; - for (var idx_ = 0; idx_ < len_; ++idx_) { - ans_.add(sse_decode_task_list_dto(deserializer)); - } - return ans_; - } - - @protected - List sse_decode_list_workspace_entry( - SseDeserializer deserializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - - var len_ = sse_decode_i_32(deserializer); - var ans_ = []; - for (var idx_ = 0; idx_ < len_; ++idx_) { - ans_.add(sse_decode_workspace_entry(deserializer)); - } - return ans_; - } - - @protected - String? sse_decode_opt_String(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - - if (sse_decode_bool(deserializer)) { - return (sse_decode_String(deserializer)); - } else { - return null; - } - } - - @protected - SyncResultDto sse_decode_sync_result_dto(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var var_uploaded = sse_decode_u_32(deserializer); - var var_downloaded = sse_decode_u_32(deserializer); - var var_deletedLocal = sse_decode_u_32(deserializer); - var var_deletedRemote = sse_decode_u_32(deserializer); - var var_conflicts = sse_decode_u_32(deserializer); - var var_errors = sse_decode_list_String(deserializer); - return SyncResultDto( - uploaded: var_uploaded, - downloaded: var_downloaded, - deletedLocal: var_deletedLocal, - deletedRemote: var_deletedRemote, - conflicts: var_conflicts, - errors: var_errors, - ); - } - - @protected - TaskDto sse_decode_task_dto(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var var_id = sse_decode_String(deserializer); - var var_title = sse_decode_String(deserializer); - var var_description = sse_decode_String(deserializer); - var var_status = sse_decode_String(deserializer); - var var_dueDate = sse_decode_opt_String(deserializer); - var var_hasTime = sse_decode_bool(deserializer); - var var_createdAt = sse_decode_String(deserializer); - var var_updatedAt = sse_decode_String(deserializer); - var var_parentId = sse_decode_opt_String(deserializer); - return TaskDto( - id: var_id, - title: var_title, - description: var_description, - status: var_status, - dueDate: var_dueDate, - hasTime: var_hasTime, - createdAt: var_createdAt, - updatedAt: var_updatedAt, - parentId: var_parentId, - ); - } - - @protected - TaskListDto sse_decode_task_list_dto(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var var_id = sse_decode_String(deserializer); - var var_title = sse_decode_String(deserializer); - var var_createdAt = sse_decode_String(deserializer); - var var_updatedAt = sse_decode_String(deserializer); - var var_groupByDueDate = sse_decode_bool(deserializer); - return TaskListDto( - id: var_id, - title: var_title, - createdAt: var_createdAt, - updatedAt: var_updatedAt, - groupByDueDate: var_groupByDueDate, - ); - } - - @protected - int sse_decode_u_32(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - return deserializer.buffer.getUint32(); - } - - @protected - int sse_decode_u_8(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - return deserializer.buffer.getUint8(); - } - - @protected - void sse_decode_unit(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - } - - @protected - WorkspaceEntry sse_decode_workspace_entry(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var var_name = sse_decode_String(deserializer); - var var_path = sse_decode_String(deserializer); - var var_webdavUrl = sse_decode_opt_String(deserializer); - var var_lastSync = sse_decode_opt_String(deserializer); - return WorkspaceEntry( - name: var_name, - path: var_path, - webdavUrl: var_webdavUrl, - lastSync: var_lastSync, - ); - } - - @protected - int sse_decode_i_32(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - return deserializer.buffer.getInt32(); - } - - @protected - void sse_encode_AnyhowException( - AnyhowException self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_String(self.message, serializer); - } - - @protected - void sse_encode_StreamSink_unit_Sse( - RustStreamSink self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - ), - serializer, - ); - } - - @protected - void sse_encode_String(String self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_list_prim_u_8_strict(utf8.encoder.convert(self), serializer); - } - - @protected - void sse_encode_app_config_dto(AppConfigDto self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_list_workspace_entry(self.workspaces, serializer); - sse_encode_opt_String(self.currentWorkspace, serializer); - } - - @protected - void sse_encode_bool(bool self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - serializer.buffer.putUint8(self ? 1 : 0); - } - - @protected - void sse_encode_box_autoadd_task_dto(TaskDto self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_task_dto(self, serializer); - } - - @protected - void sse_encode_list_String(List self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_i_32(self.length, serializer); - for (final item in self) { - sse_encode_String(item, serializer); - } - } - - @protected - void sse_encode_list_prim_u_8_strict( - Uint8List self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_i_32(self.length, serializer); - serializer.buffer.putUint8List(self); - } - - @protected - void sse_encode_list_task_dto(List self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_i_32(self.length, serializer); - for (final item in self) { - sse_encode_task_dto(item, serializer); - } - } - - @protected - void sse_encode_list_task_list_dto( - List self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_i_32(self.length, serializer); - for (final item in self) { - sse_encode_task_list_dto(item, serializer); - } - } - - @protected - void sse_encode_list_workspace_entry( - List self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_i_32(self.length, serializer); - for (final item in self) { - sse_encode_workspace_entry(item, serializer); - } - } - - @protected - void sse_encode_opt_String(String? self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - - sse_encode_bool(self != null, serializer); - if (self != null) { - sse_encode_String(self, serializer); - } - } - - @protected - void sse_encode_sync_result_dto( - SyncResultDto self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_u_32(self.uploaded, serializer); - sse_encode_u_32(self.downloaded, serializer); - sse_encode_u_32(self.deletedLocal, serializer); - sse_encode_u_32(self.deletedRemote, serializer); - sse_encode_u_32(self.conflicts, serializer); - sse_encode_list_String(self.errors, serializer); - } - - @protected - void sse_encode_task_dto(TaskDto self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_String(self.id, serializer); - sse_encode_String(self.title, serializer); - sse_encode_String(self.description, serializer); - sse_encode_String(self.status, serializer); - sse_encode_opt_String(self.dueDate, serializer); - sse_encode_bool(self.hasTime, serializer); - sse_encode_String(self.createdAt, serializer); - sse_encode_String(self.updatedAt, serializer); - sse_encode_opt_String(self.parentId, serializer); - } - - @protected - void sse_encode_task_list_dto(TaskListDto self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_String(self.id, serializer); - sse_encode_String(self.title, serializer); - sse_encode_String(self.createdAt, serializer); - sse_encode_String(self.updatedAt, serializer); - sse_encode_bool(self.groupByDueDate, serializer); - } - - @protected - void sse_encode_u_32(int self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - serializer.buffer.putUint32(self); - } - - @protected - void sse_encode_u_8(int self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - serializer.buffer.putUint8(self); - } - - @protected - void sse_encode_unit(void self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - } - - @protected - void sse_encode_workspace_entry( - WorkspaceEntry self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_String(self.name, serializer); - sse_encode_String(self.path, serializer); - sse_encode_opt_String(self.webdavUrl, serializer); - sse_encode_opt_String(self.lastSync, serializer); - } - - @protected - void sse_encode_i_32(int self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - serializer.buffer.putInt32(self); - } -} diff --git a/apps/flutter/lib/src/rust/frb_generated.io.dart b/apps/flutter/lib/src/rust/frb_generated.io.dart deleted file mode 100644 index fdbee3b..0000000 --- a/apps/flutter/lib/src/rust/frb_generated.io.dart +++ /dev/null @@ -1,234 +0,0 @@ -// This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. - -// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field - -import 'api.dart'; -import 'dart:async'; -import 'dart:convert'; -import 'dart:ffi' as ffi; -import 'frb_generated.dart'; -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_io.dart'; - -abstract class RustLibApiImplPlatform extends BaseApiImpl { - RustLibApiImplPlatform({ - required super.handler, - required super.wire, - required super.generalizedFrbRustBinding, - required super.portManager, - }); - - @protected - AnyhowException dco_decode_AnyhowException(dynamic raw); - - @protected - RustStreamSink dco_decode_StreamSink_unit_Sse(dynamic raw); - - @protected - String dco_decode_String(dynamic raw); - - @protected - AppConfigDto dco_decode_app_config_dto(dynamic raw); - - @protected - bool dco_decode_bool(dynamic raw); - - @protected - TaskDto dco_decode_box_autoadd_task_dto(dynamic raw); - - @protected - List dco_decode_list_String(dynamic raw); - - @protected - Uint8List dco_decode_list_prim_u_8_strict(dynamic raw); - - @protected - List dco_decode_list_task_dto(dynamic raw); - - @protected - List dco_decode_list_task_list_dto(dynamic raw); - - @protected - List dco_decode_list_workspace_entry(dynamic raw); - - @protected - String? dco_decode_opt_String(dynamic raw); - - @protected - SyncResultDto dco_decode_sync_result_dto(dynamic raw); - - @protected - TaskDto dco_decode_task_dto(dynamic raw); - - @protected - TaskListDto dco_decode_task_list_dto(dynamic raw); - - @protected - int dco_decode_u_32(dynamic raw); - - @protected - int dco_decode_u_8(dynamic raw); - - @protected - void dco_decode_unit(dynamic raw); - - @protected - WorkspaceEntry dco_decode_workspace_entry(dynamic raw); - - @protected - AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); - - @protected - RustStreamSink sse_decode_StreamSink_unit_Sse( - SseDeserializer deserializer, - ); - - @protected - String sse_decode_String(SseDeserializer deserializer); - - @protected - AppConfigDto sse_decode_app_config_dto(SseDeserializer deserializer); - - @protected - bool sse_decode_bool(SseDeserializer deserializer); - - @protected - TaskDto sse_decode_box_autoadd_task_dto(SseDeserializer deserializer); - - @protected - List sse_decode_list_String(SseDeserializer deserializer); - - @protected - Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer); - - @protected - List sse_decode_list_task_dto(SseDeserializer deserializer); - - @protected - List sse_decode_list_task_list_dto(SseDeserializer deserializer); - - @protected - List sse_decode_list_workspace_entry( - SseDeserializer deserializer, - ); - - @protected - String? sse_decode_opt_String(SseDeserializer deserializer); - - @protected - SyncResultDto sse_decode_sync_result_dto(SseDeserializer deserializer); - - @protected - TaskDto sse_decode_task_dto(SseDeserializer deserializer); - - @protected - TaskListDto sse_decode_task_list_dto(SseDeserializer deserializer); - - @protected - int sse_decode_u_32(SseDeserializer deserializer); - - @protected - int sse_decode_u_8(SseDeserializer deserializer); - - @protected - void sse_decode_unit(SseDeserializer deserializer); - - @protected - WorkspaceEntry sse_decode_workspace_entry(SseDeserializer deserializer); - - @protected - int sse_decode_i_32(SseDeserializer deserializer); - - @protected - void sse_encode_AnyhowException( - AnyhowException self, - SseSerializer serializer, - ); - - @protected - void sse_encode_StreamSink_unit_Sse( - RustStreamSink self, - SseSerializer serializer, - ); - - @protected - void sse_encode_String(String self, SseSerializer serializer); - - @protected - void sse_encode_app_config_dto(AppConfigDto self, SseSerializer serializer); - - @protected - void sse_encode_bool(bool self, SseSerializer serializer); - - @protected - void sse_encode_box_autoadd_task_dto(TaskDto self, SseSerializer serializer); - - @protected - void sse_encode_list_String(List self, SseSerializer serializer); - - @protected - void sse_encode_list_prim_u_8_strict( - Uint8List self, - SseSerializer serializer, - ); - - @protected - void sse_encode_list_task_dto(List self, SseSerializer serializer); - - @protected - void sse_encode_list_task_list_dto( - List self, - SseSerializer serializer, - ); - - @protected - void sse_encode_list_workspace_entry( - List self, - SseSerializer serializer, - ); - - @protected - void sse_encode_opt_String(String? self, SseSerializer serializer); - - @protected - void sse_encode_sync_result_dto(SyncResultDto self, SseSerializer serializer); - - @protected - void sse_encode_task_dto(TaskDto self, SseSerializer serializer); - - @protected - void sse_encode_task_list_dto(TaskListDto self, SseSerializer serializer); - - @protected - void sse_encode_u_32(int self, SseSerializer serializer); - - @protected - void sse_encode_u_8(int self, SseSerializer serializer); - - @protected - void sse_encode_unit(void self, SseSerializer serializer); - - @protected - void sse_encode_workspace_entry( - WorkspaceEntry self, - SseSerializer serializer, - ); - - @protected - void sse_encode_i_32(int self, SseSerializer serializer); -} - -// Section: wire_class - -class RustLibWire implements BaseWire { - factory RustLibWire.fromExternalLibrary(ExternalLibrary lib) => - RustLibWire(lib.ffiDynamicLibrary); - - /// Holds the symbol lookup function. - final ffi.Pointer Function(String symbolName) - _lookup; - - /// The symbols are looked up in [dynamicLibrary]. - RustLibWire(ffi.DynamicLibrary dynamicLibrary) - : _lookup = dynamicLibrary.lookup; -} diff --git a/apps/flutter/lib/src/rust/frb_generated.web.dart b/apps/flutter/lib/src/rust/frb_generated.web.dart deleted file mode 100644 index 5a30b0a..0000000 --- a/apps/flutter/lib/src/rust/frb_generated.web.dart +++ /dev/null @@ -1,234 +0,0 @@ -// This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. - -// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field - -// Static analysis wrongly picks the IO variant, thus ignore this -// ignore_for_file: argument_type_not_assignable - -import 'api.dart'; -import 'dart:async'; -import 'dart:convert'; -import 'frb_generated.dart'; -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_web.dart'; - -abstract class RustLibApiImplPlatform extends BaseApiImpl { - RustLibApiImplPlatform({ - required super.handler, - required super.wire, - required super.generalizedFrbRustBinding, - required super.portManager, - }); - - @protected - AnyhowException dco_decode_AnyhowException(dynamic raw); - - @protected - RustStreamSink dco_decode_StreamSink_unit_Sse(dynamic raw); - - @protected - String dco_decode_String(dynamic raw); - - @protected - AppConfigDto dco_decode_app_config_dto(dynamic raw); - - @protected - bool dco_decode_bool(dynamic raw); - - @protected - TaskDto dco_decode_box_autoadd_task_dto(dynamic raw); - - @protected - List dco_decode_list_String(dynamic raw); - - @protected - Uint8List dco_decode_list_prim_u_8_strict(dynamic raw); - - @protected - List dco_decode_list_task_dto(dynamic raw); - - @protected - List dco_decode_list_task_list_dto(dynamic raw); - - @protected - List dco_decode_list_workspace_entry(dynamic raw); - - @protected - String? dco_decode_opt_String(dynamic raw); - - @protected - SyncResultDto dco_decode_sync_result_dto(dynamic raw); - - @protected - TaskDto dco_decode_task_dto(dynamic raw); - - @protected - TaskListDto dco_decode_task_list_dto(dynamic raw); - - @protected - int dco_decode_u_32(dynamic raw); - - @protected - int dco_decode_u_8(dynamic raw); - - @protected - void dco_decode_unit(dynamic raw); - - @protected - WorkspaceEntry dco_decode_workspace_entry(dynamic raw); - - @protected - AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); - - @protected - RustStreamSink sse_decode_StreamSink_unit_Sse( - SseDeserializer deserializer, - ); - - @protected - String sse_decode_String(SseDeserializer deserializer); - - @protected - AppConfigDto sse_decode_app_config_dto(SseDeserializer deserializer); - - @protected - bool sse_decode_bool(SseDeserializer deserializer); - - @protected - TaskDto sse_decode_box_autoadd_task_dto(SseDeserializer deserializer); - - @protected - List sse_decode_list_String(SseDeserializer deserializer); - - @protected - Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer); - - @protected - List sse_decode_list_task_dto(SseDeserializer deserializer); - - @protected - List sse_decode_list_task_list_dto(SseDeserializer deserializer); - - @protected - List sse_decode_list_workspace_entry( - SseDeserializer deserializer, - ); - - @protected - String? sse_decode_opt_String(SseDeserializer deserializer); - - @protected - SyncResultDto sse_decode_sync_result_dto(SseDeserializer deserializer); - - @protected - TaskDto sse_decode_task_dto(SseDeserializer deserializer); - - @protected - TaskListDto sse_decode_task_list_dto(SseDeserializer deserializer); - - @protected - int sse_decode_u_32(SseDeserializer deserializer); - - @protected - int sse_decode_u_8(SseDeserializer deserializer); - - @protected - void sse_decode_unit(SseDeserializer deserializer); - - @protected - WorkspaceEntry sse_decode_workspace_entry(SseDeserializer deserializer); - - @protected - int sse_decode_i_32(SseDeserializer deserializer); - - @protected - void sse_encode_AnyhowException( - AnyhowException self, - SseSerializer serializer, - ); - - @protected - void sse_encode_StreamSink_unit_Sse( - RustStreamSink self, - SseSerializer serializer, - ); - - @protected - void sse_encode_String(String self, SseSerializer serializer); - - @protected - void sse_encode_app_config_dto(AppConfigDto self, SseSerializer serializer); - - @protected - void sse_encode_bool(bool self, SseSerializer serializer); - - @protected - void sse_encode_box_autoadd_task_dto(TaskDto self, SseSerializer serializer); - - @protected - void sse_encode_list_String(List self, SseSerializer serializer); - - @protected - void sse_encode_list_prim_u_8_strict( - Uint8List self, - SseSerializer serializer, - ); - - @protected - void sse_encode_list_task_dto(List self, SseSerializer serializer); - - @protected - void sse_encode_list_task_list_dto( - List self, - SseSerializer serializer, - ); - - @protected - void sse_encode_list_workspace_entry( - List self, - SseSerializer serializer, - ); - - @protected - void sse_encode_opt_String(String? self, SseSerializer serializer); - - @protected - void sse_encode_sync_result_dto(SyncResultDto self, SseSerializer serializer); - - @protected - void sse_encode_task_dto(TaskDto self, SseSerializer serializer); - - @protected - void sse_encode_task_list_dto(TaskListDto self, SseSerializer serializer); - - @protected - void sse_encode_u_32(int self, SseSerializer serializer); - - @protected - void sse_encode_u_8(int self, SseSerializer serializer); - - @protected - void sse_encode_unit(void self, SseSerializer serializer); - - @protected - void sse_encode_workspace_entry( - WorkspaceEntry self, - SseSerializer serializer, - ); - - @protected - void sse_encode_i_32(int self, SseSerializer serializer); -} - -// Section: wire_class - -class RustLibWire implements BaseWire { - RustLibWire.fromExternalLibrary(ExternalLibrary lib); -} - -@JS('wasm_bindgen') -external RustLibWasmModule get wasmModule; - -@JS() -@anonymous -extension type RustLibWasmModule._(JSObject _) implements JSObject {} diff --git a/apps/flutter/lib/src/screens/settings_screen.dart b/apps/flutter/lib/src/screens/settings_screen.dart deleted file mode 100644 index 1bd4dc9..0000000 --- a/apps/flutter/lib/src/screens/settings_screen.dart +++ /dev/null @@ -1,372 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import '../rust/api.dart' as api; -import '../state/app_state.dart'; -import '../theme.dart'; - -class SettingsScreen extends StatefulWidget { - const SettingsScreen({super.key}); - - @override - State createState() => _SettingsScreenState(); -} - -class _SettingsScreenState extends State { - final _urlController = TextEditingController(); - final _userController = TextEditingController(); - final _passController = TextEditingController(); - String _testStatus = 'idle'; // idle | testing | ok | fail - - @override - void initState() { - super.initState(); - _loadCredentials(); - } - - @override - void dispose() { - _urlController.dispose(); - _userController.dispose(); - _passController.dispose(); - super.dispose(); - } - - Future _loadCredentials() async { - final state = context.read(); - final wsName = state.config?.currentWorkspace; - if (wsName == null) return; - final ws = state.config!.workspaces.cast().firstWhere( - (w) => w?.name == wsName, orElse: () => null); - if (ws?.webdavUrl != null) { - _urlController.text = ws!.webdavUrl!; - try { - final domain = Uri.parse(ws.webdavUrl!).host; - final creds = await api.loadCredentials(domain: domain); - if (mounted) { - setState(() { - _userController.text = creds[0]; - _passController.text = creds[1]; - }); - } - } catch (_) {} - } - } - - Future _testConnection() async { - setState(() => _testStatus = 'testing'); - try { - await api.testWebdavConnection( - url: _urlController.text, - username: _userController.text, - password: _passController.text, - ); - if (mounted) setState(() => _testStatus = 'ok'); - } catch (_) { - if (mounted) setState(() => _testStatus = 'fail'); - } - } - - Future _save() async { - final state = context.read(); - final wsName = state.config?.currentWorkspace; - if (wsName == null || _urlController.text.trim().isEmpty) return; - await api.setWebdavConfig( - workspaceName: wsName, - webdavUrl: _urlController.text.trim(), - ); - if (_userController.text.isNotEmpty && _passController.text.isNotEmpty) { - final domain = Uri.parse(_urlController.text.trim()).host; - await api.storeCredentials( - domain: domain, - username: _userController.text, - password: _passController.text, - ); - } - await state.loadConfig(); - } - - @override - Widget build(BuildContext context) { - final state = context.watch(); - final isDark = Theme.of(context).brightness == Brightness.dark; - final borderColor = isDark ? AppTheme.borderDark : AppTheme.borderLight; - final inputDecoration = InputDecoration( - isDense: true, - contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide(color: borderColor), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide(color: borderColor), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: const BorderSide(color: AppTheme.primary), - ), - ); - - final wsName = state.config?.currentWorkspace; - final ws = wsName == null ? null : state.config!.workspaces.cast() - .firstWhere((w) => w?.name == wsName, orElse: () => null); - final lastSync = ws?.lastSync; - String? relTime; - if (lastSync != null) { - final t = DateTime.tryParse(lastSync); - if (t != null) { - final secsAgo = DateTime.now().difference(t).inSeconds; - if (secsAgo < 60) { - relTime = 'just now'; - } else if (secsAgo < 3600) { - relTime = '${secsAgo ~/ 60}m ago'; - } else { - relTime = '${secsAgo ~/ 3600}h ago'; - } - } - } - - return GestureDetector( - onTap: () => state.setScreen('tasks'), - child: Container( - color: Colors.black.withValues(alpha: 0.5), - padding: EdgeInsets.symmetric( - horizontal: MediaQuery.of(context).size.width * 0.04, - vertical: MediaQuery.of(context).size.height * 0.04, - ), - child: GestureDetector( - onTap: () {}, - child: Container( - decoration: BoxDecoration( - color: isDark ? AppTheme.surfaceDark : AppTheme.surfaceLight, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: Colors.white.withValues(alpha: 0.1)), - boxShadow: [ - BoxShadow(color: Colors.black.withValues(alpha: 0.7), blurRadius: 60, offset: const Offset(0, 25)), - BoxShadow(color: Colors.black.withValues(alpha: 0.5), blurRadius: 20, offset: const Offset(0, 10)), - ], - ), - clipBehavior: Clip.antiAlias, - child: Column( - children: [ - // Header - Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - decoration: BoxDecoration( - border: Border(bottom: BorderSide(color: borderColor, width: 0.5)), - ), - child: Row( - children: [ - const Text('Settings', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w700)), - const Spacer(), - GestureDetector( - onTap: () => state.setScreen('tasks'), - child: Container( - padding: const EdgeInsets.all(6), - decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)), - child: Icon(Icons.close, size: 20, - color: isDark ? AppTheme.textDark : AppTheme.textLight), - ), - ), - ], - ), - ), - // Content - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // WebDAV section header - Text('WEBDAV SYNC', - style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, - letterSpacing: 0.5, - color: (isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight).withValues(alpha: 0.5))), - const SizedBox(height: 12), - // Credentials card - Container( - width: double.infinity, - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - border: Border.all(color: borderColor), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Server URL', style: TextStyle(fontSize: 11, fontWeight: FontWeight.w500, - color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight)), - const SizedBox(height: 4), - TextField(controller: _urlController, style: const TextStyle(fontSize: 13), - decoration: inputDecoration.copyWith(hintText: 'https://dav.example.com/tasks/')), - const SizedBox(height: 10), - Text('Username', style: TextStyle(fontSize: 11, fontWeight: FontWeight.w500, - color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight)), - const SizedBox(height: 4), - TextField(controller: _userController, style: const TextStyle(fontSize: 13), - decoration: inputDecoration), - const SizedBox(height: 10), - Text('Password', style: TextStyle(fontSize: 11, fontWeight: FontWeight.w500, - color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight)), - const SizedBox(height: 4), - TextField(controller: _passController, obscureText: true, - style: const TextStyle(fontSize: 13), decoration: inputDecoration), - const SizedBox(height: 14), - Row( - children: [ - Expanded( - child: OutlinedButton( - onPressed: _urlController.text.isEmpty ? null : _testConnection, - style: OutlinedButton.styleFrom( - side: BorderSide(color: borderColor), - padding: const EdgeInsets.symmetric(vertical: 8), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - ), - child: Text( - _testStatus == 'testing' ? 'Testing…' - : _testStatus == 'ok' ? 'Connected' - : _testStatus == 'fail' ? 'Failed — Retry' - : 'Test Connection', - style: const TextStyle(fontSize: 13), - ), - ), - ), - const SizedBox(width: 8), - Expanded( - child: ElevatedButton( - onPressed: _urlController.text.isEmpty ? null : _save, - style: ElevatedButton.styleFrom( - backgroundColor: AppTheme.primary, - foregroundColor: Colors.white, - padding: const EdgeInsets.symmetric(vertical: 8), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - ), - child: const Text('Save', style: TextStyle(fontSize: 13)), - ), - ), - ], - ), - ], - ), - ), - // Sync direction + Sync Now - if (wsName != null) ...[ - const SizedBox(height: 10), - Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 12), - decoration: BoxDecoration( - border: Border.all(color: borderColor), - borderRadius: BorderRadius.circular(8), - color: isDark ? AppTheme.surfaceDark : AppTheme.surfaceLight, - ), - child: DropdownButton( - value: state.syncMode, - isExpanded: true, - underline: const SizedBox.shrink(), - style: TextStyle(fontSize: 13, - color: isDark ? AppTheme.textDark : AppTheme.textLight), - dropdownColor: isDark ? AppTheme.surfaceDark : AppTheme.surfaceLight, - items: const [ - DropdownMenuItem(value: 'full', child: Text('Sync both ways')), - DropdownMenuItem(value: 'push', child: Text('Push only')), - DropdownMenuItem(value: 'pull', child: Text('Pull only')), - ], - onChanged: (v) { if (v != null) state.setSyncMode(v); }, - ), - ), - ), - const SizedBox(width: 8), - Expanded( - child: ElevatedButton( - onPressed: state.syncing ? null : () => state.triggerSync(), - style: ElevatedButton.styleFrom( - backgroundColor: AppTheme.primary, - foregroundColor: Colors.white, - padding: const EdgeInsets.symmetric(vertical: 10), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - disabledBackgroundColor: AppTheme.primary.withValues(alpha: 0.4), - ), - child: Text(state.syncing ? 'Syncing…' : 'Sync Now', - style: const TextStyle(fontSize: 13)), - ), - ), - ], - ), - if (relTime != null) ...[ - const SizedBox(height: 6), - Row( - children: [ - Text('Last sync: $relTime', - style: TextStyle(fontSize: 11, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4))), - if (state.lastSyncResult != null) ...[ - Text(' · ↑${state.lastSyncResult!.uploaded} ↓${state.lastSyncResult!.downloaded}', - style: TextStyle(fontSize: 11, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4))), - ], - ], - ), - ], - ], - const SizedBox(height: 24), - // Appearance - Text('APPEARANCE', - style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, - letterSpacing: 0.5, - color: (isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight).withValues(alpha: 0.5))), - const SizedBox(height: 12), - GestureDetector( - onTap: () => state.toggleDarkMode(), - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - border: Border.all(color: borderColor), - ), - child: Row( - children: [ - const Text('Dark mode', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500)), - const Spacer(), - AnimatedContainer( - duration: const Duration(milliseconds: 150), - width: 44, height: 24, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: state.darkMode ? AppTheme.primary : (isDark ? const Color(0xFF4B5563) : const Color(0xFFD1D5DB)), - ), - child: AnimatedAlign( - duration: const Duration(milliseconds: 150), - alignment: state.darkMode ? Alignment.centerRight : Alignment.centerLeft, - child: Container( - width: 20, height: 20, - margin: const EdgeInsets.symmetric(horizontal: 2), - decoration: const BoxDecoration(shape: BoxShape.circle, color: Colors.white), - ), - ), - ), - ], - ), - ), - ), - const SizedBox(height: 32), - Center( - child: Text('Flutter + Rust', - style: TextStyle(fontSize: 12, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.3))), - ), - ], - ), - ), - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/apps/flutter/lib/src/screens/setup_screen.dart b/apps/flutter/lib/src/screens/setup_screen.dart deleted file mode 100644 index ada62d7..0000000 --- a/apps/flutter/lib/src/screens/setup_screen.dart +++ /dev/null @@ -1,155 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:file_picker/file_picker.dart'; -import 'package:provider/provider.dart'; -import '../state/app_state.dart'; -import '../theme.dart'; - -class SetupScreen extends StatefulWidget { - const SetupScreen({super.key}); - - @override - State createState() => _SetupScreenState(); -} - -class _SetupScreenState extends State { - final _nameController = TextEditingController(); - String? _selectedPath; - - @override - void dispose() { - _nameController.dispose(); - super.dispose(); - } - - Future _pickFolder() async { - final result = await FilePicker.platform.getDirectoryPath(); - if (result != null) setState(() => _selectedPath = result); - } - - Future _create() async { - final name = _nameController.text.trim(); - if (name.isEmpty || _selectedPath == null) return; - await context.read().addWorkspace(name, _selectedPath!); - } - - @override - Widget build(BuildContext context) { - final isDark = Theme.of(context).brightness == Brightness.dark; - return Center( - child: Padding( - padding: const EdgeInsets.all(24), - child: Container( - constraints: const BoxConstraints(maxWidth: 384), - padding: const EdgeInsets.all(32), - decoration: BoxDecoration( - color: isDark ? AppTheme.cardDark : AppTheme.cardLight, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow(color: Colors.black.withValues(alpha: 0.15), blurRadius: 10, offset: const Offset(0, 4)), - ], - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Onyx', - style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, - color: isDark ? AppTheme.textDark : AppTheme.textLight)), - const SizedBox(height: 4), - Text('Create or open a workspace to get started.', - style: TextStyle(fontSize: 14, color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight)), - const SizedBox(height: 24), - // Workspace name label + input - Padding( - padding: const EdgeInsets.only(bottom: 4), - child: Text('Workspace name', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, - color: isDark ? AppTheme.textDark : AppTheme.textLight)), - ), - TextField( - controller: _nameController, - style: TextStyle(fontSize: 14, color: isDark ? AppTheme.textDark : AppTheme.textLight), - decoration: InputDecoration( - hintText: 'My Tasks', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: const BorderSide(color: AppTheme.primary), - ), - contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - isDense: true, - filled: false, - ), - ), - const SizedBox(height: 16), - // Folder label + picker row - Padding( - padding: const EdgeInsets.only(bottom: 4), - child: Text('Folder', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, - color: isDark ? AppTheme.textDark : AppTheme.textLight)), - ), - Row( - children: [ - Expanded( - child: TextField( - readOnly: true, - style: TextStyle(fontSize: 14, color: isDark ? AppTheme.textDark : AppTheme.textLight), - controller: TextEditingController(text: _selectedPath ?? ''), - decoration: InputDecoration( - hintText: 'Select a folder\u2026', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), - ), - contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - isDense: true, - filled: false, - ), - ), - ), - const SizedBox(width: 8), - ElevatedButton( - onPressed: _pickFolder, - style: ElevatedButton.styleFrom( - backgroundColor: AppTheme.primary, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - ), - child: const Text('Browse', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500)), - ), - ], - ), - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - child: ElevatedButton( - onPressed: (_nameController.text.trim().isNotEmpty && _selectedPath != null) ? _create : null, - style: ElevatedButton.styleFrom( - backgroundColor: AppTheme.primary, - foregroundColor: Colors.white, - disabledBackgroundColor: AppTheme.primary.withValues(alpha: 0.4), - disabledForegroundColor: Colors.white.withValues(alpha: 0.6), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - padding: const EdgeInsets.symmetric(vertical: 10), - ), - child: const Text('Create Workspace', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500)), - ), - ), - ], - ), - ), - ), - ); - } -} diff --git a/apps/flutter/lib/src/screens/tasks_screen.dart b/apps/flutter/lib/src/screens/tasks_screen.dart deleted file mode 100644 index c7bd4e4..0000000 --- a/apps/flutter/lib/src/screens/tasks_screen.dart +++ /dev/null @@ -1,874 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import '../rust/api.dart' as api; -import '../state/app_state.dart'; -import '../theme.dart'; -import '../widgets/custom_title_bar.dart'; -import '../widgets/task_item.dart'; -import '../widgets/task_detail_view.dart'; -import '../widgets/new_task_input.dart'; - -class TasksScreen extends StatefulWidget { - const TasksScreen({super.key}); - - @override - State createState() => _TasksScreenState(); -} - -class _TasksScreenState extends State with SingleTickerProviderStateMixin { - bool _drawerOpen = false; - bool _showCompleted = false; - bool _completedVisible = false; - bool _addingList = false; - bool _workspaceSwitcherOpen = false; - bool _newTaskOpen = false; - final _newListController = TextEditingController(); - final _newListFocus = FocusNode(); - late final AnimationController _newTaskAnim; - late final Animation _newTaskSlide; - late final Animation _newTaskFade; - - @override - void initState() { - super.initState(); - _newTaskAnim = AnimationController(vsync: this, duration: const Duration(milliseconds: 150)); - _newTaskSlide = Tween(begin: const Offset(0, 1), end: Offset.zero) - .animate(CurvedAnimation(parent: _newTaskAnim, curve: Curves.easeOut)); - _newTaskFade = CurvedAnimation(parent: _newTaskAnim, curve: Curves.easeOut); - } - - @override - void dispose() { - _newTaskAnim.dispose(); - _newListController.dispose(); - _newListFocus.dispose(); - super.dispose(); - } - - void _toggleDrawer() => setState(() { - _drawerOpen = !_drawerOpen; - if (!_drawerOpen) _workspaceSwitcherOpen = false; - }); - - void _closeDrawer() => setState(() { - _drawerOpen = false; - _workspaceSwitcherOpen = false; - _addingList = false; - }); - - void _showNewTask() { - final state = context.read(); - if (state.activeListId == null) return; - setState(() => _newTaskOpen = true); - _newTaskAnim.forward(); - } - - void _closeNewTask() { - _newTaskAnim.reverse().then((_) { - if (mounted) setState(() => _newTaskOpen = false); - }); - } - - Future _handleCreateTask(String title, String desc, {String? dueDate, bool hasTime = false}) async { - final state = context.read(); - final task = await state.createTask(title, desc); - if (task != null && dueDate != null) { - await state.updateTask(api.TaskDto( - id: task.id, title: task.title, description: task.description, - status: task.status, dueDate: dueDate, hasTime: hasTime, - createdAt: task.createdAt, updatedAt: task.updatedAt, parentId: task.parentId, - )); - } - _closeNewTask(); - } - - void _startAddingList() { - setState(() { - _addingList = true; - _newListController.clear(); - }); - WidgetsBinding.instance.addPostFrameCallback((_) => _newListFocus.requestFocus()); - } - - Future _submitNewList() async { - final name = _newListController.text.trim(); - if (name.isNotEmpty) await context.read().createList(name); - setState(() => _addingList = false); - } - - @override - Widget build(BuildContext context) { - final state = context.watch(); - final isDark = Theme.of(context).brightness == Brightness.dark; - - return LayoutBuilder(builder: (context, constraints) { - final width = constraints.maxWidth; - final drawerWidth = width * 0.8; - final hasDetail = state.selectedTask != null; - - return Stack( - clipBehavior: Clip.hardEdge, - children: [ - // Sliding container: drawer + main + detail - Positioned.fill( - child: ClipRect( - child: OverflowBox( - maxWidth: drawerWidth + width, - alignment: Alignment.centerLeft, - child: AnimatedSlide( - duration: const Duration(milliseconds: 150), - curve: Curves.easeOut, - offset: _drawerOpen ? Offset.zero : Offset(-drawerWidth / (drawerWidth + width), 0), - child: SizedBox( - width: drawerWidth + width, - child: Row( - children: [ - SizedBox(width: drawerWidth, child: _buildDrawer(state, isDark)), - SizedBox( - width: width, - child: _buildMainWithDetail(state, isDark, width), - ), - ], - ), - ), - ), - ), - ), - ), - // FAB button (centered, 56px, hidden when drawer/detail/newTask open) - if (!_drawerOpen && !hasDetail && !_newTaskOpen && state.activeListId != null) - Positioned( - bottom: 24, - left: 0, - right: 0, - child: Center( - child: SizedBox( - width: 56, - height: 56, - child: FloatingActionButton( - onPressed: _showNewTask, - backgroundColor: AppTheme.primary, - foregroundColor: Colors.white, - elevation: 6, - shape: const CircleBorder(), - child: const Icon(Icons.add, size: 28), - ), - ), - ), - ), - // New task overlay (animated, inside app bounds) - if (_newTaskOpen || _newTaskAnim.isAnimating) - Positioned.fill( - child: FadeTransition( - opacity: _newTaskFade, - child: GestureDetector( - onTap: _closeNewTask, - child: Container( - color: Colors.black.withValues(alpha: 0.4), - alignment: Alignment.bottomCenter, - child: GestureDetector( - onTap: () {}, - child: SlideTransition( - position: _newTaskSlide, - child: NewTaskInput(onCreate: _handleCreateTask), - ), - ), - ), - ), - ), - ), - ], - ); - }); - } - - Widget _buildMainWithDetail(AppState state, bool isDark, double totalWidth) { - final hasDetail = state.selectedTask != null; - return Stack( - clipBehavior: Clip.hardEdge, - children: [ - ClipRect( - child: OverflowBox( - maxWidth: totalWidth * 2, - alignment: Alignment.centerLeft, - child: AnimatedSlide( - duration: const Duration(milliseconds: 150), - curve: Curves.easeOut, - offset: hasDetail ? const Offset(-0.5, 0) : Offset.zero, - child: SizedBox( - width: totalWidth * 2, - child: Row( - children: [ - SizedBox(width: totalWidth, child: _buildMain(state, isDark)), - SizedBox( - width: totalWidth, - child: Container( - color: isDark ? AppTheme.surfaceDark : AppTheme.surfaceLight, - child: hasDetail - ? TaskDetailView(task: state.selectedTask!) - : const SizedBox.shrink(), - ), - ), - ], - ), - ), - ), - ), - ), - // Drawer shadow (narrow element at left edge casting right) - Positioned( - left: 0, - top: 0, - bottom: 0, - width: 1, - child: IgnorePointer( - child: AnimatedOpacity( - duration: const Duration(milliseconds: 150), - curve: Curves.easeOut, - opacity: _drawerOpen ? 1.0 : 0.0, - child: Container( - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.4), - blurRadius: 16, - offset: const Offset(4, 0), - ), - ], - ), - ), - ), - ), - ), - // Dim overlay when drawer is open - Positioned.fill( - child: IgnorePointer( - ignoring: !_drawerOpen, - child: GestureDetector( - onTap: _closeDrawer, - child: AnimatedOpacity( - duration: const Duration(milliseconds: 150), - curve: Curves.easeOut, - opacity: _drawerOpen ? 1.0 : 0.0, - child: Container( - color: Colors.black.withValues(alpha: 0.4), - ), - ), - ), - ), - ), - // Sync status indicator - Positioned( - bottom: 16, - right: 16, - child: IgnorePointer( - child: state.syncing - ? const SizedBox( - width: 20, height: 20, - child: CircularProgressIndicator( - strokeWidth: 2, color: AppTheme.primary)) - : state.lastSyncResult != null - ? Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), - decoration: BoxDecoration( - color: isDark ? Colors.white.withValues(alpha: 0.1) : Colors.black.withValues(alpha: 0.08), - borderRadius: BorderRadius.circular(12), - ), - child: Text( - '↑${state.lastSyncResult!.uploaded} ↓${state.lastSyncResult!.downloaded}', - style: TextStyle(fontSize: 11, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.6)), - ), - ) - : const SizedBox.shrink(), - ), - ), - ], - ); - } - - Widget _buildDrawer(AppState state, bool isDark) { - return Container( - color: isDark ? AppTheme.surfaceDark : AppTheme.surfaceLight, - child: Stack( - children: [ - Column( - children: [ - // Header: workspace switcher - GestureDetector( - onPanStart: (_) {}, - child: Container( - height: 44, - padding: const EdgeInsets.symmetric(horizontal: 12), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide(color: isDark ? AppTheme.borderDark : AppTheme.borderLight, width: 0.5), - ), - ), - child: Row( - children: [ - Expanded( - child: GestureDetector( - onTap: () => setState(() => _workspaceSwitcherOpen = !_workspaceSwitcherOpen), - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: Text( - state.config?.currentWorkspace ?? 'Workspace', - style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), - overflow: TextOverflow.ellipsis, - ), - ), - const SizedBox(width: 6), - AnimatedRotation( - turns: _workspaceSwitcherOpen ? 0.5 : 0, - duration: const Duration(milliseconds: 150), - child: Icon(Icons.expand_more, size: 14, - color: isDark ? AppTheme.textDark : AppTheme.textLight), - ), - ], - ), - ), - ), - ), - ], - ), - ), - ), - // List items - Expanded( - child: ListView( - padding: const EdgeInsets.symmetric(vertical: 8), - children: [ - for (final list in state.lists) - _ListTile( - list: list, - isActive: list.id == state.activeListId, - onTap: () { - state.selectList(list.id); - _closeDrawer(); - }, - onDelete: () => state.deleteList(list.id), - onRename: (newName) => state.renameList(list.id, newName), - onToggleGroupByDueDate: () => state.setGroupByDueDate(list.id, !list.groupByDueDate), - ), - // New list button / input - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - child: _addingList - ? Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Row( - children: [ - Expanded( - child: TextField( - controller: _newListController, - focusNode: _newListFocus, - style: const TextStyle(fontSize: 14), - decoration: InputDecoration( - hintText: 'List name', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: const BorderSide(color: AppTheme.primary), - ), - contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - isDense: true, - ), - onSubmitted: (_) => _submitNewList(), - onTapOutside: (_) => setState(() => _addingList = false), - ), - ), - const SizedBox(width: 8), - ElevatedButton( - onPressed: _submitNewList, - style: ElevatedButton.styleFrom( - backgroundColor: AppTheme.primary, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - ), - child: const Text('Add', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500)), - ), - ], - ), - ) - : GestureDetector( - onTap: _startAddingList, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), - child: Text('+ New list', style: TextStyle(fontSize: 14, color: AppTheme.primary)), - ), - ), - ), - ], - ), - ), - // Footer: Settings button (matching Tauri) - GestureDetector( - onTap: () => state.setScreen('settings'), - child: Container( - decoration: BoxDecoration( - border: Border(top: BorderSide(color: isDark ? AppTheme.borderDark : AppTheme.borderLight, width: 0.5)), - ), - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), - child: Row( - children: [ - Icon(Icons.settings, size: 18, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.5)), - const SizedBox(width: 8), - Text('Settings', style: TextStyle(fontSize: 14, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.5))), - ], - ), - ), - ), - ], - ), - // Workspace switcher popup backdrop - if (_workspaceSwitcherOpen) - Positioned.fill( - child: GestureDetector( - onTap: () => setState(() => _workspaceSwitcherOpen = false), - behavior: HitTestBehavior.opaque, - child: const SizedBox.expand(), - ), - ), - // Workspace switcher popup menu - Positioned( - left: 8, - right: 8, - top: 48, - child: AnimatedScale( - scale: _workspaceSwitcherOpen ? 1.0 : 0.9, - duration: const Duration(milliseconds: 150), - curve: Curves.easeOut, - alignment: Alignment.topLeft, - child: AnimatedOpacity( - opacity: _workspaceSwitcherOpen ? 1.0 : 0.0, - duration: const Duration(milliseconds: 150), - curve: Curves.easeOut, - child: IgnorePointer( - ignoring: !_workspaceSwitcherOpen, - child: Container( - constraints: const BoxConstraints(maxHeight: 200), - decoration: BoxDecoration( - color: isDark ? AppTheme.cardDark : AppTheme.surfaceLight, - borderRadius: BorderRadius.circular(8), - boxShadow: [ - BoxShadow(color: Colors.black.withValues(alpha: 0.2), blurRadius: 12, offset: const Offset(0, 4)), - ], - ), - clipBehavior: Clip.antiAlias, - child: state.config != null - ? ListView( - shrinkWrap: true, - padding: const EdgeInsets.symmetric(vertical: 4), - children: [ - for (final ws in state.config!.workspaces) - _WorkspaceMenuItem( - name: ws.name, - path: ws.path, - isActive: ws.name == state.config?.currentWorkspace, - onTap: () { - state.switchWorkspace(ws.name); - setState(() => _workspaceSwitcherOpen = false); - }, - ), - // Add workspace - _WorkspaceMenuItem( - icon: null, - name: '+ Add workspace', - path: null, - isActive: false, - isAccent: true, - showDivider: true, - onTap: () { - setState(() => _workspaceSwitcherOpen = false); - state.setScreen('setup'); - }, - ), - ], - ) - : const SizedBox.shrink(), - ), - ), - ), - ), - ), - ], - ), - ); - } - - Widget _buildMain(AppState state, bool isDark) { - return Column( - children: [ - // Title bar with menu button + centered title + close - CustomTitleBar( - leading: GestureDetector( - onTap: _toggleDrawer, - child: Padding( - padding: const EdgeInsets.all(6), - child: Icon(Icons.menu, size: 20, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.6)), - ), - ), - title: state.activeList?.title ?? 'Tasks', - centerTitle: true, - ), - // Task list - Expanded( - child: state.lists.isEmpty - ? Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text('No lists yet', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.6))), - const SizedBox(height: 4), - Text('Tap the list name above to create one', style: TextStyle(fontSize: 14, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4))), - ], - ), - ) - : state.activeList == null - ? Center( - child: Text('Select a list', style: TextStyle( - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4))), - ) - : _buildTaskList(state, isDark), - ), - ], - ); - } - - Widget _buildTaskList(AppState state, bool isDark) { - if (state.pendingTasks.isEmpty && state.completedTasks.isEmpty) { - return Center( - child: Padding( - padding: const EdgeInsets.all(32), - child: Text('No tasks. Add one below.', style: TextStyle(fontSize: 14, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4))), - ), - ); - } - return ReorderableListView( - buildDefaultDragHandles: false, - onReorder: (oldIndex, newIndex) { - if (newIndex > oldIndex) newIndex--; - final task = state.pendingTasks[oldIndex]; - state.reorderTask(task.id, newIndex); - }, - proxyDecorator: (child, index, animation) { - return AnimatedBuilder( - animation: animation, - builder: (context, child) => Material( - elevation: 4, - color: isDark ? AppTheme.surfaceDark : AppTheme.surfaceLight, - child: child, - ), - child: child, - ); - }, - footer: _buildCompletedSection(state, isDark), - children: [ - for (var i = 0; i < state.pendingTasks.length; i++) - ReorderableDragStartListener( - key: ValueKey(state.pendingTasks[i].id), - index: i, - child: TaskItem( - task: state.pendingTasks[i], - onToggle: () => state.toggleTask(state.pendingTasks[i].id), - onTap: () => state.selectTask(state.pendingTasks[i].id), - ), - ), - ], - ); - } - - Widget? _buildCompletedSection(AppState state, bool isDark) { - if (state.completedTasks.isEmpty) return null; - return Column( - children: [ - const SizedBox(height: 16), - // Completed header (matching Tauri: full-width, border-top, text left, chevron right) - GestureDetector( - onTap: () { - setState(() { - if (_showCompleted) { - _showCompleted = false; - Future.delayed(const Duration(milliseconds: 150), () { - if (mounted) setState(() => _completedVisible = false); - }); - } else { - _completedVisible = true; - WidgetsBinding.instance.addPostFrameCallback((_) { - if (mounted) setState(() => _showCompleted = true); - }); - } - }); - }, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - decoration: BoxDecoration( - color: isDark ? AppTheme.surfaceDark : AppTheme.surfaceLight, - border: Border(top: BorderSide(color: isDark ? AppTheme.borderDark : AppTheme.borderLight, width: 0.5)), - ), - child: Row( - children: [ - Expanded( - child: Text( - 'Completed (${state.completedTasks.length})', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight, - ), - ), - ), - AnimatedRotation( - turns: _showCompleted ? 0.25 : 0, - duration: const Duration(milliseconds: 150), - child: Icon(Icons.chevron_right, size: 16, - color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight), - ), - ], - ), - ), - ), - if (_completedVisible) - AnimatedOpacity( - duration: const Duration(milliseconds: 150), - opacity: _showCompleted ? 1.0 : 0.0, - child: AnimatedSlide( - duration: const Duration(milliseconds: 150), - offset: _showCompleted ? Offset.zero : const Offset(0, -0.05), - child: Column( - children: [ - for (final task in state.completedTasks) - TaskItem( - task: task, - onToggle: () => state.toggleTask(task.id), - onTap: () => state.selectTask(task.id), - ), - ], - ), - ), - ), - ], - ); - } -} - -class _ListTile extends StatefulWidget { - final dynamic list; - final bool isActive; - final VoidCallback onTap; - final VoidCallback onDelete; - final void Function(String newName) onRename; - final VoidCallback onToggleGroupByDueDate; - - const _ListTile({required this.list, required this.isActive, required this.onTap, required this.onDelete, required this.onRename, required this.onToggleGroupByDueDate}); - - @override - State<_ListTile> createState() => _ListTileState(); -} - -class _ListTileState extends State<_ListTile> { - bool _hovering = false; - - void _showRenameDialog(BuildContext context) { - final controller = TextEditingController(text: widget.list.title); - showDialog( - context: context, - builder: (ctx) => AlertDialog( - title: const Text('Rename list'), - content: TextField( - controller: controller, - autofocus: true, - decoration: const InputDecoration(hintText: 'List name'), - onSubmitted: (value) { - Navigator.pop(ctx); - if (value.trim().isNotEmpty && value.trim() != widget.list.title) { - widget.onRename(value.trim()); - } - }, - ), - actions: [ - TextButton(onPressed: () => Navigator.pop(ctx), child: const Text('Cancel')), - TextButton( - onPressed: () { - Navigator.pop(ctx); - final name = controller.text.trim(); - if (name.isNotEmpty && name != widget.list.title) widget.onRename(name); - }, - child: const Text('Rename'), - ), - ], - ), - ); - } - - @override - Widget build(BuildContext context) { - final isDark = Theme.of(context).brightness == Brightness.dark; - return MouseRegion( - onEnter: (_) => setState(() => _hovering = true), - onExit: (_) => setState(() => _hovering = false), - child: GestureDetector( - onTap: widget.onTap, - onSecondaryTapUp: (details) { - showMenu( - context: context, - position: RelativeRect.fromLTRB(details.globalPosition.dx, details.globalPosition.dy, 0, 0), - items: [ - PopupMenuItem( - onTap: () => _showRenameDialog(context), - child: const Text('Rename', style: TextStyle(fontSize: 13)), - ), - PopupMenuItem( - onTap: widget.onToggleGroupByDueDate, - child: Row( - children: [ - Expanded(child: Text('Group by due date', style: const TextStyle(fontSize: 13))), - if (widget.list.groupByDueDate) - const Icon(Icons.check, size: 16, color: AppTheme.primary), - ], - ), - ), - PopupMenuItem( - onTap: widget.onDelete, - child: const Text('Delete', style: TextStyle(color: AppTheme.danger, fontSize: 13)), - ), - ], - ); - }, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), - margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 1), - decoration: BoxDecoration( - color: _hovering && !widget.isActive - ? (isDark ? Colors.white.withValues(alpha: 0.1) : Colors.black.withValues(alpha: 0.05)) - : Colors.transparent, - borderRadius: BorderRadius.circular(6), - ), - child: Row( - children: [ - if (widget.isActive) - Padding( - padding: const EdgeInsets.only(right: 8), - child: Icon(Icons.check, size: 16, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.5)), - ), - Expanded( - child: Text( - widget.list.title, - style: TextStyle( - fontSize: 14, - fontWeight: widget.isActive ? FontWeight.w700 : FontWeight.normal, - ), - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ), - ), - ); - } -} - -class _WorkspaceMenuItem extends StatefulWidget { - final String name; - final String? path; - final bool isActive; - final bool isAccent; - final bool showDivider; - final IconData? icon; - final VoidCallback onTap; - - const _WorkspaceMenuItem({ - required this.name, - this.path, - required this.isActive, - this.isAccent = false, - this.showDivider = false, - this.icon, - required this.onTap, - }); - - @override - State<_WorkspaceMenuItem> createState() => _WorkspaceMenuItemState(); -} - -class _WorkspaceMenuItemState extends State<_WorkspaceMenuItem> { - bool _hovering = false; - - @override - Widget build(BuildContext context) { - final isDark = Theme.of(context).brightness == Brightness.dark; - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - if (widget.showDivider) - Divider(height: 1, thickness: 0.5, color: isDark ? AppTheme.borderDark : AppTheme.borderLight), - MouseRegion( - onEnter: (_) => setState(() => _hovering = true), - onExit: (_) => setState(() => _hovering = false), - child: GestureDetector( - onTap: widget.onTap, - child: Container( - color: _hovering - ? (isDark ? Colors.white.withValues(alpha: 0.1) : Colors.black.withValues(alpha: 0.05)) - : Colors.transparent, - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), - child: Row( - children: [ - if (widget.isActive) - Padding( - padding: const EdgeInsets.only(right: 8), - child: Icon(Icons.check, size: 16, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.5)), - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(widget.name, - style: TextStyle( - fontSize: 14, - fontWeight: widget.isActive ? FontWeight.w700 : FontWeight.normal, - color: widget.isAccent ? AppTheme.primary : null, - ), - overflow: TextOverflow.ellipsis), - if (widget.path != null) - Text(widget.path!, - style: TextStyle(fontSize: 12, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4)), - overflow: TextOverflow.ellipsis), - ], - ), - ), - ], - ), - ), - ), - ), - ], - ); - } -} diff --git a/apps/flutter/lib/src/state/app_state.dart b/apps/flutter/lib/src/state/app_state.dart deleted file mode 100644 index 7b131c8..0000000 --- a/apps/flutter/lib/src/state/app_state.dart +++ /dev/null @@ -1,322 +0,0 @@ -import 'dart:async'; -import 'package:flutter/material.dart'; -import '../rust/api.dart' as api; - -class AppState extends ChangeNotifier { - String screen = 'setup'; - api.AppConfigDto? config; - List lists = []; - String? activeListId; - List tasks = []; - bool darkMode = true; - StreamSubscription? _watcherSub; - bool syncing = false; - String syncMode = 'full'; - api.SyncResultDto? lastSyncResult; - String? error; - - // Selected task for detail view - String? selectedTaskId; - - api.TaskListDto? get activeList => - activeListId == null ? null : lists.cast().firstWhere((l) => l?.id == activeListId, orElse: () => null); - - List get pendingTasks => tasks.where((t) => t.status == 'backlog').toList(); - List get completedTasks => tasks.where((t) => t.status == 'completed').toList(); - - bool get hasWorkspace => - config != null && config!.currentWorkspace != null && config!.workspaces.isNotEmpty; - - api.TaskDto? get selectedTask => - selectedTaskId == null ? null : tasks.cast().firstWhere((t) => t?.id == selectedTaskId, orElse: () => null); - - Future _startWatcher(String path) async { - _watcherSub?.cancel(); - try { - final stream = await api.watchWorkspaceChanges(path: path); - _watcherSub = stream.listen((_) => loadLists()); - } catch (_) {} - } - - Future loadConfig() async { - try { - config = await api.getConfig(); - if (hasWorkspace) { - screen = 'tasks'; - await loadLists(); - final ws = config!.workspaces.firstWhere((w) => w.name == config!.currentWorkspace); - _startWatcher(ws.path); - } else { - screen = 'setup'; - } - } catch (e) { - config = const api.AppConfigDto(workspaces: [], currentWorkspace: null); - screen = 'setup'; - } - notifyListeners(); - } - - Future addWorkspace(String name, String path) async { - try { - await api.initWorkspace(path: path); - await api.addWorkspace(name: name, path: path); - config = await api.getConfig(); - await loadLists(); - _startWatcher(path); - screen = 'tasks'; - error = null; - } catch (e) { - error = e.toString(); - } - notifyListeners(); - } - - Future switchWorkspace(String name) async { - try { - await api.setCurrentWorkspace(name: name); - config = await api.getConfig(); - activeListId = null; - await loadLists(); - final ws = config!.workspaces.firstWhere((w) => w.name == name); - _startWatcher(ws.path); - error = null; - } catch (e) { - error = e.toString(); - } - notifyListeners(); - } - - Future removeWorkspace(String name) async { - try { - await api.removeWorkspace(name: name); - config = await api.getConfig(); - if (!hasWorkspace) { - screen = 'setup'; - lists = []; - tasks = []; - activeListId = null; - } - } catch (e) { - error = e.toString(); - } - notifyListeners(); - } - - Future loadLists() async { - try { - lists = await api.getLists(); - if (lists.isNotEmpty && activeListId == null) { - activeListId = lists[0].id; - } - if (activeListId != null) await loadTasks(); - } catch (e) { - error = e.toString(); - } - } - - Future loadTasks() async { - if (activeListId == null) return; - try { - tasks = await api.listTasks(listId: activeListId!); - } catch (e) { - error = e.toString(); - } - } - - Future selectList(String id) async { - activeListId = id; - selectedTaskId = null; - await loadTasks(); - notifyListeners(); - } - - Future createList(String name) async { - try { - final list = await api.createList(name: name); - lists = [...lists, list]; - activeListId = list.id; - tasks = []; - error = null; - } catch (e) { - error = e.toString(); - } - notifyListeners(); - } - - Future deleteList(String id) async { - try { - await api.deleteList(listId: id); - lists = lists.where((l) => l.id != id).toList(); - if (activeListId == id) { - activeListId = lists.isNotEmpty ? lists[0].id : null; - if (activeListId != null) { - await loadTasks(); - } else { - tasks = []; - } - } - } catch (e) { - error = e.toString(); - } - notifyListeners(); - } - - Future createTask(String title, String description) async { - if (activeListId == null) return null; - try { - final task = await api.createTask(listId: activeListId!, title: title, description: description); - tasks = [...tasks, task]; - error = null; - notifyListeners(); - return task; - } catch (e) { - error = e.toString(); - notifyListeners(); - return null; - } - } - - Future toggleTask(String taskId) async { - if (activeListId == null) return; - try { - final updated = await api.toggleTask(listId: activeListId!, taskId: taskId); - if (updated.status == 'backlog') { - tasks = [updated, ...tasks.where((t) => t.id != taskId)]; - try { - await api.reorderTask(listId: activeListId!, taskId: taskId, newPosition: 0); - } catch (_) {} - } else { - tasks = tasks.map((t) => t.id == taskId ? updated : t).toList(); - } - } catch (e) { - error = e.toString(); - } - notifyListeners(); - } - - Future updateTask(api.TaskDto task) async { - if (activeListId == null) return; - try { - await api.updateTask(listId: activeListId!, task: task); - tasks = tasks.map((t) => t.id == task.id ? task : t).toList(); - } catch (e) { - error = e.toString(); - } - notifyListeners(); - } - - Future reorderTask(String taskId, int newPosition) async { - if (activeListId == null) return; - try { - await api.reorderTask(listId: activeListId!, taskId: taskId, newPosition: newPosition); - await loadTasks(); - } catch (e) { - error = e.toString(); - } - notifyListeners(); - } - - Future moveTask(String taskId, String targetListId) async { - if (activeListId == null) return; - try { - await api.moveTask(fromListId: activeListId!, toListId: targetListId, taskId: taskId); - tasks = tasks.where((t) => t.id != taskId).toList(); - if (selectedTaskId == taskId) selectedTaskId = null; - } catch (e) { - error = e.toString(); - } - notifyListeners(); - } - - Future renameList(String listId, String newName) async { - try { - await api.renameList(listId: listId, newName: newName); - await loadLists(); - } catch (e) { - error = e.toString(); - } - notifyListeners(); - } - - Future setGroupByDueDate(String listId, bool enabled) async { - try { - await api.setGroupByDueDate(listId: listId, enabled: enabled); - await loadLists(); - if (listId == activeListId) await loadTasks(); - } catch (e) { - error = e.toString(); - } - notifyListeners(); - } - - Future deleteTask(String taskId) async { - if (activeListId == null) return; - try { - await api.deleteTask(listId: activeListId!, taskId: taskId); - tasks = tasks.where((t) => t.id != taskId).toList(); - if (selectedTaskId == taskId) selectedTaskId = null; - } catch (e) { - error = e.toString(); - } - notifyListeners(); - } - - void selectTask(String? taskId) { - selectedTaskId = taskId; - notifyListeners(); - } - - void setSyncMode(String mode) { - syncMode = mode; - notifyListeners(); - } - - Future triggerSync() async { - if (config?.currentWorkspace == null) return; - final wsName = config!.currentWorkspace!; - final ws = config!.workspaces.firstWhere((w) => w.name == wsName); - if (ws.webdavUrl == null) { - error = 'No WebDAV URL configured'; - notifyListeners(); - return; - } - syncing = true; - error = null; - notifyListeners(); - try { - final domain = Uri.parse(ws.webdavUrl!).host; - final creds = await api.loadCredentials(domain: domain); - final result = await api.syncWorkspaceCmd( - workspaceName: wsName, - workspacePath: ws.path, - webdavUrl: ws.webdavUrl!, - username: creds[0], - password: creds[1], - mode: syncMode, - ); - lastSyncResult = result; - if (result.errors.isNotEmpty) error = result.errors.join('; '); - config = await api.getConfig(); - await loadLists(); - } catch (e) { - error = e.toString(); - } - syncing = false; - notifyListeners(); - } - - void toggleDarkMode() { - darkMode = !darkMode; - notifyListeners(); - } - - void setScreen(String s) { - screen = s; - notifyListeners(); - } - - void clearError() { - error = null; - notifyListeners(); - } -} diff --git a/apps/flutter/lib/src/theme.dart b/apps/flutter/lib/src/theme.dart deleted file mode 100644 index eecd8d0..0000000 --- a/apps/flutter/lib/src/theme.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; - -class AppTheme { - static const primary = Color(0xFF2D87B8); - static const primaryHover = Color(0xFF2474A0); - static const danger = Color(0xFFEF4444); - - static const surfaceLight = Color(0xFFFFFFFF); - static const cardLight = Color(0xFFF9FAFB); - static const textLight = Color(0xFF1F2937); - static const textSecondaryLight = Color(0xFF6B7280); - static const borderLight = Color(0xFFE5E7EB); - - static const surfaceDark = Color(0xFF242424); - static const cardDark = Color(0xFF303030); - static const textDark = Color(0xFFE5E7EB); - static const textSecondaryDark = Color(0xFF9CA3AF); - static const borderDark = Color(0xFF3D3D3D); - - static ThemeData light() => ThemeData( - brightness: Brightness.light, - colorScheme: const ColorScheme.light( - primary: primary, - surface: surfaceLight, - error: danger, - ), - scaffoldBackgroundColor: surfaceLight, - textTheme: GoogleFonts.notoSansTextTheme(ThemeData.light().textTheme), - dividerColor: borderLight, - cardColor: cardLight, - ); - - static ThemeData dark() => ThemeData( - brightness: Brightness.dark, - colorScheme: const ColorScheme.dark( - primary: primary, - surface: surfaceDark, - error: danger, - ), - scaffoldBackgroundColor: surfaceDark, - textTheme: GoogleFonts.notoSansTextTheme(ThemeData.dark().textTheme), - dividerColor: borderDark, - cardColor: cardDark, - ); -} diff --git a/apps/flutter/lib/src/widgets/custom_title_bar.dart b/apps/flutter/lib/src/widgets/custom_title_bar.dart deleted file mode 100644 index f2e834c..0000000 --- a/apps/flutter/lib/src/widgets/custom_title_bar.dart +++ /dev/null @@ -1,101 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:window_manager/window_manager.dart'; -import '../theme.dart'; - -class CustomTitleBar extends StatelessWidget { - final Widget? leading; - final String? title; - final bool centerTitle; - final List? actions; - final bool showClose; - - const CustomTitleBar({super.key, this.leading, this.title, this.centerTitle = false, this.actions, this.showClose = true}); - - @override - Widget build(BuildContext context) { - final isDark = Theme.of(context).brightness == Brightness.dark; - return GestureDetector( - onPanStart: (_) => windowManager.startDragging(), - child: Container( - height: 44, - padding: const EdgeInsets.symmetric(horizontal: 8), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: isDark ? AppTheme.borderDark : AppTheme.borderLight, - width: 0.5, - ), - ), - ), - child: Row( - children: [ - if (leading != null) leading!, - if (title != null) - Expanded( - child: centerTitle - ? Center( - child: Text( - title!, - style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), - overflow: TextOverflow.ellipsis, - ), - ) - : Text( - title!, - style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), - overflow: TextOverflow.ellipsis, - ), - ) - else - const Expanded(child: SizedBox.shrink()), - if (actions != null) ...actions!, - if (showClose) ...[ - const SizedBox(width: 4), - _TitleBarButton( - icon: Icons.close, - onPressed: () => windowManager.close(), - hoverColor: AppTheme.danger, - ), - ], - ], - ), - ), - ); - } -} - -class _TitleBarButton extends StatefulWidget { - final IconData icon; - final VoidCallback onPressed; - final Color hoverColor; - - const _TitleBarButton({required this.icon, required this.onPressed, required this.hoverColor}); - - @override - State<_TitleBarButton> createState() => _TitleBarButtonState(); -} - -class _TitleBarButtonState extends State<_TitleBarButton> { - bool _hovering = false; - - @override - Widget build(BuildContext context) { - return MouseRegion( - onEnter: (_) => setState(() => _hovering = true), - onExit: (_) => setState(() => _hovering = false), - child: GestureDetector( - onTap: widget.onPressed, - child: Container( - width: 28, - height: 28, - decoration: BoxDecoration( - color: _hovering ? Colors.black.withValues(alpha: 0.1) : Colors.transparent, - borderRadius: BorderRadius.circular(6), - ), - child: Icon(widget.icon, size: 14, - color: _hovering ? widget.hoverColor : Theme.of(context).iconTheme.color?.withValues(alpha: 0.5)), - ), - ), - ); - } -} diff --git a/apps/flutter/lib/src/widgets/date_time_picker.dart b/apps/flutter/lib/src/widgets/date_time_picker.dart deleted file mode 100644 index 3cd0109..0000000 --- a/apps/flutter/lib/src/widgets/date_time_picker.dart +++ /dev/null @@ -1,209 +0,0 @@ -import 'package:flutter/material.dart'; -import '../theme.dart'; - -class DateTimePicker extends StatefulWidget { - final DateTime? initialDate; - final bool initialHasTime; - final void Function(DateTime date, bool hasTime) onDone; - final VoidCallback onClear; - - const DateTimePicker({super.key, this.initialDate, this.initialHasTime = false, required this.onDone, required this.onClear}); - - @override - State createState() => _DateTimePickerState(); -} - -class _DateTimePickerState extends State { - late DateTime _viewMonth; - DateTime? _selected; - bool _showTime = false; - int _hour = 12; - int _minute = 0; - - @override - void initState() { - super.initState(); - _selected = widget.initialDate; - _viewMonth = widget.initialDate ?? DateTime.now(); - if (widget.initialDate != null) { - _hour = widget.initialDate!.hour; - _minute = widget.initialDate!.minute; - _showTime = widget.initialHasTime; - } - } - - void _prevMonth() => setState(() => _viewMonth = DateTime(_viewMonth.year, _viewMonth.month - 1)); - void _nextMonth() => setState(() => _viewMonth = DateTime(_viewMonth.year, _viewMonth.month + 1)); - - void _done() { - if (_selected == null) return; - final result = _showTime - ? DateTime(_selected!.year, _selected!.month, _selected!.day, _hour, _minute) - : DateTime(_selected!.year, _selected!.month, _selected!.day); - widget.onDone(result, _showTime); - Navigator.of(context).pop(); - } - - void _clear() { - widget.onClear(); - Navigator.of(context).pop(); - } - - @override - Widget build(BuildContext context) { - final isDark = Theme.of(context).brightness == Brightness.dark; - final now = DateTime.now(); - final today = DateTime(now.year, now.month, now.day); - final firstDay = DateTime(_viewMonth.year, _viewMonth.month, 1); - final lastDay = DateTime(_viewMonth.year, _viewMonth.month + 1, 0); - final startWeekday = firstDay.weekday; // 1=Mon - const dayNames = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su']; - const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; - - return Padding( - padding: const EdgeInsets.all(16), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - // Header - Row( - children: [ - const Text('Date & Time', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600)), - const Spacer(), - GestureDetector( - onTap: _done, - child: const Text('Done', style: TextStyle(fontSize: 14, color: AppTheme.primary, fontWeight: FontWeight.w500)), - ), - ], - ), - const SizedBox(height: 16), - // Month navigation - Row( - children: [ - GestureDetector(onTap: _prevMonth, child: const Icon(Icons.chevron_left, size: 20)), - Expanded( - child: Center( - child: Text('${months[_viewMonth.month - 1]} ${_viewMonth.year}', - style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500)), - ), - ), - GestureDetector(onTap: _nextMonth, child: const Icon(Icons.chevron_right, size: 20)), - ], - ), - const SizedBox(height: 12), - // Day names - Row( - children: [ - for (final name in dayNames) - Expanded( - child: Center( - child: Text(name, style: TextStyle(fontSize: 11, color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight)), - ), - ), - ], - ), - const SizedBox(height: 4), - // Calendar grid - ...List.generate(6, (week) { - return Row( - children: List.generate(7, (dow) { - final dayIndex = week * 7 + dow - (startWeekday - 1); - if (dayIndex < 0 || dayIndex >= lastDay.day) return const Expanded(child: SizedBox(height: 32)); - final day = dayIndex + 1; - final date = DateTime(_viewMonth.year, _viewMonth.month, day); - final isToday = date == today; - final isSelected = _selected != null && date.year == _selected!.year && date.month == _selected!.month && date.day == _selected!.day; - return Expanded( - child: GestureDetector( - onTap: () => setState(() => _selected = date), - child: Container( - height: 32, - alignment: Alignment.center, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: isSelected ? AppTheme.primary : Colors.transparent, - ), - child: Text( - '$day', - style: TextStyle( - fontSize: 13, - fontWeight: isToday ? FontWeight.w700 : FontWeight.normal, - color: isSelected ? Colors.white : (isToday ? AppTheme.primary : null), - ), - ), - ), - ), - ); - }), - ); - }), - const SizedBox(height: 8), - // Time section - Container( - padding: const EdgeInsets.only(top: 12), - decoration: BoxDecoration( - border: Border(top: BorderSide(color: isDark ? AppTheme.borderDark : AppTheme.borderLight, width: 0.5)), - ), - child: _showTime - ? Row( - children: [ - Text('Time', style: TextStyle(fontSize: 13, color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight)), - const SizedBox(width: 12), - // Hour - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - border: Border.all(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), - borderRadius: BorderRadius.circular(6), - ), - child: DropdownButton( - value: _hour, - underline: const SizedBox.shrink(), - isDense: true, - style: TextStyle(fontSize: 14, color: isDark ? AppTheme.textDark : AppTheme.textLight), - items: List.generate(24, (i) => DropdownMenuItem(value: i, child: Text(i.toString().padLeft(2, '0')))), - onChanged: (v) => setState(() => _hour = v!), - ), - ), - const Padding(padding: EdgeInsets.symmetric(horizontal: 6), child: Text(':', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600))), - // Minute - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - border: Border.all(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), - borderRadius: BorderRadius.circular(6), - ), - child: DropdownButton( - value: _minute, - underline: const SizedBox.shrink(), - isDense: true, - style: TextStyle(fontSize: 14, color: isDark ? AppTheme.textDark : AppTheme.textLight), - items: List.generate(12, (i) => i * 5).map((m) => DropdownMenuItem(value: m, child: Text(m.toString().padLeft(2, '0')))).toList(), - onChanged: (v) => setState(() => _minute = v!), - ), - ), - const Spacer(), - GestureDetector( - onTap: () => setState(() => _showTime = false), - child: Icon(Icons.close, size: 18, color: (isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight).withAlpha(160)), - ), - ], - ) - : GestureDetector( - onTap: () => setState(() { _showTime = true; if (_selected == null) _selected = DateTime.now(); }), - child: Text('Set time', style: TextStyle(fontSize: 13, color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight)), - ), - ), - // Clear button - if (widget.initialDate != null) ...[ - const SizedBox(height: 12), - GestureDetector( - onTap: _clear, - child: const Text('Clear date', style: TextStyle(fontSize: 13, color: AppTheme.danger)), - ), - ], - ], - ), - ); - } -} diff --git a/apps/flutter/lib/src/widgets/new_task_input.dart b/apps/flutter/lib/src/widgets/new_task_input.dart deleted file mode 100644 index c88688c..0000000 --- a/apps/flutter/lib/src/widgets/new_task_input.dart +++ /dev/null @@ -1,201 +0,0 @@ -import 'package:flutter/material.dart'; -import '../theme.dart'; -import 'date_time_picker.dart'; - -class NewTaskInput extends StatefulWidget { - final Future Function(String title, String description, {String? dueDate, bool hasTime}) onCreate; - - const NewTaskInput({super.key, required this.onCreate}); - - @override - State createState() => _NewTaskInputState(); -} - -class _NewTaskInputState extends State { - final _titleController = TextEditingController(); - final _descController = TextEditingController(); - final _titleFocus = FocusNode(); - DateTime? _selectedDate; - bool _selectedHasTime = false; - - @override - void initState() { - super.initState(); - _titleFocus.requestFocus(); - } - - @override - void dispose() { - _titleController.dispose(); - _descController.dispose(); - _titleFocus.dispose(); - super.dispose(); - } - - Future _submit() async { - final title = _titleController.text.trim(); - if (title.isEmpty) return; - await widget.onCreate(title, _descController.text.trim(), dueDate: _selectedDate?.toUtc().toIso8601String(), hasTime: _selectedHasTime); - } - - void _pickDate() { - showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(top: Radius.circular(16)), - ), - builder: (_) => DateTimePicker( - initialDate: _selectedDate, - initialHasTime: _selectedHasTime, - onDone: (date, hasTime) => setState(() { _selectedDate = date; _selectedHasTime = hasTime; }), - onClear: () => setState(() { _selectedDate = null; _selectedHasTime = false; }), - ), - ); - } - - String _formatDateChip(DateTime d) { - final now = DateTime.now(); - final today = DateTime(now.year, now.month, now.day); - final taskDate = DateTime(d.year, d.month, d.day); - final dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; - final day = dayNames[d.weekday % 7]; - final pad = (int n) => n.toString().padLeft(2, '0'); - final timePart = _selectedHasTime ? ', ${pad(d.hour)}:${pad(d.minute)}' : ''; - if (taskDate == today) return 'Today$timePart'; - return '$day, ${pad(d.day)}/${pad(d.month)}$timePart'; - } - - @override - Widget build(BuildContext context) { - final isDark = Theme.of(context).brightness == Brightness.dark; - return Container( - decoration: BoxDecoration( - color: isDark ? AppTheme.cardDark : AppTheme.surfaceLight, - borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), - ), - child: Padding( - padding: EdgeInsets.only( - left: 16, right: 16, top: 16, - bottom: MediaQuery.of(context).viewInsets.bottom + 16, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Title input - TextField( - controller: _titleController, - focusNode: _titleFocus, - style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w700), - decoration: InputDecoration( - hintText: 'Task title', - hintStyle: TextStyle( - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.3)), - border: InputBorder.none, - isDense: true, - contentPadding: EdgeInsets.zero, - ), - onSubmitted: (_) => _submit(), - ), - const SizedBox(height: 16), - // Description with icon (matching Tauri) - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(top: 2), - child: Icon(Icons.subject, size: 20, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4)), - ), - const SizedBox(width: 12), - Expanded( - child: TextField( - controller: _descController, - style: const TextStyle(fontSize: 14), - maxLines: 3, - decoration: InputDecoration( - hintText: 'Add details', - hintStyle: TextStyle( - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4)), - border: InputBorder.none, - isDense: true, - contentPadding: EdgeInsets.zero, - ), - ), - ), - ], - ), - const SizedBox(height: 16), - // Date/time with icon (matching Tauri) - Row( - children: [ - Icon(Icons.access_time, size: 20, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4)), - const SizedBox(width: 12), - if (_selectedDate != null) - Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(100), - border: Border.all(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), - color: isDark ? Colors.white.withValues(alpha: 0.1) : Colors.black.withValues(alpha: 0.05), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - GestureDetector( - onTap: _pickDate, - child: Text( - _formatDateChip(_selectedDate!), - style: const TextStyle(fontSize: 14), - ), - ), - const SizedBox(width: 6), - GestureDetector( - onTap: () => setState(() => _selectedDate = null), - child: Icon(Icons.close, size: 14, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4)), - ), - ], - ), - ) - else - GestureDetector( - onTap: _pickDate, - child: Text('Add date/time', style: TextStyle(fontSize: 14, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4))), - ), - ], - ), - const SizedBox(height: 16), - // Save button (centered, matching Tauri) - Container( - padding: const EdgeInsets.only(top: 12), - decoration: BoxDecoration( - border: Border(top: BorderSide(color: isDark ? AppTheme.borderDark : AppTheme.borderLight, width: 0.5)), - ), - child: SizedBox( - width: double.infinity, - child: GestureDetector( - onTap: _submit, - child: Text('Save', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - color: _titleController.text.trim().isNotEmpty - ? AppTheme.primary - : AppTheme.primary.withValues(alpha: 0.3), - fontWeight: FontWeight.w500, - ), - ), - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/flutter/lib/src/widgets/task_detail_view.dart b/apps/flutter/lib/src/widgets/task_detail_view.dart deleted file mode 100644 index 0e0311a..0000000 --- a/apps/flutter/lib/src/widgets/task_detail_view.dart +++ /dev/null @@ -1,430 +0,0 @@ -import 'dart:async'; -import 'package:flutter/material.dart'; -import 'package:window_manager/window_manager.dart'; -import '../rust/api.dart' as api; -import '../state/app_state.dart'; -import '../theme.dart'; -import 'package:provider/provider.dart'; -import 'date_time_picker.dart'; - -class TaskDetailView extends StatefulWidget { - final api.TaskDto task; - - const TaskDetailView({super.key, required this.task}); - - @override - State createState() => _TaskDetailViewState(); -} - -class _TaskDetailViewState extends State with SingleTickerProviderStateMixin { - late TextEditingController _titleController; - late TextEditingController _descController; - Timer? _debounce; - bool _showMenu = false; - late final AnimationController _menuAnim; - late final Animation _menuFade; - late final Animation _menuScale; - - @override - void initState() { - super.initState(); - _titleController = TextEditingController(text: widget.task.title); - _descController = TextEditingController(text: widget.task.description); - _menuAnim = AnimationController(vsync: this, duration: const Duration(milliseconds: 150)); - _menuFade = CurvedAnimation(parent: _menuAnim, curve: Curves.easeOut); - _menuScale = Tween(begin: 0.9, end: 1.0) - .animate(CurvedAnimation(parent: _menuAnim, curve: Curves.easeOut)); - } - - @override - void didUpdateWidget(TaskDetailView oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.task.id != widget.task.id) { - _titleController.text = widget.task.title; - _descController.text = widget.task.description; - _showMenu = false; - } - } - - @override - void dispose() { - _debounce?.cancel(); - _menuAnim.dispose(); - _titleController.dispose(); - _descController.dispose(); - super.dispose(); - } - - void _scheduleUpdate({String? dueDate, bool? hasTime}) { - _debounce?.cancel(); - _debounce = Timer(const Duration(milliseconds: 400), () { - final state = context.read(); - state.updateTask(api.TaskDto( - id: widget.task.id, - title: _titleController.text, - description: _descController.text, - status: widget.task.status, - dueDate: dueDate ?? widget.task.dueDate, - hasTime: hasTime ?? widget.task.hasTime, - createdAt: widget.task.createdAt, - updatedAt: widget.task.updatedAt, - parentId: widget.task.parentId, - )); - }); - } - - void _updateDueDate(String? dueDate, {bool hasTime = false}) { - final state = context.read(); - state.updateTask(api.TaskDto( - id: widget.task.id, - title: _titleController.text, - description: _descController.text, - status: widget.task.status, - dueDate: dueDate, - hasTime: hasTime, - createdAt: widget.task.createdAt, - updatedAt: widget.task.updatedAt, - parentId: widget.task.parentId, - )); - } - - void _editDate() { - showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(top: Radius.circular(16)), - ), - builder: (_) => DateTimePicker( - initialDate: widget.task.dueDate != null ? DateTime.tryParse(widget.task.dueDate!) : null, - initialHasTime: widget.task.hasTime, - onDone: (date, hasTime) => _updateDueDate(date.toUtc().toIso8601String(), hasTime: hasTime), - onClear: () => _updateDueDate(null), - ), - ); - } - - String _formatDateChip(String iso) { - final d = DateTime.tryParse(iso); - if (d == null) return iso; - final local = d.toLocal(); - final now = DateTime.now(); - final today = DateTime(now.year, now.month, now.day); - final taskDate = DateTime(local.year, local.month, local.day); - final dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; - final day = dayNames[local.weekday % 7]; - final pad = (int n) => n.toString().padLeft(2, '0'); - final timePart = widget.task.hasTime ? ', ${pad(local.hour)}:${pad(local.minute)}' : ''; - if (taskDate == today) return 'Today$timePart'; - return '$day, ${pad(local.day)}/${pad(local.month)}$timePart'; - } - - void _showMoveToSheet(BuildContext context, AppState state) { - final otherLists = state.lists.where((l) => l.id != state.activeListId).toList(); - showModalBottomSheet( - context: context, - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(top: Radius.circular(16)), - ), - builder: (_) => SafeArea( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Padding( - padding: EdgeInsets.fromLTRB(16, 16, 16, 8), - child: Text('Move to...', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)), - ), - for (final list in otherLists) - ListTile( - title: Text(list.title, style: const TextStyle(fontSize: 14)), - onTap: () { - Navigator.pop(context); - state.moveTask(widget.task.id, list.id); - state.selectTask(null); - }, - ), - const SizedBox(height: 8), - ], - ), - ), - ); - } - - @override - Widget build(BuildContext context) { - final isDark = Theme.of(context).brightness == Brightness.dark; - final state = context.read(); - final isCompleted = widget.task.status == 'completed'; - return Column( - children: [ - // Header (just back button, matching Tauri) - GestureDetector( - onPanStart: (_) => windowManager.startDragging(), - child: Container( - height: 44, - padding: const EdgeInsets.symmetric(horizontal: 8), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: isDark ? AppTheme.borderDark : AppTheme.borderLight, - width: 0.5, - ), - ), - ), - child: Row( - children: [ - GestureDetector( - onTap: () => state.selectTask(null), - child: Padding( - padding: const EdgeInsets.all(6), - child: Icon(Icons.arrow_back, size: 20, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.6)), - ), - ), - ], - ), - ), - ), - // Content - Expanded( - child: Stack( - children: [ - SingleChildScrollView( - padding: const EdgeInsets.only(left: 16, right: 16, top: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Title - TextField( - controller: _titleController, - style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w700), - decoration: const InputDecoration( - border: InputBorder.none, - hintText: 'Task title', - isDense: true, - contentPadding: EdgeInsets.zero, - ), - onChanged: (_) => _scheduleUpdate(), - ), - const SizedBox(height: 16), - // Description with icon (matching Tauri) - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(top: 2), - child: Icon(Icons.subject, size: 20, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4)), - ), - const SizedBox(width: 12), - Expanded( - child: TextField( - controller: _descController, - style: const TextStyle(fontSize: 14), - maxLines: null, - minLines: 3, - decoration: InputDecoration( - border: InputBorder.none, - hintText: 'Add details', - hintStyle: TextStyle( - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4)), - isDense: true, - contentPadding: EdgeInsets.zero, - ), - onChanged: (_) => _scheduleUpdate(), - ), - ), - ], - ), - const SizedBox(height: 16), - // Date/time with icon (matching Tauri) - Row( - children: [ - Icon(Icons.access_time, size: 20, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4)), - const SizedBox(width: 12), - if (widget.task.dueDate != null) - Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(100), - border: Border.all(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), - color: isDark ? Colors.white.withValues(alpha: 0.1) : Colors.black.withValues(alpha: 0.05), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - GestureDetector( - onTap: _editDate, - child: Text( - _formatDateChip(widget.task.dueDate!), - style: const TextStyle(fontSize: 14), - ), - ), - const SizedBox(width: 6), - GestureDetector( - onTap: () => _updateDueDate(null), - child: Icon(Icons.close, size: 14, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4)), - ), - ], - ), - ) - else - GestureDetector( - onTap: _editDate, - child: Text('Add date/time', style: TextStyle(fontSize: 14, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.4))), - ), - ], - ), - ], - ), - ), - // Click-off backdrop to close kebab menu - if (_showMenu) - Positioned.fill( - child: GestureDetector( - onTap: () { - _menuAnim.reverse().then((_) { - if (mounted) setState(() => _showMenu = false); - }); - }, - behavior: HitTestBehavior.opaque, - child: const SizedBox.expand(), - ), - ), - // Kebab menu (absolute positioned in content, matching Tauri) - Positioned( - right: 12, - top: 8, - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisSize: MainAxisSize.min, - children: [ - GestureDetector( - onTap: () { - setState(() => _showMenu = !_showMenu); - if (_showMenu) _menuAnim.forward(); else _menuAnim.reverse(); - }, - child: Padding( - padding: const EdgeInsets.all(6), - child: Icon(Icons.more_vert, size: 20, - color: (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.5)), - ), - ), - ScaleTransition( - scale: _menuScale, - alignment: Alignment.topRight, - child: FadeTransition( - opacity: _menuFade, - child: IgnorePointer( - ignoring: !_showMenu, - child: Container( - margin: const EdgeInsets.only(top: 4), - width: 200, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), - boxShadow: [ - BoxShadow(color: Colors.black.withValues(alpha: 0.15), blurRadius: 8, offset: const Offset(0, 2)), - ], - ), - child: Container( - decoration: BoxDecoration( - color: isDark ? AppTheme.surfaceDark : AppTheme.surfaceLight, - borderRadius: BorderRadius.circular(7), - ), - clipBehavior: Clip.antiAlias, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - _KebabMenuItem( - icon: isCompleted ? Icons.close : Icons.check, - label: isCompleted ? 'Restore task' : 'Mark as completed', - onTap: () { - setState(() => _showMenu = false); - state.toggleTask(widget.task.id); - state.selectTask(null); - }, - ), - if (state.lists.where((l) => l.id != state.activeListId).isNotEmpty) - _KebabMenuItem( - icon: Icons.drive_file_move_outline, - label: 'Move to...', - onTap: () { - setState(() => _showMenu = false); - _showMoveToSheet(context, state); - }, - ), - _KebabMenuItem( - icon: Icons.delete_outline, - label: 'Delete', - color: AppTheme.danger, - onTap: () { - setState(() => _showMenu = false); - state.deleteTask(widget.task.id); - }, - ), - ], - ), - ), - ), - ), - ), - ), - ], - ), - ), - ], - ), - ), - ], - ); - } -} - -class _KebabMenuItem extends StatefulWidget { - final IconData icon; - final String label; - final Color? color; - final VoidCallback onTap; - - const _KebabMenuItem({required this.icon, required this.label, this.color, required this.onTap}); - - @override - State<_KebabMenuItem> createState() => _KebabMenuItemState(); -} - -class _KebabMenuItemState extends State<_KebabMenuItem> { - bool _hovering = false; - - @override - Widget build(BuildContext context) { - final isDark = Theme.of(context).brightness == Brightness.dark; - return MouseRegion( - onEnter: (_) => setState(() => _hovering = true), - onExit: (_) => setState(() => _hovering = false), - child: GestureDetector( - onTap: widget.onTap, - child: Container( - color: _hovering - ? (isDark ? Colors.white.withValues(alpha: 0.1) : Colors.black.withValues(alpha: 0.05)) - : Colors.transparent, - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - child: Row( - children: [ - Icon(widget.icon, size: 16, color: widget.color), - const SizedBox(width: 8), - Text(widget.label, style: TextStyle(color: widget.color, fontSize: 14)), - ], - ), - ), - ), - ); - } -} diff --git a/apps/flutter/lib/src/widgets/task_item.dart b/apps/flutter/lib/src/widgets/task_item.dart deleted file mode 100644 index 44432cb..0000000 --- a/apps/flutter/lib/src/widgets/task_item.dart +++ /dev/null @@ -1,179 +0,0 @@ -import 'package:flutter/material.dart'; -import '../rust/api.dart' as api; -import '../theme.dart'; - -class TaskItem extends StatefulWidget { - final api.TaskDto task; - final VoidCallback onToggle; - final VoidCallback onTap; - - const TaskItem({super.key, required this.task, required this.onToggle, required this.onTap}); - - @override - State createState() => _TaskItemState(); -} - -class _TaskItemState extends State { - bool _hovering = false; - double _swipeOffset = 0; - - String _formatDueDate(String isoDate) { - final date = DateTime.tryParse(isoDate); - if (date == null) return ''; - final now = DateTime.now(); - final today = DateTime(now.year, now.month, now.day); - final taskDate = DateTime(date.year, date.month, date.day); - final diff = taskDate.difference(today).inDays; - if (diff == 0) return 'Today'; - if (diff == 1) return 'Tomorrow'; - return date.toLocal().toIso8601String().substring(5, 10).replaceAll('-', '/'); - } - - @override - Widget build(BuildContext context) { - final isDark = Theme.of(context).brightness == Brightness.dark; - final isCompleted = widget.task.status == 'completed'; - final canSwipeLeft = !isCompleted; - final canSwipeRight = isCompleted; - - return MouseRegion( - onEnter: (_) => setState(() => _hovering = true), - onExit: (_) => setState(() => _hovering = false), - child: GestureDetector( - onTap: () { - setState(() => _hovering = false); - widget.onTap(); - }, - onHorizontalDragUpdate: (details) { - setState(() { - _swipeOffset += details.delta.dx; - if (canSwipeLeft) _swipeOffset = _swipeOffset.clamp(-150.0, 0.0); - else if (canSwipeRight) _swipeOffset = _swipeOffset.clamp(0.0, 150.0); - else _swipeOffset = 0; - }); - }, - onHorizontalDragEnd: (details) { - if (_swipeOffset.abs() > 100) widget.onToggle(); - setState(() => _swipeOffset = 0); - }, - child: Stack( - children: [ - // Swipe background - if (_swipeOffset != 0) - Positioned.fill( - child: Container( - color: AppTheme.primary, - alignment: _swipeOffset < 0 ? Alignment.centerRight : Alignment.centerLeft, - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text( - _swipeOffset < 0 ? 'Complete' : 'Undo', - style: const TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w500), - ), - ), - ), - // Task content - Container( - transform: Matrix4.translationValues(_swipeOffset, 0, 0), - color: _hovering - ? (isDark ? Colors.white.withValues(alpha: 0.05) : Colors.black.withValues(alpha: 0.05)) - : (isDark ? AppTheme.surfaceDark : AppTheme.surfaceLight), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Checkbox with expanded touch target - GestureDetector( - onTap: widget.onToggle, - behavior: HitTestBehavior.opaque, - child: Padding( - padding: const EdgeInsets.all(2), - child: Container( - width: 20, - height: 20, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: isCompleted ? AppTheme.primary : Colors.transparent, - border: Border.all( - color: isCompleted ? AppTheme.primary : (isDark ? const Color(0xFF6B7280) : const Color(0xFF9CA3AF)), - width: 2, - ), - ), - child: isCompleted - ? const Icon(Icons.check, size: 12, color: Colors.white) - : null, - ), - ), - ), - const SizedBox(width: 12), - // Content column (title, description, due date below) - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - widget.task.title, - style: TextStyle( - fontSize: 14, - fontWeight: isCompleted ? FontWeight.normal : FontWeight.w500, - decoration: isCompleted ? TextDecoration.lineThrough : null, - color: isCompleted - ? (isDark ? AppTheme.textDark : AppTheme.textLight).withValues(alpha: 0.5) - : null, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - if (widget.task.description.isNotEmpty) - Padding( - padding: const EdgeInsets.only(top: 2), - child: Text( - widget.task.description, - style: TextStyle( - fontSize: 12, - color: (isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight).withValues(alpha: 0.4), - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - // Due date badge (below title/description, matching Tauri) - if (widget.task.dueDate != null) - Padding( - padding: const EdgeInsets.only(top: 4), - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), - decoration: BoxDecoration( - border: Border.all(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), - borderRadius: BorderRadius.circular(100), - ), - child: Text( - _formatDueDate(widget.task.dueDate!), - style: TextStyle( - fontSize: 12, - color: (isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight).withValues(alpha: 0.5), - ), - ), - ), - ), - ], - ), - ), - // Chevron (show on hover only) - AnimatedOpacity( - duration: const Duration(milliseconds: 150), - opacity: _hovering ? 0.3 : 0, - child: Padding( - padding: const EdgeInsets.only(left: 4, top: 4), - child: Icon(Icons.chevron_right, size: 16, - color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight), - ), - ), - ], - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/flutter/linux/.gitignore b/apps/flutter/linux/.gitignore deleted file mode 100644 index d3896c9..0000000 --- a/apps/flutter/linux/.gitignore +++ /dev/null @@ -1 +0,0 @@ -flutter/ephemeral diff --git a/apps/flutter/linux/CMakeLists.txt b/apps/flutter/linux/CMakeLists.txt deleted file mode 100644 index 685dbb5..0000000 --- a/apps/flutter/linux/CMakeLists.txt +++ /dev/null @@ -1,155 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.13) -project(runner LANGUAGES CXX) - -# The name of the executable created for the application. Change this to change -# the on-disk name of your application. -set(BINARY_NAME "onyx") -# The unique GTK application identifier for this application. See: -# https://wiki.gnome.org/HowDoI/ChooseApplicationID -set(APPLICATION_ID "com.onyx.onyx") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(SET CMP0063 NEW) - -# Load bundled libraries from the lib/ directory relative to the binary. -set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") - -# Root filesystem for cross-building. -if(FLUTTER_TARGET_PLATFORM_SYSROOT) - set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) - set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -endif() - -# Define build configuration options. -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") -endif() - -# Compilation settings that should be applied to most targets. -# -# Be cautious about adding new options here, as plugins use this function by -# default. In most cases, you should add new options to specific targets instead -# of modifying this function. -function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror) - target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") - target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") -endfunction() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# System-level dependencies. -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) - -# Application build; see runner/CMakeLists.txt. -add_subdirectory("runner") - -# Build the Rust FFI library for flutter_rust_bridge -set(RUST_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../rust") -set(RUST_LIB_NAME "libonyx_flutter.so") -if(CMAKE_BUILD_TYPE MATCHES "Debug") - set(RUST_TARGET_DIR "${RUST_DIR}/target/debug") - add_custom_command( - OUTPUT "${RUST_TARGET_DIR}/${RUST_LIB_NAME}" - COMMAND cargo build - WORKING_DIRECTORY "${RUST_DIR}" - COMMENT "Building Rust FFI library (debug)" - ) -else() - set(RUST_TARGET_DIR "${RUST_DIR}/target/release") - add_custom_command( - OUTPUT "${RUST_TARGET_DIR}/${RUST_LIB_NAME}" - COMMAND cargo build --release - WORKING_DIRECTORY "${RUST_DIR}" - COMMENT "Building Rust FFI library (release)" - ) -endif() -add_custom_target(rust_lib DEPENDS "${RUST_TARGET_DIR}/${RUST_LIB_NAME}") - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble rust_lib) - -# Only the install-generated bundle's copy of the executable will launch -# correctly, since the resources must in the right relative locations. To avoid -# people trying to run the unbundled copy, put it in a subdirectory instead of -# the default top-level location. -set_target_properties(${BINARY_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" -) - - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# By default, "installing" just makes a relocatable bundle in the build -# directory. -set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() - -# Start with a clean build bundle directory every time. -install(CODE " - file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") - " COMPONENT Runtime) - -set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") -set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") - -install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) - install(FILES "${bundled_library}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endforeach(bundled_library) - -# Install the Rust FFI library into the bundle -install(FILES "${RUST_TARGET_DIR}/${RUST_LIB_NAME}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -# Copy the native assets provided by the build.dart from all packages. -set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") -install(DIRECTORY "${NATIVE_ASSETS_DIR}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -# Fully re-copy the assets directory on each build to avoid having stale files -# from a previous install. -set(FLUTTER_ASSET_DIR_NAME "flutter_assets") -install(CODE " - file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") - " COMPONENT Runtime) -install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) - -# Install the AOT library on non-Debug builds only. -if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") - install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() diff --git a/apps/flutter/linux/flutter/CMakeLists.txt b/apps/flutter/linux/flutter/CMakeLists.txt deleted file mode 100644 index d5bd016..0000000 --- a/apps/flutter/linux/flutter/CMakeLists.txt +++ /dev/null @@ -1,88 +0,0 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.10) - -set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") - -# Configuration provided via flutter tool. -include(${EPHEMERAL_DIR}/generated_config.cmake) - -# TODO: Move the rest of this into files in ephemeral. See -# https://github.com/flutter/flutter/issues/57146. - -# Serves the same purpose as list(TRANSFORM ... PREPEND ...), -# which isn't available in 3.10. -function(list_prepend LIST_NAME PREFIX) - set(NEW_LIST "") - foreach(element ${${LIST_NAME}}) - list(APPEND NEW_LIST "${PREFIX}${element}") - endforeach(element) - set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) -endfunction() - -# === Flutter Library === -# System-level dependencies. -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) -pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) -pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) - -set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") - -# Published to parent scope for install step. -set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) -set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) -set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) -set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) - -list(APPEND FLUTTER_LIBRARY_HEADERS - "fl_basic_message_channel.h" - "fl_binary_codec.h" - "fl_binary_messenger.h" - "fl_dart_project.h" - "fl_engine.h" - "fl_json_message_codec.h" - "fl_json_method_codec.h" - "fl_message_codec.h" - "fl_method_call.h" - "fl_method_channel.h" - "fl_method_codec.h" - "fl_method_response.h" - "fl_plugin_registrar.h" - "fl_plugin_registry.h" - "fl_standard_message_codec.h" - "fl_standard_method_codec.h" - "fl_string_codec.h" - "fl_value.h" - "fl_view.h" - "flutter_linux.h" -) -list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") -add_library(flutter INTERFACE) -target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" -) -target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") -target_link_libraries(flutter INTERFACE - PkgConfig::GTK - PkgConfig::GLIB - PkgConfig::GIO -) -add_dependencies(flutter flutter_assemble) - -# === Flutter tool backend === -# _phony_ is a non-existent file to force this command to run every time, -# since currently there's no way to get a full input/output list from the -# flutter tool. -add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CMAKE_CURRENT_BINARY_DIR}/_phony_ - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} - VERBATIM -) -add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} -) diff --git a/apps/flutter/linux/flutter/generated_plugin_registrant.cc b/apps/flutter/linux/flutter/generated_plugin_registrant.cc deleted file mode 100644 index c8f3dcc..0000000 --- a/apps/flutter/linux/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,19 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include -#include - -void fl_register_plugins(FlPluginRegistry* registry) { - g_autoptr(FlPluginRegistrar) screen_retriever_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverLinuxPlugin"); - screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar); - g_autoptr(FlPluginRegistrar) window_manager_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin"); - window_manager_plugin_register_with_registrar(window_manager_registrar); -} diff --git a/apps/flutter/linux/flutter/generated_plugin_registrant.h b/apps/flutter/linux/flutter/generated_plugin_registrant.h deleted file mode 100644 index e0f0a47..0000000 --- a/apps/flutter/linux/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void fl_register_plugins(FlPluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/apps/flutter/linux/flutter/generated_plugins.cmake b/apps/flutter/linux/flutter/generated_plugins.cmake deleted file mode 100644 index 00303ac..0000000 --- a/apps/flutter/linux/flutter/generated_plugins.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - screen_retriever_linux - window_manager -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/apps/flutter/linux/runner/CMakeLists.txt b/apps/flutter/linux/runner/CMakeLists.txt deleted file mode 100644 index e97dabc..0000000 --- a/apps/flutter/linux/runner/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -cmake_minimum_required(VERSION 3.13) -project(runner LANGUAGES CXX) - -# Define the application target. To change its name, change BINARY_NAME in the -# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer -# work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add preprocessor definitions for the application ID. -add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") - -# Add dependency libraries. Add any application-specific dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter) -target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) - -target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/apps/flutter/linux/runner/main.cc b/apps/flutter/linux/runner/main.cc deleted file mode 100644 index e7c5c54..0000000 --- a/apps/flutter/linux/runner/main.cc +++ /dev/null @@ -1,6 +0,0 @@ -#include "my_application.h" - -int main(int argc, char** argv) { - g_autoptr(MyApplication) app = my_application_new(); - return g_application_run(G_APPLICATION(app), argc, argv); -} diff --git a/apps/flutter/linux/runner/my_application.cc b/apps/flutter/linux/runner/my_application.cc deleted file mode 100644 index e908bd6..0000000 --- a/apps/flutter/linux/runner/my_application.cc +++ /dev/null @@ -1,130 +0,0 @@ -#include "my_application.h" - -#include -#ifdef GDK_WINDOWING_X11 -#include -#endif - -#include "flutter/generated_plugin_registrant.h" - -struct _MyApplication { - GtkApplication parent_instance; - char** dart_entrypoint_arguments; -}; - -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) - -// Called when first Flutter frame received. -static void first_frame_cb(MyApplication* self, FlView* view) { - gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view))); -} - -// Implements GApplication::activate. -static void my_application_activate(GApplication* application) { - MyApplication* self = MY_APPLICATION(application); - GtkWindow* window = - GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - - // Frameless transparent window - gtk_window_set_decorated(window, FALSE); - gtk_window_set_title(window, "onyx"); - gtk_window_set_default_size(window, 400, 700); - - // Enable transparency - GdkScreen* screen = gtk_widget_get_screen(GTK_WIDGET(window)); - GdkVisual* visual = gdk_screen_get_rgba_visual(screen); - if (visual != nullptr) { - gtk_widget_set_visual(GTK_WIDGET(window), visual); - } - gtk_widget_set_app_paintable(GTK_WIDGET(window), TRUE); - - g_autoptr(FlDartProject) project = fl_dart_project_new(); - fl_dart_project_set_dart_entrypoint_arguments( - project, self->dart_entrypoint_arguments); - - FlView* view = fl_view_new(project); - GdkRGBA background_color; - gdk_rgba_parse(&background_color, "#00000000"); - fl_view_set_background_color(view, &background_color); - gtk_widget_show(GTK_WIDGET(view)); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); - - // Show the window when Flutter renders. - // Requires the view to be realized so we can start rendering. - g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), - self); - gtk_widget_realize(GTK_WIDGET(view)); - - fl_register_plugins(FL_PLUGIN_REGISTRY(view)); - - gtk_widget_grab_focus(GTK_WIDGET(view)); -} - -// Implements GApplication::local_command_line. -static gboolean my_application_local_command_line(GApplication* application, - gchar*** arguments, - int* exit_status) { - MyApplication* self = MY_APPLICATION(application); - // Strip out the first argument as it is the binary name. - self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); - - g_autoptr(GError) error = nullptr; - if (!g_application_register(application, nullptr, &error)) { - g_warning("Failed to register: %s", error->message); - *exit_status = 1; - return TRUE; - } - - g_application_activate(application); - *exit_status = 0; - - return TRUE; -} - -// Implements GApplication::startup. -static void my_application_startup(GApplication* application) { - // MyApplication* self = MY_APPLICATION(object); - - // Perform any actions required at application startup. - - G_APPLICATION_CLASS(my_application_parent_class)->startup(application); -} - -// Implements GApplication::shutdown. -static void my_application_shutdown(GApplication* application) { - // MyApplication* self = MY_APPLICATION(object); - - // Perform any actions required at application shutdown. - - G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); -} - -// Implements GObject::dispose. -static void my_application_dispose(GObject* object) { - MyApplication* self = MY_APPLICATION(object); - g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); - G_OBJECT_CLASS(my_application_parent_class)->dispose(object); -} - -static void my_application_class_init(MyApplicationClass* klass) { - G_APPLICATION_CLASS(klass)->activate = my_application_activate; - G_APPLICATION_CLASS(klass)->local_command_line = - my_application_local_command_line; - G_APPLICATION_CLASS(klass)->startup = my_application_startup; - G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; - G_OBJECT_CLASS(klass)->dispose = my_application_dispose; -} - -static void my_application_init(MyApplication* self) {} - -MyApplication* my_application_new() { - // Set the program name to the application ID, which helps various systems - // like GTK and desktop environments map this running application to its - // corresponding .desktop file. This ensures better integration by allowing - // the application to be recognized beyond its binary name. - g_set_prgname(APPLICATION_ID); - - return MY_APPLICATION(g_object_new(my_application_get_type(), - "application-id", APPLICATION_ID, "flags", - G_APPLICATION_NON_UNIQUE, nullptr)); -} diff --git a/apps/flutter/linux/runner/my_application.h b/apps/flutter/linux/runner/my_application.h deleted file mode 100644 index db16367..0000000 --- a/apps/flutter/linux/runner/my_application.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef FLUTTER_MY_APPLICATION_H_ -#define FLUTTER_MY_APPLICATION_H_ - -#include - -G_DECLARE_FINAL_TYPE(MyApplication, - my_application, - MY, - APPLICATION, - GtkApplication) - -/** - * my_application_new: - * - * Creates a new Flutter-based application. - * - * Returns: a new #MyApplication. - */ -MyApplication* my_application_new(); - -#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/apps/flutter/pubspec.lock b/apps/flutter/pubspec.lock deleted file mode 100644 index 136587f..0000000 --- a/apps/flutter/pubspec.lock +++ /dev/null @@ -1,538 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - args: - dependency: transitive - description: - name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" - source: hosted - version: "2.7.0" - async: - dependency: transitive - description: - name: async - sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 - url: "https://pub.dev" - source: hosted - version: "2.13.1" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - build_cli_annotations: - dependency: transitive - description: - name: build_cli_annotations - sha256: e563c2e01de8974566a1998410d3f6f03521788160a02503b0b1f1a46c7b3d95 - url: "https://pub.dev" - source: hosted - version: "2.1.1" - characters: - dependency: transitive - description: - name: characters - sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b - url: "https://pub.dev" - source: hosted - version: "1.4.1" - clock: - dependency: transitive - description: - name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" - source: hosted - version: "1.1.2" - code_assets: - dependency: transitive - description: - name: code_assets - sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - collection: - dependency: transitive - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - cross_file: - dependency: transitive - description: - name: cross_file - sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937" - url: "https://pub.dev" - source: hosted - version: "0.3.5+2" - crypto: - dependency: transitive - description: - name: crypto - sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf - url: "https://pub.dev" - source: hosted - version: "3.0.7" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" - source: hosted - version: "1.3.3" - ffi: - dependency: transitive - description: - name: ffi - sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - file: - dependency: transitive - description: - name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" - source: hosted - version: "7.0.1" - file_picker: - dependency: "direct main" - description: - name: file_picker - sha256: ab13ae8ef5580a411c458d6207b6774a6c237d77ac37011b13994879f68a8810 - url: "https://pub.dev" - source: hosted - version: "8.3.7" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" - url: "https://pub.dev" - source: hosted - version: "6.0.0" - flutter_plugin_android_lifecycle: - dependency: transitive - description: - name: flutter_plugin_android_lifecycle - sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0" - url: "https://pub.dev" - source: hosted - version: "2.0.34" - flutter_rust_bridge: - dependency: "direct main" - description: - name: flutter_rust_bridge - sha256: "37ef40bc6f863652e865f0b2563ea07f0d3c58d8efad803cc01933a4b2ee067e" - url: "https://pub.dev" - source: hosted - version: "2.11.1" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - glob: - dependency: transitive - description: - name: glob - sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.dev" - source: hosted - version: "2.1.3" - google_fonts: - dependency: "direct main" - description: - name: google_fonts - sha256: ba03d03bcaa2f6cb7bd920e3b5027181db75ab524f8891c8bc3aa603885b8055 - url: "https://pub.dev" - source: hosted - version: "6.3.3" - hooks: - dependency: transitive - description: - name: hooks - sha256: e79ed1e8e1929bc6ecb6ec85f0cb519c887aa5b423705ded0d0f2d9226def388 - url: "https://pub.dev" - source: hosted - version: "1.0.2" - http: - dependency: transitive - description: - name: http - sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" - url: "https://pub.dev" - source: hosted - version: "1.6.0" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" - source: hosted - version: "4.1.2" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 - url: "https://pub.dev" - source: hosted - version: "4.11.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.dev" - source: hosted - version: "11.0.2" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.dev" - source: hosted - version: "3.0.10" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - lints: - dependency: transitive - description: - name: lints - sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" - url: "https://pub.dev" - source: hosted - version: "6.1.0" - logging: - dependency: transitive - description: - name: logging - sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" - source: hosted - version: "1.3.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 - url: "https://pub.dev" - source: hosted - version: "0.12.19" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" - url: "https://pub.dev" - source: hosted - version: "0.13.0" - meta: - dependency: transitive - description: - name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" - url: "https://pub.dev" - source: hosted - version: "1.17.0" - native_toolchain_c: - dependency: transitive - description: - name: native_toolchain_c - sha256: "6ba77bb18063eebe9de401f5e6437e95e1438af0a87a3a39084fbd37c90df572" - url: "https://pub.dev" - source: hosted - version: "0.17.6" - nested: - dependency: transitive - description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - objective_c: - dependency: transitive - description: - name: objective_c - sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" - url: "https://pub.dev" - source: hosted - version: "9.3.0" - path: - dependency: transitive - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - path_provider: - dependency: transitive - description: - name: path_provider - sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: "149441ca6e4f38193b2e004c0ca6376a3d11f51fa5a77552d8bd4d2b0c0912ba" - url: "https://pub.dev" - source: hosted - version: "2.2.23" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" - url: "https://pub.dev" - source: hosted - version: "2.6.0" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" - source: hosted - version: "2.3.0" - platform: - dependency: transitive - description: - name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" - source: hosted - version: "3.1.6" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" - provider: - dependency: "direct main" - description: - name: provider - sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" - url: "https://pub.dev" - source: hosted - version: "6.1.5+1" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - screen_retriever: - dependency: transitive - description: - name: screen_retriever - sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - screen_retriever_linux: - dependency: transitive - description: - name: screen_retriever_linux - sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18 - url: "https://pub.dev" - source: hosted - version: "0.2.0" - screen_retriever_macos: - dependency: transitive - description: - name: screen_retriever_macos - sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - screen_retriever_platform_interface: - dependency: transitive - description: - name: screen_retriever_platform_interface - sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0 - url: "https://pub.dev" - source: hosted - version: "0.2.0" - screen_retriever_windows: - dependency: transitive - description: - name: screen_retriever_windows - sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - source_span: - dependency: transitive - description: - name: source_span - sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" - url: "https://pub.dev" - source: hosted - version: "1.10.2" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" - source: hosted - version: "1.12.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test_api: - dependency: transitive - description: - name: test_api - sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" - url: "https://pub.dev" - source: hosted - version: "0.7.10" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.dev" - source: hosted - version: "2.2.0" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" - url: "https://pub.dev" - source: hosted - version: "15.0.2" - web: - dependency: transitive - description: - name: web - sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - win32: - dependency: transitive - description: - name: win32 - sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e - url: "https://pub.dev" - source: hosted - version: "5.15.0" - window_manager: - dependency: "direct main" - description: - name: window_manager - sha256: "732896e1416297c63c9e3fb95aea72d0355f61390263982a47fd519169dc5059" - url: "https://pub.dev" - source: hosted - version: "0.4.3" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - yaml: - dependency: transitive - description: - name: yaml - sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.dev" - source: hosted - version: "3.1.3" -sdks: - dart: ">=3.11.1 <4.0.0" - flutter: ">=3.38.4" diff --git a/apps/flutter/pubspec.yaml b/apps/flutter/pubspec.yaml deleted file mode 100644 index b24d432..0000000 --- a/apps/flutter/pubspec.yaml +++ /dev/null @@ -1,24 +0,0 @@ -name: onyx -description: "Onyx - local-first task management" -publish_to: 'none' -version: 1.0.0+1 - -environment: - sdk: ^3.11.1 - -dependencies: - flutter: - sdk: flutter - flutter_rust_bridge: 2.11.1 - provider: ^6.1.0 - window_manager: ^0.4.0 - file_picker: ^8.0.0 - google_fonts: ^6.0.0 - -dev_dependencies: - flutter_test: - sdk: flutter - flutter_lints: ^6.0.0 - -flutter: - uses-material-design: true diff --git a/apps/flutter/rust/Cargo.lock b/apps/flutter/rust/Cargo.lock deleted file mode 100644 index 2ec4983..0000000 --- a/apps/flutter/rust/Cargo.lock +++ /dev/null @@ -1,2767 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "addr2line" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - -[[package]] -name = "aho-corasick" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" -dependencies = [ - "memchr", -] - -[[package]] -name = "allo-isolate" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449e356a4864c017286dbbec0e12767ea07efba29e3b7d984194c2a7ff3c4550" -dependencies = [ - "anyhow", - "atomic", - "backtrace", -] - -[[package]] -name = "android_log-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" - -[[package]] -name = "android_logger" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3" -dependencies = [ - "android_log-sys", - "env_filter", - "log", -] - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anyhow" -version = "1.0.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" - -[[package]] -name = "atomic" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "backtrace" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link", -] - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "build-target" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "832133bbabbbaa9fbdba793456a2827627a7d2b8fb96032fa1e7666d7895832b" - -[[package]] -name = "bumpalo" -version = "3.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" - -[[package]] -name = "bytemuck" -version = "1.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" - -[[package]] -name = "cc" -version = "1.2.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" -dependencies = [ - "find-msvc-tools", - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "chrono" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-link", -] - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "dart-sys" -version = "4.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57967e4b200d767d091b961d6ab42cc7d0cc14fe9e052e75d0d3cf9eb732d895" -dependencies = [ - "cc", -] - -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "dbus" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b3aa68d7e7abee336255bd7248ea965cc393f3e70411135a6f6a4b651345d4" -dependencies = [ - "libc", - "libdbus-sys", - "windows-sys 0.59.0", -] - -[[package]] -name = "dbus-secret-service" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "708b509edf7889e53d7efb0ffadd994cc6c2345ccb62f55cfd6b0682165e4fa6" -dependencies = [ - "dbus", - "zeroize", -] - -[[package]] -name = "delegate-attr" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51aac4c99b2e6775164b412ea33ae8441b2fde2dbf05a20bc0052a63d08c475b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "directories" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.48.0", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "env_filter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "filetime" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" -dependencies = [ - "cfg-if", - "libc", - "libredox", -] - -[[package]] -name = "find-msvc-tools" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" - -[[package]] -name = "flutter_rust_bridge" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde126295b2acc5f0a712e265e91b6fdc0ed38767496483e592ae7134db83725" -dependencies = [ - "allo-isolate", - "android_logger", - "anyhow", - "build-target", - "bytemuck", - "byteorder", - "console_error_panic_hook", - "dart-sys", - "delegate-attr", - "flutter_rust_bridge_macros", - "futures", - "js-sys", - "lazy_static", - "log", - "oslog", - "portable-atomic", - "threadpool", - "tokio", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "flutter_rust_bridge_macros" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f0420326b13675321b194928bb7830043b68cf8b810e1c651285c747abb080" -dependencies = [ - "hex", - "md-5", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] - -[[package]] -name = "futures" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" - -[[package]] -name = "futures-executor" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" - -[[package]] -name = "futures-macro" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" - -[[package]] -name = "futures-task" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" - -[[package]] -name = "futures-util" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi 5.3.0", - "wasip2", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" -dependencies = [ - "cfg-if", - "libc", - "r-efi 6.0.0", - "wasip2", - "wasip3", -] - -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "http" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" -dependencies = [ - "bytes", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "hyper" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" -dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "pin-utils", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" -dependencies = [ - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", - "webpki-roots", -] - -[[package]] -name = "hyper-util" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" -dependencies = [ - "base64", - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "ipnet", - "libc", - "percent-encoding", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "icu_collections" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" -dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" - -[[package]] -name = "icu_properties" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" -dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" - -[[package]] -name = "icu_provider" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "indexmap" -version = "2.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" -dependencies = [ - "equivalent", - "hashbrown 0.16.1", - "serde", - "serde_core", -] - -[[package]] -name = "inotify" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd168d97690d0b8c412d6b6c10360277f4d7ee495c5d0d5d5fe0854923255cc" -dependencies = [ - "bitflags 1.3.2", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "ipnet" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" - -[[package]] -name = "iri-string" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "itoa" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" - -[[package]] -name = "js-sys" -version = "0.3.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "keyring" -version = "3.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eebcc3aff044e5944a8fbaf69eb277d11986064cba30c468730e8b9909fb551c" -dependencies = [ - "byteorder", - "dbus-secret-service", - "log", - "security-framework 2.11.1", - "security-framework 3.7.0", - "windows-sys 0.60.2", - "zeroize", -] - -[[package]] -name = "kqueue" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" -dependencies = [ - "bitflags 1.3.2", - "libc", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - -[[package]] -name = "libc" -version = "0.2.183" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" - -[[package]] -name = "libdbus-sys" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328c4789d42200f1eeec05bd86c9c13c7f091d2ba9a6ea35acdf51f31bc0f043" -dependencies = [ - "pkg-config", -] - -[[package]] -name = "libredox" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" -dependencies = [ - "bitflags 2.11.0", - "libc", - "plain", - "redox_syscall 0.7.3", -] - -[[package]] -name = "linux-raw-sys" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" - -[[package]] -name = "litemap" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest", -] - -[[package]] -name = "memchr" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] - -[[package]] -name = "mio" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "notify" -version = "7.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c533b4c39709f9ba5005d8002048266593c1cfaf3c5f0739d5b8ab0c6c504009" -dependencies = [ - "bitflags 2.11.0", - "filetime", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "log", - "mio", - "notify-types", - "walkdir", - "windows-sys 0.52.0", -] - -[[package]] -name = "notify-debouncer-mini" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaa5a66d07ed97dce782be94dcf5ab4d1b457f4243f7566c7557f15cabc8c799" -dependencies = [ - "log", - "notify", - "notify-types", - "tempfile", -] - -[[package]] -name = "notify-types" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585d3cb5e12e01aed9e8a1f70d5c6b5e86fe2a6e48fc8cd0b3e0b8df6f6eb174" -dependencies = [ - "instant", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "onyx-core" -version = "0.1.0" -dependencies = [ - "chrono", - "directories", - "keyring", - "quick-xml", - "reqwest", - "serde", - "serde_json", - "serde_yaml", - "sha2", - "tokio", - "uuid", -] - -[[package]] -name = "onyx-flutter" -version = "0.1.0" -dependencies = [ - "chrono", - "flutter_rust_bridge", - "notify", - "notify-debouncer-mini", - "once_cell", - "onyx-core", - "tokio", - "uuid", -] - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "oslog" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d2043d1f61d77cb2f4b1f7b7b2295f40507f5f8e9d1c8bf10a1ca5f97a3969" -dependencies = [ - "cc", - "dashmap", - "log", -] - -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.5.18", - "smallvec", - "windows-link", -] - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "pin-project-lite" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - -[[package]] -name = "portable-atomic" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" - -[[package]] -name = "potential_utf" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" -dependencies = [ - "zerovec", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quick-xml" -version = "0.36.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" -dependencies = [ - "memchr", -] - -[[package]] -name = "quinn" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror 2.0.18", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" -dependencies = [ - "bytes", - "getrandom 0.3.4", - "lru-slab", - "rand", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "slab", - "thiserror 2.0.18", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.60.2", -] - -[[package]] -name = "quote" -version = "1.0.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "r-efi" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" - -[[package]] -name = "rand" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", -] - -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "redox_syscall" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "redox_users" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" -dependencies = [ - "getrandom 0.2.17", - "libredox", - "thiserror 1.0.69", -] - -[[package]] -name = "regex" -version = "1.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" - -[[package]] -name = "reqwest" -version = "0.12.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" -dependencies = [ - "base64", - "bytes", - "futures-core", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-rustls", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.17", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" - -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "rustix" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" -dependencies = [ - "bitflags 2.11.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustls" -version = "0.23.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" -dependencies = [ - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pki-types" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" -dependencies = [ - "web-time", - "zeroize", -] - -[[package]] -name = "rustls-webpki" -version = "0.103.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "ryu" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.11.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" -dependencies = [ - "bitflags 2.11.0", - "core-foundation 0.10.1", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.149" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" -dependencies = [ - "indexmap", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" -dependencies = [ - "errno", - "libc", -] - -[[package]] -name = "slab" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "socket2" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "2.0.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tempfile" -version = "3.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" -dependencies = [ - "fastrand", - "getrandom 0.4.2", - "once_cell", - "rustix", - "windows-sys 0.61.2", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" -dependencies = [ - "thiserror-impl 2.0.18", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "tinystr" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tinyvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" -dependencies = [ - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.61.2", -] - -[[package]] -name = "tokio-macros" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tower" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-http" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" -dependencies = [ - "bitflags 2.11.0", - "bytes", - "futures-util", - "http", - "http-body", - "iri-string", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" -dependencies = [ - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" - -[[package]] -name = "unicode-ident" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "uuid" -version = "1.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" -dependencies = [ - "getrandom 0.4.2", - "js-sys", - "serde_core", - "wasm-bindgen", -] - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasip2" -version = "1.0.2+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.114" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" -dependencies = [ - "cfg-if", - "futures-util", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.114" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.114" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.114" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.11.0", - "hashbrown 0.15.5", - "indexmap", - "semver", -] - -[[package]] -name = "web-sys" -version = "0.3.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-roots" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.11.0", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - -[[package]] -name = "writeable" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" - -[[package]] -name = "yoke" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerocopy" -version = "0.8.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zeroize" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zerotrie" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/apps/flutter/rust/Cargo.toml b/apps/flutter/rust/Cargo.toml deleted file mode 100644 index 14d1a65..0000000 --- a/apps/flutter/rust/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "onyx-flutter" -version = "0.1.0" -edition = "2021" - -[lib] -crate-type = ["cdylib", "staticlib"] - -[dependencies] -flutter_rust_bridge = "=2.11.1" -onyx-core = { path = "../../../crates/onyx-core" } -uuid = { version = "1", features = ["serde", "v4"] } -chrono = { version = "0.4", features = ["serde"] } -once_cell = "1" -notify = "7" -notify-debouncer-mini = "0.5" -tokio = { version = "1", features = ["full"] } diff --git a/apps/flutter/rust/src/api.rs b/apps/flutter/rust/src/api.rs deleted file mode 100644 index 00baa04..0000000 --- a/apps/flutter/rust/src/api.rs +++ /dev/null @@ -1,422 +0,0 @@ -use std::path::PathBuf; -use std::sync::Mutex; -use std::time::{Duration, Instant}; - -use flutter_rust_bridge::frb; -use notify_debouncer_mini::{new_debouncer, DebouncedEventKind}; -use once_cell::sync::Lazy; -use uuid::Uuid; - -use onyx_core::{ - config::{AppConfig, WorkspaceConfig}, - models::{Task, TaskStatus}, - repository::TaskRepository, - sync::{self, SyncMode}, - webdav, -}; - -// ── State ─────────────────────────────────────────────────────────── - -struct AppState { - config: AppConfig, - repo: Option, -} - -static STATE: Lazy> = Lazy::new(|| { - let config_path = AppConfig::get_config_path(); - let config = AppConfig::load_from_file(&config_path).unwrap_or_default(); - Mutex::new(AppState { config, repo: None }) -}); - -fn ensure_repo(state: &mut AppState) -> Result<(), String> { - if state.repo.is_some() { - return Ok(()); - } - let (_name, ws) = state.config.get_current_workspace().map_err(|e| e.to_string())?; - let repo = TaskRepository::new(ws.path.clone()).map_err(|e| e.to_string())?; - state.repo = Some(repo); - Ok(()) -} - -// ── DTOs ──────────────────────────────────────────────────────────── - -pub struct TaskDto { - pub id: String, - pub title: String, - pub description: String, - pub status: String, - pub due_date: Option, - pub has_time: bool, - pub created_at: String, - pub updated_at: String, - pub parent_id: Option, -} - -pub struct SyncResultDto { - pub uploaded: u32, - pub downloaded: u32, - pub deleted_local: u32, - pub deleted_remote: u32, - pub conflicts: u32, - pub errors: Vec, -} - -pub struct TaskListDto { - pub id: String, - pub title: String, - pub created_at: String, - pub updated_at: String, - pub group_by_due_date: bool, -} - -pub struct WorkspaceEntry { - pub name: String, - pub path: String, - pub webdav_url: Option, - pub last_sync: Option, -} - -pub struct AppConfigDto { - pub workspaces: Vec, - pub current_workspace: Option, -} - -fn task_to_dto(t: &Task) -> TaskDto { - TaskDto { - id: t.id.to_string(), - title: t.title.clone(), - description: t.description.clone(), - status: match t.status { - TaskStatus::Backlog => "backlog".into(), - TaskStatus::Completed => "completed".into(), - }, - due_date: t.due_date.map(|d| d.to_rfc3339()), - has_time: t.has_time, - created_at: t.created_at.to_rfc3339(), - updated_at: t.updated_at.to_rfc3339(), - parent_id: t.parent_id.map(|id| id.to_string()), - } -} - -fn config_to_dto(c: &AppConfig) -> AppConfigDto { - AppConfigDto { - workspaces: c - .workspaces - .iter() - .map(|(name, ws)| WorkspaceEntry { - name: name.clone(), - path: ws.path.to_string_lossy().into_owned(), - webdav_url: ws.webdav_url.clone(), - last_sync: ws.last_sync.map(|d| d.to_rfc3339()), - }) - .collect(), - current_workspace: c.current_workspace.clone(), - } -} - -// ── Config commands ───────────────────────────────────────────────── - -pub fn get_config() -> Result { - let s = STATE.lock().unwrap(); - Ok(config_to_dto(&s.config)) -} - -pub fn init_workspace(path: String) -> Result<(), String> { - TaskRepository::init(PathBuf::from(path)) - .map(|_| ()) - .map_err(|e| e.to_string()) -} - -pub fn add_workspace(name: String, path: String) -> Result<(), String> { - let mut s = STATE.lock().unwrap(); - let ws = WorkspaceConfig::new(PathBuf::from(&path)); - s.config.add_workspace(name.clone(), ws); - s.config.set_current_workspace(name).map_err(|e| e.to_string())?; - s.repo = None; - let config_path = AppConfig::get_config_path(); - s.config.save_to_file(&config_path).map_err(|e| e.to_string()) -} - -pub fn set_current_workspace(name: String) -> Result<(), String> { - let mut s = STATE.lock().unwrap(); - s.config.set_current_workspace(name).map_err(|e| e.to_string())?; - s.repo = None; - let config_path = AppConfig::get_config_path(); - s.config.save_to_file(&config_path).map_err(|e| e.to_string()) -} - -pub fn remove_workspace(name: String) -> Result<(), String> { - let mut s = STATE.lock().unwrap(); - s.config.remove_workspace(&name); - s.repo = None; - let config_path = AppConfig::get_config_path(); - s.config.save_to_file(&config_path).map_err(|e| e.to_string()) -} - -// ── List commands ─────────────────────────────────────────────────── - -pub fn get_lists() -> Result, String> { - let mut s = STATE.lock().unwrap(); - ensure_repo(&mut s)?; - let lists = s.repo.as_ref().unwrap().get_lists().map_err(|e| e.to_string())?; - Ok(lists - .iter() - .map(|l| TaskListDto { - id: l.id.to_string(), - title: l.title.clone(), - created_at: l.created_at.to_rfc3339(), - updated_at: l.updated_at.to_rfc3339(), - group_by_due_date: l.group_by_due_date, - }) - .collect()) -} - -pub fn create_list(name: String) -> Result { - let mut s = STATE.lock().unwrap(); - ensure_repo(&mut s)?; - mute_watcher(); - let list = s.repo.as_mut().unwrap().create_list(name).map_err(|e| e.to_string())?; - Ok(TaskListDto { - id: list.id.to_string(), - title: list.title.clone(), - created_at: list.created_at.to_rfc3339(), - updated_at: list.updated_at.to_rfc3339(), - group_by_due_date: list.group_by_due_date, - }) -} - -pub fn delete_list(list_id: String) -> Result<(), String> { - let mut s = STATE.lock().unwrap(); - ensure_repo(&mut s)?; - mute_watcher(); - let id = Uuid::parse_str(&list_id).map_err(|e| e.to_string())?; - s.repo.as_mut().unwrap().delete_list(id).map_err(|e| e.to_string()) -} - -// ── Task commands ─────────────────────────────────────────────────── - -pub fn list_tasks(list_id: String) -> Result, String> { - let mut s = STATE.lock().unwrap(); - ensure_repo(&mut s)?; - let id = Uuid::parse_str(&list_id).map_err(|e| e.to_string())?; - let tasks = s.repo.as_ref().unwrap().list_tasks(id).map_err(|e| e.to_string())?; - Ok(tasks.iter().map(|t| task_to_dto(t)).collect()) -} - -pub fn create_task(list_id: String, title: String, description: String) -> Result { - let mut s = STATE.lock().unwrap(); - ensure_repo(&mut s)?; - mute_watcher(); - let id = Uuid::parse_str(&list_id).map_err(|e| e.to_string())?; - let mut task = Task::new(title); - if !description.is_empty() { - task.description = description; - } - let created = s.repo.as_mut().unwrap().create_task(id, task).map_err(|e| e.to_string())?; - Ok(task_to_dto(&created)) -} - -pub fn update_task(list_id: String, task: TaskDto) -> Result<(), String> { - let mut s = STATE.lock().unwrap(); - ensure_repo(&mut s)?; - mute_watcher(); - let lid = Uuid::parse_str(&list_id).map_err(|e| e.to_string())?; - let tid = Uuid::parse_str(&task.id).map_err(|e| e.to_string())?; - - let mut existing = s.repo.as_ref().unwrap().get_task(lid, tid).map_err(|e| e.to_string())?; - existing.title = task.title; - existing.description = task.description; - existing.due_date = task - .due_date - .as_deref() - .and_then(|d| chrono::DateTime::parse_from_rfc3339(d).ok()) - .map(|d| d.with_timezone(&chrono::Utc)); - existing.has_time = task.has_time; - - s.repo.as_mut().unwrap().update_task(lid, existing).map_err(|e| e.to_string()) -} - -pub fn delete_task(list_id: String, task_id: String) -> Result<(), String> { - let mut s = STATE.lock().unwrap(); - ensure_repo(&mut s)?; - mute_watcher(); - let lid = Uuid::parse_str(&list_id).map_err(|e| e.to_string())?; - let tid = Uuid::parse_str(&task_id).map_err(|e| e.to_string())?; - s.repo.as_mut().unwrap().delete_task(lid, tid).map_err(|e| e.to_string()) -} - -pub fn toggle_task(list_id: String, task_id: String) -> Result { - let mut s = STATE.lock().unwrap(); - ensure_repo(&mut s)?; - mute_watcher(); - let lid = Uuid::parse_str(&list_id).map_err(|e| e.to_string())?; - let tid = Uuid::parse_str(&task_id).map_err(|e| e.to_string())?; - let repo = s.repo.as_mut().unwrap(); - let mut task = repo.get_task(lid, tid).map_err(|e| e.to_string())?; - match task.status { - TaskStatus::Backlog => task.complete(), - TaskStatus::Completed => task.uncomplete(), - } - repo.update_task(lid, task.clone()).map_err(|e| e.to_string())?; - Ok(task_to_dto(&task)) -} - -pub fn reorder_task(list_id: String, task_id: String, new_position: u32) -> Result<(), String> { - let mut s = STATE.lock().unwrap(); - ensure_repo(&mut s)?; - mute_watcher(); - let lid = Uuid::parse_str(&list_id).map_err(|e| e.to_string())?; - let tid = Uuid::parse_str(&task_id).map_err(|e| e.to_string())?; - s.repo - .as_mut() - .unwrap() - .reorder_task(lid, tid, new_position as usize) - .map_err(|e| e.to_string()) -} - -// ── Move / rename / grouping ─────────────────────────────────────── - -pub fn move_task(from_list_id: String, to_list_id: String, task_id: String) -> Result<(), String> { - let mut s = STATE.lock().unwrap(); - ensure_repo(&mut s)?; - mute_watcher(); - let from = Uuid::parse_str(&from_list_id).map_err(|e| e.to_string())?; - let to = Uuid::parse_str(&to_list_id).map_err(|e| e.to_string())?; - let tid = Uuid::parse_str(&task_id).map_err(|e| e.to_string())?; - s.repo.as_mut().unwrap().move_task(from, to, tid).map_err(|e| e.to_string()) -} - -pub fn rename_list(list_id: String, new_name: String) -> Result<(), String> { - let mut s = STATE.lock().unwrap(); - ensure_repo(&mut s)?; - mute_watcher(); - let id = Uuid::parse_str(&list_id).map_err(|e| e.to_string())?; - s.repo.as_mut().unwrap().rename_list(id, new_name).map_err(|e| e.to_string()) -} - -pub fn set_group_by_due_date(list_id: String, enabled: bool) -> Result<(), String> { - let mut s = STATE.lock().unwrap(); - ensure_repo(&mut s)?; - mute_watcher(); - let id = Uuid::parse_str(&list_id).map_err(|e| e.to_string())?; - s.repo.as_mut().unwrap().set_group_by_due_date(id, enabled).map_err(|e| e.to_string()) -} - -pub fn get_group_by_due_date(list_id: String) -> Result { - let mut s = STATE.lock().unwrap(); - ensure_repo(&mut s)?; - let id = Uuid::parse_str(&list_id).map_err(|e| e.to_string())?; - s.repo.as_ref().unwrap().get_group_by_due_date(id).map_err(|e| e.to_string()) -} - -// ── Sync commands ────────────────────────────────────────────────── - -pub fn store_credentials(domain: String, username: String, password: String) -> Result<(), String> { - webdav::store_credentials(&domain, &username, &password).map_err(|e| e.to_string()) -} - -pub fn load_credentials(domain: String) -> Result, String> { - let (u, p) = webdav::load_credentials(&domain).map_err(|e| e.to_string())?; - Ok(vec![u, p]) -} - -pub fn set_webdav_config(workspace_name: String, webdav_url: String) -> Result<(), String> { - let mut s = STATE.lock().unwrap(); - if let Some(ws) = s.config.workspaces.get_mut(&workspace_name) { - ws.webdav_url = Some(webdav_url); - } - let config_path = AppConfig::get_config_path(); - s.config.save_to_file(&config_path).map_err(|e| e.to_string()) -} - -pub async fn test_webdav_connection(url: String, username: String, password: String) -> Result<(), String> { - let client = webdav::WebDavClient::new(&url, &username, &password); - client.test_connection().await.map_err(|e| e.to_string()) -} - -pub async fn sync_workspace_cmd( - workspace_name: String, - workspace_path: String, - webdav_url: String, - username: String, - password: String, - mode: String, -) -> Result { - let sync_mode = match mode.as_str() { - "push" => SyncMode::Push, - "pull" => SyncMode::Pull, - _ => SyncMode::Full, - }; - let result = sync::sync_workspace( - &PathBuf::from(&workspace_path), - &webdav_url, - &username, - &password, - sync_mode, - None, - ) - .await - .map_err(|e| e.to_string())?; - - { - let mut s = STATE.lock().unwrap(); - if let Some(ws) = s.config.workspaces.get_mut(&workspace_name) { - ws.last_sync = Some(chrono::Utc::now()); - } - let config_path = AppConfig::get_config_path(); - s.config.save_to_file(&config_path).map_err(|e| e.to_string())?; - } - - Ok(SyncResultDto { - uploaded: result.uploaded, - downloaded: result.downloaded, - deleted_local: result.deleted_local, - deleted_remote: result.deleted_remote, - conflicts: result.conflicts, - errors: result.errors, - }) -} - -// ── File watcher ─────────────────────────────────────────────────── - -static WATCHER: Mutex>> = - Mutex::new(None); - -static LAST_WRITE: Mutex> = Mutex::new(None); - -fn mute_watcher() { - *LAST_WRITE.lock().unwrap() = Some(Instant::now()); -} - -#[frb(stream_dart_await)] -pub fn watch_workspace_changes(path: String, sink: crate::frb_generated::StreamSink<()>) { - let debouncer = new_debouncer( - Duration::from_millis(500), - move |events: Result, notify::Error>| { - let Ok(events) = events else { return }; - let has_data_change = events.iter().any(|e| { - if e.kind != DebouncedEventKind::Any { return false; } - let p = e.path.to_string_lossy(); - p.ends_with(".md") || p.ends_with(".json") - }); - if !has_data_change { return; } - if let Some(t) = *LAST_WRITE.lock().unwrap() { - if t.elapsed() < Duration::from_secs(1) { return; } - } - let _ = sink.add(()); - }, - ); - match debouncer { - Ok(mut d) => { - let _ = d.watcher().watch(&PathBuf::from(&path), notify::RecursiveMode::Recursive); - *WATCHER.lock().unwrap() = Some(d); - } - Err(e) => eprintln!("Failed to start file watcher: {e}"), - } -} - -// ── Test function ─────────────────────────────────────────────────── - -pub fn greet(name: String) -> String { - format!("Hello, {name}! From Rust via flutter_rust_bridge.") -} diff --git a/apps/flutter/rust/src/frb_generated.rs b/apps/flutter/rust/src/frb_generated.rs deleted file mode 100644 index 766401e..0000000 --- a/apps/flutter/rust/src/frb_generated.rs +++ /dev/null @@ -1,1505 +0,0 @@ -// This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. - -#![allow( - non_camel_case_types, - unused, - non_snake_case, - clippy::needless_return, - clippy::redundant_closure_call, - clippy::redundant_closure, - clippy::useless_conversion, - clippy::unit_arg, - clippy::unused_unit, - clippy::double_parens, - clippy::let_and_return, - clippy::too_many_arguments, - clippy::match_single_binding, - clippy::clone_on_copy, - clippy::let_unit_value, - clippy::deref_addrof, - clippy::explicit_auto_deref, - clippy::borrow_deref_ref, - clippy::needless_borrow -)] - -// Section: imports - -use flutter_rust_bridge::for_generated::byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt}; -use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; -use flutter_rust_bridge::{Handler, IntoIntoDart}; - -// Section: boilerplate - -flutter_rust_bridge::frb_generated_boilerplate!( - default_stream_sink_codec = SseCodec, - default_rust_opaque = RustOpaqueMoi, - default_rust_auto_opaque = RustAutoOpaqueMoi, -); -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.11.1"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1094746925; - -// Section: executor - -flutter_rust_bridge::frb_generated_default_handler!(); - -// Section: wire_funcs - -fn wire__crate__api__add_workspace_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "add_workspace", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_name = ::sse_decode(&mut deserializer); - let api_path = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::add_workspace(api_name, api_path)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__create_list_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "create_list", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_name = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::create_list(api_name)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__create_task_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "create_task", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_list_id = ::sse_decode(&mut deserializer); - let api_title = ::sse_decode(&mut deserializer); - let api_description = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = - crate::api::create_task(api_list_id, api_title, api_description)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__delete_list_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "delete_list", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_list_id = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::delete_list(api_list_id)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__delete_task_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "delete_task", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_list_id = ::sse_decode(&mut deserializer); - let api_task_id = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::delete_task(api_list_id, api_task_id)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__get_config_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "get_config", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::get_config()?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__get_group_by_due_date_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "get_group_by_due_date", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_list_id = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::get_group_by_due_date(api_list_id)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__get_lists_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "get_lists", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::get_lists()?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__greet_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "greet", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_name = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, ()>((move || { - let output_ok = Result::<_, ()>::Ok(crate::api::greet(api_name))?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__init_workspace_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "init_workspace", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_path = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::init_workspace(api_path)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__list_tasks_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "list_tasks", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_list_id = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::list_tasks(api_list_id)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__load_credentials_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "load_credentials", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_domain = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::load_credentials(api_domain)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__move_task_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "move_task", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_from_list_id = ::sse_decode(&mut deserializer); - let api_to_list_id = ::sse_decode(&mut deserializer); - let api_task_id = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = - crate::api::move_task(api_from_list_id, api_to_list_id, api_task_id)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__remove_workspace_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "remove_workspace", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_name = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::remove_workspace(api_name)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__rename_list_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "rename_list", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_list_id = ::sse_decode(&mut deserializer); - let api_new_name = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::rename_list(api_list_id, api_new_name)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__reorder_task_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "reorder_task", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_list_id = ::sse_decode(&mut deserializer); - let api_task_id = ::sse_decode(&mut deserializer); - let api_new_position = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = - crate::api::reorder_task(api_list_id, api_task_id, api_new_position)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__set_current_workspace_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "set_current_workspace", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_name = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::set_current_workspace(api_name)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__set_group_by_due_date_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "set_group_by_due_date", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_list_id = ::sse_decode(&mut deserializer); - let api_enabled = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::set_group_by_due_date(api_list_id, api_enabled)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__set_webdav_config_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "set_webdav_config", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_workspace_name = ::sse_decode(&mut deserializer); - let api_webdav_url = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = - crate::api::set_webdav_config(api_workspace_name, api_webdav_url)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__store_credentials_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "store_credentials", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_domain = ::sse_decode(&mut deserializer); - let api_username = ::sse_decode(&mut deserializer); - let api_password = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = - crate::api::store_credentials(api_domain, api_username, api_password)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__sync_workspace_cmd_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "sync_workspace_cmd", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_workspace_name = ::sse_decode(&mut deserializer); - let api_workspace_path = ::sse_decode(&mut deserializer); - let api_webdav_url = ::sse_decode(&mut deserializer); - let api_username = ::sse_decode(&mut deserializer); - let api_password = ::sse_decode(&mut deserializer); - let api_mode = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| async move { - transform_result_sse::<_, String>( - (move || async move { - let output_ok = crate::api::sync_workspace_cmd( - api_workspace_name, - api_workspace_path, - api_webdav_url, - api_username, - api_password, - api_mode, - ) - .await?; - Ok(output_ok) - })() - .await, - ) - } - }, - ) -} -fn wire__crate__api__test_webdav_connection_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "test_webdav_connection", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_url = ::sse_decode(&mut deserializer); - let api_username = ::sse_decode(&mut deserializer); - let api_password = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| async move { - transform_result_sse::<_, String>( - (move || async move { - let output_ok = - crate::api::test_webdav_connection(api_url, api_username, api_password) - .await?; - Ok(output_ok) - })() - .await, - ) - } - }, - ) -} -fn wire__crate__api__toggle_task_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "toggle_task", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_list_id = ::sse_decode(&mut deserializer); - let api_task_id = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::toggle_task(api_list_id, api_task_id)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__update_task_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "update_task", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_list_id = ::sse_decode(&mut deserializer); - let api_task = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::update_task(api_list_id, api_task)?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__watch_workspace_changes_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "watch_workspace_changes", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_path = ::sse_decode(&mut deserializer); - let api_sink = - >::sse_decode( - &mut deserializer, - ); - deserializer.end(); - move |context| { - transform_result_sse::<_, ()>((move || { - let output_ok = Result::<_, ()>::Ok({ - crate::api::watch_workspace_changes(api_path, api_sink); - })?; - Ok(output_ok) - })()) - } - }, - ) -} - -// Section: dart2rust - -impl SseDecode for flutter_rust_bridge::for_generated::anyhow::Error { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut inner = ::sse_decode(deserializer); - return flutter_rust_bridge::for_generated::anyhow::anyhow!("{}", inner); - } -} - -impl SseDecode for StreamSink<(), flutter_rust_bridge::for_generated::SseCodec> { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut inner = ::sse_decode(deserializer); - return StreamSink::deserialize(inner); - } -} - -impl SseDecode for String { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut inner = >::sse_decode(deserializer); - return String::from_utf8(inner).unwrap(); - } -} - -impl SseDecode for crate::api::AppConfigDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_workspaces = >::sse_decode(deserializer); - let mut var_currentWorkspace = >::sse_decode(deserializer); - return crate::api::AppConfigDto { - workspaces: var_workspaces, - current_workspace: var_currentWorkspace, - }; - } -} - -impl SseDecode for bool { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - deserializer.cursor.read_u8().unwrap() != 0 - } -} - -impl SseDecode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut len_ = ::sse_decode(deserializer); - let mut ans_ = vec![]; - for idx_ in 0..len_ { - ans_.push(::sse_decode(deserializer)); - } - return ans_; - } -} - -impl SseDecode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut len_ = ::sse_decode(deserializer); - let mut ans_ = vec![]; - for idx_ in 0..len_ { - ans_.push(::sse_decode(deserializer)); - } - return ans_; - } -} - -impl SseDecode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut len_ = ::sse_decode(deserializer); - let mut ans_ = vec![]; - for idx_ in 0..len_ { - ans_.push(::sse_decode(deserializer)); - } - return ans_; - } -} - -impl SseDecode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut len_ = ::sse_decode(deserializer); - let mut ans_ = vec![]; - for idx_ in 0..len_ { - ans_.push(::sse_decode(deserializer)); - } - return ans_; - } -} - -impl SseDecode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut len_ = ::sse_decode(deserializer); - let mut ans_ = vec![]; - for idx_ in 0..len_ { - ans_.push(::sse_decode(deserializer)); - } - return ans_; - } -} - -impl SseDecode for Option { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - if (::sse_decode(deserializer)) { - return Some(::sse_decode(deserializer)); - } else { - return None; - } - } -} - -impl SseDecode for crate::api::SyncResultDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_uploaded = ::sse_decode(deserializer); - let mut var_downloaded = ::sse_decode(deserializer); - let mut var_deletedLocal = ::sse_decode(deserializer); - let mut var_deletedRemote = ::sse_decode(deserializer); - let mut var_conflicts = ::sse_decode(deserializer); - let mut var_errors = >::sse_decode(deserializer); - return crate::api::SyncResultDto { - uploaded: var_uploaded, - downloaded: var_downloaded, - deleted_local: var_deletedLocal, - deleted_remote: var_deletedRemote, - conflicts: var_conflicts, - errors: var_errors, - }; - } -} - -impl SseDecode for crate::api::TaskDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_id = ::sse_decode(deserializer); - let mut var_title = ::sse_decode(deserializer); - let mut var_description = ::sse_decode(deserializer); - let mut var_status = ::sse_decode(deserializer); - let mut var_dueDate = >::sse_decode(deserializer); - let mut var_hasTime = ::sse_decode(deserializer); - let mut var_createdAt = ::sse_decode(deserializer); - let mut var_updatedAt = ::sse_decode(deserializer); - let mut var_parentId = >::sse_decode(deserializer); - return crate::api::TaskDto { - id: var_id, - title: var_title, - description: var_description, - status: var_status, - due_date: var_dueDate, - has_time: var_hasTime, - created_at: var_createdAt, - updated_at: var_updatedAt, - parent_id: var_parentId, - }; - } -} - -impl SseDecode for crate::api::TaskListDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_id = ::sse_decode(deserializer); - let mut var_title = ::sse_decode(deserializer); - let mut var_createdAt = ::sse_decode(deserializer); - let mut var_updatedAt = ::sse_decode(deserializer); - let mut var_groupByDueDate = ::sse_decode(deserializer); - return crate::api::TaskListDto { - id: var_id, - title: var_title, - created_at: var_createdAt, - updated_at: var_updatedAt, - group_by_due_date: var_groupByDueDate, - }; - } -} - -impl SseDecode for u32 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - deserializer.cursor.read_u32::().unwrap() - } -} - -impl SseDecode for u8 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - deserializer.cursor.read_u8().unwrap() - } -} - -impl SseDecode for () { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {} -} - -impl SseDecode for crate::api::WorkspaceEntry { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_name = ::sse_decode(deserializer); - let mut var_path = ::sse_decode(deserializer); - let mut var_webdavUrl = >::sse_decode(deserializer); - let mut var_lastSync = >::sse_decode(deserializer); - return crate::api::WorkspaceEntry { - name: var_name, - path: var_path, - webdav_url: var_webdavUrl, - last_sync: var_lastSync, - }; - } -} - -impl SseDecode for i32 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - deserializer.cursor.read_i32::().unwrap() - } -} - -fn pde_ffi_dispatcher_primary_impl( - func_id: i32, - port: flutter_rust_bridge::for_generated::MessagePort, - ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len: i32, - data_len: i32, -) { - // Codec=Pde (Serialization + dispatch), see doc to use other codecs - match func_id { - 1 => wire__crate__api__add_workspace_impl(port, ptr, rust_vec_len, data_len), - 2 => wire__crate__api__create_list_impl(port, ptr, rust_vec_len, data_len), - 3 => wire__crate__api__create_task_impl(port, ptr, rust_vec_len, data_len), - 4 => wire__crate__api__delete_list_impl(port, ptr, rust_vec_len, data_len), - 5 => wire__crate__api__delete_task_impl(port, ptr, rust_vec_len, data_len), - 6 => wire__crate__api__get_config_impl(port, ptr, rust_vec_len, data_len), - 7 => wire__crate__api__get_group_by_due_date_impl(port, ptr, rust_vec_len, data_len), - 8 => wire__crate__api__get_lists_impl(port, ptr, rust_vec_len, data_len), - 9 => wire__crate__api__greet_impl(port, ptr, rust_vec_len, data_len), - 10 => wire__crate__api__init_workspace_impl(port, ptr, rust_vec_len, data_len), - 11 => wire__crate__api__list_tasks_impl(port, ptr, rust_vec_len, data_len), - 12 => wire__crate__api__load_credentials_impl(port, ptr, rust_vec_len, data_len), - 13 => wire__crate__api__move_task_impl(port, ptr, rust_vec_len, data_len), - 14 => wire__crate__api__remove_workspace_impl(port, ptr, rust_vec_len, data_len), - 15 => wire__crate__api__rename_list_impl(port, ptr, rust_vec_len, data_len), - 16 => wire__crate__api__reorder_task_impl(port, ptr, rust_vec_len, data_len), - 17 => wire__crate__api__set_current_workspace_impl(port, ptr, rust_vec_len, data_len), - 18 => wire__crate__api__set_group_by_due_date_impl(port, ptr, rust_vec_len, data_len), - 19 => wire__crate__api__set_webdav_config_impl(port, ptr, rust_vec_len, data_len), - 20 => wire__crate__api__store_credentials_impl(port, ptr, rust_vec_len, data_len), - 21 => wire__crate__api__sync_workspace_cmd_impl(port, ptr, rust_vec_len, data_len), - 22 => wire__crate__api__test_webdav_connection_impl(port, ptr, rust_vec_len, data_len), - 23 => wire__crate__api__toggle_task_impl(port, ptr, rust_vec_len, data_len), - 24 => wire__crate__api__update_task_impl(port, ptr, rust_vec_len, data_len), - 25 => wire__crate__api__watch_workspace_changes_impl(port, ptr, rust_vec_len, data_len), - _ => unreachable!(), - } -} - -fn pde_ffi_dispatcher_sync_impl( - func_id: i32, - ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len: i32, - data_len: i32, -) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { - // Codec=Pde (Serialization + dispatch), see doc to use other codecs - match func_id { - _ => unreachable!(), - } -} - -// Section: rust2dart - -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::AppConfigDto { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.workspaces.into_into_dart().into_dart(), - self.current_workspace.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::AppConfigDto {} -impl flutter_rust_bridge::IntoIntoDart for crate::api::AppConfigDto { - fn into_into_dart(self) -> crate::api::AppConfigDto { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::SyncResultDto { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.uploaded.into_into_dart().into_dart(), - self.downloaded.into_into_dart().into_dart(), - self.deleted_local.into_into_dart().into_dart(), - self.deleted_remote.into_into_dart().into_dart(), - self.conflicts.into_into_dart().into_dart(), - self.errors.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::SyncResultDto {} -impl flutter_rust_bridge::IntoIntoDart for crate::api::SyncResultDto { - fn into_into_dart(self) -> crate::api::SyncResultDto { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::TaskDto { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.id.into_into_dart().into_dart(), - self.title.into_into_dart().into_dart(), - self.description.into_into_dart().into_dart(), - self.status.into_into_dart().into_dart(), - self.due_date.into_into_dart().into_dart(), - self.has_time.into_into_dart().into_dart(), - self.created_at.into_into_dart().into_dart(), - self.updated_at.into_into_dart().into_dart(), - self.parent_id.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::TaskDto {} -impl flutter_rust_bridge::IntoIntoDart for crate::api::TaskDto { - fn into_into_dart(self) -> crate::api::TaskDto { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::TaskListDto { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.id.into_into_dart().into_dart(), - self.title.into_into_dart().into_dart(), - self.created_at.into_into_dart().into_dart(), - self.updated_at.into_into_dart().into_dart(), - self.group_by_due_date.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::TaskListDto {} -impl flutter_rust_bridge::IntoIntoDart for crate::api::TaskListDto { - fn into_into_dart(self) -> crate::api::TaskListDto { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::WorkspaceEntry { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.name.into_into_dart().into_dart(), - self.path.into_into_dart().into_dart(), - self.webdav_url.into_into_dart().into_dart(), - self.last_sync.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::WorkspaceEntry {} -impl flutter_rust_bridge::IntoIntoDart for crate::api::WorkspaceEntry { - fn into_into_dart(self) -> crate::api::WorkspaceEntry { - self - } -} - -impl SseEncode for flutter_rust_bridge::for_generated::anyhow::Error { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(format!("{:?}", self), serializer); - } -} - -impl SseEncode for StreamSink<(), flutter_rust_bridge::for_generated::SseCodec> { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - unimplemented!("") - } -} - -impl SseEncode for String { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - >::sse_encode(self.into_bytes(), serializer); - } -} - -impl SseEncode for crate::api::AppConfigDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - >::sse_encode(self.workspaces, serializer); - >::sse_encode(self.current_workspace, serializer); - } -} - -impl SseEncode for bool { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - serializer.cursor.write_u8(self as _).unwrap(); - } -} - -impl SseEncode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.len() as _, serializer); - for item in self { - ::sse_encode(item, serializer); - } - } -} - -impl SseEncode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.len() as _, serializer); - for item in self { - ::sse_encode(item, serializer); - } - } -} - -impl SseEncode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.len() as _, serializer); - for item in self { - ::sse_encode(item, serializer); - } - } -} - -impl SseEncode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.len() as _, serializer); - for item in self { - ::sse_encode(item, serializer); - } - } -} - -impl SseEncode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.len() as _, serializer); - for item in self { - ::sse_encode(item, serializer); - } - } -} - -impl SseEncode for Option { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.is_some(), serializer); - if let Some(value) = self { - ::sse_encode(value, serializer); - } - } -} - -impl SseEncode for crate::api::SyncResultDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.uploaded, serializer); - ::sse_encode(self.downloaded, serializer); - ::sse_encode(self.deleted_local, serializer); - ::sse_encode(self.deleted_remote, serializer); - ::sse_encode(self.conflicts, serializer); - >::sse_encode(self.errors, serializer); - } -} - -impl SseEncode for crate::api::TaskDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.id, serializer); - ::sse_encode(self.title, serializer); - ::sse_encode(self.description, serializer); - ::sse_encode(self.status, serializer); - >::sse_encode(self.due_date, serializer); - ::sse_encode(self.has_time, serializer); - ::sse_encode(self.created_at, serializer); - ::sse_encode(self.updated_at, serializer); - >::sse_encode(self.parent_id, serializer); - } -} - -impl SseEncode for crate::api::TaskListDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.id, serializer); - ::sse_encode(self.title, serializer); - ::sse_encode(self.created_at, serializer); - ::sse_encode(self.updated_at, serializer); - ::sse_encode(self.group_by_due_date, serializer); - } -} - -impl SseEncode for u32 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - serializer.cursor.write_u32::(self).unwrap(); - } -} - -impl SseEncode for u8 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - serializer.cursor.write_u8(self).unwrap(); - } -} - -impl SseEncode for () { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {} -} - -impl SseEncode for crate::api::WorkspaceEntry { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.name, serializer); - ::sse_encode(self.path, serializer); - >::sse_encode(self.webdav_url, serializer); - >::sse_encode(self.last_sync, serializer); - } -} - -impl SseEncode for i32 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - serializer.cursor.write_i32::(self).unwrap(); - } -} - -#[cfg(not(target_family = "wasm"))] -mod io { - // This file is automatically generated, so please do not edit it. - // @generated by `flutter_rust_bridge`@ 2.11.1. - - // Section: imports - - use super::*; - use flutter_rust_bridge::for_generated::byteorder::{ - NativeEndian, ReadBytesExt, WriteBytesExt, - }; - use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; - use flutter_rust_bridge::{Handler, IntoIntoDart}; - - // Section: boilerplate - - flutter_rust_bridge::frb_generated_boilerplate_io!(); -} -#[cfg(not(target_family = "wasm"))] -pub use io::*; - -/// cbindgen:ignore -#[cfg(target_family = "wasm")] -mod web { - // This file is automatically generated, so please do not edit it. - // @generated by `flutter_rust_bridge`@ 2.11.1. - - // Section: imports - - use super::*; - use flutter_rust_bridge::for_generated::byteorder::{ - NativeEndian, ReadBytesExt, WriteBytesExt, - }; - use flutter_rust_bridge::for_generated::wasm_bindgen; - use flutter_rust_bridge::for_generated::wasm_bindgen::prelude::*; - use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; - use flutter_rust_bridge::{Handler, IntoIntoDart}; - - // Section: boilerplate - - flutter_rust_bridge::frb_generated_boilerplate_web!(); -} -#[cfg(target_family = "wasm")] -pub use web::*; diff --git a/apps/flutter/rust/src/lib.rs b/apps/flutter/rust/src/lib.rs deleted file mode 100644 index 25448a4..0000000 --- a/apps/flutter/rust/src/lib.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod frb_generated; /* AUTO INJECTED BY flutter_rust_bridge. This line may not be accurate, and you can change it according to your needs. */ -pub mod api; diff --git a/apps/flutter/test/widget_test.dart b/apps/flutter/test/widget_test.dart deleted file mode 100644 index 0c63a1a..0000000 --- a/apps/flutter/test/widget_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility in the flutter_test package. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:onyx/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} diff --git a/apps/flutter/windows/.gitignore b/apps/flutter/windows/.gitignore deleted file mode 100644 index d492d0d..0000000 --- a/apps/flutter/windows/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -flutter/ephemeral/ - -# Visual Studio user-specific files. -*.suo -*.user -*.userosscache -*.sln.docstates - -# Visual Studio build-related files. -x64/ -x86/ - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ diff --git a/apps/flutter/windows/CMakeLists.txt b/apps/flutter/windows/CMakeLists.txt deleted file mode 100644 index 94b4c4c..0000000 --- a/apps/flutter/windows/CMakeLists.txt +++ /dev/null @@ -1,108 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.14) -project(onyx LANGUAGES CXX) - -# The name of the executable created for the application. Change this to change -# the on-disk name of your application. -set(BINARY_NAME "onyx") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(VERSION 3.14...3.25) - -# Define build configuration option. -get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(IS_MULTICONFIG) - set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" - CACHE STRING "" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") - endif() -endif() -# Define settings for the Profile build mode. -set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") -set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") -set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") -set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") - -# Use Unicode for all projects. -add_definitions(-DUNICODE -D_UNICODE) - -# Compilation settings that should be applied to most targets. -# -# Be cautious about adding new options here, as plugins use this function by -# default. In most cases, you should add new options to specific targets instead -# of modifying this function. -function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_17) - target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") - target_compile_options(${TARGET} PRIVATE /EHsc) - target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") - target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") -endfunction() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# Application build; see runner/CMakeLists.txt. -add_subdirectory("runner") - - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# Support files are copied into place next to the executable, so that it can -# run in place. This is done instead of making a separate bundle (as on Linux) -# so that building and running from within Visual Studio will work. -set(BUILD_BUNDLE_DIR "$") -# Make the "install" step default, as it's required to run. -set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() - -set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") -set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") - -install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() - -# Copy the native assets provided by the build.dart from all packages. -set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") -install(DIRECTORY "${NATIVE_ASSETS_DIR}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -# Fully re-copy the assets directory on each build to avoid having stale files -# from a previous install. -set(FLUTTER_ASSET_DIR_NAME "flutter_assets") -install(CODE " - file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") - " COMPONENT Runtime) -install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) - -# Install the AOT library on non-Debug builds only. -install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - CONFIGURATIONS Profile;Release - COMPONENT Runtime) diff --git a/apps/flutter/windows/flutter/CMakeLists.txt b/apps/flutter/windows/flutter/CMakeLists.txt deleted file mode 100644 index 903f489..0000000 --- a/apps/flutter/windows/flutter/CMakeLists.txt +++ /dev/null @@ -1,109 +0,0 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.14) - -set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") - -# Configuration provided via flutter tool. -include(${EPHEMERAL_DIR}/generated_config.cmake) - -# TODO: Move the rest of this into files in ephemeral. See -# https://github.com/flutter/flutter/issues/57146. -set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") - -# Set fallback configurations for older versions of the flutter tool. -if (NOT DEFINED FLUTTER_TARGET_PLATFORM) - set(FLUTTER_TARGET_PLATFORM "windows-x64") -endif() - -# === Flutter Library === -set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") - -# Published to parent scope for install step. -set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) -set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) -set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) -set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) - -list(APPEND FLUTTER_LIBRARY_HEADERS - "flutter_export.h" - "flutter_windows.h" - "flutter_messenger.h" - "flutter_plugin_registrar.h" - "flutter_texture_registrar.h" -) -list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") -add_library(flutter INTERFACE) -target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" -) -target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") -add_dependencies(flutter flutter_assemble) - -# === Wrapper === -list(APPEND CPP_WRAPPER_SOURCES_CORE - "core_implementations.cc" - "standard_codec.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") -list(APPEND CPP_WRAPPER_SOURCES_PLUGIN - "plugin_registrar.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") -list(APPEND CPP_WRAPPER_SOURCES_APP - "flutter_engine.cc" - "flutter_view_controller.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") - -# Wrapper sources needed for a plugin. -add_library(flutter_wrapper_plugin STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} -) -apply_standard_settings(flutter_wrapper_plugin) -set_target_properties(flutter_wrapper_plugin PROPERTIES - POSITION_INDEPENDENT_CODE ON) -set_target_properties(flutter_wrapper_plugin PROPERTIES - CXX_VISIBILITY_PRESET hidden) -target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) -target_include_directories(flutter_wrapper_plugin PUBLIC - "${WRAPPER_ROOT}/include" -) -add_dependencies(flutter_wrapper_plugin flutter_assemble) - -# Wrapper sources needed for the runner. -add_library(flutter_wrapper_app STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_APP} -) -apply_standard_settings(flutter_wrapper_app) -target_link_libraries(flutter_wrapper_app PUBLIC flutter) -target_include_directories(flutter_wrapper_app PUBLIC - "${WRAPPER_ROOT}/include" -) -add_dependencies(flutter_wrapper_app flutter_assemble) - -# === Flutter tool backend === -# _phony_ is a non-existent file to force this command to run every time, -# since currently there's no way to get a full input/output list from the -# flutter tool. -set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") -set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) -add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} - ${PHONY_OUTPUT} - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - ${FLUTTER_TARGET_PLATFORM} $ - VERBATIM -) -add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} -) diff --git a/apps/flutter/windows/flutter/generated_plugin_registrant.cc b/apps/flutter/windows/flutter/generated_plugin_registrant.cc deleted file mode 100644 index c6fe39a..0000000 --- a/apps/flutter/windows/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,17 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include -#include - -void RegisterPlugins(flutter::PluginRegistry* registry) { - ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi")); - WindowManagerPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("WindowManagerPlugin")); -} diff --git a/apps/flutter/windows/flutter/generated_plugin_registrant.h b/apps/flutter/windows/flutter/generated_plugin_registrant.h deleted file mode 100644 index dc139d8..0000000 --- a/apps/flutter/windows/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void RegisterPlugins(flutter::PluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/apps/flutter/windows/flutter/generated_plugins.cmake b/apps/flutter/windows/flutter/generated_plugins.cmake deleted file mode 100644 index 5e3bc3d..0000000 --- a/apps/flutter/windows/flutter/generated_plugins.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - screen_retriever_windows - window_manager -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/apps/flutter/windows/runner/CMakeLists.txt b/apps/flutter/windows/runner/CMakeLists.txt deleted file mode 100644 index 394917c..0000000 --- a/apps/flutter/windows/runner/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -cmake_minimum_required(VERSION 3.14) -project(runner LANGUAGES CXX) - -# Define the application target. To change its name, change BINARY_NAME in the -# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer -# work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} WIN32 - "flutter_window.cpp" - "main.cpp" - "utils.cpp" - "win32_window.cpp" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" - "Runner.rc" - "runner.exe.manifest" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add preprocessor definitions for the build version. -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") - -# Disable Windows macros that collide with C++ standard library functions. -target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") - -# Add dependency libraries and include directories. Add any application-specific -# dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) -target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") -target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/apps/flutter/windows/runner/Runner.rc b/apps/flutter/windows/runner/Runner.rc deleted file mode 100644 index 59c146e..0000000 --- a/apps/flutter/windows/runner/Runner.rc +++ /dev/null @@ -1,121 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#pragma code_page(65001) -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_APP_ICON ICON "resources\\app_icon.ico" - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) -#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD -#else -#define VERSION_AS_NUMBER 1,0,0,0 -#endif - -#if defined(FLUTTER_VERSION) -#define VERSION_AS_STRING FLUTTER_VERSION -#else -#define VERSION_AS_STRING "1.0.0" -#endif - -VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_AS_NUMBER - PRODUCTVERSION VERSION_AS_NUMBER - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "com.example" "\0" - VALUE "FileDescription", "onyx" "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "onyx" "\0" - VALUE "LegalCopyright", "Copyright (C) 2026 com.example. All rights reserved." "\0" - VALUE "OriginalFilename", "onyx.exe" "\0" - VALUE "ProductName", "onyx" "\0" - VALUE "ProductVersion", VERSION_AS_STRING "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END -END - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/apps/flutter/windows/runner/flutter_window.cpp b/apps/flutter/windows/runner/flutter_window.cpp deleted file mode 100644 index 955ee30..0000000 --- a/apps/flutter/windows/runner/flutter_window.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "flutter_window.h" - -#include - -#include "flutter/generated_plugin_registrant.h" - -FlutterWindow::FlutterWindow(const flutter::DartProject& project) - : project_(project) {} - -FlutterWindow::~FlutterWindow() {} - -bool FlutterWindow::OnCreate() { - if (!Win32Window::OnCreate()) { - return false; - } - - RECT frame = GetClientArea(); - - // The size here must match the window dimensions to avoid unnecessary surface - // creation / destruction in the startup path. - flutter_controller_ = std::make_unique( - frame.right - frame.left, frame.bottom - frame.top, project_); - // Ensure that basic setup of the controller was successful. - if (!flutter_controller_->engine() || !flutter_controller_->view()) { - return false; - } - RegisterPlugins(flutter_controller_->engine()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); - - flutter_controller_->engine()->SetNextFrameCallback([&]() { - this->Show(); - }); - - // Flutter can complete the first frame before the "show window" callback is - // registered. The following call ensures a frame is pending to ensure the - // window is shown. It is a no-op if the first frame hasn't completed yet. - flutter_controller_->ForceRedraw(); - - return true; -} - -void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - flutter_controller_ = nullptr; - } - - Win32Window::OnDestroy(); -} - -LRESULT -FlutterWindow::MessageHandler(HWND hwnd, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opportunity to handle window messages. - if (flutter_controller_) { - std::optional result = - flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, - lparam); - if (result) { - return *result; - } - } - - switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; - } - - return Win32Window::MessageHandler(hwnd, message, wparam, lparam); -} diff --git a/apps/flutter/windows/runner/flutter_window.h b/apps/flutter/windows/runner/flutter_window.h deleted file mode 100644 index 6da0652..0000000 --- a/apps/flutter/windows/runner/flutter_window.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef RUNNER_FLUTTER_WINDOW_H_ -#define RUNNER_FLUTTER_WINDOW_H_ - -#include -#include - -#include - -#include "win32_window.h" - -// A window that does nothing but host a Flutter view. -class FlutterWindow : public Win32Window { - public: - // Creates a new FlutterWindow hosting a Flutter view running |project|. - explicit FlutterWindow(const flutter::DartProject& project); - virtual ~FlutterWindow(); - - protected: - // Win32Window: - bool OnCreate() override; - void OnDestroy() override; - LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept override; - - private: - // The project to run. - flutter::DartProject project_; - - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; -}; - -#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/apps/flutter/windows/runner/main.cpp b/apps/flutter/windows/runner/main.cpp deleted file mode 100644 index 8789bfb..0000000 --- a/apps/flutter/windows/runner/main.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -#include "flutter_window.h" -#include "utils.h" - -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } - - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - - flutter::DartProject project(L"data"); - - std::vector command_line_arguments = - GetCommandLineArguments(); - - project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); - - FlutterWindow window(project); - Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); - if (!window.Create(L"onyx", origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); - - ::MSG msg; - while (::GetMessage(&msg, nullptr, 0, 0)) { - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - } - - ::CoUninitialize(); - return EXIT_SUCCESS; -} diff --git a/apps/flutter/windows/runner/resource.h b/apps/flutter/windows/runner/resource.h deleted file mode 100644 index 66a65d1..0000000 --- a/apps/flutter/windows/runner/resource.h +++ /dev/null @@ -1,16 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Runner.rc -// -#define IDI_APP_ICON 101 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/apps/flutter/windows/runner/resources/app_icon.ico b/apps/flutter/windows/runner/resources/app_icon.ico deleted file mode 100644 index c04e20caf6370ebb9253ad831cc31de4a9c965f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33772 zcmeHQc|26z|35SKE&G-*mXah&B~fFkXr)DEO&hIfqby^T&>|8^_Ub8Vp#`BLl3lbZ zvPO!8k!2X>cg~Elr=IVxo~J*a`+9wR=A83c-k-DFd(XM&UI1VKCqM@V;DDtJ09WB} zRaHKiW(GT00brH|0EeTeKVbpbGZg?nK6-j827q-+NFM34gXjqWxJ*a#{b_apGN<-L_m3#8Z26atkEn& ze87Bvv^6vVmM+p+cQ~{u%=NJF>#(d;8{7Q{^rWKWNtf14H}>#&y7$lqmY6xmZryI& z($uy?c5-+cPnt2%)R&(KIWEXww>Cnz{OUpT>W$CbO$h1= z#4BPMkFG1Y)x}Ui+WXr?Z!w!t_hjRq8qTaWpu}FH{MsHlU{>;08goVLm{V<&`itk~ zE_Ys=D(hjiy+5=?=$HGii=Y5)jMe9|wWoD_K07(}edAxh`~LBorOJ!Cf@f{_gNCC| z%{*04ViE!#>@hc1t5bb+NO>ncf@@Dv01K!NxH$3Eg1%)|wLyMDF8^d44lV!_Sr}iEWefOaL z8f?ud3Q%Sen39u|%00W<#!E=-RpGa+H8}{ulxVl4mwpjaU+%2pzmi{3HM)%8vb*~-M9rPUAfGCSos8GUXp02|o~0BTV2l#`>>aFV&_P$ejS;nGwSVP8 zMbOaG7<7eKD>c12VdGH;?2@q7535sa7MN*L@&!m?L`ASG%boY7(&L5imY#EQ$KrBB z4@_tfP5m50(T--qv1BJcD&aiH#b-QC>8#7Fx@3yXlonJI#aEIi=8&ChiVpc#N=5le zM*?rDIdcpawoc5kizv$GEjnveyrp3sY>+5_R5;>`>erS%JolimF=A^EIsAK zsPoVyyUHCgf0aYr&alx`<)eb6Be$m&`JYSuBu=p8j%QlNNp$-5C{b4#RubPb|CAIS zGE=9OFLP7?Hgc{?k45)84biT0k&-C6C%Q}aI~q<(7BL`C#<6HyxaR%!dFx7*o^laG z=!GBF^cwK$IA(sn9y6>60Rw{mYRYkp%$jH z*xQM~+bp)G$_RhtFPYx2HTsWk80+p(uqv9@I9)y{b$7NK53rYL$ezbmRjdXS?V}fj zWxX_feWoLFNm3MG7pMUuFPs$qrQWO9!l2B(SIuy2}S|lHNbHzoE+M2|Zxhjq9+Ws8c{*}x^VAib7SbxJ*Q3EnY5lgI9 z=U^f3IW6T=TWaVj+2N%K3<%Un;CF(wUp`TC&Y|ZjyFu6co^uqDDB#EP?DV5v_dw~E zIRK*BoY9y-G_ToU2V_XCX4nJ32~`czdjT!zwme zGgJ0nOk3U4@IE5JwtM}pwimLjk{ln^*4HMU%Fl4~n(cnsLB}Ja-jUM>xIB%aY;Nq8 z)Fp8dv1tkqKanv<68o@cN|%thj$+f;zGSO7H#b+eMAV8xH$hLggtt?O?;oYEgbq@= zV(u9bbd12^%;?nyk6&$GPI%|+<_mEpJGNfl*`!KV;VfmZWw{n{rnZ51?}FDh8we_L z8OI9nE31skDqJ5Oa_ybn7|5@ui>aC`s34p4ZEu6-s!%{uU45$Zd1=p$^^dZBh zu<*pDDPLW+c>iWO$&Z_*{VSQKg7=YEpS3PssPn1U!lSm6eZIho*{@&20e4Y_lRklKDTUCKI%o4Pc<|G^Xgu$J^Q|B87U;`c1zGwf^-zH*VQ^x+i^OUWE0yd z;{FJq)2w!%`x7yg@>uGFFf-XJl4H`YtUG%0slGKOlXV`q?RP>AEWg#x!b{0RicxGhS!3$p7 zij;{gm!_u@D4$Ox%>>bPtLJ> zwKtYz?T_DR1jN>DkkfGU^<#6sGz|~p*I{y`aZ>^Di#TC|Z!7j_O1=Wo8thuit?WxR zh9_S>kw^{V^|g}HRUF=dcq>?q(pHxw!8rx4dC6vbQVmIhmICF#zU!HkHpQ>9S%Uo( zMw{eC+`&pb=GZRou|3;Po1}m46H6NGd$t<2mQh}kaK-WFfmj_66_17BX0|j-E2fe3Jat}ijpc53 zJV$$;PC<5aW`{*^Z6e5##^`Ed#a0nwJDT#Qq~^e8^JTA=z^Kl>La|(UQ!bI@#ge{Dzz@61p-I)kc2?ZxFt^QQ}f%ldLjO*GPj(5)V9IyuUakJX=~GnTgZ4$5!3E=V#t`yOG4U z(gphZB6u2zsj=qNFLYShhg$}lNpO`P9xOSnO*$@@UdMYES*{jJVj|9z-}F^riksLK zbsU+4-{281P9e2UjY6tse^&a)WM1MFw;p#_dHhWI7p&U*9TR0zKdVuQed%6{otTsq z$f~S!;wg#Bd9kez=Br{m|66Wv z#g1xMup<0)H;c2ZO6su_ii&m8j&+jJz4iKnGZ&wxoQX|5a>v&_e#6WA!MB_4asTxLRGQCC5cI(em z%$ZfeqP>!*q5kU>a+BO&ln=4Jm>Ef(QE8o&RgLkk%2}4Tf}U%IFP&uS7}&|Q-)`5< z+e>;s#4cJ-z%&-^&!xsYx777Wt(wZY9(3(avmr|gRe4cD+a8&!LY`1^T?7x{E<=kdY9NYw>A;FtTvQ=Y&1M%lyZPl$ss1oY^Sl8we}n}Aob#6 zl4jERwnt9BlSoWb@3HxYgga(752Vu6Y)k4yk9u~Kw>cA5&LHcrvn1Y-HoIuFWg~}4 zEw4bR`mXZQIyOAzo)FYqg?$5W<;^+XX%Uz61{-L6@eP|lLH%|w?g=rFc;OvEW;^qh z&iYXGhVt(G-q<+_j}CTbPS_=K>RKN0&;dubh0NxJyDOHFF;<1k!{k#7b{|Qok9hac z;gHz}6>H6C6RnB`Tt#oaSrX0p-j-oRJ;_WvS-qS--P*8}V943RT6kou-G=A+7QPGQ z!ze^UGxtW3FC0$|(lY9^L!Lx^?Q8cny(rR`es5U;-xBhphF%_WNu|aO<+e9%6LuZq zt(0PoagJG<%hyuf;te}n+qIl_Ej;czWdc{LX^pS>77s9t*2b4s5dvP_!L^3cwlc)E!(!kGrg~FescVT zZCLeua3f4;d;Tk4iXzt}g}O@nlK3?_o91_~@UMIl?@77Qc$IAlLE95#Z=TES>2E%z zxUKpK{_HvGF;5%Q7n&vA?`{%8ohlYT_?(3A$cZSi)MvIJygXD}TS-3UwyUxGLGiJP znblO~G|*uA^|ac8E-w#}uBtg|s_~s&t>-g0X%zIZ@;o_wNMr_;{KDg^O=rg`fhDZu zFp(VKd1Edj%F zWHPl+)FGj%J1BO3bOHVfH^3d1F{)*PL&sRX`~(-Zy3&9UQX)Z;c51tvaI2E*E7!)q zcz|{vpK7bjxix(k&6=OEIBJC!9lTkUbgg?4-yE{9+pFS)$Ar@vrIf`D0Bnsed(Cf? zObt2CJ>BKOl>q8PyFO6w)+6Iz`LW%T5^R`U_NIW0r1dWv6OY=TVF?N=EfA(k(~7VBW(S;Tu5m4Lg8emDG-(mOSSs=M9Q&N8jc^Y4&9RqIsk(yO_P(mcCr}rCs%1MW1VBrn=0-oQN(Xj!k%iKV zb%ricBF3G4S1;+8lzg5PbZ|$Se$)I=PwiK=cDpHYdov2QO1_a-*dL4KUi|g&oh>(* zq$<`dQ^fat`+VW?m)?_KLn&mp^-@d=&7yGDt<=XwZZC=1scwxO2^RRI7n@g-1o8ps z)&+et_~)vr8aIF1VY1Qrq~Xe``KJrQSnAZ{CSq3yP;V*JC;mmCT6oRLSs7=GA?@6g zUooM}@tKtx(^|aKK8vbaHlUQqwE0}>j&~YlN3H#vKGm@u)xxS?n9XrOWUfCRa< z`20Fld2f&;gg7zpo{Adh+mqNntMc-D$N^yWZAZRI+u1T1zWHPxk{+?vcS1D>08>@6 zLhE@`gt1Y9mAK6Z4p|u(5I%EkfU7rKFSM=E4?VG9tI;a*@?6!ey{lzN5=Y-!$WFSe z&2dtO>^0@V4WRc#L&P%R(?@KfSblMS+N+?xUN$u3K4Ys%OmEh+tq}fnU}i>6YHM?< zlnL2gl~sF!j!Y4E;j3eIU-lfa`RsOL*Tt<%EFC0gPzoHfNWAfKFIKZN8}w~(Yi~=q z>=VNLO2|CjkxP}RkutxjV#4fWYR1KNrPYq5ha9Wl+u>ipsk*I(HS@iLnmGH9MFlTU zaFZ*KSR0px>o+pL7BbhB2EC1%PJ{67_ z#kY&#O4@P=OV#-79y_W>Gv2dxL*@G7%LksNSqgId9v;2xJ zrh8uR!F-eU$NMx@S*+sk=C~Dxr9Qn7TfWnTupuHKuQ$;gGiBcU>GF5sWx(~4IP3`f zWE;YFO*?jGwYh%C3X<>RKHC-DZ!*r;cIr}GLOno^3U4tFSSoJp%oHPiSa%nh=Zgn% z14+8v@ygy0>UgEN1bczD6wK45%M>psM)y^)IfG*>3ItX|TzV*0i%@>L(VN!zdKb8S?Qf7BhjNpziA zR}?={-eu>9JDcl*R=OP9B8N$IcCETXah9SUDhr{yrld{G;PnCWRsPD7!eOOFBTWUQ=LrA_~)mFf&!zJX!Oc-_=kT<}m|K52 z)M=G#;p;Rdb@~h5D{q^K;^fX-m5V}L%!wVC2iZ1uu401Ll}#rocTeK|7FAeBRhNdQ zCc2d^aQnQp=MpOmak60N$OgS}a;p(l9CL`o4r(e-nN}mQ?M&isv-P&d$!8|1D1I(3-z!wi zTgoo)*Mv`gC?~bm?S|@}I|m-E2yqPEvYybiD5azInexpK8?9q*$9Yy9-t%5jU8~ym zgZDx>!@ujQ=|HJnwp^wv-FdD{RtzO9SnyfB{mH_(c!jHL*$>0o-(h(eqe*ZwF6Lvu z{7rkk%PEqaA>o+f{H02tzZ@TWy&su?VNw43! z-X+rN`6llvpUms3ZiSt)JMeztB~>9{J8SPmYs&qohxdYFi!ra8KR$35Zp9oR)eFC4 zE;P31#3V)n`w$fZ|4X-|%MX`xZDM~gJyl2W;O$H25*=+1S#%|53>|LyH za@yh+;325%Gq3;J&a)?%7X%t@WXcWL*BaaR*7UEZad4I8iDt7^R_Fd`XeUo256;sAo2F!HcIQKk;h})QxEsPE5BcKc7WyerTchgKmrfRX z!x#H_%cL#B9TWAqkA4I$R^8{%do3Y*&(;WFmJ zU7Dih{t1<{($VtJRl9|&EB?|cJ)xse!;}>6mSO$o5XIx@V|AA8ZcoD88ZM?C*;{|f zZVmf94_l1OmaICt`2sTyG!$^UeTHx9YuUP!omj(r|7zpm5475|yXI=rR>>fteLI+| z)MoiGho0oEt=*J(;?VY0QzwCqw@cVm?d7Y!z0A@u#H?sCJ*ecvyhj& z-F77lO;SH^dmf?L>3i>?Z*U}Em4ZYV_CjgfvzYsRZ+1B!Uo6H6mbS<-FFL`ytqvb& zE7+)2ahv-~dz(Hs+f})z{*4|{)b=2!RZK;PWwOnO=hG7xG`JU5>bAvUbdYd_CjvtHBHgtGdlO+s^9ca^Bv3`t@VRX2_AD$Ckg36OcQRF zXD6QtGfHdw*hx~V(MV-;;ZZF#dJ-piEF+s27z4X1qi5$!o~xBnvf=uopcn7ftfsZc zy@(PuOk`4GL_n(H9(E2)VUjqRCk9kR?w)v@xO6Jm_Mx})&WGEl=GS0#)0FAq^J*o! zAClhvoTsNP*-b~rN{8Yym3g{01}Ep^^Omf=SKqvN?{Q*C4HNNAcrowIa^mf+3PRy! z*_G-|3i8a;+q;iP@~Of_$(vtFkB8yOyWt2*K)vAn9El>=D;A$CEx6b*XF@4y_6M+2 zpeW`RHoI_p(B{%(&jTHI->hmNmZjHUj<@;7w0mx3&koy!2$@cfX{sN19Y}euYJFn& z1?)+?HCkD0MRI$~uB2UWri})0bru_B;klFdwsLc!ne4YUE;t41JqfG# zZJq6%vbsdx!wYeE<~?>o4V`A3?lN%MnKQ`z=uUivQN^vzJ|C;sdQ37Qn?;lpzg})y z)_2~rUdH}zNwX;Tp0tJ78+&I=IwOQ-fl30R79O8@?Ub8IIA(6I`yHn%lARVL`%b8+ z4$8D-|MZZWxc_)vu6@VZN!HsI$*2NOV&uMxBNzIbRgy%ob_ zhwEH{J9r$!dEix9XM7n&c{S(h>nGm?el;gaX0@|QnzFD@bne`el^CO$yXC?BDJ|Qg z+y$GRoR`?ST1z^e*>;!IS@5Ovb7*RlN>BV_UC!7E_F;N#ky%1J{+iixp(dUJj93aK zzHNN>R-oN7>kykHClPnoPTIj7zc6KM(Pnlb(|s??)SMb)4!sMHU^-ntJwY5Big7xv zb1Ew`Xj;|D2kzGja*C$eS44(d&RMU~c_Y14V9_TLTz0J#uHlsx`S6{nhsA0dWZ#cG zJ?`fO50E>*X4TQLv#nl%3GOk*UkAgt=IY+u0LNXqeln3Z zv$~&Li`ZJOKkFuS)dJRA>)b_Da%Q~axwA_8zNK{BH{#}#m}zGcuckz}riDE-z_Ms> zR8-EqAMcfyGJCtvTpaUVQtajhUS%c@Yj}&6Zz;-M7MZzqv3kA7{SuW$oW#=0az2wQ zg-WG@Vb4|D`pl~Il54N7Hmsauc_ne-a!o5#j3WaBBh@Wuefb!QJIOn5;d)%A#s+5% zuD$H=VNux9bE-}1&bcYGZ+>1Fo;3Z@e&zX^n!?JK*adSbONm$XW9z;Q^L>9U!}Toj2WdafJ%oL#h|yWWwyAGxzfrAWdDTtaKl zK4`5tDpPg5>z$MNv=X0LZ0d6l%D{(D8oT@+w0?ce$DZ6pv>{1&Ok67Ix1 zH}3=IEhPJEhItCC8E=`T`N5(k?G=B4+xzZ?<4!~ ze~z6Wk9!CHTI(0rLJ4{JU?E-puc;xusR?>G?;4vt;q~iI9=kDL=z0Rr%O$vU`30X$ zDZRFyZ`(omOy@u|i6h;wtJlP;+}$|Ak|k2dea7n?U1*$T!sXqqOjq^NxLPMmk~&qI zYg0W?yK8T(6+Ea+$YyspKK?kP$+B`~t3^Pib_`!6xCs32!i@pqXfFV6PmBIR<-QW= zN8L{pt0Vap0x`Gzn#E@zh@H)0FfVfA_Iu4fjYZ+umO1LXIbVc$pY+E234u)ttcrl$ z>s92z4vT%n6cMb>=XT6;l0+9e(|CZG)$@C7t7Z7Ez@a)h)!hyuV&B5K%%)P5?Lk|C zZZSVzdXp{@OXSP0hoU-gF8s8Um(#xzjP2Vem zec#-^JqTa&Y#QJ>-FBxd7tf`XB6e^JPUgagB8iBSEps;92KG`!#mvVcPQ5yNC-GEG zTiHEDYfH+0O15}r^+ z#jxj=@x8iNHWALe!P3R67TwmhItn**0JwnzSV2O&KE8KcT+0hWH^OPD1pwiuyx=b@ zNf5Jh0{9X)8;~Es)$t@%(3!OnbY+`@?i{mGX7Yy}8T_*0a6g;kaFPq;*=px5EhO{Cp%1kI<0?*|h8v!6WnO3cCJRF2-CRrU3JiLJnj@6;L)!0kWYAc_}F{2P))3HmCrz zQ&N&gE70;`!6*eJ4^1IR{f6j4(-l&X!tjHxkbHA^Zhrnhr9g{exN|xrS`5Pq=#Xf& zG%P=#ra-TyVFfgW%cZo5OSIwFL9WtXAlFOa+ubmI5t*3=g#Y zF%;70p5;{ZeFL}&}yOY1N1*Q;*<(kTB!7vM$QokF)yr2FlIU@$Ph58$Bz z0J?xQG=MlS4L6jA22eS42g|9*9pX@$#*sUeM(z+t?hr@r5J&D1rx}2pW&m*_`VDCW zUYY@v-;bAO0HqoAgbbiGGC<=ryf96}3pouhy3XJrX+!!u*O_>Si38V{uJmQ&USptX zKp#l(?>%^7;2%h(q@YWS#9;a!JhKlkR#Vd)ERILlgu!Hr@jA@V;sk4BJ-H#p*4EqC zDGjC*tl=@3Oi6)Bn^QwFpul18fpkbpg0+peH$xyPBqb%`$OUhPKyWb32o7clB*9Z< zN=i~NLjavrLtwgJ01bufP+>p-jR2I95|TpmKpQL2!oV>g(4RvS2pK4*ou%m(h6r3A zX#s&`9LU1ZG&;{CkOK!4fLDTnBys`M!vuz>Q&9OZ0hGQl!~!jSDg|~s*w52opC{sB ze|Cf2luD(*G13LcOAGA!s2FjSK8&IE5#W%J25w!vM0^VyQM!t)inj&RTiJ!wXzFgz z3^IqzB7I0L$llljsGq})thBy9UOyjtFO_*hYM_sgcMk>44jeH0V1FDyELc{S1F-;A zS;T^k^~4biG&V*Irq}O;e}j$$+E_#G?HKIn05iP3j|87TkGK~SqG!-KBg5+mN(aLm z8ybhIM`%C19UX$H$KY6JgXbY$0AT%rEpHC;u`rQ$Y=rxUdsc5*Kvc8jaYaO$^)cI6){P6K0r)I6DY4Wr4&B zLQUBraey#0HV|&c4v7PVo3n$zHj99(TZO^3?Ly%C4nYvJTL9eLBLHsM3WKKD>5!B` zQ=BsR3aR6PD(Fa>327E2HAu5TM~Wusc!)>~(gM)+3~m;92Jd;FnSib=M5d6;;5{%R zb4V7DEJ0V!CP-F*oU?gkc>ksUtAYP&V4ND5J>J2^jt*vcFflQWCrB&fLdT%O59PVJ zhid#toR=FNgD!q3&r8#wEBr`!wzvQu5zX?Q>nlSJ4i@WC*CN*-xU66F^V5crWevQ9gsq$I@z1o(a=k7LL~ z7m_~`o;_Ozha1$8Q}{WBehvAlO4EL60y5}8GDrZ< zXh&F}71JbW2A~8KfEWj&UWV#4+Z4p`b{uAj4&WC zha`}X@3~+Iz^WRlOHU&KngK>#j}+_o@LdBC1H-`gT+krWX3-;!)6?{FBp~%20a}FL zFP9%Emqcwa#(`=G>BBZ0qZDQhmZKJg_g8<=bBFKWr!dyg(YkpE+|R*SGpDVU!+VlU zFC54^DLv}`qa%49T>nNiA9Q7Ips#!Xx90tCU2gvK`(F+GPcL=J^>No{)~we#o@&mUb6c$ zCc*<|NJBk-#+{j9xkQ&ujB zI~`#kN~7W!f*-}wkG~Ld!JqZ@tK}eeSnsS5J1fMFXm|`LJx&}5`@dK3W^7#Wnm+_P zBZkp&j1fa2Y=eIjJ0}gh85jt43kaIXXv?xmo@eHrka!Z|vQv12HN#+!I5E z`(fbuW>gFiJL|uXJ!vKt#z3e3HlVdboH7;e#i3(2<)Fg-I@BR!qY#eof3MFZ&*Y@l zI|KJf&ge@p2Dq09Vu$$Qxb7!}{m-iRk@!)%KL)txi3;~Z4Pb}u@GsW;ELiWeG9V51 znX#}B&4Y2E7-H=OpNE@q{%hFLxwIpBF2t{vPREa8_{linXT;#1vMRWjOzLOP$-hf( z>=?$0;~~PnkqY;~K{EM6Vo-T(0K{A0}VUGmu*hR z{tw3hvBN%N3G3Yw`X5Te+F{J`(3w1s3-+1EbnFQKcrgrX1Jqvs@ADGe%M0s$EbK$$ zK)=y=upBc6SjGYAACCcI=Y*6Fi8_jgwZlLxD26fnQfJmb8^gHRN5(TemhX@0e=vr> zg`W}6U>x6VhoA3DqsGGD9uL1DhB3!OXO=k}59TqD@(0Nb{)Ut_luTioK_>7wjc!5C zIr@w}b`Fez3)0wQfKl&bae7;PcTA7%?f2xucM0G)wt_KO!Ewx>F~;=BI0j=Fb4>pp zv}0R^xM4eti~+^+gE$6b81p(kwzuDti(-K9bc|?+pJEl@H+jSYuxZQV8rl8 zjp@M{#%qItIUFN~KcO9Hed*`$5A-2~pAo~K&<-Q+`9`$CK>rzqAI4w~$F%vs9s{~x zg4BP%Gy*@m?;D6=SRX?888Q6peF@_4Z->8wAH~Cn!R$|Hhq2cIzFYqT_+cDourHbY z0qroxJnrZ4Gh+Ay+F`_c%+KRT>y3qw{)89?=hJ@=KO=@ep)aBJ$c!JHfBMJpsP*3G za7|)VJJ8B;4?n{~ldJF7%jmb`-ftIvNd~ekoufG(`K(3=LNc;HBY& z(lp#q8XAD#cIf}k49zX_i`*fO+#!zKA&%T3j@%)R+#yag067CU%yUEe47>wzGU8^` z1EXFT^@I!{J!F8!X?S6ph8J=gUi5tl93*W>7}_uR<2N2~e}FaG?}KPyugQ=-OGEZs z!GBoyYY+H*ANn4?Z)X4l+7H%`17i5~zRlRIX?t)6_eu=g2Q`3WBhxSUeea+M-S?RL zX9oBGKn%a!H+*hx4d2(I!gsi+@SQK%<{X22M~2tMulJoa)0*+z9=-YO+;DFEm5eE1U9b^B(Z}2^9!Qk`!A$wUE z7$Ar5?NRg2&G!AZqnmE64eh^Anss3i!{}%6@Et+4rr!=}!SBF8eZ2*J3ujCWbl;3; z48H~goPSv(8X61fKKdpP!Z7$88NL^Z?j`!^*I?-P4X^pMxyWz~@$(UeAcTSDd(`vO z{~rc;9|GfMJcApU3k}22a!&)k4{CU!e_ny^Y3cO;tOvOMKEyWz!vG(Kp*;hB?d|R3`2X~=5a6#^o5@qn?J-bI8Ppip{-yG z!k|VcGsq!jF~}7DMr49Wap-s&>o=U^T0!Lcy}!(bhtYsPQy z4|EJe{12QL#=c(suQ89Mhw9<`bui%nx7Nep`C&*M3~vMEACmcRYYRGtANq$F%zh&V zc)cEVeHz*Z1N)L7k-(k3np#{GcDh2Q@ya0YHl*n7fl*ZPAsbU-a94MYYtA#&!c`xGIaV;yzsmrjfieTEtqB_WgZp2*NplHx=$O{M~2#i_vJ{ps-NgK zQsxKK_CBM2PP_je+Xft`(vYfXXgIUr{=PA=7a8`2EHk)Ym2QKIforz# tySWtj{oF3N9@_;i*Fv5S)9x^z=nlWP>jpp-9)52ZmLVA=i*%6g{{fxOO~wEK diff --git a/apps/flutter/windows/runner/runner.exe.manifest b/apps/flutter/windows/runner/runner.exe.manifest deleted file mode 100644 index 153653e..0000000 --- a/apps/flutter/windows/runner/runner.exe.manifest +++ /dev/null @@ -1,14 +0,0 @@ - - - - - PerMonitorV2 - - - - - - - - - diff --git a/apps/flutter/windows/runner/utils.cpp b/apps/flutter/windows/runner/utils.cpp deleted file mode 100644 index 3a0b465..0000000 --- a/apps/flutter/windows/runner/utils.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "utils.h" - -#include -#include -#include -#include - -#include - -void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); - } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } -} - -std::vector GetCommandLineArguments() { - // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. - int argc; - wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - if (argv == nullptr) { - return std::vector(); - } - - std::vector command_line_arguments; - - // Skip the first argument as it's the binary name. - for (int i = 1; i < argc; i++) { - command_line_arguments.push_back(Utf8FromUtf16(argv[i])); - } - - ::LocalFree(argv); - - return command_line_arguments; -} - -std::string Utf8FromUtf16(const wchar_t* utf16_string) { - if (utf16_string == nullptr) { - return std::string(); - } - unsigned int target_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr) - -1; // remove the trailing null character - int input_length = (int)wcslen(utf16_string); - std::string utf8_string; - if (target_length == 0 || target_length > utf8_string.max_size()) { - return utf8_string; - } - utf8_string.resize(target_length); - int converted_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - input_length, utf8_string.data(), target_length, nullptr, nullptr); - if (converted_length == 0) { - return std::string(); - } - return utf8_string; -} diff --git a/apps/flutter/windows/runner/utils.h b/apps/flutter/windows/runner/utils.h deleted file mode 100644 index 3879d54..0000000 --- a/apps/flutter/windows/runner/utils.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef RUNNER_UTILS_H_ -#define RUNNER_UTILS_H_ - -#include -#include - -// Creates a console for the process, and redirects stdout and stderr to -// it for both the runner and the Flutter library. -void CreateAndAttachConsole(); - -// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string -// encoded in UTF-8. Returns an empty std::string on failure. -std::string Utf8FromUtf16(const wchar_t* utf16_string); - -// Gets the command line arguments passed in as a std::vector, -// encoded in UTF-8. Returns an empty std::vector on failure. -std::vector GetCommandLineArguments(); - -#endif // RUNNER_UTILS_H_ diff --git a/apps/flutter/windows/runner/win32_window.cpp b/apps/flutter/windows/runner/win32_window.cpp deleted file mode 100644 index 60608d0..0000000 --- a/apps/flutter/windows/runner/win32_window.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include "win32_window.h" - -#include -#include - -#include "resource.h" - -namespace { - -/// Window attribute that enables dark mode window decorations. -/// -/// Redefined in case the developer's machine has a Windows SDK older than -/// version 10.0.22000.0. -/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute -#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE -#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 -#endif - -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; - -/// Registry key for app theme preference. -/// -/// A value of 0 indicates apps should use dark mode. A non-zero or missing -/// value indicates apps should use light mode. -constexpr const wchar_t kGetPreferredBrightnessRegKey[] = - L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; -constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; - -// The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; - -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); - -// Scale helper to convert logical scaler values to physical using passed in -// scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} - -// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. -// This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { - return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - } - FreeLibrary(user32_module); -} - -} // namespace - -// Manages the Win32Window's window class registration. -class WindowClassRegistrar { - public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registrar instance. - static WindowClassRegistrar* GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); - } - return instance_; - } - - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t* GetWindowClass(); - - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); - - private: - WindowClassRegistrar() = default; - - static WindowClassRegistrar* instance_; - - bool class_registered_ = false; -}; - -WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; - -const wchar_t* WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; -} - -void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; -} - -Win32Window::Win32Window() { - ++g_active_window_count; -} - -Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); -} - -bool Win32Window::Create(const std::wstring& title, - const Point& origin, - const Size& size) { - Destroy(); - - const wchar_t* window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); - - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; - - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); - - if (!window) { - return false; - } - - UpdateTheme(window); - - return OnCreate(); -} - -bool Win32Window::Show() { - return ShowWindow(window_handle_, SW_SHOWNORMAL); -} - -// static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window* that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } - - return DefWindowProc(window, message, wparam, lparam); -} - -LRESULT -Win32Window::MessageHandler(HWND hwnd, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: { - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; - } - - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - - case WM_DWMCOLORIZATIONCOLORCHANGED: - UpdateTheme(hwnd); - return 0; - } - - return DefWindowProc(window_handle_, message, wparam, lparam); -} - -void Win32Window::Destroy() { - OnDestroy(); - - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } -} - -Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); -} - -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame = GetClientArea(); - - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); - - SetFocus(child_content_); -} - -RECT Win32Window::GetClientArea() { - RECT frame; - GetClientRect(window_handle_, &frame); - return frame; -} - -HWND Win32Window::GetHandle() { - return window_handle_; -} - -void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; -} - -bool Win32Window::OnCreate() { - // No-op; provided for subclasses. - return true; -} - -void Win32Window::OnDestroy() { - // No-op; provided for subclasses. -} - -void Win32Window::UpdateTheme(HWND const window) { - DWORD light_mode; - DWORD light_mode_size = sizeof(light_mode); - LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, - RRF_RT_REG_DWORD, nullptr, &light_mode, - &light_mode_size); - - if (result == ERROR_SUCCESS) { - BOOL enable_dark_mode = light_mode == 0; - DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, - &enable_dark_mode, sizeof(enable_dark_mode)); - } -} diff --git a/apps/flutter/windows/runner/win32_window.h b/apps/flutter/windows/runner/win32_window.h deleted file mode 100644 index e901dde..0000000 --- a/apps/flutter/windows/runner/win32_window.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef RUNNER_WIN32_WINDOW_H_ -#define RUNNER_WIN32_WINDOW_H_ - -#include - -#include -#include -#include - -// A class abstraction for a high DPI-aware Win32 Window. Intended to be -// inherited from by classes that wish to specialize with custom -// rendering and input handling -class Win32Window { - public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates a win32 window with |title| that is positioned and sized using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size this function will scale the inputted width and height as - // as appropriate for the default monitor. The window is invisible until - // |Show| is called. Returns true if the window was created successfully. - bool Create(const std::wstring& title, const Point& origin, const Size& size); - - // Show the current window. Returns true if the window was successfully shown. - bool Show(); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - // Return a RECT representing the bounds of the current client area. - RECT GetClientArea(); - - protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Called when CreateAndShow is called, allowing subclass window-related - // setup. Subclasses should return false if setup fails. - virtual bool OnCreate(); - - // Called when Destroy is called. - virtual void OnDestroy(); - - private: - friend class WindowClassRegistrar; - - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Retrieves a class instance pointer for |window| - static Win32Window* GetThisFromHandle(HWND const window) noexcept; - - // Update the window frame's theme to match the system theme. - static void UpdateTheme(HWND const window); - - bool quit_on_close_ = false; - - // window handle for top level window. - HWND window_handle_ = nullptr; - - // window handle for hosted content. - HWND child_content_ = nullptr; -}; - -#endif // RUNNER_WIN32_WINDOW_H_