diff --git a/lib/model/app/dependencies.dart b/lib/model/app/dependencies.dart index de4ed2669..1c72094d2 100644 --- a/lib/model/app/dependencies.dart +++ b/lib/model/app/dependencies.dart @@ -370,11 +370,6 @@ class Dependencies { license: mit, sourceUrl: 'https://github.com/brianegan/transparent_image', ), - Dependency( - name: 'Tuple', - license: bsd2, - sourceUrl: 'https://github.com/google/tuple.dart', - ), Dependency( name: 'Vector Math', license: '$zlib, $bsd3', diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index adba0b911..f68db515d 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -49,7 +49,6 @@ import 'package:material_color_utilities/material_color_utilities.dart'; import 'package:overlay_support/overlay_support.dart'; import 'package:provider/provider.dart'; import 'package:screen_brightness/screen_brightness.dart'; -import 'package:tuple/tuple.dart'; import 'package:url_launcher/url_launcher.dart' as ul; class AvesApp extends StatefulWidget { @@ -236,16 +235,14 @@ class _AvesAppState extends State with WidgetsBindingObserver { : AvesScaffold( body: snapshot.hasError ? _buildError(snapshot.error!) : const SizedBox(), ); - return Selector>( - selector: (context, s) => Tuple3( + return Selector( + selector: (context, s) => ( s.locale, s.initialized ? s.themeBrightness : SettingsDefaults.themeBrightness, s.initialized ? s.enableDynamicColor : SettingsDefaults.enableDynamicColor, ), builder: (context, s, child) { - final settingsLocale = s.item1; - final themeBrightness = s.item2; - final enableDynamicColor = s.item3; + final (settingsLocale, themeBrightness, enableDynamicColor) = s; AStyles.updateStylesForLocale(settings.appliedLocale); diff --git a/lib/widgets/collection/app_bar.dart b/lib/widgets/collection/app_bar.dart index 6c2c14b75..542cdede8 100644 --- a/lib/widgets/collection/app_bar.dart +++ b/lib/widgets/collection/app_bar.dart @@ -37,7 +37,6 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class CollectionAppBar extends StatefulWidget { final ValueNotifier appBarHeightNotifier; @@ -647,14 +646,14 @@ class _CollectionAppBarState extends State with SingleTickerPr } Future _configureView() async { - final initialValue = Tuple4( + final initialValue = ( settings.collectionSortFactor, settings.collectionSectionFactor, settings.getTileLayout(CollectionPage.routeName), settings.collectionSortReverse, ); final extentController = context.read(); - final value = await showDialog>( + final value = await showDialog<(EntrySortFactor?, EntryGroupFactor?, TileLayout?, bool)>( context: context, builder: (context) { return TileViewDialog( @@ -672,10 +671,10 @@ class _CollectionAppBarState extends State with SingleTickerPr // wait for the dialog to hide as applying the change may block the UI await Future.delayed(ADurations.dialogTransitionAnimation * timeDilation); if (value != null && initialValue != value) { - settings.collectionSortFactor = value.item1!; - settings.collectionSectionFactor = value.item2!; - settings.setTileLayout(CollectionPage.routeName, value.item3!); - settings.collectionSortReverse = value.item4; + settings.collectionSortFactor = value.$1!; + settings.collectionSectionFactor = value.$2!; + settings.setTileLayout(CollectionPage.routeName, value.$3!); + settings.collectionSortReverse = value.$4; } } diff --git a/lib/widgets/collection/collection_grid.dart b/lib/widgets/collection/collection_grid.dart index 77f8cbc06..974eba8bc 100644 --- a/lib/widgets/collection/collection_grid.dart +++ b/lib/widgets/collection/collection_grid.dart @@ -51,7 +51,6 @@ import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:intl/intl.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class CollectionGrid extends StatefulWidget { final String settingsRouteKey; @@ -132,13 +131,10 @@ class _CollectionGridContentState extends State<_CollectionGridContent> { valueListenable: context.select>((controller) => controller.extentNotifier), builder: (context, thumbnailExtent, child) { assert(thumbnailExtent > 0); - return Selector>( - selector: (context, c) => Tuple4(c.viewportSize.width, c.columnCount, c.spacing, c.horizontalPadding), + return Selector( + selector: (context, c) => (c.viewportSize.width, c.columnCount, c.spacing, c.horizontalPadding), builder: (context, c, child) { - final scrollableWidth = c.item1; - final columnCount = c.item2; - final tileSpacing = c.item3; - final horizontalPadding = c.item4; + final (scrollableWidth, columnCount, tileSpacing, horizontalPadding) = c; final source = collection.source; return GridTheme( extent: thumbnailExtent, @@ -369,9 +365,7 @@ class _CollectionScaler extends StatelessWidget { @override Widget build(BuildContext context) { - final metrics = context.select>((v) => Tuple2(v.spacing, v.horizontalPadding)); - final tileSpacing = metrics.item1; - final horizontalPadding = metrics.item2; + final (tileSpacing, horizontalPadding) = context.select((v) => (v.spacing, v.horizontalPadding)); final brightness = Theme.of(context).brightness; final borderColor = DecoratedThumbnail.borderColor; final borderWidth = DecoratedThumbnail.borderWidth(context); diff --git a/lib/widgets/collection/entry_set_action_delegate.dart b/lib/widgets/collection/entry_set_action_delegate.dart index ace60d48d..09b0bca10 100644 --- a/lib/widgets/collection/entry_set_action_delegate.dart +++ b/lib/widgets/collection/entry_set_action_delegate.dart @@ -45,7 +45,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:latlong2/latlong.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMixin, EntryEditorMixin, EntryStorageMixin { bool isVisible( @@ -709,7 +708,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware final sortedFilters = List.from(filters)..sort(); defaultName = sortedFilters.first.getLabel(context).replaceAll('\n', ' '); } - final result = await showDialog>( + final result = await showDialog<(AvesEntry?, String)>( context: context, builder: (context) => AddShortcutDialog( defaultName: defaultName ?? '', @@ -719,8 +718,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware ); if (result == null) return; - final coverEntry = result.item1; - final name = result.item2; + final (coverEntry, name) = result; if (name.isEmpty) return; await appService.pinToHomeScreen(name, coverEntry, filters: filters); diff --git a/lib/widgets/common/basic/text/animated_diff.dart b/lib/widgets/common/basic/text/animated_diff.dart index 8ac807e14..091804f12 100644 --- a/lib/widgets/common/basic/text/animated_diff.dart +++ b/lib/widgets/common/basic/text/animated_diff.dart @@ -3,7 +3,6 @@ import 'dart:math'; import 'package:aves/utils/diff_match.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; -import 'package:tuple/tuple.dart'; class AnimatedDiffText extends StatefulWidget { final String text; @@ -71,10 +70,7 @@ class _AnimatedDiffTextState extends State with SingleTickerPr return Text.rich( TextSpan( children: _diffs.map((diff) { - final oldText = diff.item1; - final newText = diff.item2; - final oldSize = diff.item3; - final newSize = diff.item4; + final (oldText, newText, oldSize, newSize) = diff; final text = (_animation.value == 0 ? oldText : newText) ?? ''; return WidgetSpan( child: AnimatedSize( @@ -144,26 +140,22 @@ class _AnimatedDiffTextState extends State with SingleTickerPr ..addAll(d.map((diff) { final text = diff.text; final size = textSize(text); - switch (diff.operation) { - case Operation.delete: - return Tuple4(text, null, size, Size.zero); - case Operation.insert: - return Tuple4(null, text, Size.zero, size); - case Operation.equal: - default: - return Tuple4(text, text, size, size); - } + return switch (diff.operation) { + Operation.delete => (text, null, size, Size.zero), + Operation.insert => (null, text, Size.zero, size), + Operation.equal || _ => (text, text, size, size), + }; }).fold>([], (prev, v) { if (prev.isNotEmpty) { final last = prev.last; - final prevNewText = last.item2; + final prevNewText = last.$2; if (prevNewText == null) { // previous diff is a deletion - final thisOldText = v.item1; + final thisOldText = v.$1; if (thisOldText == null) { // this diff is an insertion // merge deletion and insertion as a change operation - final change = Tuple4(last.item1, v.item2, last.item3, v.item4); + final change = (last.$1, v.$2, last.$3, v.$4); return [...prev.take(prev.length - 1), change]; } } @@ -173,4 +165,4 @@ class _AnimatedDiffTextState extends State with SingleTickerPr } } -typedef _TextDiff = Tuple4; +typedef _TextDiff = (String?, String?, Size, Size); diff --git a/lib/widgets/common/grid/sections/fixed/section_layout_builder.dart b/lib/widgets/common/grid/sections/fixed/section_layout_builder.dart index accf3d9d3..e450f2347 100644 --- a/lib/widgets/common/grid/sections/fixed/section_layout_builder.dart +++ b/lib/widgets/common/grid/sections/fixed/section_layout_builder.dart @@ -6,7 +6,6 @@ import 'package:aves/widgets/common/grid/sections/list_layout.dart'; import 'package:aves/widgets/common/grid/sections/section_layout.dart'; import 'package:aves/widgets/common/grid/sections/section_layout_builder.dart'; import 'package:flutter/material.dart'; -import 'package:tuple/tuple.dart'; class FixedExtentSectionLayoutBuilder extends SectionLayoutBuilder { int _currentIndex = 0; @@ -88,7 +87,7 @@ class FixedExtentSectionLayoutBuilder extends SectionLayoutBuilder { section: section, sectionGridIndex: listIndex * columnCount, sectionChildIndex: sectionChildIndex, - itemIndexRange: () => Tuple2( + itemIndexRange: () => ( (sectionChildIndex - 1) * columnCount, sectionChildIndex * columnCount, ), diff --git a/lib/widgets/common/grid/sections/mosaic/section_layout_builder.dart b/lib/widgets/common/grid/sections/mosaic/section_layout_builder.dart index 14a7b6bcb..4be25c6e6 100644 --- a/lib/widgets/common/grid/sections/mosaic/section_layout_builder.dart +++ b/lib/widgets/common/grid/sections/mosaic/section_layout_builder.dart @@ -11,7 +11,6 @@ import 'package:aves/widgets/common/grid/sections/section_layout_builder.dart'; import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:tuple/tuple.dart'; class MosaicSectionLayoutBuilder extends SectionLayoutBuilder { int _currentIndex = 0; @@ -110,7 +109,7 @@ class MosaicSectionLayoutBuilder extends SectionLayoutBuilder { section: section, sectionGridIndex: sectionGridIndex, sectionChildIndex: sectionChildIndex, - itemIndexRange: () => isHeader ? const Tuple2(0, 0) : Tuple2(row.firstIndex, row.lastIndex + 1), + itemIndexRange: () => isHeader ? const (0, 0) : (row.firstIndex, row.lastIndex + 1), sectionKey: sectionKey, headerExtent: headerExtent, itemSizes: row.itemWidths.map((v) => Size(v, row.height)).toList(), diff --git a/lib/widgets/common/grid/sections/section_layout_builder.dart b/lib/widgets/common/grid/sections/section_layout_builder.dart index 27866181d..2be7e970f 100644 --- a/lib/widgets/common/grid/sections/section_layout_builder.dart +++ b/lib/widgets/common/grid/sections/section_layout_builder.dart @@ -6,7 +6,6 @@ import 'package:aves_model/aves_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; typedef TileBuilder = Widget Function(T item, Size tileSize); @@ -54,7 +53,7 @@ abstract class SectionLayoutBuilder { required List section, required int sectionGridIndex, required int sectionChildIndex, - required Tuple2 Function() itemIndexRange, + required (int, int) Function() itemIndexRange, required SectionKey sectionKey, required double headerExtent, required List itemSizes, @@ -68,8 +67,8 @@ abstract class SectionLayoutBuilder { final sectionItemCount = section.length; final itemMinMax = itemIndexRange(); - final minItemIndex = itemMinMax.item1.clamp(0, sectionItemCount); - final maxItemIndex = itemMinMax.item2.clamp(0, sectionItemCount); + final minItemIndex = itemMinMax.$1.clamp(0, sectionItemCount); + final maxItemIndex = itemMinMax.$2.clamp(0, sectionItemCount); final childrenCount = maxItemIndex - minItemIndex; final children = []; for (var i = 0; i < childrenCount; i++) { diff --git a/lib/widgets/dialogs/add_shortcut_dialog.dart b/lib/widgets/dialogs/add_shortcut_dialog.dart index b0e30f667..308a2d1a1 100644 --- a/lib/widgets/dialogs/add_shortcut_dialog.dart +++ b/lib/widgets/dialogs/add_shortcut_dialog.dart @@ -8,7 +8,6 @@ import 'package:aves/widgets/dialogs/item_picker.dart'; import 'package:aves/widgets/dialogs/pick_dialogs/item_pick_page.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; -import 'package:tuple/tuple.dart'; import 'aves_dialog.dart'; @@ -142,7 +141,7 @@ class _AddShortcutDialogState extends State { void _submit(BuildContext context) { if (_isValidNotifier.value) { - Navigator.maybeOf(context)?.pop(Tuple2(_coverEntry, _nameController.text)); + Navigator.maybeOf(context)?.pop<(AvesEntry?, String)>((_coverEntry, _nameController.text)); } } } diff --git a/lib/widgets/dialogs/filter_editors/cover_selection_dialog.dart b/lib/widgets/dialogs/filter_editors/cover_selection_dialog.dart index 3a3c8db7d..57d093628 100644 --- a/lib/widgets/dialogs/filter_editors/cover_selection_dialog.dart +++ b/lib/widgets/dialogs/filter_editors/cover_selection_dialog.dart @@ -20,7 +20,6 @@ import 'package:aves_model/aves_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class CoverSelectionDialog extends StatefulWidget { static const routeName = '/dialog/select_cover'; @@ -81,8 +80,8 @@ class _CoverSelectionDialogState extends State { @override Widget build(BuildContext context) { final l10n = context.l10n; - final tabs = >[ - Tuple2( + final tabs = <(Tab, Widget)>[ + ( _buildTab( context, const Key('tab-entry'), @@ -92,7 +91,7 @@ class _CoverSelectionDialogState extends State { Column(children: _buildEntryOptions()), ), if (showAppTab) - Tuple2( + ( _buildTab( context, const Key('tab-package'), @@ -102,7 +101,7 @@ class _CoverSelectionDialogState extends State { Column(children: _buildAppOptions()), ), if (showColorTab) - Tuple2( + ( _buildTab( context, const Key('tab-color'), @@ -131,7 +130,7 @@ class _CoverSelectionDialogState extends State { clipBehavior: Clip.antiAlias, child: TabBar( indicatorWeight: tabIndicatorWeight, - tabs: tabs.map((t) => t.item1).toList(), + tabs: tabs.map((t) => t.$1).toList(), ), ), ConstrainedBox( @@ -140,7 +139,7 @@ class _CoverSelectionDialogState extends State { physics: const NeverScrollableScrollPhysics(), children: tabs .map((t) => SingleChildScrollView( - child: t.item2, + child: t.$2, )) .toList(), ), @@ -165,7 +164,7 @@ class _CoverSelectionDialogState extends State { final entry = _isCustomEntry ? _customEntry : null; final package = _isCustomPackage ? _customPackage : null; final color = _isCustomColor ? _customColor : null; - return Navigator.maybeOf(context)?.pop(Tuple3(entry, package, color)); + return Navigator.maybeOf(context)?.pop<(AvesEntry?, String?, Color?)>((entry, package, color)); }, child: Text(l10n.applyButtonLabel), ) diff --git a/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart b/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart index 3771a14df..c2055cb6d 100644 --- a/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart +++ b/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart @@ -27,7 +27,6 @@ import 'package:aves_model/aves_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; Future pickAlbum({ required BuildContext context, @@ -94,8 +93,8 @@ class _AlbumPickPageState extends State<_AlbumPickPage> { Widget build(BuildContext context) { return ListenableProvider>.value( value: ValueNotifier(AppMode.pickFilterInternal), - child: Selector>( - selector: (context, s) => Tuple2(s.albumGroupFactor, s.albumSortFactor), + child: Selector( + selector: (context, s) => (s.albumGroupFactor, s.albumSortFactor), builder: (context, s, child) { return StreamBuilder( stream: source.eventBus.on(), diff --git a/lib/widgets/dialogs/tile_view_dialog.dart b/lib/widgets/dialogs/tile_view_dialog.dart index db8501c5c..2c0af6253 100644 --- a/lib/widgets/dialogs/tile_view_dialog.dart +++ b/lib/widgets/dialogs/tile_view_dialog.dart @@ -11,14 +11,13 @@ import 'package:aves/widgets/common/identity/highlight_title.dart'; import 'package:aves/widgets/common/tile_extent_controller.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; import 'aves_dialog.dart'; class TileViewDialog extends StatefulWidget { static const routeName = '/dialog/tile_view'; - final Tuple4 initialValue; + final (S? sort, G? group, L? layout, bool reverse) initialValue; final List> sortOptions; final List> groupOptions; final List> layoutOptions; @@ -63,10 +62,10 @@ class _TileViewDialogState extends State> with void initState() { super.initState(); final initialValue = widget.initialValue; - _selectedSort = initialValue.item1; - _selectedGroup = initialValue.item2; - _selectedLayout = initialValue.item3; - _reverseSort = initialValue.item4; + _selectedSort = initialValue.$1; + _selectedGroup = initialValue.$2; + _selectedLayout = initialValue.$3; + _reverseSort = initialValue.$4; final extentController = tileExtentController; final columnRange = extentController.effectiveColumnRange; @@ -147,7 +146,7 @@ class _TileViewDialogState extends State> with key: const Key('button-apply'), onPressed: () { tileExtentController.setUserPreferredColumnCount(_columnCountNotifier.value); - Navigator.maybeOf(context)?.pop(Tuple4(_selectedSort, _selectedGroup, _selectedLayout, _reverseSort)); + Navigator.maybeOf(context)?.pop<(S?, G?, L?, bool)>((_selectedSort, _selectedGroup, _selectedLayout, _reverseSort)); }, child: Text(l10n.applyButtonLabel), ) diff --git a/lib/widgets/dialogs/wallpaper_settings_dialog.dart b/lib/widgets/dialogs/wallpaper_settings_dialog.dart index 9b3b759ff..20cddd718 100644 --- a/lib/widgets/dialogs/wallpaper_settings_dialog.dart +++ b/lib/widgets/dialogs/wallpaper_settings_dialog.dart @@ -5,7 +5,6 @@ import 'package:aves/widgets/dialogs/aves_dialog.dart'; import 'package:aves/widgets/dialogs/selection_dialogs/radio_list_tile.dart'; import 'package:aves_model/aves_model.dart'; import 'package:flutter/material.dart'; -import 'package:tuple/tuple.dart'; class WallpaperSettingsDialog extends StatefulWidget { static const routeName = '/dialog/wallpaper_settings'; @@ -43,7 +42,7 @@ class _WallpaperSettingsDialogState extends State { actions: [ const CancelButton(), TextButton( - onPressed: () => Navigator.maybeOf(context)?.pop(Tuple2(_selectedTarget, _useScrollEffect)), + onPressed: () => Navigator.maybeOf(context)?.pop<(WallpaperTarget, bool)>((_selectedTarget, _useScrollEffect)), child: Text(context.l10n.applyButtonLabel), ), ], diff --git a/lib/widgets/editor/transform/control_panel.dart b/lib/widgets/editor/transform/control_panel.dart index 4615563bd..47a5f41ae 100644 --- a/lib/widgets/editor/transform/control_panel.dart +++ b/lib/widgets/editor/transform/control_panel.dart @@ -13,7 +13,6 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class TransformControlPanel extends StatefulWidget { final AvesEntry entry; @@ -32,7 +31,7 @@ class TransformControlPanel extends StatefulWidget { } class _TransformControlPanelState extends State with TickerProviderStateMixin { - late final List> _tabs; + late final List<(WidgetBuilder, WidgetBuilder)> _tabs; late final TabController _tabController; static const padding = EditorControlPanel.padding; @@ -41,11 +40,11 @@ class _TransformControlPanelState extends State with Tick void initState() { super.initState(); _tabs = [ - Tuple2( + ( (context) => Tab(text: context.l10n.editorTransformCrop), (context) => const CropControlPanel(), ), - Tuple2( + ( (context) => Tab(text: context.l10n.editorTransformRotate), (context) => const RotationControlPanel(), ), @@ -74,7 +73,7 @@ class _TransformControlPanelState extends State with Tick builder: (context, child) { return AnimatedSwitcher( duration: context.select((v) => v.formTransition), - child: _tabs[_tabController.index].item2(context), + child: _tabs[_tabController.index].$2(context), ); }, ), @@ -87,7 +86,7 @@ class _TransformControlPanelState extends State with Tick ), Expanded( child: TabBar( - tabs: _tabs.map((v) => v.item1(context)).toList(), + tabs: _tabs.map((v) => v.$1(context)).toList(), controller: _tabController, padding: const EdgeInsets.symmetric(horizontal: padding), indicatorSize: TabBarIndicatorSize.label, diff --git a/lib/widgets/filter_grids/albums_page.dart b/lib/widgets/filter_grids/albums_page.dart index a40a79a66..fd346316d 100644 --- a/lib/widgets/filter_grids/albums_page.dart +++ b/lib/widgets/filter_grids/albums_page.dart @@ -17,7 +17,6 @@ import 'package:aves_model/aves_model.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class AlbumListPage extends StatelessWidget { static const routeName = '/albums'; @@ -27,12 +26,12 @@ class AlbumListPage extends StatelessWidget { @override Widget build(BuildContext context) { final source = context.read(); - return Selector>>( - selector: (context, s) => Tuple4(s.albumGroupFactor, s.albumSortFactor, s.albumSortReverse, s.pinnedFilters), + return Selector)>( + selector: (context, s) => (s.albumGroupFactor, s.albumSortFactor, s.albumSortReverse, s.pinnedFilters), shouldRebuild: (t1, t2) { - // `Selector` by default uses `DeepCollectionEquality`, which does not go deep in collections within `TupleN` + // `Selector` by default uses `DeepCollectionEquality`, which does not go deep in collections within records const eq = DeepCollectionEquality(); - return !(eq.equals(t1.item1, t2.item1) && eq.equals(t1.item2, t2.item2) && eq.equals(t1.item3, t2.item3) && eq.equals(t1.item4, t2.item4)); + return !(eq.equals(t1.$1, t2.$1) && eq.equals(t1.$2, t2.$2) && eq.equals(t1.$3, t2.$3) && eq.equals(t1.$4, t2.$4)); }, builder: (context, s, child) { return ValueListenableBuilder( diff --git a/lib/widgets/filter_grids/common/action_delegates/album_set.dart b/lib/widgets/filter_grids/common/action_delegates/album_set.dart index 45497f459..d0bcbaf80 100644 --- a/lib/widgets/filter_grids/common/action_delegates/album_set.dart +++ b/lib/widgets/filter_grids/common/action_delegates/album_set.dart @@ -32,7 +32,6 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class AlbumChipSetActionDelegate extends ChipSetActionDelegate with EntryStorageMixin { final Iterable> _items; @@ -168,14 +167,14 @@ class AlbumChipSetActionDelegate extends ChipSetActionDelegate with @override Future configureView(BuildContext context) async { - final initialValue = Tuple4( + final initialValue = ( sortFactor, settings.albumGroupFactor, tileLayout, sortReverse, ); final extentController = context.read(); - final value = await showDialog>( + final value = await showDialog<(ChipSortFactor?, AlbumChipGroupFactor?, TileLayout?, bool)>( context: context, builder: (context) { return TileViewDialog( @@ -192,10 +191,10 @@ class AlbumChipSetActionDelegate extends ChipSetActionDelegate with // wait for the dialog to hide as applying the change may block the UI await Future.delayed(ADurations.dialogTransitionAnimation * timeDilation); if (value != null && initialValue != value) { - sortFactor = value.item1!; - settings.albumGroupFactor = value.item2!; - tileLayout = value.item3!; - sortReverse = value.item4; + sortFactor = value.$1!; + settings.albumGroupFactor = value.$2!; + tileLayout = value.$3!; + sortReverse = value.$4; } } diff --git a/lib/widgets/filter_grids/common/action_delegates/chip_set.dart b/lib/widgets/filter_grids/common/action_delegates/chip_set.dart index 5fed06d3a..daf10d73d 100644 --- a/lib/widgets/filter_grids/common/action_delegates/chip_set.dart +++ b/lib/widgets/filter_grids/common/action_delegates/chip_set.dart @@ -31,7 +31,6 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; abstract class ChipSetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMixin, VaultAwareMixin { Iterable> get allItems; @@ -216,14 +215,14 @@ abstract class ChipSetActionDelegate with FeedbackMi } Future configureView(BuildContext context) async { - final initialValue = Tuple4( + final initialValue = ( sortFactor, null, tileLayout, sortReverse, ); final extentController = context.read(); - final value = await showDialog>( + final value = await showDialog<(ChipSortFactor?, void, TileLayout?, bool)>( context: context, builder: (context) { return TileViewDialog( @@ -239,9 +238,9 @@ abstract class ChipSetActionDelegate with FeedbackMi // wait for the dialog to hide as applying the change may block the UI await Future.delayed(ADurations.dialogTransitionAnimation * timeDilation); if (value != null && initialValue != value) { - sortFactor = value.item1!; - tileLayout = value.item3!; - sortReverse = value.item4; + sortFactor = value.$1!; + tileLayout = value.$3!; + sortReverse = value.$4; } } @@ -328,7 +327,7 @@ abstract class ChipSetActionDelegate with FeedbackMi final existingCover = covers.of(filter); final entryId = existingCover?.$1; final customEntry = entryId != null ? context.read().visibleEntries.firstWhereOrNull((entry) => entry.id == entryId) : null; - final selectedCover = await showDialog>( + final selectedCover = await showDialog<(AvesEntry?, String?, Color?)>( context: context, builder: (context) => CoverSelectionDialog( filter: filter, @@ -344,9 +343,7 @@ abstract class ChipSetActionDelegate with FeedbackMi context.read().clearAppColor(filter.album); } - final selectedEntry = selectedCover.item1; - final selectedPackage = selectedCover.item2; - final selectedColor = selectedCover.item3; + final (selectedEntry, selectedPackage, selectedColor) = selectedCover; await covers.set( filter: filter, entryId: selectedEntry?.id, diff --git a/lib/widgets/filter_grids/common/filter_grid_page.dart b/lib/widgets/filter_grids/common/filter_grid_page.dart index 08e77f989..abc85db03 100644 --- a/lib/widgets/filter_grids/common/filter_grid_page.dart +++ b/lib/widgets/filter_grids/common/filter_grid_page.dart @@ -46,7 +46,6 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; typedef QueryTest = List> Function(BuildContext context, List> filters, String query); @@ -317,13 +316,10 @@ class _FilterGridContentState extends State<_FilterG final sectionedListLayoutProvider = ValueListenableBuilder( valueListenable: context.select>((controller) => controller.extentNotifier), builder: (context, thumbnailExtent, child) { - return Selector>( - selector: (context, c) => Tuple4(c.viewportSize.width, c.columnCount, c.spacing, c.horizontalPadding), + return Selector( + selector: (context, c) => (c.viewportSize.width, c.columnCount, c.spacing, c.horizontalPadding), builder: (context, c, child) { - final scrollableWidth = c.item1; - final columnCount = c.item2; - final tileSpacing = c.item3; - final horizontalPadding = c.item4; + final (scrollableWidth, columnCount, tileSpacing, horizontalPadding) = c; // do not listen for animation delay change final target = context.read().staggeredAnimationPageTarget; final tileAnimationDelay = context.read().getTileAnimationDelay(target); @@ -571,9 +567,7 @@ class _FilterScaler extends StatelessWidget { @override Widget build(BuildContext context) { final textScaleFactor = MediaQuery.textScaleFactorOf(context); - final metrics = context.select>((v) => Tuple2(v.spacing, v.horizontalPadding)); - final tileSpacing = metrics.item1; - final horizontalPadding = metrics.item2; + final (tileSpacing, horizontalPadding) = context.select((v) => (v.spacing, v.horizontalPadding)); final brightness = Theme.of(context).brightness; return GridScaleGestureDetector>( scrollableKey: scrollableKey, diff --git a/lib/widgets/filter_grids/countries_page.dart b/lib/widgets/filter_grids/countries_page.dart index dcaf5e879..a26858939 100644 --- a/lib/widgets/filter_grids/countries_page.dart +++ b/lib/widgets/filter_grids/countries_page.dart @@ -13,7 +13,6 @@ import 'package:aves_model/aves_model.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class CountryListPage extends StatelessWidget { static const routeName = '/countries'; @@ -23,12 +22,12 @@ class CountryListPage extends StatelessWidget { @override Widget build(BuildContext context) { final source = context.read(); - return Selector>>( - selector: (context, s) => Tuple3(s.countrySortFactor, s.countrySortReverse, s.pinnedFilters), + return Selector)>( + selector: (context, s) => (s.countrySortFactor, s.countrySortReverse, s.pinnedFilters), shouldRebuild: (t1, t2) { - // `Selector` by default uses `DeepCollectionEquality`, which does not go deep in collections within `TupleN` + // `Selector` by default uses `DeepCollectionEquality`, which does not go deep in collections within records const eq = DeepCollectionEquality(); - return !(eq.equals(t1.item1, t2.item1) && eq.equals(t1.item2, t2.item2) && eq.equals(t1.item3, t2.item3)); + return !(eq.equals(t1.$1, t2.$1) && eq.equals(t1.$2, t2.$2) && eq.equals(t1.$3, t2.$3)); }, builder: (context, s, child) { return StreamBuilder( diff --git a/lib/widgets/filter_grids/places_page.dart b/lib/widgets/filter_grids/places_page.dart index e29dc1c97..c0b456a75 100644 --- a/lib/widgets/filter_grids/places_page.dart +++ b/lib/widgets/filter_grids/places_page.dart @@ -13,7 +13,6 @@ import 'package:aves_model/aves_model.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class PlaceListPage extends StatelessWidget { static const routeName = '/places'; @@ -23,12 +22,12 @@ class PlaceListPage extends StatelessWidget { @override Widget build(BuildContext context) { final source = context.read(); - return Selector>>( - selector: (context, s) => Tuple3(s.placeSortFactor, s.placeSortReverse, s.pinnedFilters), + return Selector)>( + selector: (context, s) => (s.placeSortFactor, s.placeSortReverse, s.pinnedFilters), shouldRebuild: (t1, t2) { - // `Selector` by default uses `DeepCollectionEquality`, which does not go deep in collections within `TupleN` + // `Selector` by default uses `DeepCollectionEquality`, which does not go deep in collections within records const eq = DeepCollectionEquality(); - return !(eq.equals(t1.item1, t2.item1) && eq.equals(t1.item2, t2.item2) && eq.equals(t1.item3, t2.item3)); + return !(eq.equals(t1.$1, t2.$1) && eq.equals(t1.$2, t2.$2) && eq.equals(t1.$3, t2.$3)); }, builder: (context, s, child) { return StreamBuilder( diff --git a/lib/widgets/filter_grids/states_page.dart b/lib/widgets/filter_grids/states_page.dart index 03c4a7dd6..b905bf794 100644 --- a/lib/widgets/filter_grids/states_page.dart +++ b/lib/widgets/filter_grids/states_page.dart @@ -14,7 +14,6 @@ import 'package:aves_model/aves_model.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class StateListPage extends StatelessWidget { static const routeName = '/states'; @@ -29,12 +28,12 @@ class StateListPage extends StatelessWidget { @override Widget build(BuildContext context) { final source = context.read(); - return Selector>>( - selector: (context, s) => Tuple3(s.stateSortFactor, s.stateSortReverse, s.pinnedFilters), + return Selector)>( + selector: (context, s) => (s.stateSortFactor, s.stateSortReverse, s.pinnedFilters), shouldRebuild: (t1, t2) { - // `Selector` by default uses `DeepCollectionEquality`, which does not go deep in collections within `TupleN` + // `Selector` by default uses `DeepCollectionEquality`, which does not go deep in collections within records const eq = DeepCollectionEquality(); - return !(eq.equals(t1.item1, t2.item1) && eq.equals(t1.item2, t2.item2) && eq.equals(t1.item3, t2.item3)); + return !(eq.equals(t1.$1, t2.$1) && eq.equals(t1.$2, t2.$2) && eq.equals(t1.$3, t2.$3)); }, builder: (context, s, child) { return StreamBuilder( diff --git a/lib/widgets/filter_grids/tags_page.dart b/lib/widgets/filter_grids/tags_page.dart index f34d44ed1..70deab605 100644 --- a/lib/widgets/filter_grids/tags_page.dart +++ b/lib/widgets/filter_grids/tags_page.dart @@ -13,7 +13,6 @@ import 'package:aves_model/aves_model.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class TagListPage extends StatelessWidget { static const routeName = '/tags'; @@ -23,12 +22,12 @@ class TagListPage extends StatelessWidget { @override Widget build(BuildContext context) { final source = context.read(); - return Selector>>( - selector: (context, s) => Tuple3(s.tagSortFactor, s.tagSortReverse, s.pinnedFilters), + return Selector)>( + selector: (context, s) => (s.tagSortFactor, s.tagSortReverse, s.pinnedFilters), shouldRebuild: (t1, t2) { - // `Selector` by default uses `DeepCollectionEquality`, which does not go deep in collections within `TupleN` + // `Selector` by default uses `DeepCollectionEquality`, which does not go deep in collections within records const eq = DeepCollectionEquality(); - return !(eq.equals(t1.item1, t2.item1) && eq.equals(t1.item2, t2.item2) && eq.equals(t1.item3, t2.item3)); + return !(eq.equals(t1.$1, t2.$1) && eq.equals(t1.$2, t2.$2) && eq.equals(t1.$3, t2.$3)); }, builder: (context, s, child) { return StreamBuilder( diff --git a/lib/widgets/settings/navigation/drawer.dart b/lib/widgets/settings/navigation/drawer.dart index 20e5a948e..cd82b9a34 100644 --- a/lib/widgets/settings/navigation/drawer.dart +++ b/lib/widgets/settings/navigation/drawer.dart @@ -15,7 +15,6 @@ import 'package:aves/widgets/settings/navigation/drawer_tab_albums.dart'; import 'package:aves/widgets/settings/navigation/drawer_tab_fixed.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:tuple/tuple.dart'; class NavigationDrawerEditorPage extends StatefulWidget { static const routeName = '/settings/navigation_drawer'; @@ -65,8 +64,8 @@ class _NavigationDrawerEditorPageState extends State @override Widget build(BuildContext context) { final l10n = context.l10n; - final tabs = >[ - Tuple2( + final tabs = <(Tab, Widget)>[ + ( Tab(text: l10n.settingsNavigationDrawerTabTypes), DrawerFixedListTab( items: _typeItems, @@ -75,13 +74,13 @@ class _NavigationDrawerEditorPageState extends State title: (item) => DrawerFilterTitle(filter: item), ), ), - Tuple2( + ( Tab(text: l10n.settingsNavigationDrawerTabAlbums), DrawerAlbumTab( items: _albumItems, ), ), - Tuple2( + ( Tab(text: l10n.settingsNavigationDrawerTabPages), DrawerFixedListTab( items: _pageItems, @@ -99,7 +98,7 @@ class _NavigationDrawerEditorPageState extends State automaticallyImplyLeading: !settings.useTvLayout, title: Text(l10n.settingsNavigationDrawerEditorPageTitle), bottom: TabBar( - tabs: tabs.map((t) => t.item1).toList(), + tabs: tabs.map((t) => t.$1).toList(), ), ), body: WillPopScope( @@ -111,7 +110,7 @@ class _NavigationDrawerEditorPageState extends State }, child: SafeArea( child: TabBarView( - children: tabs.map((t) => t.item2).toList(), + children: tabs.map((t) => t.$2).toList(), ), ), ), diff --git a/lib/widgets/settings/privacy/hidden_items_page.dart b/lib/widgets/settings/privacy/hidden_items_page.dart index 98286221f..bd5f602da 100644 --- a/lib/widgets/settings/privacy/hidden_items_page.dart +++ b/lib/widgets/settings/privacy/hidden_items_page.dart @@ -13,7 +13,6 @@ import 'package:aves/widgets/settings/privacy/file_picker/file_picker_page.dart' import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class HiddenItemsPage extends StatelessWidget { static const routeName = '/settings/hidden_items'; @@ -23,12 +22,12 @@ class HiddenItemsPage extends StatelessWidget { @override Widget build(BuildContext context) { final l10n = context.l10n; - final tabs = >[ - Tuple2( + final tabs = <(Tab, Widget)>[ + ( Tab(text: l10n.settingsHiddenItemsTabFilters), const _HiddenFilters(), ), - Tuple2( + ( Tab(text: l10n.settingsHiddenItemsTabPaths), const _HiddenPaths(), ), @@ -41,12 +40,12 @@ class HiddenItemsPage extends StatelessWidget { automaticallyImplyLeading: !settings.useTvLayout, title: Text(l10n.settingsHiddenItemsPageTitle), bottom: TabBar( - tabs: tabs.map((t) => t.item1).toList(), + tabs: tabs.map((t) => t.$1).toList(), ), ), body: SafeArea( child: TabBarView( - children: tabs.map((t) => t.item2).toList(), + children: tabs.map((t) => t.$2).toList(), ), ), ), diff --git a/lib/widgets/settings/thumbnails/collection_actions_editor_page.dart b/lib/widgets/settings/thumbnails/collection_actions_editor_page.dart index 551612110..c16762cd7 100644 --- a/lib/widgets/settings/thumbnails/collection_actions_editor_page.dart +++ b/lib/widgets/settings/thumbnails/collection_actions_editor_page.dart @@ -5,7 +5,6 @@ import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/settings/common/quick_actions/editor_page.dart'; import 'package:aves_model/aves_model.dart'; import 'package:flutter/material.dart'; -import 'package:tuple/tuple.dart'; class CollectionActionEditorPage extends StatelessWidget { static const routeName = '/settings/collection_actions'; @@ -15,8 +14,8 @@ class CollectionActionEditorPage extends StatelessWidget { @override Widget build(BuildContext context) { final l10n = context.l10n; - final tabs = >[ - Tuple2( + final tabs = <(Tab, Widget)>[ + ( Tab(text: l10n.settingsCollectionQuickActionTabBrowsing), QuickActionEditorBody( bannerText: context.l10n.settingsCollectionBrowsingQuickActionEditorBanner, @@ -27,7 +26,7 @@ class CollectionActionEditorPage extends StatelessWidget { save: (actions) => settings.collectionBrowsingQuickActions = actions, ), ), - Tuple2( + ( Tab(text: l10n.settingsCollectionQuickActionTabSelecting), QuickActionEditorBody( bannerText: context.l10n.settingsCollectionSelectionQuickActionEditorBanner, @@ -49,12 +48,12 @@ class CollectionActionEditorPage extends StatelessWidget { appBar: AppBar( title: Text(context.l10n.settingsCollectionQuickActionEditorPageTitle), bottom: TabBar( - tabs: tabs.map((t) => t.item1).toList(), + tabs: tabs.map((t) => t.$1).toList(), ), ), body: SafeArea( child: TabBarView( - children: tabs.map((t) => t.item2).toList(), + children: tabs.map((t) => t.$2).toList(), ), ), ), diff --git a/lib/widgets/settings/viewer/overlay.dart b/lib/widgets/settings/viewer/overlay.dart index f58326f1f..df9726ba7 100644 --- a/lib/widgets/settings/viewer/overlay.dart +++ b/lib/widgets/settings/viewer/overlay.dart @@ -6,7 +6,6 @@ import 'package:aves/widgets/settings/common/tiles.dart'; import 'package:aves_model/aves_model.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class ViewerOverlayPage extends StatelessWidget { static const routeName = '/settings/viewer/overlay'; @@ -36,11 +35,10 @@ class ViewerOverlayPage extends StatelessWidget { title: context.l10n.settingsViewerShowInformation, subtitle: context.l10n.settingsViewerShowInformationSubtitle, ), - Selector>( - selector: (context, s) => Tuple2(s.showOverlayInfo, s.showOverlayRatingTags), + Selector( + selector: (context, s) => (s.showOverlayInfo, s.showOverlayRatingTags), builder: (context, s, child) { - final showInfo = s.item1; - final current = s.item2; + final (showInfo, current) = s; return SwitchListTile( value: current, onChanged: showInfo ? (v) => settings.showOverlayRatingTags = v : null, @@ -48,11 +46,10 @@ class ViewerOverlayPage extends StatelessWidget { ); }, ), - Selector>( - selector: (context, s) => Tuple2(s.showOverlayInfo, s.showOverlayShootingDetails), + Selector( + selector: (context, s) => (s.showOverlayInfo, s.showOverlayShootingDetails), builder: (context, s, child) { - final showInfo = s.item1; - final current = s.item2; + final (showInfo, current) = s; return SwitchListTile( value: current, onChanged: showInfo ? (v) => settings.showOverlayShootingDetails = v : null, @@ -60,11 +57,10 @@ class ViewerOverlayPage extends StatelessWidget { ); }, ), - Selector>( - selector: (context, s) => Tuple2(s.showOverlayInfo, s.showOverlayDescription), + Selector( + selector: (context, s) => (s.showOverlayInfo, s.showOverlayDescription), builder: (context, s, child) { - final showInfo = s.item1; - final current = s.item2; + final (showInfo, current) = s; return SwitchListTile( value: current, onChanged: showInfo ? (v) => settings.showOverlayDescription = v : null, diff --git a/lib/widgets/viewer/action/entry_action_delegate.dart b/lib/widgets/viewer/action/entry_action_delegate.dart index 32bdc7f7e..7da87dd81 100644 --- a/lib/widgets/viewer/action/entry_action_delegate.dart +++ b/lib/widgets/viewer/action/entry_action_delegate.dart @@ -39,7 +39,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMixin, SingleEntryEditorMixin, EntryStorageMixin, VaultAwareMixin { final AvesEntry mainEntry, pageEntry; @@ -325,7 +324,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix } Future _addShortcut(BuildContext context, AvesEntry targetEntry) async { - final result = await showDialog>( + final result = await showDialog<(AvesEntry?, String)>( context: context, builder: (context) => AddShortcutDialog( defaultName: targetEntry.bestTitle ?? '', @@ -334,7 +333,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix ); if (result == null) return; - final name = result.item2; + final name = result.$2; if (name.isEmpty) return; await appService.pinToHomeScreen(name, targetEntry, uri: targetEntry.uri); diff --git a/lib/widgets/viewer/debug/debug_page.dart b/lib/widgets/viewer/debug/debug_page.dart index a987e9a6b..833bda5c2 100644 --- a/lib/widgets/viewer/debug/debug_page.dart +++ b/lib/widgets/viewer/debug/debug_page.dart @@ -12,7 +12,6 @@ import 'package:aves/widgets/viewer/info/common.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class ViewerDebugPage extends StatelessWidget { static const routeName = '/viewer/debug'; @@ -26,11 +25,11 @@ class ViewerDebugPage extends StatelessWidget { @override Widget build(BuildContext context) { - final tabs = >[ - Tuple2(const Tab(text: 'Entry'), _buildEntryTabView()), - if (context.select, bool>((vn) => vn.value != AppMode.view)) Tuple2(const Tab(text: 'DB'), DbTab(entry: entry)), - Tuple2(const Tab(icon: Icon(AIcons.android)), MetadataTab(entry: entry)), - Tuple2(const Tab(icon: Icon(AIcons.image)), _buildThumbnailsTabView()), + final tabs = <(Tab, Widget)>[ + (const Tab(text: 'Entry'), _buildEntryTabView()), + if (context.select, bool>((vn) => vn.value != AppMode.view)) (const Tab(text: 'DB'), DbTab(entry: entry)), + (const Tab(icon: Icon(AIcons.android)), MetadataTab(entry: entry)), + (const Tab(icon: Icon(AIcons.image)), _buildThumbnailsTabView()), ]; return Directionality( textDirection: TextDirection.ltr, @@ -40,12 +39,12 @@ class ViewerDebugPage extends StatelessWidget { appBar: AppBar( title: const Text('Debug'), bottom: TabBar( - tabs: tabs.map((t) => t.item1).toList(), + tabs: tabs.map((t) => t.$1).toList(), ), ), body: SafeArea( child: TabBarView( - children: tabs.map((t) => t.item2).toList(), + children: tabs.map((t) => t.$2).toList(), ), ), ), diff --git a/lib/widgets/viewer/info/metadata/xmp_card.dart b/lib/widgets/viewer/info/metadata/xmp_card.dart index 4550faa48..ac359fa52 100644 --- a/lib/widgets/viewer/info/metadata/xmp_card.dart +++ b/lib/widgets/viewer/info/metadata/xmp_card.dart @@ -9,9 +9,8 @@ import 'package:aves/widgets/viewer/info/common.dart'; import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; -import 'package:tuple/tuple.dart'; -typedef XmpExtractedCard = Tuple2, List?>; +typedef XmpExtractedCard = (Map, List?); class XmpCard extends StatefulWidget { final String title; @@ -30,7 +29,7 @@ class XmpCard extends StatefulWidget { directStruct = structByIndex[null]; final length = structByIndex.keys.whereNotNull().fold(0, max); - indexedStructs = length > 0 ? [for (var i = 0; i < length; i++) structByIndex[i + 1] ?? const Tuple2({}, null)] : null; + indexedStructs = length > 0 ? [for (var i = 0; i < length; i++) structByIndex[i + 1] ?? const ({}, null)] : null; } @override @@ -77,8 +76,8 @@ class _XmpCardState extends State { valueListenable: _indexNotifier, builder: (context, index, child) { final data = _isIndexed ? indexedStructs![index] : widget.directStruct!; - final props = data.item1.entries.map((kv) => XmpProp(kv.key, kv.value.value)).toList()..sort(); - final cards = data.item2; + final props = data.$1.entries.map((kv) => XmpProp(kv.key, kv.value.value)).toList()..sort(); + final cards = data.$2; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -139,7 +138,7 @@ class _XmpCardState extends State { title: card.title, structByIndex: card.data, formatValue: widget.formatValue, - spanBuilders: spanBuilders != null ? (index) => spanBuilders(index, card.data[index]!.item1) : null, + spanBuilders: spanBuilders != null ? (index) => spanBuilders(index, card.data[index]!.$1) : null, ), ); }), diff --git a/lib/widgets/viewer/info/metadata/xmp_namespaces.dart b/lib/widgets/viewer/info/metadata/xmp_namespaces.dart index bb99034b6..1a33eb4c0 100644 --- a/lib/widgets/viewer/info/metadata/xmp_namespaces.dart +++ b/lib/widgets/viewer/info/metadata/xmp_namespaces.dart @@ -19,7 +19,6 @@ import 'package:equatable/equatable.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; @immutable class XmpNamespace extends Equatable { @@ -114,7 +113,7 @@ class XmpNamespace extends Equatable { title: card.title, structByIndex: card.data, formatValue: formatValue, - spanBuilders: spanBuilders != null ? (index) => spanBuilders(index, card.data[index]!.item1) : null, + spanBuilders: spanBuilders != null ? (index) => spanBuilders(index, card.data[index]!.$1) : null, ), ); }), @@ -206,8 +205,8 @@ class XmpCardData { final match = matches.first; final field = match.group(1)!; - final fields = data.putIfAbsent(null, () => Tuple2({}, cards?.map((v) => v.cloneEmpty()).toList())); - final _cards = fields.item2; + final fields = data.putIfAbsent(null, () => ({}, cards?.map((v) => v.cloneEmpty()).toList())); + final _cards = fields.$2; if (_cards != null) { final fieldProp = XmpProp(field, prop.value); if (_cards.any((v) => v.extract(fieldProp))) { @@ -215,7 +214,7 @@ class XmpCardData { } } - fields.item1[field] = prop; + fields.$1[field] = prop; return true; } @@ -227,8 +226,8 @@ class XmpCardData { final index = int.parse(match.group(1)!); final field = match.group(2)!; - final fields = data.putIfAbsent(index, () => Tuple2({}, cards?.map((v) => v.cloneEmpty()).toList())); - final _cards = fields.item2; + final fields = data.putIfAbsent(index, () => ({}, cards?.map((v) => v.cloneEmpty()).toList())); + final _cards = fields.$2; if (_cards != null) { final fieldProp = XmpProp(field, prop.value); if (_cards.any((v) => v.extract(fieldProp))) { @@ -236,7 +235,7 @@ class XmpCardData { } } - fields.item1[field] = prop; + fields.$1[field] = prop; return true; } } diff --git a/lib/widgets/viewer/info/metadata/xmp_ns/google.dart b/lib/widgets/viewer/info/metadata/xmp_ns/google.dart index fca1e0d8c..e05ab5852 100644 --- a/lib/widgets/viewer/info/metadata/xmp_ns/google.dart +++ b/lib/widgets/viewer/info/metadata/xmp_ns/google.dart @@ -4,7 +4,6 @@ import 'package:aves/widgets/viewer/info/common.dart'; import 'package:aves/widgets/viewer/info/embedded/notifications.dart'; import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart'; import 'package:collection/collection.dart'; -import 'package:tuple/tuple.dart'; abstract class XmpGoogleNamespace extends XmpNamespace { XmpGoogleNamespace({ @@ -13,13 +12,12 @@ abstract class XmpGoogleNamespace extends XmpNamespace { required super.rawProps, }); - List> get dataProps; + List<(String, String)> get dataProps; @override Map linkifyValues(List props) { return Map.fromEntries(dataProps.map((t) { - final dataPropPath = t.item1; - final mimePropPath = t.item2; + final (dataPropPath, mimePropPath) = t; final dataProp = props.firstWhereOrNull((prop) => prop.path == dataPropPath); final mimeProp = props.firstWhereOrNull((prop) => prop.path == mimePropPath); return (dataProp != null && mimeProp != null) @@ -60,8 +58,8 @@ class XmpGAudioNamespace extends XmpGoogleNamespace { XmpGAudioNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: XmpNamespaces.gAudio); @override - List> get dataProps => [ - Tuple2('${nsPrefix}Data', '${nsPrefix}Mime'), + List<(String, String)> get dataProps => [ + ('${nsPrefix}Data', '${nsPrefix}Mime'), ]; } @@ -69,8 +67,8 @@ class XmpGCameraNamespace extends XmpGoogleNamespace { XmpGCameraNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: XmpNamespaces.gCamera); @override - List> get dataProps => [ - Tuple2('${nsPrefix}RelitInputImageData', '${nsPrefix}RelitInputImageMime'), + List<(String, String)> get dataProps => [ + ('${nsPrefix}RelitInputImageData', '${nsPrefix}RelitInputImageMime'), ]; } @@ -87,9 +85,9 @@ class XmpGDepthNamespace extends XmpGoogleNamespace { XmpGDepthNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: XmpNamespaces.gDepth); @override - List> get dataProps => [ - Tuple2('${nsPrefix}Data', '${nsPrefix}Mime'), - Tuple2('${nsPrefix}Confidence', '${nsPrefix}ConfidenceMime'), + List<(String, String)> get dataProps => [ + ('${nsPrefix}Data', '${nsPrefix}Mime'), + ('${nsPrefix}Confidence', '${nsPrefix}ConfidenceMime'), ]; } @@ -156,7 +154,7 @@ class XmpGImageNamespace extends XmpGoogleNamespace { XmpGImageNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: XmpNamespaces.gImage); @override - List> get dataProps => [ - Tuple2('${nsPrefix}Data', '${nsPrefix}Mime'), + List<(String, String)> get dataProps => [ + ('${nsPrefix}Data', '${nsPrefix}Mime'), ]; } diff --git a/lib/widgets/viewer/overlay/wallpaper_buttons.dart b/lib/widgets/viewer/overlay/wallpaper_buttons.dart index cb579f1f8..2772c6056 100644 --- a/lib/widgets/viewer/overlay/wallpaper_buttons.dart +++ b/lib/widgets/viewer/overlay/wallpaper_buttons.dart @@ -18,7 +18,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:latlong2/latlong.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class WallpaperButtons extends StatelessWidget with FeedbackMixin { final AvesEntry entry; @@ -57,16 +56,13 @@ class WallpaperButtons extends StatelessWidget with FeedbackMixin { Future _setWallpaper(BuildContext context) async { final l10n = context.l10n; - final value = await showDialog>( + final value = await showDialog<(WallpaperTarget, bool)>( context: context, builder: (context) => const WallpaperSettingsDialog(), routeSettings: const RouteSettings(name: WallpaperSettingsDialog.routeName), ); if (value == null) return; - final target = value.item1; - final useScrollEffect = value.item2; - final reportController = StreamController.broadcast(); unawaited(showOpReport( context: context, @@ -76,6 +72,7 @@ class WallpaperButtons extends StatelessWidget with FeedbackMixin { var region = _getVisibleRegion(context); if (region == null) return; + final (target, useScrollEffect) = value; if (useScrollEffect) { final deltaX = min(region.left, entry.displaySize.width - region.right); region = Rect.fromLTRB(region.left - deltaX, region.top, region.right + deltaX, region.bottom); diff --git a/lib/widgets/viewer/slideshow_page.dart b/lib/widgets/viewer/slideshow_page.dart index d05186d6f..2d59ac63a 100644 --- a/lib/widgets/viewer/slideshow_page.dart +++ b/lib/widgets/viewer/slideshow_page.dart @@ -19,7 +19,6 @@ import 'package:aves_model/aves_model.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class SlideshowPage extends StatefulWidget { static const routeName = '/collection/slideshow'; @@ -151,7 +150,7 @@ class _SlideshowPageState extends State { ); } - Tuple2 get collectionSettings => Tuple2(settings.slideshowShuffle, settings.slideshowVideoPlayback == SlideshowVideoPlayback.skip); + (bool, bool) get collectionSettings => (settings.slideshowShuffle, settings.slideshowVideoPlayback == SlideshowVideoPlayback.skip); Future _showSettings(BuildContext context) async { final oldCollectionSettings = collectionSettings; diff --git a/lib/widgets/viewer/visual/entry_page_view.dart b/lib/widgets/viewer/visual/entry_page_view.dart index b9759cd40..5ab65e474 100644 --- a/lib/widgets/viewer/visual/entry_page_view.dart +++ b/lib/widgets/viewer/visual/entry_page_view.dart @@ -5,6 +5,7 @@ import 'package:aves/model/entry/entry.dart'; import 'package:aves/model/entry/extensions/props.dart'; import 'package:aves/model/settings/enums/accessibility_animations.dart'; import 'package:aves/model/settings/settings.dart'; +import 'package:aves/model/view_state.dart'; import 'package:aves/services/common/services.dart'; import 'package:aves/services/media/media_session_service.dart'; import 'package:aves/theme/icons.dart'; @@ -18,7 +19,6 @@ import 'package:aves/widgets/viewer/video/conductor.dart'; import 'package:aves/widgets/viewer/view/conductor.dart'; import 'package:aves/widgets/viewer/visual/error.dart'; import 'package:aves/widgets/viewer/visual/raster.dart'; -import 'package:aves/model/view_state.dart'; import 'package:aves/widgets/viewer/visual/vector.dart'; import 'package:aves/widgets/viewer/visual/video/cover.dart'; import 'package:aves/widgets/viewer/visual/video/subtitle/subtitle.dart'; @@ -29,7 +29,6 @@ import 'package:aves_model/aves_model.dart'; import 'package:decorated_icon/decorated_icon.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class EntryPageView extends StatefulWidget { final AvesEntry mainEntry, pageEntry; @@ -203,16 +202,14 @@ class _EntryPageViewState extends State with SingleTickerProvider final videoDisplaySize = entry.videoDisplaySize(sar); final isPureVideo = entry.isPureVideo; - return Selector>( - selector: (context, s) => Tuple3( + return Selector( + selector: (context, s) => ( isPureVideo && s.videoGestureDoubleTapTogglePlay, isPureVideo && s.videoGestureSideDoubleTapSeek, isPureVideo && s.videoGestureVerticalDragBrightnessVolume, ), builder: (context, s, child) { - final playGesture = s.item1; - final seekGesture = s.item2; - final useVerticalDragGesture = s.item3; + final (playGesture, seekGesture, useVerticalDragGesture) = s; final useTapGesture = playGesture || seekGesture; MagnifierDoubleTapCallback? onDoubleTap; diff --git a/lib/widgets/viewer/visual/raster.dart b/lib/widgets/viewer/visual/raster.dart index 65251c618..c90f8744b 100644 --- a/lib/widgets/viewer/visual/raster.dart +++ b/lib/widgets/viewer/visual/raster.dart @@ -14,7 +14,6 @@ import 'package:aves_model/aves_model.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:latlong2/latlong.dart'; -import 'package:tuple/tuple.dart'; class RasterImageView extends StatefulWidget { final AvesEntry entry; @@ -259,10 +258,11 @@ class _RasterImageViewState extends State { viewRect: viewRect, ); if (rects != null) { + final (tileRect, regionRect) = rects; tiles.add(_RegionTile( entry: entry, - tileRect: rects.item1, - regionRect: rects.item2, + tileRect: tileRect, + regionRect: regionRect, sampleSize: sampleSize, )); } @@ -283,7 +283,7 @@ class _RasterImageViewState extends State { return viewOrigin & viewportSize; } - Tuple2>? _getTileRects({ + (Rect tileRect, Rectangle regionRect)? _getTileRects({ required int x, required int y, required int regionSide, @@ -314,7 +314,7 @@ class _RasterImageViewState extends State { } else { regionRect = Rectangle(x, y, thisRegionWidth, thisRegionHeight); } - return Tuple2>(tileRect, regionRect); + return (tileRect, regionRect); } } diff --git a/lib/widgets/viewer/visual/vector.dart b/lib/widgets/viewer/visual/vector.dart index 64ecd9cca..fbc535646 100644 --- a/lib/widgets/viewer/visual/vector.dart +++ b/lib/widgets/viewer/visual/vector.dart @@ -12,7 +12,6 @@ import 'package:aves/widgets/viewer/visual/entry_page_view.dart'; import 'package:aves_model/aves_model.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:tuple/tuple.dart'; class VectorImageView extends StatefulWidget { final AvesEntry entry; @@ -233,10 +232,11 @@ class _VectorImageViewState extends State { viewRect: viewRect, ); if (rects != null) { + final (tileRect, regionRect) = rects; tiles.add(_RegionTile( entry: entry, - tileRect: rects.item1, - regionRect: rects.item2, + tileRect: tileRect, + regionRect: regionRect, scale: svgScale, backgroundColor: backgroundColor, backgroundFrameBuilder: backgroundFrameBuilder, @@ -259,7 +259,7 @@ class _VectorImageViewState extends State { return viewOrigin & viewportSize; } - Tuple2>? _getTileRects({ + (Rect tileRect, Rectangle regionRect)? _getTileRects({ required double x, required double y, required double regionSide, @@ -278,7 +278,7 @@ class _VectorImageViewState extends State { if (!viewRect.overlaps(tileRect)) return null; final regionRect = Rectangle(x, y, thisRegionWidth, thisRegionHeight); - return Tuple2>(tileRect, regionRect); + return (tileRect, regionRect); } double _imageScaleForViewScale({ diff --git a/pubspec.lock b/pubspec.lock index 52bef2916..f193337ff 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1479,14 +1479,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" - tuple: - dependency: "direct main" - description: - name: tuple - sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 - url: "https://pub.dev" - source: hosted - version: "2.0.2" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a7cf6f3d9..ae40207b9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -111,7 +111,6 @@ dependencies: git: url: https://github.com/deckerst/aves_streams_channel.git transparent_image: - tuple: url_launcher: vector_math: volume_controller: