From ebc4cdf7547066b0ba0dd1de0fe278b58a4b797f Mon Sep 17 00:00:00 2001 From: Patryk Hegenberg Date: Wed, 16 Apr 2025 16:08:45 +0200 Subject: [PATCH] feat: add update and delete functionality to tags and improve report screen --- lib/main.dart | 10 +- lib/screens/main_screen.dart | 13 ++- lib/screens/report_screen.dart | 10 +- lib/screens/tags_screen.dart | 159 +++++++++++++++++++++++++++++++- lib/src/rust/api.dart | 6 ++ lib/src/rust/frb_generated.dart | 85 +++++++++++++++-- lib/time_tracking_service.dart | 72 ++++++++++++++- pubspec.lock | 8 ++ pubspec.yaml | 1 + rust/src/api.rs | 14 +++ rust/src/api/database.rs | 38 ++++++++ rust/src/frb_generated.rs | 91 ++++++++++++++++-- 12 files changed, 464 insertions(+), 43 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8c718de..f5c288c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -68,15 +68,7 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Rust Time Tracker', - theme: ThemeData( - primarySwatch: Colors.blue, - useMaterial3: true, - // Optional: Theme für BottomNavigationBar anpassen - // bottomNavigationBarTheme: const BottomNavigationBarThemeData( - // selectedItemColor: Colors.deepPurple, - // unselectedItemColor: Colors.grey, - // ), - ), + theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true), home: const InitializerWidget(), ); } diff --git a/lib/screens/main_screen.dart b/lib/screens/main_screen.dart index 652b864..7e42364 100644 --- a/lib/screens/main_screen.dart +++ b/lib/screens/main_screen.dart @@ -3,6 +3,7 @@ import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; import 'package:timetracker/screens/home_screen.dart'; import 'package:timetracker/screens/tags_screen.dart'; import 'package:timetracker/screens/report_screen.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; class MainScreen extends StatefulWidget { const MainScreen({super.key}); @@ -37,8 +38,8 @@ class _MainScreenState extends State { items: [ BottomNavigationBarItem( - icon: Icon(context.platformIcons.clockSolid), - activeIcon: Icon(context.platformIcons.clockSolid), + icon: FaIcon(FontAwesomeIcons.clock), + activeIcon: FaIcon(FontAwesomeIcons.solidClock), label: 'Tracking', ), BottomNavigationBarItem( @@ -47,8 +48,12 @@ class _MainScreenState extends State { label: 'Tags', ), BottomNavigationBarItem( - icon: Icon(context.platformIcons.bookmarkOutline), - activeIcon: Icon(context.platformIcons.bookmarkSolid), + icon: FaIcon( + FontAwesomeIcons.chartBar, + ), //Icon(context.platformIcons.bookmarkOutline), + activeIcon: FaIcon( + FontAwesomeIcons.solidChartBar, + ), //Icon(context.platformIcons.bookmarkSolid), label: 'Reports', ), ], diff --git a/lib/screens/report_screen.dart b/lib/screens/report_screen.dart index c546259..1c56861 100644 --- a/lib/screens/report_screen.dart +++ b/lib/screens/report_screen.dart @@ -487,8 +487,8 @@ class _ReportScreenState extends State { ), ), ), - SizedBox(height: 250, child: _buildPieChart(_reportData!)), - const Divider(), + // SizedBox(height: 250, child: _buildPieChart(_reportData!)), + // const Divider(), SizedBox( height: 250, child: _buildBarChart(_reportData!, startDate, endDate), @@ -507,7 +507,7 @@ class _ReportScreenState extends State { ), ), ), - SizedBox(height: 300, child: _buildReportList(_reportData!.entries)), + SizedBox(height: 600, child: _buildReportList(_reportData!.entries)), ], ); } @@ -649,8 +649,8 @@ class _ReportScreenState extends State { Widget _buildReportList(List entries) { return ListView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), + // shrinkWrap: true, + // physics: const NeverScrollableScrollPhysics(), itemCount: entries.length, itemBuilder: (context, index) { final entry = entries[index]; diff --git a/lib/screens/tags_screen.dart b/lib/screens/tags_screen.dart index ef079c5..a5a54c3 100644 --- a/lib/screens/tags_screen.dart +++ b/lib/screens/tags_screen.dart @@ -1,8 +1,10 @@ import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; import 'package:flutter/cupertino.dart' show CupertinoIcons; import 'package:flutter/material.dart'; +import 'package:timetracker/src/rust/api.dart'; import 'package:timetracker/time_tracking_service.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; class TagsScreen extends StatefulWidget { const TagsScreen({super.key}); @@ -40,6 +42,129 @@ class _TagsScreenState extends State { } } + void _showEditTagDialog(BuildContext context, Tag tag) { + final TextEditingController editController = TextEditingController( + text: tag.name, + ); + + showPlatformDialog( + context: context, + builder: + (dialogContext) => PlatformAlertDialog( + title: PlatformText('Tag bearbeiten'), + content: PlatformTextField( + controller: editController, + autofocus: true, + hintText: 'Neuer Tag-Name', + material: + (_, __) => MaterialTextFieldData( + decoration: const InputDecoration( + labelText: 'Neuer Tag-Name', + ), + ), + cupertino: + (_, __) => + CupertinoTextFieldData(placeholder: 'Neuer Tag-Name'), + ), + actions: [ + PlatformDialogAction( + child: PlatformText('Abbrechen'), + onPressed: () => Navigator.pop(dialogContext), + ), + PlatformDialogAction( + child: PlatformText('Speichern'), + onPressed: () async { + final newName = editController.text.trim(); + if (newName.isEmpty) { + _showPlatformFeedbackDialog( + context, + 'Fehler', + 'Tag-Name darf nicht leer sein.', + ); + return; + } + if (newName == tag.name) { + Navigator.pop(dialogContext); + return; + } + + final success = await context + .read() + .flUpdateTag(tag.id.toInt(), newName); + + if (!mounted) return; + + Navigator.pop(dialogContext); + + WidgetsBinding.instance.addPostFrameCallback((_) { + if (!mounted) return; + if (success) { + _showPlatformFeedbackDialog( + context, + 'Erfolg', + 'Tag aktualisiert.', + ); + } else { + _showPlatformFeedbackDialog( + context, + 'Fehler', + 'Tag konnte nicht aktualisiert werden (Name evtl. vergeben?).', + ); + } + }); + }, + ), + ], + ), + ); + } + + void _confirmAndDeleteTag(BuildContext context, Tag tag) { + showPlatformDialog( + context: context, + builder: + (dialogContext) => PlatformAlertDialog( + title: PlatformText('Tag löschen?'), + content: PlatformText( + 'Möchtest du den Tag "${tag.name}" wirklich löschen? Zugeordnete Zeiteinträge verlieren ihre Tag-Zuweisung.', + ), + actions: [ + PlatformDialogAction( + child: PlatformText('Abbrechen'), + onPressed: () => Navigator.pop(dialogContext), + ), + PlatformDialogAction( + child: PlatformText('Löschen'), + cupertino: + (_, __) => + CupertinoDialogActionData(isDestructiveAction: true), + onPressed: () async { + Navigator.pop(dialogContext); + + final success = await context + .read() + .flDeleteTag(tag.id.toInt()); + + if (!mounted) return; + + WidgetsBinding.instance.addPostFrameCallback((_) { + if (!mounted) return; + if (success) { + } else { + _showPlatformFeedbackDialog( + context, + 'Fehler', + 'Tag konnte nicht gelöscht werden.', + ); + } + }); + }, + ), + ], + ), + ); + } + @override Widget build(BuildContext context) { final tags = context.watch().tags; @@ -51,6 +176,7 @@ class _TagsScreenState extends State { Padding( padding: const EdgeInsets.all(16.0), child: Row( + crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: PlatformTextField( @@ -85,9 +211,36 @@ class _TagsScreenState extends State { itemCount: tags.length, itemBuilder: (context, index) { final tag = tags[index]; - return ListTile( - title: PlatformText(tag.name), - trailing: PlatformText('ID: ${tag.id}'), + return Slidable( + key: ValueKey(tag.id.toInt()), + endActionPane: ActionPane( + motion: const StretchMotion(), + children: [ + SlidableAction( + onPressed: (context) { + _showEditTagDialog(this.context, tag); + }, + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + icon: PlatformIcons(context).edit, + label: 'Bearbeiten', + ), + SlidableAction( + onPressed: (context) { + _confirmAndDeleteTag(this.context, tag); + }, + backgroundColor: Colors.red, + foregroundColor: Colors.white, + icon: PlatformIcons(context).delete, + label: 'Löschen', + ), + ], + ), + + child: ListTile( + title: PlatformText(tag.name), + trailing: PlatformText('ID: ${tag.id.toInt()}'), + ), ); }, ), diff --git a/lib/src/rust/api.dart b/lib/src/rust/api.dart index cf8ee78..e8ad8f1 100644 --- a/lib/src/rust/api.dart +++ b/lib/src/rust/api.dart @@ -14,6 +14,12 @@ Future initApp({required String dbDirectoryPath}) => Future createTag({required String name}) => RustLib.instance.api.crateApiCreateTag(name: name); +Future updateTag({required PlatformInt64 id, required String newName}) => + RustLib.instance.api.crateApiUpdateTag(id: id, newName: newName); + +Future deleteTag({required PlatformInt64 id}) => + RustLib.instance.api.crateApiDeleteTag(id: id); + Future> getTags() => RustLib.instance.api.crateApiGetTags(); Future startTracking({ diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 9b8b5f8..0bfb96e 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -62,7 +62,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.9.0'; @override - int get rustContentHash => -79634774; + int get rustContentHash => 350676645; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -75,6 +75,8 @@ class RustLib extends BaseEntrypoint { abstract class RustLibApi extends BaseApi { Future crateApiCreateTag({required String name}); + Future crateApiDeleteTag({required PlatformInt64 id}); + Future crateApiDeleteTimeEntry({required PlatformInt64 id}); Future crateApiGenerateReport({ @@ -99,6 +101,11 @@ abstract class RustLibApi extends BaseApi { required PlatformInt64 endTimeUnixTs, }); + Future crateApiUpdateTag({ + required PlatformInt64 id, + required String newName, + }); + Future crateApiUpdateTimeEntry({ required PlatformInt64 entryId, PlatformInt64? newTagId, @@ -144,7 +151,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { const TaskConstMeta(debugName: "create_tag", argNames: ["name"]); @override - Future crateApiDeleteTimeEntry({required PlatformInt64 id}) { + Future crateApiDeleteTag({required PlatformInt64 id}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -161,6 +168,34 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { decodeSuccessData: sse_decode_unit, decodeErrorData: sse_decode_AnyhowException, ), + constMeta: kCrateApiDeleteTagConstMeta, + argValues: [id], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiDeleteTagConstMeta => + const TaskConstMeta(debugName: "delete_tag", argNames: ["id"]); + + @override + Future crateApiDeleteTimeEntry({required PlatformInt64 id}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_i_64(id, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 3, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), constMeta: kCrateApiDeleteTimeEntryConstMeta, argValues: [id], apiImpl: this, @@ -187,7 +222,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 3, + funcId: 4, port: port_, ); }, @@ -216,7 +251,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 4, + funcId: 5, port: port_, ); }, @@ -246,7 +281,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 5, + funcId: 6, port: port_, ); }, @@ -274,7 +309,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 6, + funcId: 7, port: port_, ); }, @@ -306,7 +341,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 7, + funcId: 8, port: port_, ); }, @@ -340,7 +375,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 8, + funcId: 9, port: port_, ); }, @@ -360,6 +395,38 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["entryId", "endTimeUnixTs"], ); + @override + Future crateApiUpdateTag({ + required PlatformInt64 id, + required String newName, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_i_64(id, serializer); + sse_encode_String(newName, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 10, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiUpdateTagConstMeta, + argValues: [id, newName], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiUpdateTagConstMeta => + const TaskConstMeta(debugName: "update_tag", argNames: ["id", "newName"]); + @override Future crateApiUpdateTimeEntry({ required PlatformInt64 entryId, @@ -378,7 +445,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 9, + funcId: 11, port: port_, ); }, diff --git a/lib/time_tracking_service.dart b/lib/time_tracking_service.dart index 7b90af7..357e464 100644 --- a/lib/time_tracking_service.dart +++ b/lib/time_tracking_service.dart @@ -105,16 +105,13 @@ class TimeTrackingService extends ChangeNotifier { Future flCreateTag(String name) async { if (name.trim().isEmpty) { - log("Cannot create tag: Name is empty."); return false; } final trimmedName = name.trim(); - try { final tagId = await createTag(name: trimmedName); log("Tag created with ID: $tagId"); - _tags = await getTags(); - notifyListeners(); + await _loadUpdatedTags(); return true; } on FrbException catch (e) { log("Error creating tag: $e"); @@ -124,6 +121,27 @@ class TimeTrackingService extends ChangeNotifier { return false; } } + // Future flCreateTag(String name) async { + // if (name.trim().isEmpty) { + // log("Cannot create tag: Name is empty."); + // return false; + // } + // final trimmedName = name.trim(); + + // try { + // final tagId = await createTag(name: trimmedName); + // log("Tag created with ID: $tagId"); + // _tags = await getTags(); + // notifyListeners(); + // return true; + // } on FrbException catch (e) { + // log("Error creating tag: $e"); + // return false; + // } catch (e) { + // log("Unexpected error creating tag: $e"); + // return false; + // } + // } Future flGetReport( int? tagId, @@ -184,4 +202,50 @@ class TimeTrackingService extends ChangeNotifier { return false; } } + + Future flUpdateTag(int tagId, String newName) async { + if (newName.trim().isEmpty) { + log('Service: Cannot update tag $tagId: New name is empty.'); + return false; + } + final trimmedName = newName.trim(); + log('Service: Attempting to update tag $tagId to "$trimmedName"'); + try { + await updateTag(id: tagId.toInt(), newName: trimmedName); + log('Service: Successfully updated tag $tagId'); + await _loadUpdatedTags(); + return true; // Erfolg + } on FrbException catch (e, s) { + log('Service: Error updating tag $tagId: $e\n$s'); + return false; + } catch (e, s) { + log('Service: Unexpected error updating tag $tagId: $e\n$s'); + return false; + } + } + + Future flDeleteTag(int tagId) async { + log('Service: Attempting to delete tag $tagId'); + try { + await deleteTag(id: tagId.toInt()); + log('Service: Successfully deleted tag $tagId'); + await _loadUpdatedTags(); + return true; + } on FrbException catch (e, s) { + log('Service: Error deleting tag $tagId: $e\n$s'); + return false; + } catch (e, s) { + log('Service: Unexpected error deleting tag $tagId: $e\n$s'); + return false; + } + } + + Future _loadUpdatedTags() async { + try { + _tags = await getTags(); + notifyListeners(); + } catch (e) { + log("Error refreshing tags after CUD operation: $e"); + } + } } diff --git a/pubspec.lock b/pubspec.lock index 0168886..eb05bdd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -152,6 +152,14 @@ packages: description: flutter source: sdk version: "0.0.0" + font_awesome_flutter: + dependency: "direct main" + description: + name: font_awesome_flutter + sha256: d3a89184101baec7f4600d58840a764d2ef760fe1c5a20ef9e6b0e9b24a07a3a + url: "https://pub.dev" + source: hosted + version: "10.8.0" fuchsia_remote_debug_protocol: dependency: transitive description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 69c0961..b4bb4df 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -22,6 +22,7 @@ dependencies: fl_chart: ^0.70.2 flutter_platform_widgets: ^8.0.0 flutter_slidable: ^4.0.0 + font_awesome_flutter: ^10.8.0 dev_dependencies: flutter_test: diff --git a/rust/src/api.rs b/rust/src/api.rs index 1e61013..e725692 100644 --- a/rust/src/api.rs +++ b/rust/src/api.rs @@ -45,6 +45,20 @@ pub fn create_tag(name: String) -> Result { database::create_tag_internal(name.trim()) } +pub fn update_tag(id: i64, new_name: String) -> Result<()> { + log::debug!( + "API: update_tag called for id {} with name '{}'", + id, + new_name + ); + database::update_tag_internal(id, &new_name) +} + +pub fn delete_tag(id: i64) -> Result<()> { + log::debug!("API: delete_tag called for id {}", id); + database::delete_tag_internal(id) +} + pub fn get_tags() -> Result> { log::debug!("API: get_tags called"); database::get_tags_internal() diff --git a/rust/src/api/database.rs b/rust/src/api/database.rs index 7ee1d03..a2aa6b6 100644 --- a/rust/src/api/database.rs +++ b/rust/src/api/database.rs @@ -106,6 +106,44 @@ pub(super) fn get_tags_internal() -> Result> { }) } +pub(super) fn update_tag_internal(id: i64, new_name: &str) -> Result<()> { + log::debug!( + "RUST_DB: Attempting to update tag_id {} to name '{}'", + id, + new_name + ); + ensure!(!new_name.trim().is_empty(), "New tag name cannot be empty"); + + let name = new_name.trim(); + + with_db_connection(|conn| { + let rows_affected = conn + .execute("UPDATE tags SET name = ?1 WHERE id = ?2", params![name, id]) + .context("Failed to execute update tag SQL")?; + + ensure!(rows_affected > 0, "Tag {} not found for update", id); + + log::info!("RUST_DB: Successfully updated tag {}", id); + Ok(()) + }) + .with_context(|| format!("Failed operation for updating tag_id {}", id)) +} + +pub(super) fn delete_tag_internal(id: i64) -> Result<()> { + log::debug!("RUST_DB: Attempting to delete tag_id {}", id); + with_db_connection(|conn| { + let rows_affected = conn + .execute("DELETE FROM tags WHERE id = ?1", params![id]) + .context("Failed to execute delete tag SQL")?; + + ensure!(rows_affected > 0, "Tag {} not found for deletion", id); + + log::info!("RUST_DB: Successfully deleted tag {}", id); + Ok(()) + }) + .with_context(|| format!("Failed operation for deleting tag_id {}", id)) +} + pub(super) fn start_tracking_internal(tag_id: Option, start_time_unix_ts: i64) -> Result { with_db_connection(|conn| { conn.execute( diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index ba418ca..1f6a338 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -37,7 +37,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.9.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -79634774; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 350676645; // Section: executor @@ -80,6 +80,41 @@ fn wire__crate__api__create_tag_impl( }, ) } +fn wire__crate__api__delete_tag_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_tag", + 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_id = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let output_ok = crate::api::delete_tag(api_id)?; + Ok(output_ok) + })(), + ) + } + }, + ) +} fn wire__crate__api__delete_time_entry_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -333,6 +368,42 @@ fn wire__crate__api__stop_tracking_impl( }, ) } +fn wire__crate__api__update_tag_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_tag", + 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_id = ::sse_decode(&mut deserializer); + let api_new_name = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let output_ok = crate::api::update_tag(api_id, api_new_name)?; + Ok(output_ok) + })(), + ) + } + }, + ) +} fn wire__crate__api__update_time_entry_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -551,14 +622,16 @@ fn pde_ffi_dispatcher_primary_impl( // Codec=Pde (Serialization + dispatch), see doc to use other codecs match func_id { 1 => wire__crate__api__create_tag_impl(port, ptr, rust_vec_len, data_len), - 2 => wire__crate__api__delete_time_entry_impl(port, ptr, rust_vec_len, data_len), - 3 => wire__crate__api__generate_report_impl(port, ptr, rust_vec_len, data_len), - 4 => wire__crate__api__get_last_unfinished_tracking_impl(port, ptr, rust_vec_len, data_len), - 5 => wire__crate__api__get_tags_impl(port, ptr, rust_vec_len, data_len), - 6 => wire__crate__api__init_app_impl(port, ptr, rust_vec_len, data_len), - 7 => wire__crate__api__start_tracking_impl(port, ptr, rust_vec_len, data_len), - 8 => wire__crate__api__stop_tracking_impl(port, ptr, rust_vec_len, data_len), - 9 => wire__crate__api__update_time_entry_impl(port, ptr, rust_vec_len, data_len), + 2 => wire__crate__api__delete_tag_impl(port, ptr, rust_vec_len, data_len), + 3 => wire__crate__api__delete_time_entry_impl(port, ptr, rust_vec_len, data_len), + 4 => wire__crate__api__generate_report_impl(port, ptr, rust_vec_len, data_len), + 5 => wire__crate__api__get_last_unfinished_tracking_impl(port, ptr, rust_vec_len, data_len), + 6 => wire__crate__api__get_tags_impl(port, ptr, rust_vec_len, data_len), + 7 => wire__crate__api__init_app_impl(port, ptr, rust_vec_len, data_len), + 8 => wire__crate__api__start_tracking_impl(port, ptr, rust_vec_len, data_len), + 9 => wire__crate__api__stop_tracking_impl(port, ptr, rust_vec_len, data_len), + 10 => wire__crate__api__update_tag_impl(port, ptr, rust_vec_len, data_len), + 11 => wire__crate__api__update_time_entry_impl(port, ptr, rust_vec_len, data_len), _ => unreachable!(), } }