From 5b40a0d3b60fac8885e4ce56d584d653f62973a9 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 12 Sep 2026 08:41:11 +1000 Subject: [PATCH] Implement multi-note support (#883) * Implement multi-note support Ref: https://github.com/inventree/InvenTree/pull/11971 * Bump iOS target --- assets/release_notes.md | 6 + ios/Podfile | 2 +- lib/api.dart | 5 + lib/inventree/notes.dart | 39 +++ lib/l10n/app_en.arb | 3 + lib/widget/build/build_detail.dart | 14 +- lib/widget/company/company_detail.dart | 14 +- lib/widget/notes_list_widget.dart | 176 ++++++++++++ lib/widget/notes_widget.dart | 17 +- lib/widget/order/purchase_order_detail.dart | 14 +- lib/widget/order/sales_order_detail.dart | 14 +- lib/widget/order/so_shipment_detail.dart | 18 +- lib/widget/order/transfer_order_detail.dart | 14 +- lib/widget/part/part_detail.dart | 16 +- lib/widget/stock/stock_detail.dart | 14 +- pubspec.lock | 280 +++++++++++++++++++- pubspec.yaml | 1 + 17 files changed, 529 insertions(+), 118 deletions(-) create mode 100644 lib/inventree/notes.dart create mode 100644 lib/widget/notes_list_widget.dart diff --git a/assets/release_notes.md b/assets/release_notes.md index 5935701f..4f6aa7ee 100644 --- a/assets/release_notes.md +++ b/assets/release_notes.md @@ -1,3 +1,9 @@ +## xx.yy.z - Month Year +--- + +- Supports new multi-note API for model instances +- Implement rendering for HTML note content + ## 0.25.2 - September 2026 --- diff --git a/ios/Podfile b/ios/Podfile index a2be4c02..ff765be6 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -39,7 +39,7 @@ post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0' end end end diff --git a/lib/api.dart b/lib/api.dart index 015e183a..96f79be3 100644 --- a/lib/api.dart +++ b/lib/api.dart @@ -344,6 +344,11 @@ class InvenTreeAPI { // Ref: https://github.com/inventree/InvenTree/pull/12011 bool get supportsStockItemCreationDate => apiVersion >= 496; + // Does the server support the "multi notes" API? + // (Multiple HTML notes may be attached to a single model instance) + // Ref: https://github.com/inventree/InvenTree/pull/11971 + bool get supportsMultiNotes => apiVersion >= 537; + // Cached list of plugins (refreshed when we connect to the server) List _plugins = []; diff --git a/lib/inventree/notes.dart b/lib/inventree/notes.dart new file mode 100644 index 00000000..8261f5b8 --- /dev/null +++ b/lib/inventree/notes.dart @@ -0,0 +1,39 @@ +import "package:inventree/inventree/model.dart"; + +/* + * Class representing a single "note" entry. + * + * Notes can be attached to any model instance which supports the + * InvenTree "multi notes" API - multiple notes may be attached to + * a single model instance. + * + * Note content is provided by the server as editor-agnostic HTML, + * and cannot be edited from within this app. + * + * Ref: https://github.com/inventree/InvenTree/pull/11971 + */ +class InvenTreeNoteEntry extends InvenTreeModel { + InvenTreeNoteEntry() : super(); + + InvenTreeNoteEntry.fromJson(Map json) : super.fromJson(json); + + @override + InvenTreeNoteEntry createFromJson(Map json) => + InvenTreeNoteEntry.fromJson(json); + + @override + String get URL => "note/"; + + // The model type of the instance this note is associated with + String get modelType => getString("model_type"); + + // The ID of the instance this note is associated with + int get modelId => getInt("model_id"); + + String get title => getString("title"); + + // Rendered (HTML) content of this note + String get content => getString("content"); + + DateTime? get updated => getDate("updated"); +} diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 3066ffa5..e548e6c4 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -953,6 +953,9 @@ "description": "Notes" }, + "noNotesFound": "No notes found", + "@noNotesFound": {}, + "notifications": "Notifications", "@notifications": {}, diff --git a/lib/widget/build/build_detail.dart b/lib/widget/build/build_detail.dart index 382afbe4..268ebf6e 100644 --- a/lib/widget/build/build_detail.dart +++ b/lib/widget/build/build_detail.dart @@ -13,7 +13,7 @@ import "package:inventree/widget/attachment_widget.dart"; import "package:inventree/widget/dialogs.dart"; import "package:inventree/widget/link_icon.dart"; -import "package:inventree/widget/notes_widget.dart"; +import "package:inventree/widget/notes_list_widget.dart"; import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/build/build_line_list.dart"; import "package:inventree/widget/build/build_item_list.dart"; @@ -553,17 +553,7 @@ class _BuildOrderDetailState extends RefreshableState { // Notes tile tiles.add( - ListTile( - title: Text(L10().notes), - leading: Icon(TablerIcons.notes, color: COLOR_ACTION), - trailing: LinkIcon(), - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => NotesWidget(widget.order)), - ); - }, - ), + ShowNotesItem(context, widget.order, InvenTreeBuildOrder.MODEL_TYPE), ); // Attachments tile diff --git a/lib/widget/company/company_detail.dart b/lib/widget/company/company_detail.dart index 9accf9a0..212f4a59 100644 --- a/lib/widget/company/company_detail.dart +++ b/lib/widget/company/company_detail.dart @@ -13,6 +13,7 @@ import "package:inventree/inventree/purchase_order.dart"; import "package:inventree/inventree/sales_order.dart"; import "package:inventree/widget/attachment_widget.dart"; import "package:inventree/widget/link_icon.dart"; +import "package:inventree/widget/notes_list_widget.dart"; import "package:inventree/widget/order/purchase_order_list.dart"; import "package:inventree/widget/order/sales_order_list.dart"; import "package:inventree/widget/parameter_widget.dart"; @@ -400,16 +401,9 @@ class _CompanyDetailState extends RefreshableState { ); } - if (widget.company.notes.isNotEmpty) { - tiles.add( - ListTile( - title: Text(L10().notes), - subtitle: Text(widget.company.notes), - leading: Icon(TablerIcons.note), - onTap: null, - ), - ); - } + tiles.add( + ShowNotesItem(context, widget.company, InvenTreeCompany.MODEL_TYPE), + ); ListTile? parameterTile = ShowParametersItem( context, diff --git a/lib/widget/notes_list_widget.dart b/lib/widget/notes_list_widget.dart new file mode 100644 index 00000000..a630647d --- /dev/null +++ b/lib/widget/notes_list_widget.dart @@ -0,0 +1,176 @@ +import "package:cached_network_image/cached_network_image.dart"; +import "package:flutter/material.dart"; +import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; +import "package:flutter_widget_from_html/flutter_widget_from_html.dart"; + +import "package:inventree/api.dart"; +import "package:inventree/app_colors.dart"; +import "package:inventree/inventree/model.dart"; +import "package:inventree/inventree/notes.dart"; +import "package:inventree/l10.dart"; +import "package:inventree/widget/link_icon.dart"; +import "package:inventree/widget/notes_widget.dart"; +import "package:inventree/widget/refreshable_state.dart"; + +/* + * A widget for displaying the list of "notes" attached to a given model instance, + * for servers which support the "multi notes" API. + * + * Note content is rendered as HTML, and cannot be edited from within the app. + * + * Ref: https://github.com/inventree/InvenTree/pull/11971 + */ +class NotesListWidget extends StatefulWidget { + const NotesListWidget(this.modelType, this.modelId, {Key? key}) + : super(key: key); + + final String modelType; + final int modelId; + + @override + _NotesListWidgetState createState() => _NotesListWidgetState(); +} + +class _NotesListWidgetState extends RefreshableState { + _NotesListWidgetState(); + + List notes = []; + + @override + String getAppBarTitle() => L10().notes; + + @override + Future request(BuildContext context) async { + Map filters = { + "model_type": widget.modelType, + "model_id": widget.modelId.toString(), + }; + + List results = []; + + await InvenTreeNoteEntry().list(filters: filters).then((var entries) { + for (var entry in entries) { + if (entry is InvenTreeNoteEntry) { + results.add(entry); + } + } + }); + + if (mounted) { + setState(() { + notes = results; + }); + } + } + + @override + List getTiles(BuildContext context) { + List tiles = []; + + for (var note in notes) { + tiles.add( + ListTile( + title: Text(note.title.isNotEmpty ? note.title : L10().notes), + subtitle: note.description.isNotEmpty ? Text(note.description) : null, + leading: Icon(TablerIcons.note, color: COLOR_ACTION), + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => NoteViewWidget(note)), + ); + }, + ), + ); + } + + if (tiles.isEmpty && !loading) { + tiles.add( + ListTile( + leading: Icon(TablerIcons.note_off, color: COLOR_WARNING), + title: Text(L10().noNotesFound), + ), + ); + } + + return tiles; + } +} + +/* + * Custom WidgetFactory which authenticates image requests against the + * InvenTree server, so that (e.g.) note images hosted behind the server's + * media API can be displayed. + */ +class _NoteWidgetFactory extends WidgetFactory { + @override + ImageProvider? imageProviderFromNetwork(String url) { + if (url.isEmpty) { + return null; + } + + return CachedNetworkImageProvider( + url, + headers: InvenTreeAPI().defaultHeaders(), + cacheManager: InvenTreeAPI().imageCacheManager, + ); + } +} + +/* + * A read-only widget for viewing the (HTML) content of a single note. + * + * Note content is generated server-side by a rich text editor, + * and cannot be edited from within this app. + */ +class NoteViewWidget extends StatelessWidget { + const NoteViewWidget(this.note, {Key? key}) : super(key: key); + + final InvenTreeNoteEntry note; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(note.title.isNotEmpty ? note.title : L10().notes), + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(12), + child: HtmlWidget( + note.content, + baseUrl: Uri.tryParse(InvenTreeAPI().baseUrl), + factoryBuilder: () => _NoteWidgetFactory(), + ), + ), + ); + } +} + +/* + * Return a ListTile which navigates to the "notes" for the given model instance. + * + * If the server supports the "multi notes" API, the user is first presented + * with a list of available notes to select from. + * + * Otherwise, we fall back to the legacy single-notes (markdown) implementation. + */ +ListTile ShowNotesItem( + BuildContext context, + InvenTreeModel model, + String modelType, +) { + return ListTile( + title: Text(L10().notes), + leading: Icon(TablerIcons.note, color: COLOR_ACTION), + trailing: LinkIcon(), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => InvenTreeAPI().supportsMultiNotes + ? NotesListWidget(modelType, model.pk) + : LegacyNotesWidget(model), + ), + ); + }, + ); +} diff --git a/lib/widget/notes_widget.dart b/lib/widget/notes_widget.dart index 196eb918..2b53f79e 100644 --- a/lib/widget/notes_widget.dart +++ b/lib/widget/notes_widget.dart @@ -6,26 +6,27 @@ import "package:flutter_markdown/flutter_markdown.dart"; import "package:inventree/l10.dart"; /* - * A widget for displaying the notes associated with a given model. + * A widget for displaying the single (markdown) notes field associated with + * a given model, for servers which do not support the "multi notes" API. * We need to pass in the following parameters: - * + * * - Model instance * - Title for the app bar */ -class NotesWidget extends StatefulWidget { - const NotesWidget(this.model, {Key? key}) : super(key: key); +class LegacyNotesWidget extends StatefulWidget { + const LegacyNotesWidget(this.model, {Key? key}) : super(key: key); final InvenTreeModel model; @override - _NotesState createState() => _NotesState(); + _LegacyNotesState createState() => _LegacyNotesState(); } /* - * Class representing the state of the NotesWidget + * Class representing the state of the LegacyNotesWidget */ -class _NotesState extends RefreshableState { - _NotesState(); +class _LegacyNotesState extends RefreshableState { + _LegacyNotesState(); @override Future request(BuildContext context) async { diff --git a/lib/widget/order/purchase_order_detail.dart b/lib/widget/order/purchase_order_detail.dart index add805d1..e8b5c31a 100644 --- a/lib/widget/order/purchase_order_detail.dart +++ b/lib/widget/order/purchase_order_detail.dart @@ -22,7 +22,7 @@ import "package:inventree/widget/order/po_extra_line_list.dart"; import "package:inventree/widget/order/po_line_list.dart"; import "package:inventree/widget/attachment_widget.dart"; -import "package:inventree/widget/notes_widget.dart"; +import "package:inventree/widget/notes_list_widget.dart"; import "package:inventree/widget/parameter_widget.dart"; import "package:inventree/widget/progress.dart"; import "package:inventree/widget/refreshable_state.dart"; @@ -567,17 +567,7 @@ class _PurchaseOrderDetailState // Notes tile tiles.add( - ListTile( - title: Text(L10().notes), - leading: Icon(TablerIcons.note, color: COLOR_ACTION), - trailing: LinkIcon(), - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => NotesWidget(widget.order)), - ); - }, - ), + ShowNotesItem(context, widget.order, InvenTreePurchaseOrder.MODEL_TYPE), ); ListTile? parameterTile = ShowParametersItem( diff --git a/lib/widget/order/sales_order_detail.dart b/lib/widget/order/sales_order_detail.dart index 8844e6bd..482efb1a 100644 --- a/lib/widget/order/sales_order_detail.dart +++ b/lib/widget/order/sales_order_detail.dart @@ -20,7 +20,7 @@ import "package:inventree/l10.dart"; import "package:inventree/app_colors.dart"; import "package:inventree/widget/attachment_widget.dart"; import "package:inventree/widget/dialogs.dart"; -import "package:inventree/widget/notes_widget.dart"; +import "package:inventree/widget/notes_list_widget.dart"; import "package:inventree/widget/snacks.dart"; import "package:inventree/widget/progress.dart"; @@ -492,17 +492,7 @@ class _SalesOrderDetailState extends RefreshableState { // Notes tile tiles.add( - ListTile( - title: Text(L10().notes), - leading: Icon(TablerIcons.note, color: COLOR_ACTION), - trailing: LinkIcon(), - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => NotesWidget(widget.order)), - ); - }, - ), + ShowNotesItem(context, widget.order, InvenTreeSalesOrder.MODEL_TYPE), ); ListTile? parameterTile = ShowParametersItem( diff --git a/lib/widget/order/so_shipment_detail.dart b/lib/widget/order/so_shipment_detail.dart index 1a53aeb4..1cfe70f3 100644 --- a/lib/widget/order/so_shipment_detail.dart +++ b/lib/widget/order/so_shipment_detail.dart @@ -14,7 +14,7 @@ import "package:inventree/l10.dart"; import "package:inventree/preferences.dart"; import "package:inventree/widget/attachment_widget.dart"; import "package:inventree/widget/link_icon.dart"; -import "package:inventree/widget/notes_widget.dart"; +import "package:inventree/widget/notes_list_widget.dart"; import "package:inventree/widget/order/so_allocation_list.dart"; import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/snacks.dart"; @@ -336,18 +336,10 @@ class _SOShipmentDetailWidgetState // Notes tile tiles.add( - ListTile( - title: Text(L10().notes), - leading: Icon(TablerIcons.note, color: COLOR_ACTION), - trailing: LinkIcon(), - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => NotesWidget(widget.shipment), - ), - ); - }, + ShowNotesItem( + context, + widget.shipment, + InvenTreeSalesOrderShipment.MODEL_TYPE, ), ); diff --git a/lib/widget/order/transfer_order_detail.dart b/lib/widget/order/transfer_order_detail.dart index 2c6ab60d..7922413d 100644 --- a/lib/widget/order/transfer_order_detail.dart +++ b/lib/widget/order/transfer_order_detail.dart @@ -12,7 +12,7 @@ import "package:inventree/inventree/transfer_order.dart"; import "package:inventree/widget/dialogs.dart"; import "package:inventree/widget/link_icon.dart"; -import "package:inventree/widget/notes_widget.dart"; +import "package:inventree/widget/notes_list_widget.dart"; import "package:inventree/widget/order/transfer_order_line_list.dart"; import "package:inventree/widget/progress.dart"; import "package:inventree/widget/refreshable_state.dart"; @@ -406,17 +406,7 @@ class _TransferOrderDetailState } tiles.add( - ListTile( - title: Text(L10().notes), - leading: Icon(TablerIcons.note, color: COLOR_ACTION), - trailing: LinkIcon(), - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => NotesWidget(widget.order)), - ); - }, - ), + ShowNotesItem(context, widget.order, InvenTreeTransferOrder.MODEL_TYPE), ); return tiles; diff --git a/lib/widget/part/part_detail.dart b/lib/widget/part/part_detail.dart index c2975c4c..1259c524 100644 --- a/lib/widget/part/part_detail.dart +++ b/lib/widget/part/part_detail.dart @@ -21,7 +21,7 @@ import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/parameter_widget.dart"; import "package:inventree/widget/part/bom_list.dart"; import "package:inventree/widget/part/part_list.dart"; -import "package:inventree/widget/notes_widget.dart"; +import "package:inventree/widget/notes_list_widget.dart"; import "package:inventree/widget/part/part_pricing.dart"; import "package:inventree/widget/progress.dart"; import "package:inventree/widget/part/category_display.dart"; @@ -726,19 +726,7 @@ class _PartDisplayState extends RefreshableState { } // Notes field - tiles.add( - ListTile( - title: Text(L10().notes), - leading: Icon(TablerIcons.note, color: COLOR_ACTION), - trailing: LinkIcon(), - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => NotesWidget(part)), - ); - }, - ), - ); + tiles.add(ShowNotesItem(context, part, InvenTreePart.MODEL_TYPE)); ListTile? parameterTile = ShowParametersItem( context, diff --git a/lib/widget/stock/stock_detail.dart b/lib/widget/stock/stock_detail.dart index 7b46db54..cf8ea881 100644 --- a/lib/widget/stock/stock_detail.dart +++ b/lib/widget/stock/stock_detail.dart @@ -27,7 +27,7 @@ import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/snacks.dart"; import "package:inventree/widget/stock/stock_item_history.dart"; import "package:inventree/widget/stock/stock_item_test_results.dart"; -import "package:inventree/widget/notes_widget.dart"; +import "package:inventree/widget/notes_list_widget.dart"; class StockDetailWidget extends StatefulWidget { const StockDetailWidget(this.item, {Key? key}) : super(key: key); @@ -840,17 +840,7 @@ class _StockItemDisplayState extends RefreshableState { // Notes field tiles.add( - ListTile( - title: Text(L10().notes), - leading: Icon(TablerIcons.note, color: COLOR_ACTION), - trailing: LinkIcon(), - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => NotesWidget(widget.item)), - ); - }, - ), + ShowNotesItem(context, widget.item, InvenTreeStockItem.MODEL_TYPE), ); ListTile? attachmentTile = ShowAttachmentsItem( diff --git a/pubspec.lock b/pubspec.lock index 390c99f8..7e5df9f2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -49,6 +49,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.13.0" + audio_session: + dependency: transitive + description: + name: audio_session + sha256: f9e7711a0e24ca8b40f5d7ac374c3c6e55016f3157912badd18199cdbbca5c4d + url: "https://pub.dev" + source: hosted + version: "0.2.4" audioplayers: dependency: "direct main" description: @@ -189,10 +197,10 @@ packages: dependency: transitive description: name: characters - sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.4.0" checked_yaml: dependency: transitive description: @@ -201,6 +209,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.4" + chewie: + dependency: transitive + description: + name: chewie + sha256: "53dadd2c5b6748742d7744072b38a417ad22691ca55715850300ee793dc7cb27" + url: "https://pub.dev" + source: hosted + version: "1.13.1" cli_config: dependency: transitive description: @@ -265,6 +281,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.6" + csslib: + dependency: transitive + description: + name: csslib + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" cupertino_icons: dependency: "direct main" description: @@ -523,6 +547,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.0" + flutter_svg: + dependency: transitive + description: + name: flutter_svg + sha256: "35882981abcbfb8c15b286f0cd690ff25bac12d95eff3e25ee207f37d4c42e7f" + url: "https://pub.dev" + source: hosted + version: "2.3.0" flutter_tabler_icons: dependency: "direct main" description: @@ -541,6 +573,22 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_widget_from_html: + dependency: "direct main" + description: + name: flutter_widget_from_html + sha256: "16fedbf9cc41656d50a2d27b7ef196bfe85c3fcecb2c84e69e288a1fb2154a1b" + url: "https://pub.dev" + source: hosted + version: "0.17.4" + flutter_widget_from_html_core: + dependency: transitive + description: + name: flutter_widget_from_html_core + sha256: "530f2e3cc57be1a00f8bfae1b0000064e8a6df0cf1fb4d48a80f85afde9b39b7" + url: "https://pub.dev" + source: hosted + version: "0.17.4" frontend_server_client: dependency: transitive description: @@ -549,6 +597,54 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + fwfh_cached_network_image: + dependency: transitive + description: + name: fwfh_cached_network_image + sha256: abbe8f65f3468bfdede4e450b2afffbdc0363f12bf0bdfef3815d47625446bb4 + url: "https://pub.dev" + source: hosted + version: "0.16.3" + fwfh_chewie: + dependency: transitive + description: + name: fwfh_chewie + sha256: ae74fc26798b0e74f3983f7b851e74c63b9eeb2d3015ecd4b829096b2c3f8818 + url: "https://pub.dev" + source: hosted + version: "0.16.1" + fwfh_just_audio: + dependency: transitive + description: + name: fwfh_just_audio + sha256: dfd622a0dfe049ac647423a2a8afa7f057d9b2b93d92710b624e3d370b1ac69a + url: "https://pub.dev" + source: hosted + version: "0.17.0" + fwfh_svg: + dependency: transitive + description: + name: fwfh_svg + sha256: "2e6bb241179eeeb1a7941e05c8c923b05d332d36a9085233e7bf110ea7deb915" + url: "https://pub.dev" + source: hosted + version: "0.16.1" + fwfh_url_launcher: + dependency: transitive + description: + name: fwfh_url_launcher + sha256: c38aa8fb373fda3a89b951fa260b539f623f6edb45eee7874cb8b492471af881 + url: "https://pub.dev" + source: hosted + version: "0.16.1" + fwfh_webview: + dependency: transitive + description: + name: fwfh_webview + sha256: a9cdfbe58a7152bcc91c420dc96cd9972c01b5d1318a6d4c6d9a1d97a1bd6e94 + url: "https://pub.dev" + source: hosted + version: "0.15.8" gesture_x_detector: dependency: transitive description: @@ -565,6 +661,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" + html: + dependency: transitive + description: + name: html + sha256: "43b67b8f43321ab066817dfac5619596c98bb1b61624e77203bb4351785f9699" + url: "https://pub.dev" + source: hosted + version: "0.15.7" http: dependency: "direct main" description: @@ -693,6 +797,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.14.2" + js: + dependency: transitive + description: + name: js + sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" + url: "https://pub.dev" + source: hosted + version: "0.7.2" json_annotation: dependency: transitive description: @@ -701,6 +813,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.9.0" + just_audio: + dependency: transitive + description: + name: just_audio + sha256: e60aa97b233ddea025e13dfac59195207f528fa5e9e4a4a49a8c0766701e5fe6 + url: "https://pub.dev" + source: hosted + version: "0.10.6" + just_audio_platform_interface: + dependency: transitive + description: + name: just_audio_platform_interface + sha256: "2532c8d6702528824445921c5ff10548b518b13f808c2e34c2fd54793b999a6a" + url: "https://pub.dev" + source: hosted + version: "4.6.0" + just_audio_web: + dependency: transitive + description: + name: just_audio_web + sha256: "6ba8a2a7e87d57d32f0f7b42856ade3d6a9fbe0f1a11fabae0a4f00bb73f0663" + url: "https://pub.dev" + source: hosted + version: "0.4.16" leak_tracker: dependency: transitive description: @@ -753,18 +889,18 @@ packages: dependency: transitive description: name: matcher - sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.19" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.13.0" + version: "0.11.1" meta: dependency: transitive description: @@ -789,6 +925,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.2.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" node_preamble: dependency: transitive description: @@ -853,6 +997,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" + url: "https://pub.dev" + source: hosted + version: "1.1.0" path_provider: dependency: "direct main" description: @@ -949,6 +1101,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.2" + provider: + dependency: transitive + description: + name: provider + sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" + url: "https://pub.dev" + source: hosted + version: "6.1.5+1" pub_semver: dependency: transitive description: @@ -1214,26 +1374,26 @@ packages: dependency: "direct dev" description: name: test - sha256: "280d6d890011ca966ad08df7e8a4ddfab0fb3aa49f96ed6de56e3521347a9ae7" + sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7" url: "https://pub.dev" source: hosted - version: "1.30.0" + version: "1.26.3" test_api: dependency: transitive description: name: test_api - sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.7.10" + version: "0.7.7" test_core: dependency: transitive description: name: test_core - sha256: "0381bd1585d1a924763c308100f2138205252fb90c9d4eeaf28489ee65ccde51" + sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0" url: "https://pub.dev" source: hosted - version: "0.6.16" + version: "0.6.12" typed_data: dependency: transitive description: @@ -1314,6 +1474,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.5.1" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "9d0e3b9cb16542ad660daee871e726a10d13a93b7b5391677c3160e8f5e83935" + url: "https://pub.dev" + source: hosted + version: "1.2.3" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" + url: "https://pub.dev" + source: hosted + version: "1.1.13" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "4dca4feb77dc3ec7f6e27e49c53241eb8217f55e4f9b12599a27f8903bca5682" + url: "https://pub.dev" + source: hosted + version: "1.3.0" vector_math: dependency: transitive description: @@ -1322,6 +1506,46 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + video_player: + dependency: transitive + description: + name: video_player + sha256: "48a7bdaa38a3d50ec10c78627abdbfad863fdf6f0d6e08c7c3c040cfd80ae36f" + url: "https://pub.dev" + source: hosted + version: "2.11.1" + video_player_android: + dependency: transitive + description: + name: video_player_android + sha256: "877a6c7ba772456077d7bfd71314629b3fe2b73733ce503fc77c3314d43a0ca0" + url: "https://pub.dev" + source: hosted + version: "2.9.5" + video_player_avfoundation: + dependency: transitive + description: + name: video_player_avfoundation + sha256: "2fc56e537324a19eb649fca991aa308ac961b5406292876fa657b062de461fd8" + url: "https://pub.dev" + source: hosted + version: "2.12.0" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + sha256: "92c0fbabe20c788e71fd10d26cea998d0d253282e65d145aed0818731cf593ce" + url: "https://pub.dev" + source: hosted + version: "6.9.0" + video_player_web: + dependency: transitive + description: + name: video_player_web + sha256: "9f3c00be2ef9b76a95d94ac5119fb843dca6f2c69e6c9968f6f2b6c9e7afbdeb" + url: "https://pub.dev" + source: hosted + version: "2.4.0" vm_service: dependency: transitive description: @@ -1386,6 +1610,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" + webview_flutter: + dependency: transitive + description: + name: webview_flutter + sha256: d53e1ccf5516f25017e3c9d44c39034db352d20fa34fe200674270242c2c5111 + url: "https://pub.dev" + source: hosted + version: "4.14.1" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + sha256: ad5182eff9a550925330cb9f0cb038eddfdd5712aba8b77aa0f0400e50f6e688 + url: "https://pub.dev" + source: hosted + version: "4.12.0" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + sha256: "1221c1b12f5278791042f2ec2841743784cf25c5a644e23d6680e5d718824f04" + url: "https://pub.dev" + source: hosted + version: "2.15.1" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + sha256: "82648217f537573e1ca9ae9952d3eacedca6ab5aee69dc84445fc763766dcea2" + url: "https://pub.dev" + source: hosted + version: "3.25.1" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 13d3033c..0288770a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,7 @@ dependencies: flutter_secure_storage: ^10.3.1 flutter_speed_dial: ^6.2.0 # Speed dial / FAB implementation flutter_tabler_icons: ^1.43.0 # Tabler icons + flutter_widget_from_html: ^0.17.4 # Rendering HTML (multi-notes) http: ^1.4.0 image: ^4.5.4 # Re-encode/compress images before upload image_picker: ^1.2.2 # Select or take photos