diff --git a/lib/main_app.dart b/lib/main_app.dart
index 4e687d4fe..afe353b2a 100644
--- a/lib/main_app.dart
+++ b/lib/main_app.dart
@@ -413,6 +413,7 @@ class InvoiceNinjaAppState extends State {
*/
theme: state.prefState.enableDarkMode
? ThemeData(
+ useMaterial3: false,
tooltipTheme: TooltipThemeData(
waitDuration: Duration(milliseconds: 500),
),
@@ -438,6 +439,7 @@ class InvoiceNinjaAppState extends State {
BottomAppBarTheme(color: const Color(0xFF1B1C1E)),
)
: ThemeData(
+ useMaterial3: false,
tooltipTheme: TooltipThemeData(
waitDuration: Duration(milliseconds: 500),
),
diff --git a/lib/redux/app/app_state.dart b/lib/redux/app/app_state.dart
index 160868dd8..a90e90883 100644
--- a/lib/redux/app/app_state.dart
+++ b/lib/redux/app/app_state.dart
@@ -162,7 +162,7 @@ abstract class AppState implements Built {
}
final companies =
- list.where((CompanyEntity company) => (company.id).isNotEmpty).toList();
+ list.where((CompanyEntity company) => company.id.isNotEmpty).toList();
return companies;
}
diff --git a/lib/redux/dashboard/dashboard_sidebar_selectors.dart b/lib/redux/dashboard/dashboard_sidebar_selectors.dart
index 59de11a0e..f6fb7d8cd 100644
--- a/lib/redux/dashboard/dashboard_sidebar_selectors.dart
+++ b/lib/redux/dashboard/dashboard_sidebar_selectors.dart
@@ -191,7 +191,7 @@ List _runningTasks({
}
});
- tasks.sort((taskA, taskB) => (taskB.updatedAt).compareTo(taskA.updatedAt));
+ tasks.sort((taskA, taskB) => taskB.updatedAt.compareTo(taskA.updatedAt));
return tasks;
}
@@ -219,7 +219,7 @@ List _recentTasks({
}
});
- tasks.sort((taskA, taskB) => (taskB.updatedAt).compareTo(taskA.updatedAt));
+ tasks.sort((taskA, taskB) => taskB.updatedAt.compareTo(taskA.updatedAt));
return tasks;
}
diff --git a/lib/redux/recurring_expense/recurring_expense_actions.dart b/lib/redux/recurring_expense/recurring_expense_actions.dart
index d172f8ad8..6d4b94edc 100644
--- a/lib/redux/recurring_expense/recurring_expense_actions.dart
+++ b/lib/redux/recurring_expense/recurring_expense_actions.dart
@@ -388,10 +388,9 @@ void handleRecurringExpenseAction(BuildContext? context,
break;
case EntityAction.start:
store.dispatch(StartRecurringExpensesRequest(
- completer: snackBarCompleter(
- (recurringExpense.lastSentDate).isEmpty
- ? localization!.startedRecurringInvoice
- : localization!.resumedRecurringInvoice),
+ completer: snackBarCompleter(recurringExpense.lastSentDate.isEmpty
+ ? localization!.startedRecurringInvoice
+ : localization!.resumedRecurringInvoice),
expenseIds: recurringExpenseIds,
));
break;
diff --git a/lib/redux/recurring_invoice/recurring_invoice_actions.dart b/lib/redux/recurring_invoice/recurring_invoice_actions.dart
index ce1bc7700..969b78525 100644
--- a/lib/redux/recurring_invoice/recurring_invoice_actions.dart
+++ b/lib/redux/recurring_invoice/recurring_invoice_actions.dart
@@ -629,10 +629,9 @@ void handleRecurringInvoiceAction(BuildContext? context,
break;
case EntityAction.start:
store.dispatch(StartRecurringInvoicesRequest(
- completer: snackBarCompleter(
- (recurringInvoice.lastSentDate).isEmpty
- ? localization!.startedRecurringInvoice
- : localization!.resumedRecurringInvoice),
+ completer: snackBarCompleter(recurringInvoice.lastSentDate.isEmpty
+ ? localization!.startedRecurringInvoice
+ : localization!.resumedRecurringInvoice),
invoiceIds: recurringInvoiceIds,
));
break;
diff --git a/lib/redux/vendor/vendor_actions.dart b/lib/redux/vendor/vendor_actions.dart
index 8adb3cc52..b0b865fe7 100644
--- a/lib/redux/vendor/vendor_actions.dart
+++ b/lib/redux/vendor/vendor_actions.dart
@@ -300,7 +300,7 @@ void handleVendorAction(
break;
case EntityAction.vendorPortal:
final contact = vendor.contacts.firstWhere((contact) {
- return (contact.link).isNotEmpty;
+ return contact.link.isNotEmpty;
}, orElse: null);
launchUrl(Uri.parse(contact.silentLink));
break;
diff --git a/lib/ui/app/dialogs/multiselect_dialog.dart b/lib/ui/app/dialogs/multiselect_dialog.dart
index 5c5ab58e9..ed101a0c5 100644
--- a/lib/ui/app/dialogs/multiselect_dialog.dart
+++ b/lib/ui/app/dialogs/multiselect_dialog.dart
@@ -74,7 +74,7 @@ class MultiSelectListState extends State {
void initState() {
super.initState();
selected =
- (widget.selected).isNotEmpty ? widget.selected : widget.defaultSelected;
+ widget.selected.isNotEmpty ? widget.selected : widget.defaultSelected;
_controller = ScrollController();
}
diff --git a/lib/ui/app/document_grid.dart b/lib/ui/app/document_grid.dart
index 2acd58969..a404e9c3d 100644
--- a/lib/ui/app/document_grid.dart
+++ b/lib/ui/app/document_grid.dart
@@ -459,7 +459,7 @@ class DocumentPreview extends StatelessWidget {
key: ValueKey(document.preview),
imageUrl:
'${cleanApiUrl(state.credentials.url)}/documents/${document.hash}',
- imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
+ //imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
httpHeaders: {'X-API-TOKEN': state.credentials.token},
placeholder: (context, url) => Container(
height: height,
diff --git a/lib/ui/app/invoice/invoice_email_view.dart b/lib/ui/app/invoice/invoice_email_view.dart
index 25c9dc49f..29caf0d52 100644
--- a/lib/ui/app/invoice/invoice_email_view.dart
+++ b/lib/ui/app/invoice/invoice_email_view.dart
@@ -87,7 +87,7 @@ class _InvoiceEmailViewState extends State
selectedTemplate = EmailTemplate.reminder3;
else if ((invoice.reminder1Sent ?? '').isNotEmpty)
selectedTemplate = EmailTemplate.reminder2;
- else if ((invoice.lastSentDate).isNotEmpty)
+ else if (invoice.lastSentDate.isNotEmpty)
selectedTemplate = EmailTemplate.reminder1;
else
selectedTemplate = EmailTemplate.invoice;
diff --git a/lib/ui/app/lists/activity_list_tile.dart b/lib/ui/app/lists/activity_list_tile.dart
index 3c90f481e..6bb74fcb1 100644
--- a/lib/ui/app/lists/activity_list_tile.dart
+++ b/lib/ui/app/lists/activity_list_tile.dart
@@ -139,7 +139,7 @@ class ActivityListTile extends StatelessWidget {
subtitle: Row(
children: [
Flexible(
- child: Text(((activity.notes).isNotEmpty
+ child: Text((activity.notes.isNotEmpty
? localization.lookup(activity.notes).trim() + '\n'
: '') +
formatDate(
diff --git a/lib/ui/client/view/client_view_overview.dart b/lib/ui/client/view/client_view_overview.dart
index 3bcc2a556..a08a907e8 100644
--- a/lib/ui/client/view/client_view_overview.dart
+++ b/lib/ui/client/view/client_view_overview.dart
@@ -165,7 +165,7 @@ class ClientOverview extends StatelessWidget {
),
),
ListDivider(),
- if ((client.privateNotes).isNotEmpty) ...[
+ if (client.privateNotes.isNotEmpty) ...[
IconMessage(client.privateNotes, iconData: Icons.lock),
ListDivider()
],
diff --git a/lib/ui/invoice/edit/invoice_item_selector.dart b/lib/ui/invoice/edit/invoice_item_selector.dart
index b11146081..93f1d6183 100644
--- a/lib/ui/invoice/edit/invoice_item_selector.dart
+++ b/lib/ui/invoice/edit/invoice_item_selector.dart
@@ -129,7 +129,7 @@ class _InvoiceItemSelectorState extends State
if (selected != null) {
_filterClientId = (selected as BelongsToClient).clientId;
- } else if ((widget.clientId).isEmpty) {
+ } else if (widget.clientId.isEmpty) {
_filterClientId = null;
}
}
diff --git a/lib/ui/purchase_order/purchase_order_list_item.dart b/lib/ui/purchase_order/purchase_order_list_item.dart
index 1127b7c44..c5693e127 100644
--- a/lib/ui/purchase_order/purchase_order_list_item.dart
+++ b/lib/ui/purchase_order/purchase_order_list_item.dart
@@ -217,7 +217,7 @@ class PurchaseOrderListItem extends StatelessWidget {
children: [
Expanded(
child: filterMatch == null
- ? Text((((purchaseOrder.number).isEmpty
+ ? Text(((purchaseOrder.number.isEmpty
? localization!.pending
: purchaseOrder.number) +
' • ' +
diff --git a/lib/ui/purchase_order/purchase_order_presenter.dart b/lib/ui/purchase_order/purchase_order_presenter.dart
index d3355e5c2..7b3b9ce54 100644
--- a/lib/ui/purchase_order/purchase_order_presenter.dart
+++ b/lib/ui/purchase_order/purchase_order_presenter.dart
@@ -73,7 +73,7 @@ class PurchaseOrderPresenter extends EntityPresenter {
case PurchaseOrderFields.status:
return EntityStatusChip(entity: purchaseOrder, showState: true);
case PurchaseOrderFields.number:
- return Text((purchaseOrder.number).isEmpty
+ return Text(purchaseOrder.number.isEmpty
? localization!.pending
: purchaseOrder.number);
case PurchaseOrderFields.client:
diff --git a/lib/ui/quote/quote_list_item.dart b/lib/ui/quote/quote_list_item.dart
index 97a6435ee..65010d23f 100644
--- a/lib/ui/quote/quote_list_item.dart
+++ b/lib/ui/quote/quote_list_item.dart
@@ -113,7 +113,7 @@ class QuoteListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
- (quote.number).isEmpty
+ quote.number.isEmpty
? localization!.pending
: quote.number,
style: textStyle,
diff --git a/lib/ui/recurring_invoice/recurring_invoice_list_item.dart b/lib/ui/recurring_invoice/recurring_invoice_list_item.dart
index d79c17e3a..0e03e7fa2 100644
--- a/lib/ui/recurring_invoice/recurring_invoice_list_item.dart
+++ b/lib/ui/recurring_invoice/recurring_invoice_list_item.dart
@@ -122,7 +122,7 @@ class RecurringInvoiceListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
- (invoice.number).isEmpty
+ invoice.number.isEmpty
? localization.pending
: invoice.number,
style: textStyle,
diff --git a/lib/utils/markdown.dart b/lib/utils/markdown.dart
index 0c942c618..32ff4c1dc 100644
--- a/lib/utils/markdown.dart
+++ b/lib/utils/markdown.dart
@@ -1,3 +1,4 @@
+/*
// DELETE THIS FILE ONCE SUPER EDITOR IS UPDATED
// Note: using the standard function crashes with h1 tags
@@ -588,3 +589,4 @@ class _EmptyParagraphSyntax extends md.BlockSyntax {
return md.Element('p', []);
}
}
+*/
\ No newline at end of file
diff --git a/lib/utils/super_editor/super_editor.dart b/lib/utils/super_editor/super_editor.dart
index c4f0f17a1..51b834663 100644
--- a/lib/utils/super_editor/super_editor.dart
+++ b/lib/utils/super_editor/super_editor.dart
@@ -1,8 +1,11 @@
+//import 'package:example/logging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
-import 'package:invoiceninja_flutter/utils/markdown.dart';
-import 'package:invoiceninja_flutter/utils/super_editor/toolbar.dart';
import 'package:super_editor/super_editor.dart';
+import 'package:super_editor_markdown/super_editor_markdown.dart';
+
+import 'package:invoiceninja_flutter/utils/super_editor/toolbar.dart';
+//import '_toolbar.dart';
/// Example of a rich text editor.
///
@@ -19,39 +22,46 @@ class ExampleEditor extends StatefulWidget {
final Function(String)? onChanged;
@override
- _ExampleEditorState createState() => _ExampleEditorState();
+ State createState() => _ExampleEditorState();
}
class _ExampleEditorState extends State {
+ final GlobalKey _viewportKey = GlobalKey();
final GlobalKey _docLayoutKey = GlobalKey();
- late Document _doc;
- DocumentEditor? _docEditor;
- DocumentComposer? _composer;
+ late MutableDocument _doc;
+ final _docChangeSignal = SignalNotifier();
+ late MutableDocumentComposer _composer;
+ late Editor _docEditor;
late CommonEditorOperations _docOps;
- FocusNode? _editorFocusNode;
+ late FocusNode _editorFocusNode;
- ScrollController? _scrollController;
+ late ScrollController _scrollController;
+
+ final SelectionLayerLinks _selectionLayerLinks = SelectionLayerLinks();
final _darkBackground = const Color(0xFF222222);
final _lightBackground = Colors.white;
- //Brightness _brightness = Brightness.light;
+ final _brightness = ValueNotifier(Brightness.light);
SuperEditorDebugVisualsConfig? _debugConfig;
- OverlayEntry? _textFormatBarOverlayEntry;
+ final _textFormatBarOverlayController = OverlayPortalController();
final _textSelectionAnchor = ValueNotifier(null);
- OverlayEntry? _imageFormatBarOverlayEntry;
+ final _imageFormatBarOverlayController = OverlayPortalController();
final _imageSelectionAnchor = ValueNotifier(null);
- final _overlayController = MagnifierAndToolbarController();
+ // TODO: get rid of overlay controller once Android is refactored to use a control scope (as follow up to: https://github.com/superlistapp/super_editor/pull/1470)
+ final _overlayController = MagnifierAndToolbarController() //
+ ..screenPadding = const EdgeInsets.all(20.0);
+
+ late final SuperEditorIosControlsController _iosControlsController;
@override
void initState() {
super.initState();
-
// Fix for tags cutting off text
var markdown = widget.value;
markdown = markdown.replaceAll('
', '\n');
@@ -60,64 +70,38 @@ class _ExampleEditorState extends State {
markdown = markdown.replaceAll('
', '');
markdown = markdown.replaceAll('', '');
+ // _doc = createInitialDocument()..addListener(_onDocumentChange);
_doc = deserializeMarkdownToDocument(markdown)
- ..addListener(_hideOrShowToolbar)
- ..addListener(_onChanged);
-
- _docEditor = DocumentEditor(document: _doc as MutableDocument);
- _composer = DocumentComposer();
- _composer!.selectionNotifier.addListener(_hideOrShowToolbar);
+ ..addListener(_onDocumentChange);
+ _composer = MutableDocumentComposer();
+ _composer.selectionNotifier.addListener(_hideOrShowToolbar);
+ _docEditor =
+ createDefaultDocumentEditor(document: _doc, composer: _composer);
_docOps = CommonEditorOperations(
- editor: _docEditor!,
- composer: _composer!,
+ editor: _docEditor,
+ document: _doc,
+ composer: _composer,
documentLayoutResolver: () =>
_docLayoutKey.currentState as DocumentLayout,
);
_editorFocusNode = FocusNode();
_scrollController = ScrollController()..addListener(_hideOrShowToolbar);
- }
- @override
- void didUpdateWidget(ExampleEditor oldWidget) {
- super.didUpdateWidget(oldWidget);
-
- if (widget.value != oldWidget.value) {
- _setValue(widget.value);
- }
- }
-
- void _setValue(String value) {
- _doc.removeListener(_hideOrShowToolbar);
- _doc.removeListener(_onChanged);
- _doc = deserializeMarkdownToDocument(value)
- ..addListener(_hideOrShowToolbar)
- ..addListener(_onChanged);
- _docEditor = DocumentEditor(document: _doc as MutableDocument);
- _editorFocusNode = FocusNode();
+ _iosControlsController = SuperEditorIosControlsController();
}
@override
void dispose() {
- if (_textFormatBarOverlayEntry != null) {
- _textFormatBarOverlayEntry!.remove();
- }
-
- _doc.removeListener(_hideOrShowToolbar);
- _doc.removeListener(_onChanged);
- _scrollController!.removeListener(_hideOrShowToolbar);
- _composer!.removeListener(_hideOrShowToolbar);
-
- _scrollController!.dispose();
- _editorFocusNode!.dispose();
- _composer!.dispose();
+ _iosControlsController.dispose();
+ _scrollController.dispose();
+ _editorFocusNode.dispose();
+ _composer.dispose();
super.dispose();
}
- void _onChanged() {
- if (widget.onChanged != null) {
- final value = serializeDocumentToMarkdown(_docEditor!.document);
- widget.onChanged!(value);
- }
+ void _onDocumentChange(_) {
+ _hideOrShowToolbar();
+ _docChangeSignal.notifyListeners();
}
void _hideOrShowToolbar() {
@@ -127,7 +111,7 @@ class _ExampleEditorState extends State {
return;
}
- final selection = _composer!.selection;
+ final selection = _composer.selection;
if (selection == null) {
// Nothing is selected. We don't want to show a toolbar
// in this case.
@@ -155,6 +139,7 @@ class _ExampleEditorState extends State {
final selectedNode = _doc.getNodeById(selection.extent.nodeId);
if (selectedNode is ImageNode) {
+ //appLog.fine("Showing image toolbar");
// Show the editor's toolbar for image sizing.
_showImageToolbar();
_hideEditorToolbar();
@@ -178,36 +163,16 @@ class _ExampleEditorState extends State {
}
void _showEditorToolbar() {
- if (_textFormatBarOverlayEntry == null) {
- // Create an overlay entry to build the editor toolbar.
- // TODO: add an overlay to the Editor widget to avoid using the
- // application overlay
- _textFormatBarOverlayEntry ??= OverlayEntry(builder: (context) {
- return EditorToolbar(
- anchor: _textSelectionAnchor,
- editorFocusNode: _editorFocusNode,
- editor: _docEditor,
- composer: _composer,
- closeToolbar: _hideEditorToolbar,
- );
- });
-
- // Display the toolbar in the application overlay.
- final overlay = Overlay.of(context);
- overlay.insert(_textFormatBarOverlayEntry!);
- }
+ _textFormatBarOverlayController.show();
// Schedule a callback after this frame to locate the selection
// bounds on the screen and display the toolbar near the selected
// text.
+ // TODO: switch this to use a Leader and Follower
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
- if (_textFormatBarOverlayEntry == null) {
- return;
- }
-
final docBoundingBox = (_docLayoutKey.currentState as DocumentLayout)
.getRectForSelection(
- _composer!.selection!.base, _composer!.selection!.extent)!;
+ _composer.selection!.base, _composer.selection!.extent)!;
final docBox =
_docLayoutKey.currentContext!.findRenderObject() as RenderBox;
final overlayBoundingBox = Rect.fromPoints(
@@ -224,22 +189,14 @@ class _ExampleEditorState extends State {
// the bar doesn't momentarily "flash" at its old anchor position.
_textSelectionAnchor.value = null;
- if (_textFormatBarOverlayEntry != null) {
- // Remove the toolbar overlay and null-out the entry.
- // We null out the entry because we can't query whether
- // or not the entry exists in the overlay, so in our
- // case, null implies the entry is not in the overlay,
- // and non-null implies the entry is in the overlay.
- _textFormatBarOverlayEntry!.remove();
- _textFormatBarOverlayEntry = null;
+ _textFormatBarOverlayController.hide();
- // Ensure that focus returns to the editor.
- //
- // I tried explicitly unfocus()'ing the URL textfield
- // in the toolbar but it didn't return focus to the
- // editor. I'm not sure why.
- _editorFocusNode!.requestFocus();
- }
+ // Ensure that focus returns to the editor.
+ //
+ // I tried explicitly unfocus()'ing the URL textfield
+ // in the toolbar but it didn't return focus to the
+ // editor. I'm not sure why.
+ _editorFocusNode.requestFocus();
}
DocumentGestureMode get _gestureMode {
@@ -267,63 +224,41 @@ class _ExampleEditorState extends State {
case TargetPlatform.macOS:
case TargetPlatform.windows:
return TextInputSource.ime;
- // return DocumentInputSource.keyboard;
}
}
void _cut() {
_docOps.cut();
+ // TODO: get rid of overlay controller once Android is refactored to use a control scope (as follow up to: https://github.com/superlistapp/super_editor/pull/1470)
_overlayController.hideToolbar();
+ _iosControlsController.hideToolbar();
}
void _copy() {
_docOps.copy();
+ // TODO: get rid of overlay controller once Android is refactored to use a control scope (as follow up to: https://github.com/superlistapp/super_editor/pull/1470)
_overlayController.hideToolbar();
+ _iosControlsController.hideToolbar();
}
void _paste() {
_docOps.paste();
+ // TODO: get rid of overlay controller once Android is refactored to use a control scope (as follow up to: https://github.com/superlistapp/super_editor/pull/1470)
_overlayController.hideToolbar();
+ _iosControlsController.hideToolbar();
}
void _selectAll() => _docOps.selectAll();
void _showImageToolbar() {
- if (_imageFormatBarOverlayEntry == null) {
- // Create an overlay entry to build the image toolbar.
- _imageFormatBarOverlayEntry ??= OverlayEntry(builder: (context) {
- return ImageFormatToolbar(
- anchor: _imageSelectionAnchor,
- composer: _composer,
- setWidth: (nodeId, width) {
- final node = _doc.getNodeById(nodeId)!;
- final currentStyles =
- SingleColumnLayoutComponentStyles.fromMetadata(node);
- SingleColumnLayoutComponentStyles(
- width: width,
- padding: currentStyles.padding,
- ).applyTo(node);
- },
- closeToolbar: _hideImageToolbar,
- );
- });
-
- // Display the toolbar in the application overlay.
- final overlay = Overlay.of(context);
- overlay.insert(_imageFormatBarOverlayEntry!);
- }
-
// Schedule a callback after this frame to locate the selection
// bounds on the screen and display the toolbar near the selected
// text.
+ // TODO: switch to a Leader and Follower for this
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
- if (_imageFormatBarOverlayEntry == null) {
- return;
- }
-
final docBoundingBox = (_docLayoutKey.currentState as DocumentLayout)
.getRectForSelection(
- _composer!.selection!.base, _composer!.selection!.extent)!;
+ _composer.selection!.base, _composer.selection!.extent)!;
final docBox =
_docLayoutKey.currentContext!.findRenderObject() as RenderBox;
final overlayBoundingBox = Rect.fromPoints(
@@ -333,6 +268,8 @@ class _ExampleEditorState extends State {
_imageSelectionAnchor.value = overlayBoundingBox.center;
});
+
+ _imageFormatBarOverlayController.show();
}
void _hideImageToolbar() {
@@ -340,56 +277,74 @@ class _ExampleEditorState extends State {
// it doesn't momentarily "flash" at its old anchor position.
_imageSelectionAnchor.value = null;
- if (_imageFormatBarOverlayEntry != null) {
- // Remove the image toolbar overlay and null-out the entry.
- // We null out the entry because we can't query whether
- // or not the entry exists in the overlay, so in our
- // case, null implies the entry is not in the overlay,
- // and non-null implies the entry is in the overlay.
- _imageFormatBarOverlayEntry!.remove();
- _imageFormatBarOverlayEntry = null;
+ _imageFormatBarOverlayController.hide();
- // Ensure that focus returns to the editor.
- _editorFocusNode!.requestFocus();
- }
+ // Ensure that focus returns to the editor.
+ _editorFocusNode.requestFocus();
}
@override
Widget build(BuildContext context) {
- return Theme(
- data: ThemeData(brightness: Brightness.light),
- child: Builder(builder: (themedContext) {
- // This builder captures the new theme
- return Stack(
- children: [
- Column(
- children: [
- Expanded(
- child: _buildEditor(themedContext),
- ),
- if (_isMobile) _buildMountedToolbar(),
- ],
- ),
- /*
- Align(
- alignment: Alignment.bottomRight,
- child: _buildCornerFabs(),
- ),
- */
- ],
+ return ValueListenableBuilder(
+ valueListenable: _brightness,
+ builder: (context, brightness, child) {
+ return Theme(
+ data: ThemeData(brightness: brightness),
+ child: child!,
);
- }),
+ },
+ child: Builder(
+ // This builder captures the new theme
+ builder: (themedContext) {
+ return OverlayPortal(
+ controller: _textFormatBarOverlayController,
+ overlayChildBuilder: _buildFloatingToolbar,
+ child: OverlayPortal(
+ controller: _imageFormatBarOverlayController,
+ overlayChildBuilder: _buildImageToolbar,
+ child: Stack(
+ children: [
+ Column(
+ children: [
+ Expanded(
+ child: _buildEditor(themedContext),
+ ),
+ if (_isMobile) //
+ _buildMountedToolbar(),
+ ],
+ ),
+ Align(
+ alignment: Alignment.bottomRight,
+ child: ListenableBuilder(
+ listenable: _composer.selectionNotifier,
+ builder: (context, child) {
+ return Padding(
+ padding: EdgeInsets.only(
+ bottom: _isMobile && _composer.selection != null
+ ? 48
+ : 0),
+ child: child,
+ );
+ },
+ child: _buildCornerFabs(),
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ },
+ ),
);
}
- /*
Widget _buildCornerFabs() {
return Padding(
padding: const EdgeInsets.only(right: 16, bottom: 16),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
- children: [
+ children: [
_buildDebugVisualsToggle(),
const SizedBox(height: 16),
_buildLightAndDarkModeToggle(),
@@ -397,21 +352,21 @@ class _ExampleEditorState extends State {
),
);
}
- */
- /*
Widget _buildDebugVisualsToggle() {
return FloatingActionButton(
- backgroundColor:
- _brightness == Brightness.light ? _darkBackground : _lightBackground,
- foregroundColor:
- _brightness == Brightness.light ? _lightBackground : _darkBackground,
+ backgroundColor: _brightness.value == Brightness.light
+ ? _darkBackground
+ : _lightBackground,
+ foregroundColor: _brightness.value == Brightness.light
+ ? _lightBackground
+ : _darkBackground,
elevation: 5,
onPressed: () {
setState(() {
_debugConfig = _debugConfig != null
? null
- : SuperEditorDebugVisualsConfig(
+ : const SuperEditorDebugVisualsConfig(
showFocus: true,
showImeConnection: true,
);
@@ -421,23 +376,23 @@ class _ExampleEditorState extends State {
Icons.bug_report,
),
);
- }
+ }
Widget _buildLightAndDarkModeToggle() {
return FloatingActionButton(
- backgroundColor:
- _brightness == Brightness.light ? _darkBackground : _lightBackground,
- foregroundColor:
- _brightness == Brightness.light ? _lightBackground : _darkBackground,
+ backgroundColor: _brightness.value == Brightness.light
+ ? _darkBackground
+ : _lightBackground,
+ foregroundColor: _brightness.value == Brightness.light
+ ? _lightBackground
+ : _darkBackground,
elevation: 5,
onPressed: () {
- setState(() {
- _brightness = _brightness == Brightness.light
- ? Brightness.dark
- : Brightness.light;
- });
+ _brightness.value = _brightness.value == Brightness.light
+ ? Brightness.dark
+ : Brightness.light;
},
- child: _brightness == Brightness.light
+ child: _brightness.value == Brightness.light
? const Icon(
Icons.dark_mode,
)
@@ -446,7 +401,6 @@ class _ExampleEditorState extends State {
),
);
}
- */
Widget _buildEditor(BuildContext context) {
final isLight = Theme.of(context).brightness == Brightness.light;
@@ -455,77 +409,134 @@ class _ExampleEditorState extends State {
color: isLight ? _lightBackground : _darkBackground,
child: SuperEditorDebugVisuals(
config: _debugConfig ?? const SuperEditorDebugVisualsConfig(),
- child: SuperEditor(
- editor: _docEditor!,
- composer: _composer,
- focusNode: _editorFocusNode,
- scrollController: _scrollController,
- documentLayoutKey: _docLayoutKey,
- documentOverlayBuilders: [
- DefaultCaretOverlayBuilder(
- CaretStyle()
- .copyWith(color: isLight ? Colors.black : Colors.redAccent),
- ),
- ],
- selectionStyle: isLight
- ? defaultSelectionStyle
- : SelectionStyles(
- selectionColor: Colors.red.withOpacity(0.3),
+ child: KeyedSubtree(
+ key: _viewportKey,
+ child: SuperEditorIosControlsScope(
+ controller: _iosControlsController,
+ child: SuperEditor(
+ editor: _docEditor,
+ document: _doc,
+ composer: _composer,
+ focusNode: _editorFocusNode,
+ scrollController: _scrollController,
+ documentLayoutKey: _docLayoutKey,
+ documentOverlayBuilders: [
+ DefaultCaretOverlayBuilder(
+ caretStyle: const CaretStyle().copyWith(
+ color: isLight ? Colors.black : Colors.redAccent),
),
- stylesheet: defaultStylesheet.copyWith(
- addRulesAfter: [
- if (!isLight) ..._darkModeStyles,
- taskStyles,
- ],
+ if (defaultTargetPlatform == TargetPlatform.iOS) ...[
+ SuperEditorAndroidToolbarFocalPointDocumentLayerBuilder(),
+ SuperEditorAndroidHandlesDocumentLayerBuilder(),
+ ],
+ if (defaultTargetPlatform == TargetPlatform.android) ...[
+ SuperEditorAndroidToolbarFocalPointDocumentLayerBuilder(),
+ SuperEditorAndroidHandlesDocumentLayerBuilder(),
+ ],
+ ],
+ selectionLayerLinks: _selectionLayerLinks,
+ selectionStyle: isLight
+ ? defaultSelectionStyle
+ : SelectionStyles(
+ selectionColor: Colors.red.withOpacity(0.3),
+ ),
+ stylesheet: defaultStylesheet.copyWith(
+ addRulesAfter: [
+ if (!isLight) ..._darkModeStyles,
+ taskStyles,
+ ],
+ ),
+ componentBuilders: [
+ TaskComponentBuilder(_docEditor),
+ ...defaultComponentBuilders,
+ ],
+ gestureMode: _gestureMode,
+ inputSource: _inputSource,
+ keyboardActions: _inputSource == TextInputSource.ime
+ ? defaultImeKeyboardActions
+ : defaultKeyboardActions,
+ androidToolbarBuilder: (_) => _buildAndroidFloatingToolbar(),
+ overlayController: _overlayController,
+ ),
),
- componentBuilders: [
- TaskComponentBuilder(_docEditor!),
- ...defaultComponentBuilders,
- ],
- gestureMode: _gestureMode,
- inputSource: _inputSource,
- keyboardActions: _inputSource == TextInputSource.ime
- ? defaultImeKeyboardActions
- : defaultKeyboardActions,
- androidToolbarBuilder: (_) => AndroidTextEditingFloatingToolbar(
+ ),
+ ),
+ );
+ }
+
+ Widget _buildAndroidFloatingToolbar() {
+ return ListenableBuilder(
+ listenable: _brightness,
+ builder: (context, _) {
+ return Theme(
+ data: ThemeData(brightness: _brightness.value),
+ child: AndroidTextEditingFloatingToolbar(
onCutPressed: _cut,
onCopyPressed: _copy,
onPastePressed: _paste,
onSelectAllPressed: _selectAll,
),
- iOSToolbarBuilder: (_) => IOSTextEditingFloatingToolbar(
- onCutPressed: _cut,
- onCopyPressed: _copy,
- onPastePressed: _paste,
- focalPoint: _overlayController.toolbarTopAnchor!,
- ),
- overlayController: _overlayController,
- ),
- ),
+ );
+ },
);
}
Widget _buildMountedToolbar() {
return MultiListenableBuilder(
listenables: {
- _doc,
- _composer!.selectionNotifier,
+ _docChangeSignal,
+ _composer.selectionNotifier,
},
builder: (_) {
- final selection = _composer!.selection;
+ final selection = _composer.selection;
if (selection == null) {
return const SizedBox();
}
return KeyboardEditingToolbar(
+ editor: _docEditor,
document: _doc,
- composer: _composer!,
+ composer: _composer,
commonOps: _docOps,
);
},
);
}
+
+ Widget _buildFloatingToolbar(BuildContext context) {
+ return EditorToolbar(
+ editorViewportKey: _viewportKey,
+ anchor: _selectionLayerLinks.expandedSelectionBoundsLink,
+ editorFocusNode: _editorFocusNode,
+ editor: _docEditor,
+ document: _doc,
+ composer: _composer,
+ closeToolbar: _hideEditorToolbar,
+ );
+ }
+
+ Widget _buildImageToolbar(BuildContext context) {
+ return ImageFormatToolbar(
+ anchor: _imageSelectionAnchor,
+ composer: _composer,
+ setWidth: (nodeId, width) {
+ print('Applying width $width to node $nodeId');
+ final node = _doc.getNodeById(nodeId)!;
+ final currentStyles =
+ SingleColumnLayoutComponentStyles.fromMetadata(node);
+ SingleColumnLayoutComponentStyles(
+ width: width,
+ padding: currentStyles.padding,
+ ).applyTo(node);
+
+ // TODO: schedule a presentation reflow so that the image changes size immediately (https://github.com/superlistapp/super_editor/issues/1529)
+ // Right now, nothing happens when pressing the button, unless we force a
+ // rebuild/reflow.
+ },
+ closeToolbar: _hideImageToolbar,
+ );
+ }
}
// Makes text light, for use during dark mode styling.
@@ -533,7 +544,7 @@ final _darkModeStyles = [
StyleRule(
BlockSelector.all,
(doc, docNode) {
- return {
+ return {
'textStyle': const TextStyle(
color: Color(0xFFCCCCCC),
),
@@ -543,7 +554,7 @@ final _darkModeStyles = [
StyleRule(
const BlockSelector('header1'),
(doc, docNode) {
- return {
+ return {
'textStyle': const TextStyle(
color: Color(0xFF888888),
),
@@ -553,7 +564,7 @@ final _darkModeStyles = [
StyleRule(
const BlockSelector('header2'),
(doc, docNode) {
- return {
+ return {
'textStyle': const TextStyle(
color: Color(0xFF888888),
),
diff --git a/lib/utils/super_editor/toolbar.dart b/lib/utils/super_editor/toolbar.dart
index 7939993bf..de50da096 100644
--- a/lib/utils/super_editor/toolbar.dart
+++ b/lib/utils/super_editor/toolbar.dart
@@ -1,6 +1,10 @@
import 'dart:math';
+//import 'package:example/logging.dart';
import 'package:flutter/material.dart';
+//import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:follow_the_leader/follow_the_leader.dart';
+import 'package:overlord/follow_the_leader.dart';
import 'package:super_editor/super_editor.dart';
/// Small toolbar that is intended to display near some selected
@@ -13,33 +17,40 @@ import 'package:super_editor/super_editor.dart';
class EditorToolbar extends StatefulWidget {
const EditorToolbar({
Key? key,
- required this.anchor,
+ required this.editorViewportKey,
required this.editorFocusNode,
required this.editor,
+ required this.document,
required this.composer,
+ required this.anchor,
required this.closeToolbar,
}) : super(key: key);
- /// [EditorToolbar] displays itself horizontally centered and
- /// slightly above the given [anchor] value.
+ /// [GlobalKey] that should be attached to a widget that wraps the viewport
+ /// area, which keeps the toolbar from appearing outside of the editor area.
+ final GlobalKey editorViewportKey;
+
+ /// A [LeaderLink] that should be attached to the boundary of the toolbar
+ /// focal area, such as wrapped around the user's selection area.
///
- /// [anchor] is a [ValueNotifier] so that [EditorToolbar] can
- /// reposition itself as the [Offset] value changes.
- final ValueNotifier anchor;
+ /// The toolbar is positioned relative to this anchor link.
+ final LeaderLink anchor;
/// The [FocusNode] attached to the editor to which this toolbar applies.
- final FocusNode? editorFocusNode;
+ final FocusNode editorFocusNode;
/// The [editor] is used to alter document content, such as
/// when the user selects a different block format for a
/// text blob, e.g., paragraph, header, blockquote, or
/// to apply styles to text.
- final DocumentEditor? editor;
+ final Editor? editor;
+
+ final Document document;
/// The [composer] provides access to the user's current
/// selection within the document, which dictates the
/// content that is altered by the toolbar's options.
- final DocumentComposer? composer;
+ final DocumentComposer composer;
/// Delegate that instructs the owner of this [EditorToolbar]
/// to close the toolbar, such as after submitting a URL
@@ -47,52 +58,73 @@ class EditorToolbar extends StatefulWidget {
final VoidCallback closeToolbar;
@override
- _EditorToolbarState createState() => _EditorToolbarState();
+ State createState() => _EditorToolbarState();
}
class _EditorToolbarState extends State {
+ late final FollowerAligner _toolbarAligner;
+ late FollowerBoundary _screenBoundary;
+
bool _showUrlField = false;
- FocusNode? _urlFocusNode;
- AttributedTextEditingController? _urlController;
+ late FocusNode _popoverFocusNode;
+ late FocusNode _urlFocusNode;
+ ImeAttributedTextEditingController? _urlController;
@override
void initState() {
super.initState();
+
+ _toolbarAligner = CupertinoPopoverToolbarAligner(widget.editorViewportKey);
+
+ _popoverFocusNode = FocusNode();
+
_urlFocusNode = FocusNode();
- _urlController = SingleLineAttributedTextEditingController(_applyLink);
+ _urlController = ImeAttributedTextEditingController(
+ controller: SingleLineAttributedTextEditingController(_applyLink)) //
+ ..onPerformActionPressed = _onPerformAction
+ ..text = AttributedText('https://');
+ }
+
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+
+ _screenBoundary = WidgetFollowerBoundary(
+ boundaryKey: widget.editorViewportKey,
+ devicePixelRatio: MediaQuery.devicePixelRatioOf(context),
+ );
}
@override
void dispose() {
- _urlFocusNode!.dispose();
+ _urlFocusNode.dispose();
_urlController!.dispose();
+ _popoverFocusNode.dispose();
super.dispose();
}
- /*
/// Returns true if the currently selected text node is capable of being
/// transformed into a different type text node, returns false if
/// multiple nodes are selected, no node is selected, or the selected
/// node is not a standard text block.
bool _isConvertibleNode() {
- final selection = widget.composer.selection;
+ final selection = widget.composer.selection!;
if (selection.base.nodeId != selection.extent.nodeId) {
return false;
}
- final selectedNode =
- widget.editor.document.getNodeById(selection.extent.nodeId);
+ final selectedNode = widget.document.getNodeById(selection.extent.nodeId);
return selectedNode is ParagraphNode || selectedNode is ListItemNode;
}
-
+
/// Returns the block type of the currently selected text node.
///
/// Throws an exception if the currently selected node is not a text node.
_TextType _getCurrentTextType() {
- final selectedNode = widget.editor.document
- .getNodeById(widget.composer.selection.extent.nodeId);
+ final selectedNode =
+ widget.document.getNodeById(widget.composer.selection!.extent.nodeId);
if (selectedNode is ParagraphNode) {
- final dynamic type = selectedNode.getMetadataValue('blockType');
+ final type = selectedNode.getMetadataValue('blockType');
if (type == header1Attribution) {
return _TextType.header1;
@@ -118,10 +150,10 @@ class _EditorToolbarState extends State {
///
/// Throws an exception if the currently selected node is not a text node.
TextAlign _getCurrentTextAlignment() {
- final selectedNode = widget.editor.document
- .getNodeById(widget.composer.selection.extent.nodeId);
+ final selectedNode =
+ widget.document.getNodeById(widget.composer.selection!.extent.nodeId);
if (selectedNode is ParagraphNode) {
- final dynamic align = selectedNode.getMetadataValue('textAlign');
+ final align = selectedNode.getMetadataValue('textAlign');
switch (align) {
case 'left':
return TextAlign.left;
@@ -143,13 +175,12 @@ class _EditorToolbarState extends State {
/// Returns true if a single text node is selected and that text node
/// is capable of respecting alignment, returns false otherwise.
bool _isTextAlignable() {
- final selection = widget.composer.selection;
+ final selection = widget.composer.selection!;
if (selection.base.nodeId != selection.extent.nodeId) {
return false;
}
- final selectedNode =
- widget.editor.document.getNodeById(selection.extent.nodeId);
+ final selectedNode = widget.document.getNodeById(selection.extent.nodeId);
return selectedNode is ParagraphNode;
}
@@ -158,7 +189,7 @@ class _EditorToolbarState extends State {
///
/// For example: convert a paragraph to a blockquote, or a header
/// to a list item.
- void _convertTextToNewType(_TextType newType) {
+ void _convertTextToNewType(_TextType? newType) {
final existingTextType = _getCurrentTextType();
if (existingTextType == newType) {
@@ -167,53 +198,53 @@ class _EditorToolbarState extends State {
}
if (_isListItem(existingTextType) && _isListItem(newType)) {
- widget.editor.executeCommand(
- ChangeListItemTypeCommand(
- nodeId: widget.composer.selection.extent.nodeId,
+ widget.editor!.execute([
+ ChangeListItemTypeRequest(
+ nodeId: widget.composer.selection!.extent.nodeId,
newType: newType == _TextType.orderedListItem
? ListItemType.ordered
: ListItemType.unordered,
),
- );
+ ]);
} else if (_isListItem(existingTextType) && !_isListItem(newType)) {
- widget.editor.executeCommand(
- ConvertListItemToParagraphCommand(
- nodeId: widget.composer.selection.extent.nodeId,
- paragraphMetadata: {
+ widget.editor!.execute([
+ ConvertListItemToParagraphRequest(
+ nodeId: widget.composer.selection!.extent.nodeId,
+ paragraphMetadata: {
'blockType': _getBlockTypeAttribution(newType),
},
),
- );
+ ]);
} else if (!_isListItem(existingTextType) && _isListItem(newType)) {
- widget.editor.executeCommand(
- ConvertParagraphToListItemCommand(
- nodeId: widget.composer.selection.extent.nodeId,
+ widget.editor!.execute([
+ ConvertParagraphToListItemRequest(
+ nodeId: widget.composer.selection!.extent.nodeId,
type: newType == _TextType.orderedListItem
? ListItemType.ordered
: ListItemType.unordered,
),
- );
+ ]);
} else {
// Apply a new block type to an existing paragraph node.
- final existingNode = widget.editor.document
- .getNodeById(widget.composer.selection.extent.nodeId)
- as ParagraphNode;
- existingNode.putMetadataValue(
- 'blockType', _getBlockTypeAttribution(newType));
+ widget.editor!.execute([
+ ChangeParagraphBlockTypeRequest(
+ nodeId: widget.composer.selection!.extent.nodeId,
+ blockType: _getBlockTypeAttribution(newType),
+ ),
+ ]);
}
}
-
/// Returns true if the given [_TextType] represents an
/// ordered or unordered list item, returns false otherwise.
- bool _isListItem(_TextType type) {
+ bool _isListItem(_TextType? type) {
return type == _TextType.orderedListItem ||
type == _TextType.unorderedListItem;
}
/// Returns the text [Attribution] associated with the given
/// [_TextType], e.g., [_TextType.header1] -> [header1Attribution].
- Attribution _getBlockTypeAttribution(_TextType newType) {
+ Attribution? _getBlockTypeAttribution(_TextType? newType) {
switch (newType) {
case _TextType.header1:
return header1Attribution;
@@ -228,36 +259,35 @@ class _EditorToolbarState extends State {
return null;
}
}
- */
/// Toggles bold styling for the current selected text.
void _toggleBold() {
- widget.editor!.executeCommand(
- ToggleTextAttributionsCommand(
- documentSelection: widget.composer!.selection!,
+ widget.editor!.execute([
+ ToggleTextAttributionsRequest(
+ documentRange: widget.composer.selection!,
attributions: {boldAttribution},
),
- );
+ ]);
}
/// Toggles italic styling for the current selected text.
void _toggleItalics() {
- widget.editor!.executeCommand(
- ToggleTextAttributionsCommand(
- documentSelection: widget.composer!.selection!,
+ widget.editor!.execute([
+ ToggleTextAttributionsRequest(
+ documentRange: widget.composer.selection!,
attributions: {italicsAttribution},
),
- );
+ ]);
}
/// Toggles strikethrough styling for the current selected text.
void _toggleStrikethrough() {
- widget.editor!.executeCommand(
- ToggleTextAttributionsCommand(
- documentSelection: widget.composer!.selection!,
+ widget.editor!.execute([
+ ToggleTextAttributionsRequest(
+ documentRange: widget.composer.selection!,
attributions: {strikethroughAttribution},
),
- );
+ ]);
}
/// Returns true if the current text selection includes part
@@ -276,16 +306,15 @@ class _EditorToolbarState extends State {
/// Returns any link-based [AttributionSpan]s that appear partially
/// or wholly within the current text selection.
Set _getSelectedLinkSpans() {
- final selection = widget.composer!.selection!;
+ final selection = widget.composer.selection!;
final baseOffset = (selection.base.nodePosition as TextPosition).offset;
final extentOffset = (selection.extent.nodePosition as TextPosition).offset;
final selectionStart = min(baseOffset, extentOffset);
final selectionEnd = max(baseOffset, extentOffset);
- final selectionRange =
- SpanRange(start: selectionStart, end: selectionEnd - 1);
+ final selectionRange = SpanRange(selectionStart, selectionEnd - 1);
- final textNode = widget.editor!.document
- .getNodeById(selection.extent.nodeId) as TextNode;
+ final textNode =
+ widget.document.getNodeById(selection.extent.nodeId) as TextNode;
final text = textNode.text;
final overlappingLinkAttributions = text.getAttributionSpansInRange(
@@ -300,16 +329,15 @@ class _EditorToolbarState extends State {
/// Takes appropriate action when the toolbar's link button is
/// pressed.
void _onLinkPressed() {
- final selection = widget.composer!.selection!;
+ final selection = widget.composer.selection!;
final baseOffset = (selection.base.nodePosition as TextPosition).offset;
final extentOffset = (selection.extent.nodePosition as TextPosition).offset;
final selectionStart = min(baseOffset, extentOffset);
final selectionEnd = max(baseOffset, extentOffset);
- final selectionRange =
- SpanRange(start: selectionStart, end: selectionEnd - 1);
+ final selectionRange = SpanRange(selectionStart, selectionEnd - 1);
- final textNode = widget.editor!.document
- .getNodeById(selection.extent.nodeId) as TextNode;
+ final textNode =
+ widget.document.getNodeById(selection.extent.nodeId) as TextNode;
final text = textNode.text;
final overlappingLinkAttributions = text.getAttributionSpansInRange(
@@ -341,15 +369,14 @@ class _EditorToolbarState extends State {
// the entire link attribution.
text.removeAttribution(
overlappingLinkSpan.attribution,
- SpanRange(
- start: overlappingLinkSpan.start, end: overlappingLinkSpan.end),
+ SpanRange(overlappingLinkSpan.start, overlappingLinkSpan.end),
);
}
} else {
// There are no other links in the selection. Show the URL text field.
setState(() {
_showUrlField = true;
- _urlFocusNode!.requestFocus();
+ _urlFocusNode.requestFocus();
});
}
}
@@ -359,7 +386,7 @@ class _EditorToolbarState extends State {
void _applyLink() {
final url = _urlController!.text.text;
- final selection = widget.composer!.selection!;
+ final selection = widget.composer.selection!;
final baseOffset = (selection.base.nodePosition as TextPosition).offset;
final extentOffset = (selection.extent.nodePosition as TextPosition).offset;
final selectionStart = min(baseOffset, extentOffset);
@@ -367,8 +394,8 @@ class _EditorToolbarState extends State {
final selectionRange =
TextRange(start: selectionStart, end: selectionEnd - 1);
- final textNode = widget.editor!.document
- .getNodeById(selection.extent.nodeId) as TextNode;
+ final textNode =
+ widget.document.getNodeById(selection.extent.nodeId) as TextNode;
final text = textNode.text;
final trimmedRange = _trimTextRangeWhitespace(text, selectionRange);
@@ -383,8 +410,8 @@ class _EditorToolbarState extends State {
_urlController!.clear();
setState(() {
_showUrlField = false;
- _urlFocusNode!
- .unfocus(disposition: UnfocusDisposition.previouslyFocusedChild);
+ _urlFocusNode.unfocus(
+ disposition: UnfocusDisposition.previouslyFocusedChild);
widget.closeToolbar();
});
}
@@ -403,17 +430,16 @@ class _EditorToolbarState extends State {
endOffset -= 1;
}
- return SpanRange(start: startOffset, end: endOffset);
+ return SpanRange(startOffset, endOffset);
}
- /*
/// Changes the alignment of the current selected text node
/// to reflect [newAlignment].
- void _changeAlignment(TextAlign newAlignment) {
+ void _changeAlignment(TextAlign? newAlignment) {
if (newAlignment == null) {
return;
}
- String newAlignmentValue;
+ String? newAlignmentValue;
switch (newAlignment) {
case TextAlign.left:
case TextAlign.start:
@@ -431,8 +457,8 @@ class _EditorToolbarState extends State {
break;
}
- final selectedNode = widget.editor.document
- .getNodeById(widget.composer.selection.extent.nodeId) as ParagraphNode;
+ final selectedNode = widget.document
+ .getNodeById(widget.composer.selection!.extent.nodeId) as ParagraphNode;
selectedNode.putMetadataValue('textAlign', newAlignmentValue);
}
@@ -441,190 +467,199 @@ class _EditorToolbarState extends State {
String _getTextTypeName(_TextType textType) {
switch (textType) {
case _TextType.header1:
+ // return AppLocalizations.of(context)!.labelHeader1;
return 'Header 1';
case _TextType.header2:
+ // return AppLocalizations.of(context)!.labelHeader2;
return 'Header 2';
case _TextType.header3:
+ // return AppLocalizations.of(context)!.labelHeader3;
return 'Header 3';
case _TextType.paragraph:
+ // return AppLocalizations.of(context)!.labelParagraph;
return 'Paragraph';
case _TextType.blockquote:
+ // return AppLocalizations.of(context)!.labelBlockquote;
return 'Blockquote';
case _TextType.orderedListItem:
+ // return AppLocalizations.of(context)!.labelOrderedListItem;
return 'Ordered List Item';
case _TextType.unorderedListItem:
+ // return AppLocalizations.of(context)!.labelUnorderedListItem;
return 'Unordered List Item';
}
-
- return '';
}
- */
+
+ void _onPerformAction(TextInputAction action) {
+ if (action == TextInputAction.done) {
+ _applyLink();
+ }
+ }
@override
Widget build(BuildContext context) {
- return Stack(
+ return BuildInOrder(
children: [
- // Conditionally display the URL text field below
- // the standard toolbar.
- if (_showUrlField)
- Positioned(
- left: widget.anchor.value!.dx,
- top: widget.anchor.value!.dy,
- child: FractionalTranslation(
- translation: const Offset(-0.5, 0.0),
- child: _buildUrlField(),
- ),
- ),
- _PositionedToolbar(
- anchor: widget.anchor,
- composer: widget.composer,
- child: ValueListenableBuilder(
- valueListenable: widget.composer!.selectionNotifier,
- builder: (context, selection, child) {
- if (selection == null) {
- return const SizedBox();
- }
- if (selection.extent.nodePosition is! TextPosition) {
- // The user selected non-text content. This toolbar is probably
- // about to disappear. Until then, build nothing, because the
- // toolbar needs to inspect selected text to build correctly.
- return const SizedBox();
- }
-
- return _buildToolbar();
- },
+ FollowerFadeOutBeyondBoundary(
+ link: widget.anchor,
+ boundary: _screenBoundary,
+ child: Follower.withAligner(
+ link: widget.anchor,
+ aligner: _toolbarAligner,
+ boundary: _screenBoundary,
+ showWhenUnlinked: false,
+ child: _buildToolbars(),
),
),
],
);
}
- Widget _buildToolbar() {
- return Material(
- shape: const StadiumBorder(),
- elevation: 5,
- clipBehavior: Clip.hardEdge,
- child: SizedBox(
- height: 40,
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.stretch,
- children: [
- /*
- // https://github.com/superlistapp/super_editor/issues/689
- // https://github.com/flutter/flutter/issues/106923
- // Only allow the user to select a new type of text node if
- // the currently selected node can be converted.
- if (_isConvertibleNode()) ...[
- Tooltip(
- message: 'Text Block Type',
- child: DropdownButton<_TextType>(
- value: _getCurrentTextType(),
- items: _TextType.values
- .map((textType) => DropdownMenuItem<_TextType>(
- value: textType,
- child: Padding(
- padding: const EdgeInsets.only(left: 16.0),
- child: Text(_getTextTypeName(textType)),
- ),
- ))
- .toList(),
- icon: const Icon(Icons.arrow_drop_down),
- style: TextStyle(
- color: Theme.of(context).brightness == Brightness.dark
- ? Colors.white
- : Colors.black,
- fontSize: 12,
- ),
- underline: const SizedBox(),
- elevation: 0,
- itemHeight: 48,
- onChanged: _convertTextToNewType,
- ),
- ),
- _buildVerticalDivider(),
- ],
- */
- Center(
- child: IconButton(
- onPressed: _toggleBold,
- icon: const Icon(Icons.format_bold),
- splashRadius: 16,
- tooltip: 'Bold',
- ),
- ),
- Center(
- child: IconButton(
- onPressed: _toggleItalics,
- icon: const Icon(Icons.format_italic),
- splashRadius: 16,
- tooltip: 'Italics',
- ),
- ),
- Center(
- child: IconButton(
- onPressed: _toggleStrikethrough,
- icon: const Icon(Icons.strikethrough_s),
- splashRadius: 16,
- tooltip: 'Strikethrough',
- ),
- ),
- Center(
- child: IconButton(
- onPressed: _areMultipleLinksSelected() ? null : _onLinkPressed,
- icon: const Icon(Icons.link),
- color: _isSingleLinkSelected()
- ? const Color(0xFF007AFF)
- : IconTheme.of(context).color,
- splashRadius: 16,
- tooltip: 'Link',
- ),
- ),
- // Only display alignment controls if the currently selected text
- // node respects alignment. List items, for example, do not.
- /*
- if (_isTextAlignable()) ...[
- _buildVerticalDivider(),
- Tooltip(
- message: 'Text Alignment',
- child: DropdownButton(
- value: _getCurrentTextAlignment(),
- items: [
- TextAlign.left,
- TextAlign.center,
- TextAlign.right,
- TextAlign.justify
- ]
- .map((textAlign) => DropdownMenuItem(
- value: textAlign,
- child: Padding(
- padding: const EdgeInsets.only(left: 8.0),
- child: Icon(_buildTextAlignIcon(textAlign)),
- ),
- ))
- .toList(),
- icon: const Icon(Icons.arrow_drop_down),
- style: const TextStyle(
- color: Colors.black,
- fontSize: 12,
- ),
- underline: const SizedBox(),
- elevation: 0,
- itemHeight: 48,
- onChanged: _changeAlignment,
- ),
- ),
- ],
- _buildVerticalDivider(),
- Center(
- child: IconButton(
- onPressed: () {},
- icon: const Icon(Icons.more_vert),
- splashRadius: 16,
- tooltip: 'More Options',
- ),
- ),
- */
+ Widget _buildToolbars() {
+ return SuperEditorPopover(
+ popoverFocusNode: _popoverFocusNode,
+ editorFocusNode: widget.editorFocusNode,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ _buildToolbar(),
+ if (_showUrlField) ...[
+ const SizedBox(height: 8),
+ _buildUrlField(),
],
+ ],
+ ),
+ );
+ }
+
+ Widget _buildToolbar() {
+ return IntrinsicWidth(
+ child: Material(
+ shape: const StadiumBorder(),
+ elevation: 5,
+ clipBehavior: Clip.hardEdge,
+ child: SizedBox(
+ height: 40,
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ // Only allow the user to select a new type of text node if
+ // the currently selected node can be converted.
+ if (_isConvertibleNode()) ...[
+ Tooltip(
+ //message: AppLocalizations.of(context)!.labelTextBlockType,
+ message: 'Block Type',
+ child: DropdownButton<_TextType>(
+ value: _getCurrentTextType(),
+ items: _TextType.values
+ .map((textType) => DropdownMenuItem<_TextType>(
+ value: textType,
+ child: Padding(
+ padding: const EdgeInsets.only(left: 16.0),
+ child: Text(_getTextTypeName(textType)),
+ ),
+ ))
+ .toList(),
+ icon: const Icon(Icons.arrow_drop_down),
+ style: const TextStyle(
+ color: Colors.black,
+ fontSize: 12,
+ ),
+ underline: const SizedBox(),
+ elevation: 0,
+ itemHeight: 48,
+ onChanged: _convertTextToNewType,
+ ),
+ ),
+ _buildVerticalDivider(),
+ ],
+ Center(
+ child: IconButton(
+ onPressed: _toggleBold,
+ icon: const Icon(Icons.format_bold),
+ splashRadius: 16,
+ //tooltip: AppLocalizations.of(context)!.Bold,
+ tooltip: 'Bold',
+ ),
+ ),
+ Center(
+ child: IconButton(
+ onPressed: _toggleItalics,
+ icon: const Icon(Icons.format_italic),
+ splashRadius: 16,
+ //tooltip: AppLocalizations.of(context)!.labelItalics,
+ tooltip: 'Italics',
+ ),
+ ),
+ Center(
+ child: IconButton(
+ onPressed: _toggleStrikethrough,
+ icon: const Icon(Icons.strikethrough_s),
+ splashRadius: 16,
+ //tooltip: AppLocalizations.of(context)!.labelStrikethrough,
+ tooltip: 'Strikethrough',
+ ),
+ ),
+ Center(
+ child: IconButton(
+ onPressed:
+ _areMultipleLinksSelected() ? null : _onLinkPressed,
+ icon: const Icon(Icons.link),
+ color: _isSingleLinkSelected()
+ ? const Color(0xFF007AFF)
+ : IconTheme.of(context).color,
+ splashRadius: 16,
+ //tooltip: AppLocalizations.of(context)!.labelLink,
+ tooltip: 'Link',
+ ),
+ ),
+ // Only display alignment controls if the currently selected text
+ // node respects alignment. List items, for example, do not.
+ if (_isTextAlignable()) ...[
+ _buildVerticalDivider(),
+ Tooltip(
+ //message: AppLocalizations.of(context)!.labelTextAlignment,
+ message: 'Text Alignment',
+ child: DropdownButton(
+ value: _getCurrentTextAlignment(),
+ items: [
+ TextAlign.left,
+ TextAlign.center,
+ TextAlign.right,
+ TextAlign.justify
+ ]
+ .map((textAlign) => DropdownMenuItem(
+ value: textAlign,
+ child: Padding(
+ padding: const EdgeInsets.only(left: 8.0),
+ child: Icon(_buildTextAlignIcon(textAlign)),
+ ),
+ ))
+ .toList(),
+ icon: const Icon(Icons.arrow_drop_down),
+ style: const TextStyle(
+ color: Colors.black,
+ fontSize: 12,
+ ),
+ underline: const SizedBox(),
+ elevation: 0,
+ itemHeight: 48,
+ onChanged: _changeAlignment,
+ ),
+ ),
+ ],
+ _buildVerticalDivider(),
+ Center(
+ child: IconButton(
+ onPressed: () {},
+ icon: const Icon(Icons.more_vert),
+ splashRadius: 16,
+ //tooltip: AppLocalizations.of(context)!.labelMoreOptions,
+ tooltip: 'More Options',
+ ),
+ ),
+ ],
+ ),
),
),
);
@@ -642,9 +677,9 @@ class _EditorToolbarState extends State {
child: Row(
children: [
Expanded(
- child: FocusWithCustomParent(
+ child: Focus(
focusNode: _urlFocusNode,
- parentFocusNode: widget.editorFocusNode,
+ parentNode: _popoverFocusNode,
// We use a SuperTextField instead of a TextField because TextField
// automatically re-parents its FocusNode, which causes #609. Flutter
// #106923 tracks the TextField issue.
@@ -656,19 +691,17 @@ class _EditorToolbarState extends State {
inputSource: TextInputSource.ime,
hintBehavior: HintBehavior.displayHintUntilTextEntered,
hintBuilder: (context) {
- return Text(
- 'Enter a url...',
- style: const TextStyle(
+ return const Text(
+ 'enter a url...',
+ style: TextStyle(
color: Colors.grey,
fontSize: 16,
),
);
},
textStyleBuilder: (_) {
- return TextStyle(
- color: Theme.of(context).brightness == Brightness.dark
- ? Colors.white
- : Colors.black,
+ return const TextStyle(
+ color: Colors.black,
fontSize: 16,
);
},
@@ -682,7 +715,7 @@ class _EditorToolbarState extends State {
padding: EdgeInsets.zero,
onPressed: () {
setState(() {
- _urlFocusNode!.unfocus();
+ _urlFocusNode.unfocus();
_showUrlField = false;
_urlController!.clear();
});
@@ -694,7 +727,6 @@ class _EditorToolbarState extends State {
);
}
- /*
Widget _buildVerticalDivider() {
return Container(
width: 1,
@@ -702,7 +734,6 @@ class _EditorToolbarState extends State {
);
}
-
IconData _buildTextAlignIcon(TextAlign align) {
switch (align) {
case TextAlign.left:
@@ -716,13 +747,9 @@ class _EditorToolbarState extends State {
case TextAlign.justify:
return Icons.format_align_justify;
}
-
- return null;
}
- */
}
-/*
enum _TextType {
header1,
header2,
@@ -732,7 +759,6 @@ enum _TextType {
orderedListItem,
unorderedListItem,
}
-*/
/// Small toolbar that is intended to display over an image and
/// offer controls to expand or contract the size of the image.
@@ -760,7 +786,7 @@ class ImageFormatToolbar extends StatefulWidget {
/// The [composer] provides access to the user's current
/// selection within the document, which dictates the
/// content that is altered by the toolbar's options.
- final DocumentComposer? composer;
+ final DocumentComposer composer;
/// Callback that should update the width of the component with
/// the given [nodeId] to match the given [width].
@@ -771,16 +797,16 @@ class ImageFormatToolbar extends StatefulWidget {
final VoidCallback closeToolbar;
@override
- _ImageFormatToolbarState createState() => _ImageFormatToolbarState();
+ State createState() => _ImageFormatToolbarState();
}
class _ImageFormatToolbarState extends State {
void _makeImageConfined() {
- widget.setWidth(widget.composer!.selection!.extent.nodeId, null);
+ widget.setWidth(widget.composer.selection!.extent.nodeId, null);
}
void _makeImageFullBleed() {
- widget.setWidth(widget.composer!.selection!.extent.nodeId, double.infinity);
+ widget.setWidth(widget.composer.selection!.extent.nodeId, double.infinity);
}
@override
@@ -789,8 +815,9 @@ class _ImageFormatToolbarState extends State {
anchor: widget.anchor,
composer: widget.composer,
child: ValueListenableBuilder(
- valueListenable: widget.composer!.selectionNotifier,
+ valueListenable: widget.composer.selectionNotifier,
builder: (context, selection, child) {
+ //appLog.fine("Building image toolbar. Selection: $selection");
if (selection == null) {
return const SizedBox();
}
@@ -825,6 +852,7 @@ class _ImageFormatToolbarState extends State {
onPressed: _makeImageConfined,
icon: const Icon(Icons.photo_size_select_large),
splashRadius: 16,
+ //tooltip: AppLocalizations.of(context)!.labelBold,
tooltip: 'Bold',
),
),
@@ -833,6 +861,7 @@ class _ImageFormatToolbarState extends State {
onPressed: _makeImageFullBleed,
icon: const Icon(Icons.photo_size_select_actual),
splashRadius: 16,
+ //tooltip: AppLocalizations.of(context)!.labelItalics,
tooltip: 'Italics',
),
),
@@ -853,7 +882,7 @@ class _PositionedToolbar extends StatelessWidget {
}) : super(key: key);
final ValueNotifier anchor;
- final DocumentComposer? composer;
+ final DocumentComposer composer;
final Widget child;
@override
@@ -861,12 +890,16 @@ class _PositionedToolbar extends StatelessWidget {
return ValueListenableBuilder(
valueListenable: anchor,
builder: (context, offset, _) {
- if (offset == null || composer!.selection == null) {
+ //appLog.fine(
+ // "(Re)Building _PositionedToolbar widget due to anchor change");
+ if (offset == null || composer.selection == null) {
+ //appLog.fine("Anchor is null. Building an empty box.");
// When no anchor position is available, or the user hasn't
// selected any text, show nothing.
return const SizedBox();
}
+ //appLog.fine("Anchor is non-null: $offset, child: $child");
return SizedBox.expand(
child: Stack(
children: [
diff --git a/pubspec.lock b/pubspec.lock
index 624115ec5..94910228d 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -21,10 +21,10 @@ packages:
dependency: transitive
description:
name: archive
- sha256: "7e0d52067d05f2e0324268097ba723b71cb41ac8a6a2b24d1edf9c536b987b03"
+ sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b"
url: "https://pub.dev"
source: hosted
- version: "3.4.6"
+ version: "3.4.9"
args:
dependency: transitive
description:
@@ -42,12 +42,13 @@ packages:
source: hosted
version: "2.11.0"
attributed_text:
- dependency: transitive
+ dependency: "direct overridden"
description:
- name: attributed_text
- sha256: e43495051b63e6cdbe96aa62123974074cca109d9c56f74ce2ffaec8060e044e
- url: "https://pub.dev"
- source: hosted
+ path: attributed_text
+ ref: stable
+ resolved-ref: c040c690f1dc0f7c482d8ece02622c200cb8e1b1
+ url: "https://github.com/superlistapp/super_editor"
+ source: git
version: "0.2.2"
barcode:
dependency: transitive
@@ -102,10 +103,10 @@ packages:
dependency: transitive
description:
name: build_daemon
- sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
+ sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1"
url: "https://pub.dev"
source: hosted
- version: "4.0.0"
+ version: "4.0.1"
build_resolvers:
dependency: transitive
description:
@@ -118,10 +119,10 @@ packages:
dependency: "direct dev"
description:
name: build_runner
- sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b"
+ sha256: "67d591d602906ef9201caf93452495ad1812bea2074f04e25dbd7c133785821b"
url: "https://pub.dev"
source: hosted
- version: "2.4.6"
+ version: "2.4.7"
build_runner_core:
dependency: transitive
description:
@@ -142,26 +143,42 @@ packages:
dependency: "direct main"
description:
name: built_value
- sha256: a8de5955205b4d1dbbbc267daddf2178bd737e4bab8987c04a500478c9651e74
+ sha256: "69acb7007eb2a31dc901512bfe0f7b767168be34cb734835d54c070bfa74c1b2"
url: "https://pub.dev"
source: hosted
- version: "8.6.3"
+ version: "8.8.0"
built_value_generator:
dependency: "direct dev"
description:
name: built_value_generator
- sha256: a7a20bd4a943316c46c6e89b1a5631a2dace50ca6742b73d0b719fd243a7da00
+ sha256: "78680d78a6cab222fc5725ffa21065a05bba951452ae84d08b3c0e150fd3f9f6"
url: "https://pub.dev"
source: hosted
- version: "8.6.3"
+ version: "8.8.0"
cached_network_image:
dependency: "direct main"
description:
name: cached_network_image
- sha256: ebab9f6c55a7aa8d62cdfe0877f8b5ce806c1956b0a244ba39fcadeb0e1aad85
+ sha256: f98972704692ba679db144261172a8e20feb145636c617af0eb4022132a6797f
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.3.0"
+ cached_network_image_platform_interface:
+ dependency: transitive
+ description:
+ name: cached_network_image_platform_interface
+ sha256: "56aa42a7a01e3c9db8456d9f3f999931f1e05535b5a424271e9a38cabf066613"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
+ cached_network_image_web:
+ dependency: transitive
+ description:
+ name: cached_network_image_web
+ sha256: "759b9a9f8f6ccbb66c185df805fac107f05730b1dab9c64626d1008cca532257"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.0"
characters:
dependency: transitive
description:
@@ -222,18 +239,18 @@ packages:
dependency: transitive
description:
name: code_builder
- sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677"
+ sha256: b2151ce26a06171005b379ecff6e08d34c470180ffe16b8e14b6d52be292b55f
url: "https://pub.dev"
source: hosted
- version: "4.7.0"
+ version: "4.8.0"
collection:
dependency: "direct main"
description:
name: collection
- sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
+ sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.dev"
source: hosted
- version: "1.17.2"
+ version: "1.18.0"
console:
dependency: transitive
description:
@@ -262,18 +279,18 @@ packages:
dependency: transitive
description:
name: coverage
- sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097"
+ sha256: "595a29b55ce82d53398e1bcc2cba525d7bd7c59faeb2d2540e9d42c390cfeeeb"
url: "https://pub.dev"
source: hosted
- version: "1.6.3"
+ version: "1.6.4"
cross_file:
dependency: transitive
description:
name: cross_file
- sha256: "445db18de832dba8d851e287aff8ccf169bed30d2e94243cb54c7d2f1ed2142c"
+ sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e
url: "https://pub.dev"
source: hosted
- version: "0.3.3+6"
+ version: "0.3.3+8"
crypto:
dependency: transitive
description:
@@ -310,10 +327,10 @@ packages:
dependency: "direct main"
description:
name: device_info_plus
- sha256: "7035152271ff67b072a211152846e9f1259cf1be41e34cd3e0b5463d2d6b8419"
+ sha256: "0042cb3b2a76413ea5f8a2b40cec2a33e01d0c937e91f0f7c211fde4f7739ba6"
url: "https://pub.dev"
source: hosted
- version: "9.1.0"
+ version: "9.1.1"
device_info_plus_platform_interface:
dependency: transitive
description:
@@ -423,14 +440,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
- flutter_blurhash:
- dependency: transitive
- description:
- name: flutter_blurhash
- sha256: "05001537bd3fac7644fa6558b09ec8c0a3f2eba78c0765f88912882b1331a5c6"
- url: "https://pub.dev"
- source: hosted
- version: "0.7.0"
flutter_cache_manager:
dependency: transitive
description:
@@ -469,10 +478,10 @@ packages:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
- sha256: f185ac890306b5779ecbd611f52502d8d4d63d27703ef73161ca0407e815f02c
+ sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da
url: "https://pub.dev"
source: hosted
- version: "2.0.16"
+ version: "2.0.17"
flutter_redux:
dependency: "direct main"
description:
@@ -485,10 +494,10 @@ packages:
dependency: "direct main"
description:
name: flutter_slidable
- sha256: cc4231579e3eae41ae166660df717f4bad1359c87f4a4322ad8ba1befeb3d2be
+ sha256: "19ed4813003a6ff4e9c6bcce37e792a2a358919d7603b2b31ff200229191e44c"
url: "https://pub.dev"
source: hosted
- version: "3.0.0"
+ version: "3.0.1"
flutter_staggered_grid_view:
dependency: "direct main"
description:
@@ -527,10 +536,10 @@ packages:
dependency: transitive
description:
name: follow_the_leader
- sha256: "40112c4fa8fdc9e60c3350f09e5b9c86e1205f4f8427feee15ef8da4c60c635c"
+ sha256: "71f4bfca904974a98d21558bbf7489e1262da6ac46de912791fe84cf6516b9ae"
url: "https://pub.dev"
source: hosted
- version: "0.0.4+5"
+ version: "0.0.4+7"
frontend_server_client:
dependency: transitive
description:
@@ -580,18 +589,18 @@ packages:
dependency: transitive
description:
name: google_sign_in_ios
- sha256: "974944859f9cd40eb8a15b3fe8efb2d47fb7e99438f763f61a1ccd28d74ff4ce"
+ sha256: "81495441405c138e3c638f5097bebaa0db644567b3976e08944cfb8926ff2e6d"
url: "https://pub.dev"
source: hosted
- version: "5.6.4"
+ version: "5.6.5"
google_sign_in_platform_interface:
dependency: transitive
description:
name: google_sign_in_platform_interface
- sha256: "35ceee5f0eadc1c07b0b4af7553246e315c901facbb7d3dadf734ba2693ceec4"
+ sha256: e10eaaa30a0cb03af12dd324fb2e630ac7e9d854d0530f7a87a4d825031f9a4a
url: "https://pub.dev"
source: hosted
- version: "2.4.2"
+ version: "2.4.3"
google_sign_in_web:
dependency: transitive
description:
@@ -692,10 +701,10 @@ packages:
dependency: transitive
description:
name: image_picker_android
- sha256: "0c7b83bbe2980c8a8e36e974f055e11e51675784e13a4762889feed0f3937ff2"
+ sha256: d6a6e78821086b0b737009b09363018309bbc6de3fd88cc5c26bc2bb44a4957f
url: "https://pub.dev"
source: hosted
- version: "0.8.8+1"
+ version: "0.8.8+2"
image_picker_for_web:
dependency: transitive
description:
@@ -708,10 +717,10 @@ packages:
dependency: transitive
description:
name: image_picker_ios
- sha256: c5538cacefacac733c724be7484377923b476216ad1ead35a0d2eadcdc0fc497
+ sha256: "76ec722aeea419d03aa915c2c96bf5b47214b053899088c9abb4086ceecf97a7"
url: "https://pub.dev"
source: hosted
- version: "0.8.8+2"
+ version: "0.8.8+4"
image_picker_linux:
dependency: transitive
description:
@@ -764,10 +773,10 @@ packages:
dependency: transitive
description:
name: in_app_purchase_android
- sha256: "63997b855f10799a1022939bbf02e3f59b6f400f4deee858f46fd528df5f5fab"
+ sha256: c4b84caa4e2c7ffebda444c5033fd8423cc3a45a6e1066929bbbcd4daf665db5
url: "https://pub.dev"
source: hosted
- version: "0.3.0+13"
+ version: "0.3.0+15"
in_app_purchase_platform_interface:
dependency: transitive
description:
@@ -780,26 +789,26 @@ packages:
dependency: transitive
description:
name: in_app_purchase_storekit
- sha256: "88afd256c7605d431f0ce29d0161f9554851f90ecb92ceb9e18196c4e7858d52"
+ sha256: "29526f5ce85bd908b4cacdadb2e8ef299bccbb516b90d2881805343f868502ab"
url: "https://pub.dev"
source: hosted
- version: "0.3.6+7"
+ version: "0.3.7"
in_app_review:
dependency: "direct main"
description:
name: in_app_review
- sha256: "16328b8202d36522322b95804ae5d975577aa9f584d634985849ba1099645850"
+ sha256: "41ec6f30427ab09eb6ae1c85c4a2a624a145fc5d726f023de4d97170ec9e5466"
url: "https://pub.dev"
source: hosted
- version: "2.0.6"
+ version: "2.0.8"
in_app_review_platform_interface:
dependency: transitive
description:
name: in_app_review_platform_interface
- sha256: b12ec9aaf6b34d3a72aa95895eb252b381896246bdad4ef378d444affe8410ef
+ sha256: fed2c755f2125caa9ae10495a3c163aa7fab5af3585a9c62ef4a6920c5b45f10
url: "https://pub.dev"
source: hosted
- version: "2.0.4"
+ version: "2.0.5"
intl:
dependency: "direct main"
description:
@@ -844,10 +853,10 @@ packages:
dependency: transitive
description:
name: linkify
- sha256: bdfbdafec6cdc9cd0ebb333a868cafc046714ad508e48be8095208c54691d959
+ sha256: "4139ea77f4651ab9c315b577da2dd108d9aa0bd84b5d03d33323f1970c645832"
url: "https://pub.dev"
source: hosted
- version: "4.1.0"
+ version: "5.0.0"
local_auth:
dependency: "direct main"
description:
@@ -860,18 +869,18 @@ packages:
dependency: transitive
description:
name: local_auth_android
- sha256: "9ad0b1ffa6f04f4d91e38c2d4c5046583e23f4cae8345776a994e8670df57fb1"
+ sha256: df4ccb3193525b8a60c78a5ca7bf188a47705bcf77bcc837a6b2cf6da64ae0e2
url: "https://pub.dev"
source: hosted
- version: "1.0.34"
+ version: "1.0.35"
local_auth_ios:
dependency: transitive
description:
name: local_auth_ios
- sha256: "26a8d1ad0b4ef6f861d29921be8383000fda952e323a5b6752cf82ca9cf9a7a9"
+ sha256: "8293faf72ef0ac4710f209edd03916c2d4c1eeab0483bdcf9b2e659c2f7d737b"
url: "https://pub.dev"
source: hosted
- version: "1.1.4"
+ version: "1.1.5"
local_auth_platform_interface:
dependency: transitive
description:
@@ -940,10 +949,10 @@ packages:
dependency: transitive
description:
name: meta
- sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
+ sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
url: "https://pub.dev"
source: hosted
- version: "1.9.1"
+ version: "1.10.0"
mime:
dependency: transitive
description:
@@ -964,10 +973,10 @@ packages:
dependency: "direct dev"
description:
name: msix
- sha256: "6e76e2491d5c809d784ce2b68e6c3426097fb5c68e61fe121c8c3341ab89bf46"
+ sha256: "519b183d15dc9f9c594f247e2d2339d855cf0eaacc30e19b128e14f3ecc62047"
url: "https://pub.dev"
source: hosted
- version: "3.16.4"
+ version: "3.16.7"
navigation_builder:
dependency: "direct overridden"
description:
@@ -988,10 +997,10 @@ packages:
dependency: transitive
description:
name: octo_image
- sha256: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143"
+ sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d"
url: "https://pub.dev"
source: hosted
- version: "1.0.2"
+ version: "2.0.0"
overflow_view:
dependency: "direct main"
description:
@@ -1028,10 +1037,10 @@ packages:
dependency: transitive
description:
name: package_info_plus
- sha256: "7e76fad405b3e4016cd39d08f455a4eb5199723cf594cd1b8916d47140d93017"
+ sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79"
url: "https://pub.dev"
source: hosted
- version: "4.2.0"
+ version: "5.0.1"
package_info_plus_platform_interface:
dependency: transitive
description:
@@ -1068,10 +1077,10 @@ packages:
dependency: transitive
description:
name: path_provider_android
- sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1"
+ sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
url: "https://pub.dev"
source: hosted
- version: "2.2.0"
+ version: "2.2.1"
path_provider_foundation:
dependency: transitive
description:
@@ -1108,58 +1117,66 @@ packages:
dependency: transitive
description:
name: pdf
- sha256: "9f75fc7f5580ea5e635b5724de58fb27f684c9ad03ed46fdc1aac768e4557315"
+ sha256: "93cbb2c06de9bab91844550f19896b2373e7a5ce25173995e7e5ec5e1741429d"
url: "https://pub.dev"
source: hosted
- version: "3.10.4"
+ version: "3.10.7"
permission_handler:
dependency: "direct main"
description:
name: permission_handler
- sha256: "284a66179cabdf942f838543e10413246f06424d960c92ba95c84439154fcac8"
+ sha256: "860c6b871c94c78e202dc69546d4d8fd84bd59faeb36f8fb9888668a53ff4f78"
url: "https://pub.dev"
source: hosted
- version: "11.0.1"
+ version: "11.1.0"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
- sha256: f9fddd3b46109bd69ff3f9efa5006d2d309b7aec0f3c1c5637a60a2d5659e76e
+ sha256: "2f1bec180ee2f5665c22faada971a8f024761f632e93ddc23310487df52dcfa6"
url: "https://pub.dev"
source: hosted
- version: "11.1.0"
+ version: "12.0.1"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
- sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5"
+ sha256: "1a816084338ada8d574b1cb48390e6e8b19305d5120fe3a37c98825bacc78306"
url: "https://pub.dev"
source: hosted
- version: "9.1.4"
+ version: "9.2.0"
+ permission_handler_html:
+ dependency: transitive
+ description:
+ name: permission_handler_html
+ sha256: "11b762a8c123dced6461933a88ea1edbbe036078c3f9f41b08886e678e7864df"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.0+2"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
- sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4"
+ sha256: d87349312f7eaf6ce0adaf668daf700ac5b06af84338bd8b8574dfbd93ffe1a1
url: "https://pub.dev"
source: hosted
- version: "3.12.0"
+ version: "4.0.2"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
- sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098
+ sha256: "1e8640c1e39121128da6b816d236e714d2cf17fac5a105dd6acdd3403a628004"
url: "https://pub.dev"
source: hosted
- version: "0.1.3"
+ version: "0.2.0"
petitparser:
dependency: transitive
description:
name: petitparser
- sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
+ sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
url: "https://pub.dev"
source: hosted
- version: "5.4.0"
+ version: "6.0.2"
pigeon:
dependency: transitive
description:
@@ -1188,26 +1205,26 @@ packages:
dependency: transitive
description:
name: platform
- sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
+ sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102
url: "https://pub.dev"
source: hosted
- version: "3.1.0"
+ version: "3.1.2"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
- sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
+ sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8
url: "https://pub.dev"
source: hosted
- version: "2.1.6"
+ version: "2.1.7"
pointer_interceptor:
dependency: "direct main"
description:
name: pointer_interceptor
- sha256: "7626e034489820fd599380d2bb4d3f4a0a5e3529370b62bfce53ab736b91adb2"
+ sha256: adf7a637f97c077041d36801b43be08559fd4322d2127b3f20bb7be1b9eebc22
url: "https://pub.dev"
source: hosted
- version: "0.9.3+6"
+ version: "0.9.3+7"
pointycastle:
dependency: transitive
description:
@@ -1228,10 +1245,10 @@ packages:
dependency: "direct main"
description:
name: printing
- sha256: e7c383dca95ee7b88c02dc1c66638628d3dcdc2fb2cc47e7a595facd47e46b56
+ sha256: ad39a42a5f83125952457dfd94f395c8cf0eb1f7759583dadb769be5c7f99d24
url: "https://pub.dev"
source: hosted
- version: "5.11.0"
+ version: "5.11.1"
process:
dependency: transitive
description:
@@ -1325,34 +1342,34 @@ packages:
dependency: transitive
description:
name: sentry
- sha256: "9cfd325611ab54b57d5e26957466823f05bea9d6cfcc8d48f11817b8bcedf0d1"
+ sha256: e7ded42974bac5f69e4ca4ddc57d30499dd79381838f24b7e8fd9aa4139e7b79
url: "https://pub.dev"
source: hosted
- version: "7.12.0"
+ version: "7.13.2"
sentry_flutter:
dependency: "direct main"
description:
name: sentry_flutter
- sha256: "0cd7d622cb63c94fd1b2f87ab508e158b950bd281e2a80f327ebf73bb217eaf3"
+ sha256: d6f55ec7a1f681784165021f749007712a72ff57eadf91e963331b6ae326f089
url: "https://pub.dev"
source: hosted
- version: "7.12.0"
+ version: "7.13.2"
share_plus:
dependency: "direct main"
description:
name: share_plus
- sha256: "2dafa6c1f8d8ee67b0e0587881947b78baab4671b7c08792cf91279e7ac14192"
+ sha256: f74fc3f1cbd99f39760182e176802f693fa0ec9625c045561cfad54681ea93dd
url: "https://pub.dev"
source: hosted
- version: "7.2.0"
+ version: "7.2.1"
share_plus_platform_interface:
dependency: transitive
description:
name: share_plus_platform_interface
- sha256: "357412af4178d8e11d14f41723f80f12caea54cf0d5cd29af9dcdab85d58aea7"
+ sha256: df08bc3a07d01f5ea47b45d03ffcba1fa9cd5370fb44b3f38c70e42cced0f956
url: "https://pub.dev"
source: hosted
- version: "3.3.0"
+ version: "3.3.1"
shared_preferences:
dependency: "direct main"
description:
@@ -1397,10 +1414,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_web
- sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf
+ sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
url: "https://pub.dev"
source: hosted
- version: "2.2.1"
+ version: "2.2.2"
shared_preferences_windows:
dependency: transitive
description:
@@ -1522,18 +1539,18 @@ packages:
dependency: transitive
description:
name: sqflite_common
- sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a"
+ sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6
url: "https://pub.dev"
source: hosted
- version: "2.5.0"
+ version: "2.5.0+2"
stack_trace:
dependency: transitive
description:
name: stack_trace
- sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
+ sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
url: "https://pub.dev"
source: hosted
- version: "1.11.0"
+ version: "1.11.1"
states_rebuilder:
dependency: "direct main"
description:
@@ -1546,10 +1563,10 @@ packages:
dependency: transitive
description:
name: stream_channel
- sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
+ sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "2.1.2"
stream_transform:
dependency: transitive
description:
@@ -1567,29 +1584,32 @@ packages:
source: hosted
version: "1.2.0"
super_editor:
- dependency: "direct main"
+ dependency: "direct overridden"
description:
- name: super_editor
- sha256: "2d5acf95449f53eec1c7d0788530b3a667758224a1e4aa4164bd5d6c0d159bab"
- url: "https://pub.dev"
- source: hosted
+ path: super_editor
+ ref: stable
+ resolved-ref: c040c690f1dc0f7c482d8ece02622c200cb8e1b1
+ url: "https://github.com/superlistapp/super_editor"
+ source: git
version: "0.2.6"
super_editor_markdown:
- dependency: "direct main"
+ dependency: "direct overridden"
description:
- name: super_editor_markdown
- sha256: "2515d0183ee21aa22d577e95e80b1e4bc1b9ce0f651127d40844be7cb58b5330"
- url: "https://pub.dev"
- source: hosted
+ path: super_editor_markdown
+ ref: stable
+ resolved-ref: c040c690f1dc0f7c482d8ece02622c200cb8e1b1
+ url: "https://github.com/superlistapp/super_editor"
+ source: git
version: "0.1.5"
super_text_layout:
- dependency: transitive
+ dependency: "direct overridden"
description:
- name: super_text_layout
- sha256: "2f2a8b36553f775c390924f079b5a8ba6c717b0885f44d80a9602bfa182b6f9f"
- url: "https://pub.dev"
- source: hosted
- version: "0.1.7"
+ path: super_text_layout
+ ref: stable
+ resolved-ref: c040c690f1dc0f7c482d8ece02622c200cb8e1b1
+ url: "https://github.com/superlistapp/super_editor"
+ source: git
+ version: "0.1.8"
sync_http:
dependency: transitive
description:
@@ -1618,34 +1638,34 @@ packages:
dependency: "direct dev"
description:
name: test
- sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46"
+ sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f
url: "https://pub.dev"
source: hosted
- version: "1.24.3"
+ version: "1.24.9"
test_api:
dependency: transitive
description:
name: test_api
- sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
+ sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
url: "https://pub.dev"
source: hosted
- version: "0.6.0"
+ version: "0.6.1"
test_core:
dependency: transitive
description:
name: test_core
- sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e"
+ sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a
url: "https://pub.dev"
source: hosted
- version: "0.5.3"
+ version: "0.5.9"
timeago:
dependency: "direct main"
description:
name: timeago
- sha256: "4addcda362e51f23cf7ae2357fccd053f29d59b4ddd17fb07fc3e7febb47a456"
+ sha256: c44b80cbc6b44627c00d76960f2af571f6f50e5dbedef4d9215d455e4335165b
url: "https://pub.dev"
source: hosted
- version: "3.5.0"
+ version: "3.6.0"
timing:
dependency: transitive
description:
@@ -1682,66 +1702,66 @@ packages:
dependency: "direct main"
description:
name: url_launcher
- sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27"
+ sha256: b1c9e98774adf8820c96fbc7ae3601231d324a7d5ebd8babe27b6dfac91357ba
url: "https://pub.dev"
source: hosted
- version: "6.1.14"
+ version: "6.2.1"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
- sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330
+ sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def"
url: "https://pub.dev"
source: hosted
- version: "6.1.0"
+ version: "6.2.0"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
- sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f"
+ sha256: bba3373219b7abb6b5e0d071b0fe66dfbe005d07517a68e38d4fc3638f35c6d3
url: "https://pub.dev"
source: hosted
- version: "6.1.5"
+ version: "6.2.1"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
- sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e
+ sha256: "9f2d390e096fdbe1e6e6256f97851e51afc2d9c423d3432f1d6a02a8a9a8b9fd"
url: "https://pub.dev"
source: hosted
- version: "3.0.6"
+ version: "3.1.0"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
- sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88
+ sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234
url: "https://pub.dev"
source: hosted
- version: "3.0.7"
+ version: "3.1.0"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
- sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618"
+ sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50"
url: "https://pub.dev"
source: hosted
- version: "2.1.5"
+ version: "2.2.0"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
- sha256: "2942294a500b4fa0b918685aff406773ba0a4cd34b7f42198742a94083020ce5"
+ sha256: "138bd45b3a456dcfafc46d1a146787424f8d2edfbf2809c9324361e58f851cf7"
url: "https://pub.dev"
source: hosted
- version: "2.0.20"
+ version: "2.2.1"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
- sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069"
+ sha256: "7754a1ad30ee896b265f8d14078b0513a4dba28d358eabb9d5f339886f4a1adc"
url: "https://pub.dev"
source: hosted
- version: "3.0.8"
+ version: "3.1.0"
uuid:
dependency: transitive
description:
@@ -1778,10 +1798,10 @@ packages:
dependency: transitive
description:
name: vm_service
- sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f
+ sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583
url: "https://pub.dev"
source: hosted
- version: "11.7.1"
+ version: "11.10.0"
vs_scrollbar:
dependency: transitive
description:
@@ -1802,10 +1822,10 @@ packages:
dependency: transitive
description:
name: web
- sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
+ sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
url: "https://pub.dev"
source: hosted
- version: "0.1.4-beta"
+ version: "0.3.0"
web_socket_channel:
dependency: transitive
description:
@@ -1834,34 +1854,34 @@ packages:
dependency: "direct main"
description:
name: webview_flutter
- sha256: c1ab9b81090705c6069197d9fdc1625e587b52b8d70cdde2339d177ad0dbb98e
+ sha256: "42393b4492e629aa3a88618530a4a00de8bb46e50e7b3993fedbfdc5352f0dbf"
url: "https://pub.dev"
source: hosted
- version: "4.4.1"
+ version: "4.4.2"
webview_flutter_android:
dependency: transitive
description:
name: webview_flutter_android
- sha256: b0cd33dd7d3dd8e5f664e11a19e17ba12c352647269921a3b568406b001f1dff
+ sha256: "8326ee235f87605a2bfc444a4abc897f4abc78d83f054ba7d3d1074ce82b4fbf"
url: "https://pub.dev"
source: hosted
- version: "3.12.0"
+ version: "3.12.1"
webview_flutter_platform_interface:
dependency: transitive
description:
name: webview_flutter_platform_interface
- sha256: "6d9213c65f1060116757a7c473247c60f3f7f332cac33dc417c9e362a9a13e4f"
+ sha256: "68e86162aa8fc646ae859e1585995c096c95fc2476881fa0c4a8d10f56013a5a"
url: "https://pub.dev"
source: hosted
- version: "2.6.0"
+ version: "2.8.0"
webview_flutter_wkwebview:
dependency: transitive
description:
name: webview_flutter_wkwebview
- sha256: "30b9af6bdd457b44c08748b9190d23208b5165357cc2eb57914fee1366c42974"
+ sha256: accdaaa49a2aca2dc3c3230907988954cdd23fed0a19525d6c9789d380f4dc76
url: "https://pub.dev"
source: hosted
- version: "3.9.1"
+ version: "3.9.4"
widget_kit_plugin:
dependency: "direct main"
description:
@@ -1874,10 +1894,10 @@ packages:
dependency: transitive
description:
name: win32
- sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
+ sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574
url: "https://pub.dev"
source: hosted
- version: "5.0.9"
+ version: "5.1.1"
win32_registry:
dependency: transitive
description:
@@ -1906,10 +1926,10 @@ packages:
dependency: transitive
description:
name: xml
- sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84"
+ sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev"
source: hosted
- version: "6.3.0"
+ version: "6.5.0"
yaml:
dependency: transitive
description:
@@ -1919,5 +1939,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
- dart: ">=3.1.0 <4.0.0"
- flutter: ">=3.13.0"
+ dart: ">=3.2.0 <4.0.0"
+ flutter: ">=3.16.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 7bafb445e..e65877d30 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -39,7 +39,8 @@ dependencies:
built_value: ^8.1.2
built_collection: ^5.1.0
memoize: ^3.0.0
- cached_network_image: 3.0.0 # imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
+ #cached_network_image: 3.0.0 # imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
+ cached_network_image: ^3.3.0
url_launcher: ^6.0.20
share_plus: ^7.1.0
intl: 0.17.0
@@ -72,13 +73,14 @@ dependencies:
contacts_service: ^0.6.3
diacritic: ^0.1.3
states_rebuilder: ^6.2.0
- super_editor: ^0.2.6
- super_editor_markdown: ^0.1.5
+ #super_editor: ^0.2.6
+ #super_editor_markdown: ^0.1.5
#markdown: ^5.0.0 # REMOVE THIS
- #super_editor:
+ #super_editor_markdown:
# git:
# url: https://github.com/superlistapp/super_editor.git
- # path: super_editor
+ # path: super_editor_markdown
+ # ref: stable
html2md: ^1.2.6
printing: ^5.11.0
image_cropper: ^4.0.1
@@ -101,6 +103,26 @@ dependency_overrides:
intl: any
navigation_builder: ^0.0.3
states_rebuilder: ^6.3.0
+ super_editor:
+ git:
+ url: https://github.com/superlistapp/super_editor
+ path: super_editor
+ ref: stable
+ super_editor_markdown:
+ git:
+ url: https://github.com/superlistapp/super_editor
+ path: super_editor_markdown
+ ref: stable
+ super_text_layout:
+ git:
+ url: https://github.com/superlistapp/super_editor
+ path: super_text_layout
+ ref: stable
+ attributed_text:
+ git:
+ url: https://github.com/superlistapp/super_editor
+ path: attributed_text
+ ref: stable
dev_dependencies:
flutter_driver:
diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt
index 930d2071a..903f4899d 100644
--- a/windows/flutter/CMakeLists.txt
+++ b/windows/flutter/CMakeLists.txt
@@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake)
# 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")
@@ -92,7 +97,7 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
- windows-x64 $
+ ${FLUTTER_TARGET_PLATFORM} $
VERBATIM
)
add_custom_target(flutter_assemble DEPENDS