diff --git a/.github/workflows/deploy_client_prod.yaml b/.github/workflows/deploy_client_prod.yaml index e17bb3a38..d86547eee 100644 --- a/.github/workflows/deploy_client_prod.yaml +++ b/.github/workflows/deploy_client_prod.yaml @@ -17,7 +17,7 @@ jobs: - name: Set Up Flutter uses: subosito/flutter-action@v2 with: - flutter-version: "3.22.2" # could read version from pubspec file, but would need to be exact + flutter-version: "3.27.4" # could read version from pubspec file, but would need to be exact channel: "stable" cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" diff --git a/.github/workflows/deploy_client_staging.yaml b/.github/workflows/deploy_client_staging.yaml index 123dc4282..40253c65f 100644 --- a/.github/workflows/deploy_client_staging.yaml +++ b/.github/workflows/deploy_client_staging.yaml @@ -29,7 +29,7 @@ jobs: if: steps.changes.outputs.client == 'true' || github.event_name== 'workflow_dispatch' uses: subosito/flutter-action@v2 with: - flutter-version: "3.22.2" # could read version from pubspec file, but would need to be exact + flutter-version: "3.27.4" # could read version from pubspec file, but would need to be exact channel: "stable" cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" diff --git a/.github/workflows/deploy_firebase_prod.yaml b/.github/workflows/deploy_firebase_prod.yaml index 4ab0bbcef..47118be1a 100644 --- a/.github/workflows/deploy_firebase_prod.yaml +++ b/.github/workflows/deploy_firebase_prod.yaml @@ -24,7 +24,7 @@ jobs: - name: Set Up Flutter uses: subosito/flutter-action@v2 with: - flutter-version: "3.22.2" # could read version from pubspec file, but would need to be exact + flutter-version: "3.27.4" # could read version from pubspec file, but would need to be exact channel: "stable" cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" diff --git a/.github/workflows/deploy_firebase_staging.yaml b/.github/workflows/deploy_firebase_staging.yaml index 5de099b60..f0455587c 100644 --- a/.github/workflows/deploy_firebase_staging.yaml +++ b/.github/workflows/deploy_firebase_staging.yaml @@ -58,7 +58,7 @@ jobs: if: steps.changes.outputs.functions == 'true' || github.event_name== 'workflow_dispatch' || steps.changes.outputs.shared == 'true' uses: subosito/flutter-action@v2 with: - flutter-version: "3.22.2" # could read version from pubspec file, but would need to be exact + flutter-version: "3.27.4" # could read version from pubspec file, but would need to be exact channel: "stable" cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" diff --git a/.github/workflows/test_client.yaml b/.github/workflows/test_client.yaml index 02cb6e000..cacb097af 100644 --- a/.github/workflows/test_client.yaml +++ b/.github/workflows/test_client.yaml @@ -30,7 +30,7 @@ jobs: if: steps.changes.outputs.client == 'true' uses: subosito/flutter-action@v2 with: - flutter-version: "3.22.2" # could read version from pubspec file, but would need to be exact + flutter-version: "3.27.4" # could read version from pubspec file, but would need to be exact channel: "stable" cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" diff --git a/.github/workflows/test_firebase.yaml b/.github/workflows/test_firebase.yaml index 7207cabc9..76bc193f0 100644 --- a/.github/workflows/test_firebase.yaml +++ b/.github/workflows/test_firebase.yaml @@ -46,7 +46,7 @@ jobs: if: steps.changes.outputs.functions == 'true' uses: subosito/flutter-action@v2 with: - flutter-version: "3.22.2" # could read version from pubspec file, but would need to be exact + flutter-version: "3.27.4" # could read version from pubspec file, but would need to be exact channel: "stable" cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" diff --git a/README.md b/README.md index d08d834f1..a8acc551b 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Most components of Frankly can be run on your local machine. This section descri This section covers setting up a new computer for Flutter development. -> ### ⚠️ Important: Frankly runs on Flutter `3.22.2.` +> ### ⚠️ Important: Frankly runs on Flutter `3.29.2.` > > **Please use this version of Flutter in order to avoid any unexpected errors.** diff --git a/client/lib/core/widgets/markdown_serializing_text_editor.dart b/client/lib/core/widgets/markdown_serializing_text_editor.dart new file mode 100644 index 000000000..3769a924d --- /dev/null +++ b/client/lib/core/widgets/markdown_serializing_text_editor.dart @@ -0,0 +1,199 @@ +import 'package:client/styles/app_styles.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:super_editor/super_editor.dart'; +import 'package:super_editor_markdown/super_editor_markdown.dart'; + +import 'super_editor_fixed_toolbar.dart'; + +class MarkdownSerializingTextEditor extends StatefulWidget { + final String? initialValue; + final Function(String)? onChanged; + + const MarkdownSerializingTextEditor({ + this.initialValue, + this.onChanged, + }) : super(); + + @override + State createState() => + _MarkdownSerializingTextEditorState(); +} + +class _MarkdownSerializingTextEditorState + extends State { + final GlobalKey _viewportKey = GlobalKey(); + final GlobalKey _docLayoutKey = GlobalKey(); + late MutableDocument _doc; + late MutableDocumentComposer _composer; + late Editor _docEditor; + late CommonEditorOperations _docOps; + late FocusNode _editorFocusNode; + // TODO (from SuperEditor example): 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; + String _markdown = ''; + + @override + void initState() { + super.initState(); + _doc = createInitialDocument()..addListener(_onDocumentChange); + _composer = MutableDocumentComposer(); + _docEditor = createDefaultDocumentEditor( + document: _doc, + composer: _composer, + isHistoryEnabled: true, + ); + _docOps = CommonEditorOperations( + editor: _docEditor, + document: _doc, + composer: _composer, + documentLayoutResolver: () => + _docLayoutKey.currentState as DocumentLayout, + ); + _editorFocusNode = FocusNode(); + _iosControlsController = SuperEditorIosControlsController(); + } + + void _updateMarkdown() { + _markdown = serializeDocumentToMarkdown(_doc); + } + + MutableDocument createInitialDocument() { + return deserializeMarkdownToDocument(widget.initialValue ?? ''); + } + + void _onDocumentChange(_) { + _updateMarkdown(); + final onChanged = widget.onChanged; + if (onChanged != null) { + onChanged(_markdown); + } + } + + @override + void dispose() { + _iosControlsController.dispose(); + _editorFocusNode.dispose(); + _composer.dispose(); + super.dispose(); + } + + DocumentGestureMode get _gestureMode { + switch (defaultTargetPlatform) { + case TargetPlatform.android: + return DocumentGestureMode.android; + case TargetPlatform.iOS: + return DocumentGestureMode.iOS; + case TargetPlatform.fuchsia: + case TargetPlatform.linux: + case TargetPlatform.macOS: + case TargetPlatform.windows: + return DocumentGestureMode.mouse; + } + } + + Widget _buildToolbar() { + return SuperEditorFixedToolbar( + editor: _docEditor, + document: _doc, + composer: _composer, + commonOps: _docOps, + editorFocusNode: _editorFocusNode, + ); + } + + TextInputSource get _inputSource { + switch (defaultTargetPlatform) { + case TargetPlatform.android: + case TargetPlatform.iOS: + case TargetPlatform.fuchsia: + case TargetPlatform.linux: + case TargetPlatform.macOS: + case TargetPlatform.windows: + return TextInputSource.ime; + } + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + _buildToolbar(), + SizedBox(height: 2), + DecoratedBox( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: _editorFocusNode.hasFocus + ? AppColor.accentBlue + : AppColor.gray4, + width: 1, + ), + ), + child: SizedBox( + height: + 200, // fixed dimensions a requirement to contain customscrollview + child: CustomScrollView( + //scrollview a requirement to contain SuperEditor b/c they use Sliver + // See https://github.com/superlistapp/super_editor/issues/2266 + slivers: [ + KeyedSubtree( + key: _viewportKey, + child: SuperEditorIosControlsScope( + controller: + _iosControlsController, //not clear this is needed + child: SuperEditor( + editor: _docEditor, + gestureMode: _gestureMode, + focusNode: _editorFocusNode, + documentLayoutKey: _docLayoutKey, + documentOverlayBuilders: [ + DefaultCaretOverlayBuilder( + caretStyle: const CaretStyle().copyWith( + color: Colors.black, + ), + ), + if (defaultTargetPlatform == TargetPlatform.iOS) ...[ + SuperEditorIosHandlesDocumentLayerBuilder(), + SuperEditorIosToolbarFocalPointDocumentLayerBuilder(), + ], + if (defaultTargetPlatform == + TargetPlatform.android) ...[ + SuperEditorAndroidToolbarFocalPointDocumentLayerBuilder(), + SuperEditorAndroidHandlesDocumentLayerBuilder(), + ], + ], + inputSource: _inputSource, + keyboardActions: _inputSource == TextInputSource.ime + ? defaultImeKeyboardActions + : defaultKeyboardActions, + //androidToolbarBuilder: (_) => _buildAndroidFloatingToolbar(), TODO needed? + //overlayController: _overlayController, TODO needed for Android? + plugins: { + MarkdownInlineUpstreamSyntaxPlugin(), + }, + /**The selection and IME policies are set here to make sure we don't lose + * selection on keyboard mouse up. This seems to be required because of the + * CustomScrollView, which I'm guessing is gaining focus on mouse up. + * Unfortunately this leaves text selected all the time, even when you + * put focus on a different element, but not sure how else to solve. + */ + selectionPolicies: SuperEditorSelectionPolicies( + clearSelectionWhenEditorLosesFocus: false, + ), + imePolicies: SuperEditorImePolicies( + closeImeOnNonPrimaryFocusLost: false, + ), + ), + ), + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/client/lib/core/widgets/super_editor_fixed_toolbar.dart b/client/lib/core/widgets/super_editor_fixed_toolbar.dart new file mode 100644 index 000000000..f5cc1a270 --- /dev/null +++ b/client/lib/core/widgets/super_editor_fixed_toolbar.dart @@ -0,0 +1,576 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:super_editor/super_editor.dart'; + +/// A fixed toolbar to accompany a SuperEditor widget. Much of this code was derived from SuperEditor's mobile KeyboardEditingToolbar, +/// which uses an OverlayPortal to share focus between the toolbar and editor. +/// This toolbar adds refocusing of editor and selection retention to allow for placement anywhere in the widget tree. +/// It also removes the option to close the toolbar and supports toggling Bold and Italics when no text is selected. +class SuperEditorFixedToolbar extends StatefulWidget { + const SuperEditorFixedToolbar({ + Key? key, + required this.editor, + required this.document, + required this.composer, + required this.commonOps, + required this.editorFocusNode, + }) : super(key: key); + + final Editor editor; + final Document document; + final DocumentComposer composer; + final CommonEditorOperations commonOps; + + /// The [FocusNode] attached to the editor to which this toolbar applies. + final FocusNode editorFocusNode; + + @override + State createState() => + _SuperEditorFixedToolbarState(); +} + +class _SuperEditorFixedToolbarState extends State + with WidgetsBindingObserver { + bool _showUrlField = false; + late FocusNode _urlFocusNode; + ImeAttributedTextEditingController? _urlController; + DocumentSelection? lastSelection; + + @override + void initState() { + super.initState(); + _urlFocusNode = FocusNode(); + _urlController = ImeAttributedTextEditingController( + controller: SingleLineAttributedTextEditingController(_applyLink), + ) // + ..onPerformActionPressed = _onPerformAction + ..text = AttributedText('https://'); + // Listen for focus changes and update the UI + widget.editorFocusNode.addListener(_onEditorFocusChange); + } + + void _onEditorFocusChange() { + setState(() {}); // Trigger a rebuild when focus changes + } + + @override + void dispose() { + _urlFocusNode.dispose(); + _urlController!.dispose(); + widget.editorFocusNode.removeListener(_onEditorFocusChange); + super.dispose(); + } + + void _onPerformAction(TextInputAction action) { + if (action == TextInputAction.done) { + _applyLink(); + } + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Builder( + // Add a Builder so that _buildToolbar() uses theming from _buildTheming(). + builder: (themedContext) { + return _buildToolbar(themedContext); + }, + ), + if (_showUrlField) ...[ + const SizedBox(height: 8), + _buildUrlField(), + ], + ], + ); + /**return _buildTheming( + child: Builder( + // Add a Builder so that _buildToolbar() uses theming from _buildTheming(). + builder: (themedContext) { + return _buildToolbar(themedContext); + }, + ), + );**/ + } + + Widget _buildTheming({ + required Widget child, + }) { + final brightness = MediaQuery.of(context).platformBrightness; + + return Theme( + data: Theme.of(context).copyWith( + brightness: brightness, + disabledColor: brightness == Brightness.light + ? Colors.black.withValues(alpha: 0.5) + : Colors.white.withValues(alpha: 0.5), + ), + child: IconTheme( + data: IconThemeData( + color: brightness == Brightness.light ? Colors.black : Colors.white, + ), + child: child, + ), + ); + } + + Widget _buildToolbar(BuildContext context) { + final isEditorFocused = widget.editorFocusNode.hasFocus; + final selection = widget.composer.selection; + final selectedNode = selection != null + ? widget.document.getNodeById(selection.extent.nodeId) + : null; + + // Enable buttons when editor is focused, even if selection is null + bool isToolbarEnabled = isEditorFocused || selection != null; + + final isSingleNodeSelected = + selection != null ? selection.isCollapsed : false; + + return Material( + child: Container( + width: double.infinity, + height: 48, + color: Theme.of(context).brightness == Brightness.light + ? const Color(0xFFDDDDDD) + : const Color(0xFF222222), + child: LayoutBuilder( + builder: (context, constraints) { + return Row( + children: [ + Expanded( + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: ListenableBuilder( + listenable: widget.composer, + builder: (context, _) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: + isToolbarEnabled ? () => toggleBold() : null, + icon: const Icon(Icons.format_bold), + color: isBoldActive + ? Theme.of(context).primaryColor + : null, + ), + IconButton( + onPressed: isToolbarEnabled + ? () => toggleItalics() + : null, + icon: const Icon(Icons.format_italic), + color: isItalicsActive + ? Theme.of(context).primaryColor + : null, + ), + IconButton( + onPressed: !isToolbarEnabled || + _areMultipleLinksSelected() + ? null + : _onLinkPressed, + icon: const Icon(Icons.link), + color: _isSingleLinkSelected() + ? const Color(0xFF007AFF) + : IconTheme.of(context).color, + splashRadius: 16, + tooltip: 'Link', + ), + IconButton( + onPressed: isToolbarEnabled && + isSingleNodeSelected && + (selectedNode is TextNode && + selectedNode.getMetadataValue( + 'blockType', + ) != + header1Attribution) + ? _convertToHeader1 + : null, + icon: const Icon(Icons.title), + ), + IconButton( + onPressed: isToolbarEnabled && + isSingleNodeSelected && + (selectedNode is TextNode && + selectedNode.getMetadataValue( + 'blockType', + ) != + header2Attribution) + ? _convertToHeader2 + : null, + icon: const Icon(Icons.title), + iconSize: 18, + ), + IconButton( + onPressed: isToolbarEnabled && + isSingleNodeSelected && + ((selectedNode is ParagraphNode && + selectedNode.hasMetadataValue( + 'blockType', + )) || + (selectedNode is TextNode && + selectedNode is! ParagraphNode)) + ? _convertToParagraph + : null, + icon: const Icon(Icons.wrap_text), + ), + ], + ); + }, + ), + ), + ), + Container( + width: 1, + height: 32, + color: const Color(0xFFCCCCCC), + ), + ], + ); + }, + ), + ), + ); + } + + Widget _buildUrlField() { + return Material( + shape: const StadiumBorder(), + elevation: 5, + clipBehavior: Clip.hardEdge, + child: Container( + width: 400, + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Row( + children: [ + Expanded( + child: SuperTextField( + focusNode: _urlFocusNode, + textController: _urlController, + minLines: 1, + maxLines: 1, + inputSource: TextInputSource.ime, + hintBehavior: HintBehavior.displayHintUntilTextEntered, + hintBuilder: (context) { + return const Text( + 'enter a url...', + style: TextStyle( + color: Colors.grey, + fontSize: 16, + ), + ); + }, + textStyleBuilder: (_) { + return const TextStyle( + color: Colors.black, + fontSize: 16, + ); + }, + ), + ), + IconButton( + icon: const Icon(Icons.close), + iconSize: 20, + splashRadius: 16, + padding: EdgeInsets.zero, + onPressed: () { + setState(() { + _urlFocusNode.unfocus(); + _showUrlField = false; + _urlController!.clearTextAndSelection(); + }); + }, + ), + ], + ), + ), + ); + } + + bool get isBoldActive => _doesSelectionHaveAttributions({boldAttribution}); + + void toggleBold() => _toggleAttributions({boldAttribution}); + + bool get isItalicsActive => + _doesSelectionHaveAttributions({italicsAttribution}); + void toggleItalics() => _toggleAttributions({italicsAttribution}); + + bool _doesSelectionHaveAttributions(Set attributions) { + final selection = widget.composer.selection; + if (selection == null) { + return false; + } + + if (selection.isCollapsed) { + return widget.composer.preferences.currentAttributions + .containsAll(attributions); + } + + return widget.document.doesSelectedTextContainAttributions( + selection, + attributions, + ); + } + + void _toggleAttributions(Set attributions) { + final selection = widget.composer.selection!; + + if (selection.isCollapsed) { + // Toggle attribution in composer for future typing + widget.commonOps.toggleComposerAttributions(attributions); + } else { + // Toggle attribution on selected text + widget.commonOps.toggleAttributionsOnSelection(attributions); + } + _restoreFocusAndSelection(); + } + + void _restoreFocusAndSelection() { + // TODO this method was necessary before I set the selection and ime policies on the supereditor + // to never clear the selection when focus is lost. Leaving it here in case you figure out + // a way to not use that (so the selection actually does go away when you are focused on something completely different) + /**final selection = widget.composer.selection!; + + if (!selection.isCollapsed) { + widget.editor.execute([ + ChangeSelectionRequest( + DocumentSelection( + base: selection.base, + extent: selection.extent, + ), + SelectionChangeType + .expandSelection, // Ensures selection remains visible + SelectionReason.userInteraction, + ), + ]); + } + widget.editorFocusNode.requestFocus();**/ + } + + bool _isSingleLinkSelected() { + return _getSelectedLinkSpans().length == 1; + } + + /// Returns true if the current text selection includes 2+ + /// links, returns false otherwise. + bool _areMultipleLinksSelected() { + return _getSelectedLinkSpans().length >= 2; + } + + /// Returns any link-based [AttributionSpan]s that appear partially + /// or wholly within the current text selection. + Set _getSelectedLinkSpans() { + final selection = widget.composer.selection; + if (selection == null) { + return {}; + } + 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(selectionStart, selectionEnd - 1); + + final textNode = + widget.document.getNodeById(selection.extent.nodeId) as TextNode; + final text = textNode.text; + + final overlappingLinkAttributions = text.getAttributionSpansInRange( + attributionFilter: (Attribution attribution) => + attribution is LinkAttribution, + range: selectionRange, + ); + + return overlappingLinkAttributions; + } + + void _onLinkPressed() { + final selection = widget.composer.selection; + if (selection == null || selection.isCollapsed) { + return; + } + lastSelection = 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(selectionStart, selectionEnd - 1); + + final textNode = + widget.document.getNodeById(selection.extent.nodeId) as TextNode; + final text = textNode.text; + + final overlappingLinkAttributions = text.getAttributionSpansInRange( + attributionFilter: (Attribution attribution) => + attribution is LinkAttribution, + range: selectionRange, + ); + + if (overlappingLinkAttributions.length >= 2) { + // Do nothing when multiple links are selected. + return; + } + + if (overlappingLinkAttributions.isNotEmpty) { + // The selected text contains one other link. + final overlappingLinkSpan = overlappingLinkAttributions.first; + final isLinkSelectionOnTrailingEdge = + (overlappingLinkSpan.start >= selectionRange.start && + overlappingLinkSpan.start <= selectionRange.end) || + (overlappingLinkSpan.end >= selectionRange.start && + overlappingLinkSpan.end <= selectionRange.end); + + if (isLinkSelectionOnTrailingEdge) { + // The selected text covers the beginning, or the end, or the entire + // existing link. Remove the link attribution from the selected text. + text.removeAttribution(overlappingLinkSpan.attribution, selectionRange); + } else { + // The selected text sits somewhere within the existing link. Remove + // the entire link attribution. + text.removeAttribution( + overlappingLinkSpan.attribution, + overlappingLinkSpan.range, + ); + } + // Ensure the editor regains focus + widget.editorFocusNode.requestFocus(); + } else { + // There are no other links in the selection. Show the URL text field. + setState(() { + _showUrlField = true; + _urlFocusNode.requestFocus(); + }); + } + } + + /// Takes the text from the [urlController] and applies it as a link + /// attribution to the currently selected text. + void _applyLink() { + //Reselect text that was selected before URL input shown + if (!lastSelection!.isCollapsed) { + widget.editor.execute([ + ChangeSelectionRequest( + DocumentSelection( + base: lastSelection!.base, + extent: lastSelection!.extent, + ), + SelectionChangeType + .expandSelection, // Ensures selection remains visible + SelectionReason.userInteraction, + ), + ]); + } + final url = _urlController!.text.toPlainText(includePlaceholders: false); + + 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 = + TextRange(start: selectionStart, end: selectionEnd - 1); + + final textNode = + widget.document.getNodeById(selection.extent.nodeId) as TextNode; + final text = textNode.text; + + final trimmedRange = _trimTextRangeWhitespace(text, selectionRange); + + final linkAttribution = LinkAttribution.fromUri(Uri.parse(url)); + + widget.editor.execute([ + AddTextAttributionsRequest( + documentRange: DocumentRange( + start: DocumentPosition( + nodeId: textNode.id, + nodePosition: TextNodePosition(offset: trimmedRange.start), + ), + end: DocumentPosition( + nodeId: textNode.id, + nodePosition: TextNodePosition(offset: trimmedRange.end), + ), + ), + attributions: {linkAttribution}, + ), + ]); + + // Clear the field and hide the URL bar + _urlController!.clearTextAndSelection(); + setState(() { + _showUrlField = false; + _urlFocusNode.unfocus( + disposition: UnfocusDisposition.previouslyFocusedChild, + ); + }); + } + + /// Given [text] and a [range] within the [text], the [range] is + /// shortened on both sides to remove any trailing whitespace and + /// the new range is returned. + SpanRange _trimTextRangeWhitespace(AttributedText text, TextRange range) { + int startOffset = range.start; + int endOffset = range.end; + + final plainText = text.toPlainText(); + while (startOffset < range.end && plainText[startOffset] == ' ') { + startOffset += 1; + } + while (endOffset > startOffset && plainText[endOffset] == ' ') { + endOffset -= 1; + } + + // Add 1 to the end offset because SpanRange treats the end offset to be exclusive. + return SpanRange(startOffset, endOffset + 1); + } + + void _convertToHeader1() { + final selectedNode = + widget.document.getNodeById(widget.composer.selection!.extent.nodeId); + + widget.editor.execute([ + ChangeParagraphBlockTypeRequest( + nodeId: selectedNode!.id, + blockType: header1Attribution, + ), + ]); + _restoreFocusAndSelection(); + } + + void _convertToHeader2() { + final selectedNode = + widget.document.getNodeById(widget.composer.selection!.extent.nodeId); + + widget.editor.execute([ + ChangeParagraphBlockTypeRequest( + nodeId: selectedNode!.id, + blockType: header2Attribution, + ), + ]); + _restoreFocusAndSelection(); + } + + void _convertToParagraph() { + widget.commonOps.convertToParagraph(); + _restoreFocusAndSelection(); + } +} + +class SingleLineAttributedTextEditingController + extends AttributedTextEditingController { + SingleLineAttributedTextEditingController(this.onSubmit); + + final VoidCallback onSubmit; + + @override + void insertNewline() { + // Don't insert newline in a single-line text field. + + // Invoke callback to take action on enter. + onSubmit(); + + // TODO: this is a hack. SuperTextField shouldn't insert newlines in a single + // line field (#697). + } +} diff --git a/client/lib/dev_emulators_main.dart b/client/lib/dev_emulators_main.dart index 42e4643ac..ff23d419d 100644 --- a/client/lib/dev_emulators_main.dart +++ b/client/lib/dev_emulators_main.dart @@ -6,6 +6,8 @@ import 'package:client/core/data/services/logging_service.dart'; import 'package:client/services.dart'; import 'package:client/features/user/data/services/user_data_service.dart'; import 'package:client/features/user/data/services/user_service.dart'; +//import 'package:logging/logging.dart' as lg; +//import 'package:super_editor/super_editor.dart'; void main() async { loggingService.log('Running in dev emulator mode'); @@ -38,5 +40,19 @@ void main() async { } } + /** TODO remove this - just showing you to configure SuperEditor loggers if you need them */ + /** + initLoggers(lg.Level.FINEST, { + editorGesturesLog, + // editorImeLog, + // editorKeyLog, + // editorOpsLog, + // editorLayoutLog, + editorPoliciesLog, + editorDocLog, + // editorStyleLog, + // textFieldLog, + }); +*/ await runClient(); } diff --git a/client/lib/features/events/features/live_meeting/features/meeting_agenda/presentation/views/agenda_item_text.dart b/client/lib/features/events/features/live_meeting/features/meeting_agenda/presentation/views/agenda_item_text.dart index 0c6797fc8..b1313795b 100644 --- a/client/lib/features/events/features/live_meeting/features/meeting_agenda/presentation/views/agenda_item_text.dart +++ b/client/lib/features/events/features/live_meeting/features/meeting_agenda/presentation/views/agenda_item_text.dart @@ -1,9 +1,9 @@ import 'package:client/core/utils/navigation_utils.dart'; +import 'package:client/core/widgets/markdown_serializing_text_editor.dart'; import 'package:client/features/events/features/live_meeting/features/meeting_agenda/utils/agenda_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:client/features/events/features/live_meeting/features/meeting_agenda/data/models/agenda_item_text_data.dart'; -import 'package:client/core/utils/error_utils.dart'; import 'package:client/core/widgets/custom_text_field.dart'; import 'package:client/core/widgets/ui_migration.dart'; import 'package:client/styles/app_styles.dart'; @@ -39,12 +39,8 @@ class AgendaItemText extends StatelessWidget { }, ), SizedBox(height: 20), - CustomTextField( + MarkdownSerializingTextEditor( initialValue: agendaItemTextData.content, - labelText: 'Content', - hintText: - 'Keep it short! You don’t want people to spend time reading.', - maxLines: null, onChanged: (value) { agendaItemTextData.content = value; onChanged(agendaItemTextData); @@ -60,7 +56,7 @@ class AgendaItemText extends StatelessWidget { UIMigration( whiteBackground: true, child: MarkdownBody( - data: agendaItemTextData.content.replaceAll('\n', '\n\n'), + data: agendaItemTextData.content, shrinkWrap: true, selectable: true, onTapLink: (text, href, _) { diff --git a/client/lib/features/events/features/live_meeting/features/meeting_guide/presentation/widgets/meeting_guide_card_item_text.dart b/client/lib/features/events/features/live_meeting/features/meeting_guide/presentation/widgets/meeting_guide_card_item_text.dart index 6a6b8608f..d666d8620 100644 --- a/client/lib/features/events/features/live_meeting/features/meeting_guide/presentation/widgets/meeting_guide_card_item_text.dart +++ b/client/lib/features/events/features/live_meeting/features/meeting_guide/presentation/widgets/meeting_guide_card_item_text.dart @@ -16,7 +16,7 @@ class MeetingGuideCardItemText extends StatelessWidget { @override Widget build(BuildContext context) { return MarkdownBody( - data: (agendaItem.content ?? '').replaceAll('\n', '\n\n'), + data: (agendaItem.content ?? ''), shrinkWrap: true, selectable: true, styleSheet: _computeUpdatedStyleSheet(context), diff --git a/client/pubspec.lock b/client/pubspec.lock index 2a237f1c9..e17d0aabc 100644 --- a/client/pubspec.lock +++ b/client/pubspec.lock @@ -54,10 +54,18 @@ packages: dependency: "direct main" description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.12.0" + attributed_text: + dependency: transitive + description: + name: attributed_text + sha256: "9d8bdc6e54387f31e52d2dcc3d93d656072582a44bcaa855c9ea8b3b2fa7abd3" + url: "https://pub.dev" + source: hosted + version: "0.4.4" beamer: dependency: "direct main" description: @@ -70,10 +78,10 @@ packages: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" build: dependency: transitive description: @@ -142,10 +150,10 @@ packages: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" charcode: dependency: transitive description: @@ -166,10 +174,10 @@ packages: dependency: "direct main" description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" cloud_firestore: dependency: "direct main" description: @@ -250,6 +258,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.1" + coverage: + dependency: transitive + description: + name: coverage + sha256: e3493833ea012784c740e341952298f1cc77f1f01b1bbc3eb4eecf6984fb7f43 + url: "https://pub.dev" + source: hosted + version: "1.11.1" cross_file: dependency: transitive description: @@ -365,10 +381,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" ffi: dependency: transitive description: @@ -381,10 +397,10 @@ packages: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" file_picker: dependency: "direct main" description: @@ -653,10 +669,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f" + sha256: "5a1e6fb2c0561958d7e4c33574674bda7b77caaca7a33b758876956f2902eea3" url: "https://pub.dev" source: hosted - version: "2.0.19" + version: "2.0.27" flutter_portal: dependency: "direct main" description: @@ -710,6 +726,22 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_test_robots: + dependency: transitive + description: + name: flutter_test_robots + sha256: "3b00f2081148bde55190997c2772f934ad2f4529cbcfc4ccfa593f8ddc117a28" + url: "https://pub.dev" + source: hosted + version: "0.0.24" + flutter_test_runners: + dependency: transitive + description: + name: flutter_test_runners + sha256: cc575117ed66a79185a26995399d7048341517a1bd21188cb43753739627832d + url: "https://pub.dev" + source: hosted + version: "0.0.4" flutter_typeahead: dependency: "direct main" description: @@ -731,6 +763,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.2.5" + follow_the_leader: + dependency: transitive + description: + name: follow_the_leader + sha256: "798baf5211ca2461c8462d4c8e94f57bf989758f8204056d607eb9a20f1cf794" + url: "https://pub.dev" + source: hosted + version: "0.0.4+8" font_awesome_flutter: dependency: "direct main" description: @@ -986,18 +1026,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "10.0.8" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.9" leak_tracker_testing: dependency: transitive description: @@ -1034,10 +1074,10 @@ packages: dependency: transitive description: name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" markdown: dependency: transitive description: @@ -1050,18 +1090,18 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" matomo_tracker: dependency: "direct main" description: @@ -1074,10 +1114,10 @@ packages: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.16.0" metadata_fetch: dependency: "direct main" description: @@ -1134,6 +1174,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" normal: dependency: "direct main" description: @@ -1158,6 +1206,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + overlord: + dependency: transitive + description: + name: overlord + sha256: "576256bc9ce3fb0ae3042bbb26eed67bdb26a5045dd7e3c851aae65b0bbab2f5" + url: "https://pub.dev" + source: hosted + version: "0.0.3+5" package_config: dependency: transitive description: @@ -1186,10 +1242,10 @@ packages: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" path_drawing: dependency: transitive description: @@ -1274,10 +1330,10 @@ packages: dependency: transitive description: name: platform - sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.6" platform_detect: dependency: "direct main" description: @@ -1314,10 +1370,10 @@ packages: dependency: transitive description: name: process - sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" + sha256: "107d8be718f120bbba9dcd1e95e3bd325b1b4a4f07db64154635ba03f2567a0d" url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "5.0.3" properties: dependency: transitive description: @@ -1486,6 +1542,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" shelf_web_socket: dependency: transitive description: @@ -1514,7 +1586,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_gen: dependency: transitive description: @@ -1531,14 +1603,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.4" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" source_span: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.1" sprintf: dependency: transitive description: @@ -1551,18 +1639,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" stream_transform: dependency: transitive description: @@ -1575,10 +1663,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.4.1" string_validator: dependency: transitive description: @@ -1587,6 +1675,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + super_editor: + dependency: "direct main" + description: + name: super_editor + sha256: "96b67335c60a1e07856ec0b7ea7f323e89c29f256c9e13528cd8c7556241ed83" + url: "https://pub.dev" + source: hosted + version: "0.3.0-dev.22" + super_editor_markdown: + dependency: "direct main" + description: + name: super_editor_markdown + sha256: a5af6eb68a03a243378504bcebd1e855f36cc01b0122a11d9b5751232b61bf69 + url: "https://pub.dev" + source: hosted + version: "0.1.7" + super_keyboard: + dependency: transitive + description: + name: super_keyboard + sha256: "06662d12c88f0d0f0979d1a27729007a9b5e389e3b9a8adf2531e4c562df2540" + url: "https://pub.dev" + source: hosted + version: "0.1.1" + super_text_layout: + dependency: transitive + description: + name: super_text_layout + sha256: e25f01ceb809118da66fd095b3dcdc608a611bf45e364f303e7f9f0af0c5f8d1 + url: "https://pub.dev" + source: hosted + version: "0.1.18" sync_http: dependency: transitive description: @@ -1615,18 +1735,34 @@ packages: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" + test: + dependency: transitive + description: + name: test + sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e" + url: "https://pub.dev" + source: hosted + version: "1.25.15" test_api: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.4" + test_core: + dependency: transitive + description: + name: test_core + sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa" + url: "https://pub.dev" + source: hosted + version: "0.6.8" timezone: dependency: "direct main" description: @@ -1679,10 +1815,10 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "6ce1e04375be4eed30548f10a315826fd933c1e493206eab82eed01f438c8d2e" + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" url: "https://pub.dev" source: hosted - version: "6.2.6" + version: "6.3.1" url_launcher_android: dependency: transitive description: @@ -1743,10 +1879,10 @@ packages: dependency: "direct main" description: name: uuid - sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.5.1" vector_graphics: dependency: transitive description: @@ -1823,10 +1959,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "14.3.1" watcher: dependency: transitive description: @@ -1855,10 +1991,18 @@ packages: dependency: transitive description: name: webdriver - sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e" + sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.4" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" webview_flutter: dependency: transitive description: @@ -1948,5 +2092,5 @@ packages: source: hosted version: "2.0.2" sdks: - dart: ">=3.4.1 <4.0.0" - flutter: ">=3.19.0" + dart: ">=3.7.0-0 <4.0.0" + flutter: ">=3.27.0" diff --git a/client/pubspec.yaml b/client/pubspec.yaml index 0ea6d8c41..04e843214 100644 --- a/client/pubspec.yaml +++ b/client/pubspec.yaml @@ -19,6 +19,8 @@ dependencies: matomo_tracker: ^5.1.0 normal: ^0.6.0 platform_detect: ^2.0.11 + super_editor: ^0.3.0-dev.22 + super_editor_markdown: ^0.1.7 uuid: ^4.1.0 @@ -40,7 +42,7 @@ dependencies: intl: ^0.19.0 freezed_annotation: ^2.4.1 get_it: ^7.6.0 - http: ^1.2.1 + http: ^1.2.2 url_launcher: ^6.1.11 responsive_builder: ^0.7.0 datetime_picker_formfield: ^2.0.1 diff --git a/data_models/lib/events/live_meetings/live_meeting.g.dart b/data_models/lib/events/live_meetings/live_meeting.g.dart index 90567cc3a..f5ab78205 100644 --- a/data_models/lib/events/live_meetings/live_meeting.g.dart +++ b/data_models/lib/events/live_meetings/live_meeting.g.dart @@ -115,9 +115,7 @@ _$_BreakoutRoom _$$_BreakoutRoomFromJson(Map json) => _$BreakoutRoomFlagStatusEnumMap, json['flagStatus'], unknownValue: BreakoutRoomFlagStatus.unflagged) ?? BreakoutRoomFlagStatus.unflagged, - createdDate: json['createdDate'] == null - ? null - : DateTime.parse(json['createdDate'] as String), + createdDate: dateTimeFromTimestamp(json['createdDate']), record: json['record'] as bool? ?? false, ); @@ -131,7 +129,7 @@ Map _$$_BreakoutRoomToJson(_$_BreakoutRoom instance) => 'originalParticipantIdsAssignment': instance.originalParticipantIdsAssignment, 'flagStatus': _$BreakoutRoomFlagStatusEnumMap[instance.flagStatus]!, - 'createdDate': instance.createdDate?.toIso8601String(), + 'createdDate': serverTimestamp(instance.createdDate), 'record': instance.record, }; @@ -146,20 +144,14 @@ _$_BreakoutRoomSession _$$_BreakoutRoomSessionFromJson( breakoutRoomSessionId: json['breakoutRoomSessionId'] as String, breakoutRoomStatus: $enumDecodeNullable( _$BreakoutRoomStatusEnumMap, json['breakoutRoomStatus']), - statusUpdatedTime: json['statusUpdatedTime'] == null - ? null - : DateTime.parse(json['statusUpdatedTime'] as String), + statusUpdatedTime: dateTimeFromTimestamp(json['statusUpdatedTime']), assignmentMethod: $enumDecode( _$BreakoutAssignmentMethodEnumMap, json['assignmentMethod']), targetParticipantsPerRoom: json['targetParticipantsPerRoom'] as int, hasWaitingRoom: json['hasWaitingRoom'] as bool, maxRoomNumber: json['maxRoomNumber'] as int?, - createdDate: json['createdDate'] == null - ? null - : DateTime.parse(json['createdDate'] as String), - scheduledTime: json['scheduledTime'] == null - ? null - : DateTime.parse(json['scheduledTime'] as String), + createdDate: dateTimeFromTimestamp(json['createdDate']), + scheduledTime: dateTimeFromTimestamp(json['scheduledTime']), processingId: json['processingId'] as String?, ); @@ -169,14 +161,14 @@ Map _$$_BreakoutRoomSessionToJson( 'breakoutRoomSessionId': instance.breakoutRoomSessionId, 'breakoutRoomStatus': _$BreakoutRoomStatusEnumMap[instance.breakoutRoomStatus], - 'statusUpdatedTime': instance.statusUpdatedTime?.toIso8601String(), + 'statusUpdatedTime': serverTimestamp(instance.statusUpdatedTime), 'assignmentMethod': _$BreakoutAssignmentMethodEnumMap[instance.assignmentMethod]!, 'targetParticipantsPerRoom': instance.targetParticipantsPerRoom, 'hasWaitingRoom': instance.hasWaitingRoom, 'maxRoomNumber': instance.maxRoomNumber, - 'createdDate': instance.createdDate?.toIso8601String(), - 'scheduledTime': instance.scheduledTime?.toIso8601String(), + 'createdDate': serverTimestamp(instance.createdDate), + 'scheduledTime': timestampFromDateTime(instance.scheduledTime), 'processingId': instance.processingId, }; diff --git a/data_models/pubspec.lock b/data_models/pubspec.lock index 67c5cea31..73b76686e 100644 --- a/data_models/pubspec.lock +++ b/data_models/pubspec.lock @@ -61,10 +61,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "757153e5d9cd88253cb13f28c2fb55a537dc31fefd98137549895b5beb7c6169" + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "4.0.2" build_resolvers: dependency: transitive description: @@ -77,10 +77,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.13" build_runner_core: dependency: transitive description: @@ -211,13 +211,13 @@ packages: source: hosted version: "2.4.1" frontend_server_client: - dependency: transitive + dependency: "direct dev" description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "4.0.0" glob: dependency: transitive description: @@ -531,4 +531,4 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.4.0 <4.0.0" + dart: ">=3.5.0 <4.0.0" diff --git a/data_models/pubspec.yaml b/data_models/pubspec.yaml index 2a2c80be2..61e2d452b 100644 --- a/data_models/pubspec.yaml +++ b/data_models/pubspec.yaml @@ -17,6 +17,7 @@ dependencies: dev_dependencies: build_runner: ^2.3.3 + frontend_server_client: ^4.0.0 flutter_lints: ^2.0.3 freezed: ^2.4.1 diff --git a/firebase/functions/pubspec.lock b/firebase/functions/pubspec.lock index a3dcfcc76..b50780a96 100644 --- a/firebase/functions/pubspec.lock +++ b/firebase/functions/pubspec.lock @@ -126,10 +126,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" url: "https://pub.dev" source: hosted - version: "2.4.8" + version: "2.4.13" build_runner_core: dependency: transitive description: @@ -315,13 +315,13 @@ packages: source: hosted version: "2.4.1" frontend_server_client: - dependency: transitive + dependency: "direct dev" description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "4.0.0" get_it: dependency: "direct main" description: @@ -846,4 +846,4 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.4.0 <4.0.0" + dart: ">=3.5.0 <4.0.0" diff --git a/firebase/functions/pubspec.yaml b/firebase/functions/pubspec.yaml index f6002c350..d9484e74c 100644 --- a/firebase/functions/pubspec.yaml +++ b/firebase/functions/pubspec.yaml @@ -45,7 +45,8 @@ dependencies: http_parser: ^4.1.0 dev_dependencies: - build_runner: ^2.0.6 + build_runner: ^2.4.13 + frontend_server_client: ^4.0.0 mocktail: 1.0.3 test: ^1.17.10 build_node_compilers: diff --git a/matching/functions/pubspec.lock b/matching/functions/pubspec.lock index de084e1aa..3087acbcb 100644 --- a/matching/functions/pubspec.lock +++ b/matching/functions/pubspec.lock @@ -13,95 +13,95 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "45cfa8471b89fb6643fe9bf51bd7931a76b8f5ec2d65de4fb176dba8d4f22c77" + sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" url: "https://pub.dev" source: hosted - version: "73.0.0" + version: "76.0.0" _macros: dependency: transitive description: dart source: sdk - version: "0.3.2" + version: "0.3.3" analyzer: dependency: transitive description: name: analyzer - sha256: "4959fec185fe70cce007c57e9ab6983101dbe593d2bf8bbfb4453aaec0cf470a" + sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" url: "https://pub.dev" source: hosted - version: "6.8.0" + version: "6.11.0" args: dependency: transitive description: name: args - sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.7.0" async: dependency: transitive description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.13.0" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" build: dependency: transitive description: name: build - sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" build_config: dependency: transitive description: name: build_config - sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" build_daemon: dependency: transitive description: name: build_daemon - sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" + sha256: "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.0.4" build_resolvers: dependency: transitive description: name: build_resolvers - sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + sha256: b9e4fda21d846e192628e7a4f6deda6888c36b5b69ba02ff291a01fd529140f0 url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.4" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" + sha256: "058fe9dce1de7d69c4b84fada934df3e0153dd000758c4d65964d0166779aa99" url: "https://pub.dev" source: hosted - version: "2.4.13" + version: "2.4.15" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 + sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021" url: "https://pub.dev" source: hosted - version: "7.3.2" + version: "8.0.0" built_collection: dependency: transitive description: @@ -114,10 +114,10 @@ packages: dependency: transitive description: name: built_value - sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + sha256: ea90e81dc4a25a043d9bee692d20ed6d1c4a1662a28c03a96417446c093ed6b4 url: "https://pub.dev" source: hosted - version: "8.9.2" + version: "8.9.5" checked_yaml: dependency: transitive description: @@ -130,42 +130,42 @@ packages: dependency: transitive description: name: code_builder - sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 + sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" url: "https://pub.dev" source: hosted - version: "4.10.0" + version: "4.10.1" collection: dependency: transitive description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "1.19.1" convert: dependency: transitive description: name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" coverage: dependency: transitive description: name: coverage - sha256: c1fb2dce3c0085f39dc72668e85f8e0210ec7de05345821ff58530567df345a5 + sha256: e3493833ea012784c740e341952298f1cc77f1f01b1bbc3eb4eecf6984fb7f43 url: "https://pub.dev" source: hosted - version: "1.9.2" + version: "1.11.1" crypto: dependency: transitive description: name: crypto - sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" csv: dependency: "direct main" description: @@ -178,34 +178,34 @@ packages: dependency: "direct dev" description: name: dart_flutter_team_lints - sha256: c6c9c89f4038a64063b67166b2d291d19697a73e111afa42ddcf1840c410c08e + sha256: "4c8f38142598339cd28c0b48a66b6b04434ee0499b6e40baf7c62c76daa1fcad" url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.5.1" dart_style: dependency: transitive description: name: dart_style - sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" + sha256: "7306ab8a2359a48d22310ad823521d723acfed60ee1f7e37388e8986853b6820" url: "https://pub.dev" source: hosted - version: "2.3.7" + version: "2.3.8" file: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" fixnum: dependency: transitive description: name: fixnum - sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" frontend_server_client: dependency: transitive description: @@ -234,10 +234,10 @@ packages: dependency: transitive description: name: glob - sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" google_cloud: dependency: transitive description: @@ -250,10 +250,10 @@ packages: dependency: transitive description: name: google_identity_services_web - sha256: "5be191523702ba8d7a01ca97c17fca096822ccf246b0a9f11923a6ded06199b6" + sha256: "55580f436822d64c8ff9a77e37d61f5fb1e6c7ec9d632a43ee324e2a05c3c6c9" url: "https://pub.dev" source: hosted - version: "0.3.1+4" + version: "0.3.3" googleapis: dependency: transitive description: @@ -290,10 +290,10 @@ packages: dependency: "direct dev" description: name: http - sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 + sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "1.3.0" http_methods: dependency: transitive description: @@ -306,34 +306,34 @@ packages: dependency: transitive description: name: http_multi_server - sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.2" http_parser: dependency: transitive description: name: http_parser - sha256: "40f592dd352890c3b60fec1b68e786cefb9603e05ff303dbc4dda49b304ecdf4" + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" url: "https://pub.dev" source: hosted - version: "4.1.0" + version: "4.1.2" io: dependency: transitive description: name: io - sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.5" js: dependency: transitive description: name: js - sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" url: "https://pub.dev" source: hosted - version: "0.7.1" + version: "0.7.2" json_annotation: dependency: "direct main" description: @@ -346,42 +346,42 @@ packages: dependency: "direct dev" description: name: json_serializable - sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b + sha256: c2fcb3920cf2b6ae6845954186420fca40bc0a8abcc84903b7801f17d7050d7c url: "https://pub.dev" source: hosted - version: "6.8.0" + version: "6.9.0" lints: dependency: transitive description: name: lints - sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" + sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "5.1.1" logging: dependency: transitive description: name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" macros: dependency: transitive description: name: macros - sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" + sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656" url: "https://pub.dev" source: hosted - version: "0.1.2-main.4" + version: "0.1.3-main.0" matcher: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" meta: dependency: transitive description: @@ -410,18 +410,18 @@ packages: dependency: transitive description: name: package_config - sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.0" path: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" pool: dependency: transitive description: @@ -434,18 +434,18 @@ packages: dependency: transitive description: name: pub_semver - sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" pubspec_parse: dependency: transitive description: name: pubspec_parse - sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 + sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.5.0" quiver: dependency: "direct main" description: @@ -498,10 +498,10 @@ packages: dependency: transitive description: name: shelf_web_socket - sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611" + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "3.0.0" source_gen: dependency: transitive description: @@ -514,10 +514,10 @@ packages: dependency: transitive description: name: source_helper - sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" + sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c" url: "https://pub.dev" source: hosted - version: "1.3.4" + version: "1.3.5" source_map_stack_trace: dependency: transitive description: @@ -530,130 +530,130 @@ packages: dependency: transitive description: name: source_maps - sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" url: "https://pub.dev" source: hosted - version: "0.10.12" + version: "0.10.13" source_span: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.1" stack_trace: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" stream_transform: dependency: transitive description: name: stream_transform - sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner - sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.1" term_glyph: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test: dependency: "direct dev" description: name: test - sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f" + sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e" url: "https://pub.dev" source: hosted - version: "1.25.8" + version: "1.25.15" test_api: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.4" test_core: dependency: transitive description: name: test_core - sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d" + sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa" url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.8" test_process: dependency: "direct dev" description: name: test_process - sha256: "217f19b538926e4922bdb2a01410100ec4e3beb4cc48eae5ae6b20037b07bbd6" + sha256: ea79c090deffc87d8276a5d28bb498d080a9873be6b1074d9dcfb82eb87e138e url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" timing: dependency: transitive description: name: timing - sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.2" typed_data: dependency: transitive description: name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.4.0" vm_service: dependency: transitive description: name: vm_service - sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 url: "https://pub.dev" source: hosted - version: "14.3.0" + version: "15.0.0" watcher: dependency: transitive description: name: watcher - sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" web: dependency: transitive description: name: web - sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" web_socket: dependency: transitive description: @@ -666,10 +666,10 @@ packages: dependency: transitive description: name: web_socket_channel - sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" + sha256: "0b8e2457400d8a859b7b2030786835a28a8e80836ef64402abef392ff4f1d0e5" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" webkit_inspection_protocol: dependency: transitive description: @@ -682,9 +682,9 @@ packages: dependency: transitive description: name: yaml - sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.3" sdks: - dart: ">=3.5.0 <4.0.0" + dart: ">=3.7.0 <4.0.0" diff --git a/matching/pubspec.lock b/matching/pubspec.lock index 872b0b333..b13f0d880 100644 --- a/matching/pubspec.lock +++ b/matching/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: "direct main" description: name: args - sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.7.0" csv: dependency: "direct main" description: @@ -18,4 +18,4 @@ packages: source: hosted version: "5.1.1" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.3.0 <4.0.0"