tuple record migration
This commit is contained in:
parent
1117da068b
commit
a1a7b8e9e1
39 changed files with 163 additions and 241 deletions
|
@ -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',
|
||||
|
|
|
@ -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<AvesApp> with WidgetsBindingObserver {
|
|||
: AvesScaffold(
|
||||
body: snapshot.hasError ? _buildError(snapshot.error!) : const SizedBox(),
|
||||
);
|
||||
return Selector<Settings, Tuple3<Locale?, AvesThemeBrightness, bool>>(
|
||||
selector: (context, s) => Tuple3(
|
||||
return Selector<Settings, (Locale?, AvesThemeBrightness, bool)>(
|
||||
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);
|
||||
|
||||
|
|
|
@ -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<double> appBarHeightNotifier;
|
||||
|
@ -647,14 +646,14 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
|||
}
|
||||
|
||||
Future<void> _configureView() async {
|
||||
final initialValue = Tuple4(
|
||||
final initialValue = (
|
||||
settings.collectionSortFactor,
|
||||
settings.collectionSectionFactor,
|
||||
settings.getTileLayout(CollectionPage.routeName),
|
||||
settings.collectionSortReverse,
|
||||
);
|
||||
final extentController = context.read<TileExtentController>();
|
||||
final value = await showDialog<Tuple4<EntrySortFactor?, EntryGroupFactor?, TileLayout?, bool>>(
|
||||
final value = await showDialog<(EntrySortFactor?, EntryGroupFactor?, TileLayout?, bool)>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return TileViewDialog<EntrySortFactor, EntryGroupFactor, TileLayout>(
|
||||
|
@ -672,10 +671,10 @@ class _CollectionAppBarState extends State<CollectionAppBar> 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<TileExtentController, ValueNotifier<double>>((controller) => controller.extentNotifier),
|
||||
builder: (context, thumbnailExtent, child) {
|
||||
assert(thumbnailExtent > 0);
|
||||
return Selector<TileExtentController, Tuple4<double, int, double, double>>(
|
||||
selector: (context, c) => Tuple4(c.viewportSize.width, c.columnCount, c.spacing, c.horizontalPadding),
|
||||
return Selector<TileExtentController, (double, int, double, double)>(
|
||||
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<TileExtentController, Tuple2<double, double>>((v) => Tuple2(v.spacing, v.horizontalPadding));
|
||||
final tileSpacing = metrics.item1;
|
||||
final horizontalPadding = metrics.item2;
|
||||
final (tileSpacing, horizontalPadding) = context.select<TileExtentController, (double, double)>((v) => (v.spacing, v.horizontalPadding));
|
||||
final brightness = Theme.of(context).brightness;
|
||||
final borderColor = DecoratedThumbnail.borderColor;
|
||||
final borderWidth = DecoratedThumbnail.borderWidth(context);
|
||||
|
|
|
@ -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<CollectionFilter>.from(filters)..sort();
|
||||
defaultName = sortedFilters.first.getLabel(context).replaceAll('\n', ' ');
|
||||
}
|
||||
final result = await showDialog<Tuple2<AvesEntry?, String>>(
|
||||
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);
|
||||
|
|
|
@ -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<AnimatedDiffText> 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<AnimatedDiffText> 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<List<_TextDiff>>([], (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<AnimatedDiffText> with SingleTickerPr
|
|||
}
|
||||
}
|
||||
|
||||
typedef _TextDiff = Tuple4<String?, String?, Size, Size>;
|
||||
typedef _TextDiff = (String?, String?, Size, Size);
|
||||
|
|
|
@ -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<T> extends SectionLayoutBuilder<T> {
|
||||
int _currentIndex = 0;
|
||||
|
@ -88,7 +87,7 @@ class FixedExtentSectionLayoutBuilder<T> extends SectionLayoutBuilder<T> {
|
|||
section: section,
|
||||
sectionGridIndex: listIndex * columnCount,
|
||||
sectionChildIndex: sectionChildIndex,
|
||||
itemIndexRange: () => Tuple2(
|
||||
itemIndexRange: () => (
|
||||
(sectionChildIndex - 1) * columnCount,
|
||||
sectionChildIndex * columnCount,
|
||||
),
|
||||
|
|
|
@ -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<T> extends SectionLayoutBuilder<T> {
|
||||
int _currentIndex = 0;
|
||||
|
@ -110,7 +109,7 @@ class MosaicSectionLayoutBuilder<T> extends SectionLayoutBuilder<T> {
|
|||
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(),
|
||||
|
|
|
@ -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<T> = Widget Function(T item, Size tileSize);
|
||||
|
||||
|
@ -54,7 +53,7 @@ abstract class SectionLayoutBuilder<T> {
|
|||
required List<T> section,
|
||||
required int sectionGridIndex,
|
||||
required int sectionChildIndex,
|
||||
required Tuple2<int, int> Function() itemIndexRange,
|
||||
required (int, int) Function() itemIndexRange,
|
||||
required SectionKey sectionKey,
|
||||
required double headerExtent,
|
||||
required List<Size> itemSizes,
|
||||
|
@ -68,8 +67,8 @@ abstract class SectionLayoutBuilder<T> {
|
|||
|
||||
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 = <Widget>[];
|
||||
for (var i = 0; i < childrenCount; i++) {
|
||||
|
|
|
@ -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<AddShortcutDialog> {
|
|||
|
||||
void _submit(BuildContext context) {
|
||||
if (_isValidNotifier.value) {
|
||||
Navigator.maybeOf(context)?.pop(Tuple2<AvesEntry?, String>(_coverEntry, _nameController.text));
|
||||
Navigator.maybeOf(context)?.pop<(AvesEntry?, String)>((_coverEntry, _nameController.text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<CoverSelectionDialog> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
final tabs = <Tuple2<Tab, Widget>>[
|
||||
Tuple2(
|
||||
final tabs = <(Tab, Widget)>[
|
||||
(
|
||||
_buildTab(
|
||||
context,
|
||||
const Key('tab-entry'),
|
||||
|
@ -92,7 +91,7 @@ class _CoverSelectionDialogState extends State<CoverSelectionDialog> {
|
|||
Column(children: _buildEntryOptions()),
|
||||
),
|
||||
if (showAppTab)
|
||||
Tuple2(
|
||||
(
|
||||
_buildTab(
|
||||
context,
|
||||
const Key('tab-package'),
|
||||
|
@ -102,7 +101,7 @@ class _CoverSelectionDialogState extends State<CoverSelectionDialog> {
|
|||
Column(children: _buildAppOptions()),
|
||||
),
|
||||
if (showColorTab)
|
||||
Tuple2(
|
||||
(
|
||||
_buildTab(
|
||||
context,
|
||||
const Key('tab-color'),
|
||||
|
@ -131,7 +130,7 @@ class _CoverSelectionDialogState extends State<CoverSelectionDialog> {
|
|||
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<CoverSelectionDialog> {
|
|||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: tabs
|
||||
.map((t) => SingleChildScrollView(
|
||||
child: t.item2,
|
||||
child: t.$2,
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
|
@ -165,7 +164,7 @@ class _CoverSelectionDialogState extends State<CoverSelectionDialog> {
|
|||
final entry = _isCustomEntry ? _customEntry : null;
|
||||
final package = _isCustomPackage ? _customPackage : null;
|
||||
final color = _isCustomColor ? _customColor : null;
|
||||
return Navigator.maybeOf(context)?.pop(Tuple3<AvesEntry?, String?, Color?>(entry, package, color));
|
||||
return Navigator.maybeOf(context)?.pop<(AvesEntry?, String?, Color?)>((entry, package, color));
|
||||
},
|
||||
child: Text(l10n.applyButtonLabel),
|
||||
)
|
||||
|
|
|
@ -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<String?> pickAlbum({
|
||||
required BuildContext context,
|
||||
|
@ -94,8 +93,8 @@ class _AlbumPickPageState extends State<_AlbumPickPage> {
|
|||
Widget build(BuildContext context) {
|
||||
return ListenableProvider<ValueNotifier<AppMode>>.value(
|
||||
value: ValueNotifier(AppMode.pickFilterInternal),
|
||||
child: Selector<Settings, Tuple2<AlbumChipGroupFactor, ChipSortFactor>>(
|
||||
selector: (context, s) => Tuple2(s.albumGroupFactor, s.albumSortFactor),
|
||||
child: Selector<Settings, (AlbumChipGroupFactor, ChipSortFactor)>(
|
||||
selector: (context, s) => (s.albumGroupFactor, s.albumSortFactor),
|
||||
builder: (context, s, child) {
|
||||
return StreamBuilder(
|
||||
stream: source.eventBus.on<AlbumsChangedEvent>(),
|
||||
|
|
|
@ -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<S, G, L> extends StatefulWidget {
|
||||
static const routeName = '/dialog/tile_view';
|
||||
|
||||
final Tuple4<S?, G?, L?, bool> initialValue;
|
||||
final (S? sort, G? group, L? layout, bool reverse) initialValue;
|
||||
final List<TileViewDialogOption<S>> sortOptions;
|
||||
final List<TileViewDialogOption<G>> groupOptions;
|
||||
final List<TileViewDialogOption<L>> layoutOptions;
|
||||
|
@ -63,10 +62,10 @@ class _TileViewDialogState<S, G, L> extends State<TileViewDialog<S, G, L>> 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<S, G, L> extends State<TileViewDialog<S, G, L>> 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),
|
||||
)
|
||||
|
|
|
@ -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<WallpaperSettingsDialog> {
|
|||
actions: [
|
||||
const CancelButton(),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(Tuple2<WallpaperTarget, bool>(_selectedTarget, _useScrollEffect)),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop<(WallpaperTarget, bool)>((_selectedTarget, _useScrollEffect)),
|
||||
child: Text(context.l10n.applyButtonLabel),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -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<TransformControlPanel> with TickerProviderStateMixin {
|
||||
late final List<Tuple2<WidgetBuilder, WidgetBuilder>> _tabs;
|
||||
late final List<(WidgetBuilder, WidgetBuilder)> _tabs;
|
||||
late final TabController _tabController;
|
||||
|
||||
static const padding = EditorControlPanel.padding;
|
||||
|
@ -41,11 +40,11 @@ class _TransformControlPanelState extends State<TransformControlPanel> 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<TransformControlPanel> with Tick
|
|||
builder: (context, child) {
|
||||
return AnimatedSwitcher(
|
||||
duration: context.select<DurationsData, Duration>((v) => v.formTransition),
|
||||
child: _tabs[_tabController.index].item2(context),
|
||||
child: _tabs[_tabController.index].$2(context),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -87,7 +86,7 @@ class _TransformControlPanelState extends State<TransformControlPanel> 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,
|
||||
|
|
|
@ -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<CollectionSource>();
|
||||
return Selector<Settings, Tuple4<AlbumChipGroupFactor, ChipSortFactor, bool, Set<CollectionFilter>>>(
|
||||
selector: (context, s) => Tuple4(s.albumGroupFactor, s.albumSortFactor, s.albumSortReverse, s.pinnedFilters),
|
||||
return Selector<Settings, (AlbumChipGroupFactor, ChipSortFactor, bool, Set<CollectionFilter>)>(
|
||||
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<bool>(
|
||||
|
|
|
@ -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<AlbumFilter> with EntryStorageMixin {
|
||||
final Iterable<FilterGridItem<AlbumFilter>> _items;
|
||||
|
@ -168,14 +167,14 @@ class AlbumChipSetActionDelegate extends ChipSetActionDelegate<AlbumFilter> with
|
|||
|
||||
@override
|
||||
Future<void> configureView(BuildContext context) async {
|
||||
final initialValue = Tuple4(
|
||||
final initialValue = (
|
||||
sortFactor,
|
||||
settings.albumGroupFactor,
|
||||
tileLayout,
|
||||
sortReverse,
|
||||
);
|
||||
final extentController = context.read<TileExtentController>();
|
||||
final value = await showDialog<Tuple4<ChipSortFactor?, AlbumChipGroupFactor?, TileLayout?, bool>>(
|
||||
final value = await showDialog<(ChipSortFactor?, AlbumChipGroupFactor?, TileLayout?, bool)>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return TileViewDialog<ChipSortFactor, AlbumChipGroupFactor, TileLayout>(
|
||||
|
@ -192,10 +191,10 @@ class AlbumChipSetActionDelegate extends ChipSetActionDelegate<AlbumFilter> 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<T extends CollectionFilter> with FeedbackMixin, PermissionAwareMixin, SizeAwareMixin, VaultAwareMixin {
|
||||
Iterable<FilterGridItem<T>> get allItems;
|
||||
|
@ -216,14 +215,14 @@ abstract class ChipSetActionDelegate<T extends CollectionFilter> with FeedbackMi
|
|||
}
|
||||
|
||||
Future<void> configureView(BuildContext context) async {
|
||||
final initialValue = Tuple4(
|
||||
final initialValue = (
|
||||
sortFactor,
|
||||
null,
|
||||
tileLayout,
|
||||
sortReverse,
|
||||
);
|
||||
final extentController = context.read<TileExtentController>();
|
||||
final value = await showDialog<Tuple4<ChipSortFactor?, void, TileLayout?, bool>>(
|
||||
final value = await showDialog<(ChipSortFactor?, void, TileLayout?, bool)>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return TileViewDialog<ChipSortFactor, void, TileLayout>(
|
||||
|
@ -239,9 +238,9 @@ abstract class ChipSetActionDelegate<T extends CollectionFilter> 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<T extends CollectionFilter> with FeedbackMi
|
|||
final existingCover = covers.of(filter);
|
||||
final entryId = existingCover?.$1;
|
||||
final customEntry = entryId != null ? context.read<CollectionSource>().visibleEntries.firstWhereOrNull((entry) => entry.id == entryId) : null;
|
||||
final selectedCover = await showDialog<Tuple3<AvesEntry?, String?, Color?>>(
|
||||
final selectedCover = await showDialog<(AvesEntry?, String?, Color?)>(
|
||||
context: context,
|
||||
builder: (context) => CoverSelectionDialog(
|
||||
filter: filter,
|
||||
|
@ -344,9 +343,7 @@ abstract class ChipSetActionDelegate<T extends CollectionFilter> with FeedbackMi
|
|||
context.read<AvesColorsData>().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,
|
||||
|
|
|
@ -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<T extends CollectionFilter> = List<FilterGridItem<T>> Function(BuildContext context, List<FilterGridItem<T>> filters, String query);
|
||||
|
||||
|
@ -317,13 +316,10 @@ class _FilterGridContentState<T extends CollectionFilter> extends State<_FilterG
|
|||
final sectionedListLayoutProvider = ValueListenableBuilder<double>(
|
||||
valueListenable: context.select<TileExtentController, ValueNotifier<double>>((controller) => controller.extentNotifier),
|
||||
builder: (context, thumbnailExtent, child) {
|
||||
return Selector<TileExtentController, Tuple4<double, int, double, double>>(
|
||||
selector: (context, c) => Tuple4(c.viewportSize.width, c.columnCount, c.spacing, c.horizontalPadding),
|
||||
return Selector<TileExtentController, (double, int, double, double)>(
|
||||
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<DurationsData>().staggeredAnimationPageTarget;
|
||||
final tileAnimationDelay = context.read<TileExtentController>().getTileAnimationDelay(target);
|
||||
|
@ -571,9 +567,7 @@ class _FilterScaler<T extends CollectionFilter> extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final textScaleFactor = MediaQuery.textScaleFactorOf(context);
|
||||
final metrics = context.select<TileExtentController, Tuple2<double, double>>((v) => Tuple2(v.spacing, v.horizontalPadding));
|
||||
final tileSpacing = metrics.item1;
|
||||
final horizontalPadding = metrics.item2;
|
||||
final (tileSpacing, horizontalPadding) = context.select<TileExtentController, (double, double)>((v) => (v.spacing, v.horizontalPadding));
|
||||
final brightness = Theme.of(context).brightness;
|
||||
return GridScaleGestureDetector<FilterGridItem<T>>(
|
||||
scrollableKey: scrollableKey,
|
||||
|
|
|
@ -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<CollectionSource>();
|
||||
return Selector<Settings, Tuple3<ChipSortFactor, bool, Set<CollectionFilter>>>(
|
||||
selector: (context, s) => Tuple3(s.countrySortFactor, s.countrySortReverse, s.pinnedFilters),
|
||||
return Selector<Settings, (ChipSortFactor, bool, Set<CollectionFilter>)>(
|
||||
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(
|
||||
|
|
|
@ -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<CollectionSource>();
|
||||
return Selector<Settings, Tuple3<ChipSortFactor, bool, Set<CollectionFilter>>>(
|
||||
selector: (context, s) => Tuple3(s.placeSortFactor, s.placeSortReverse, s.pinnedFilters),
|
||||
return Selector<Settings, (ChipSortFactor, bool, Set<CollectionFilter>)>(
|
||||
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(
|
||||
|
|
|
@ -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<CollectionSource>();
|
||||
return Selector<Settings, Tuple3<ChipSortFactor, bool, Set<CollectionFilter>>>(
|
||||
selector: (context, s) => Tuple3(s.stateSortFactor, s.stateSortReverse, s.pinnedFilters),
|
||||
return Selector<Settings, (ChipSortFactor, bool, Set<CollectionFilter>)>(
|
||||
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(
|
||||
|
|
|
@ -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<CollectionSource>();
|
||||
return Selector<Settings, Tuple3<ChipSortFactor, bool, Set<CollectionFilter>>>(
|
||||
selector: (context, s) => Tuple3(s.tagSortFactor, s.tagSortReverse, s.pinnedFilters),
|
||||
return Selector<Settings, (ChipSortFactor, bool, Set<CollectionFilter>)>(
|
||||
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(
|
||||
|
|
|
@ -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<NavigationDrawerEditorPage>
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
final tabs = <Tuple2<Tab, Widget>>[
|
||||
Tuple2(
|
||||
final tabs = <(Tab, Widget)>[
|
||||
(
|
||||
Tab(text: l10n.settingsNavigationDrawerTabTypes),
|
||||
DrawerFixedListTab<CollectionFilter?>(
|
||||
items: _typeItems,
|
||||
|
@ -75,13 +74,13 @@ class _NavigationDrawerEditorPageState extends State<NavigationDrawerEditorPage>
|
|||
title: (item) => DrawerFilterTitle(filter: item),
|
||||
),
|
||||
),
|
||||
Tuple2(
|
||||
(
|
||||
Tab(text: l10n.settingsNavigationDrawerTabAlbums),
|
||||
DrawerAlbumTab(
|
||||
items: _albumItems,
|
||||
),
|
||||
),
|
||||
Tuple2(
|
||||
(
|
||||
Tab(text: l10n.settingsNavigationDrawerTabPages),
|
||||
DrawerFixedListTab<String>(
|
||||
items: _pageItems,
|
||||
|
@ -99,7 +98,7 @@ class _NavigationDrawerEditorPageState extends State<NavigationDrawerEditorPage>
|
|||
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<NavigationDrawerEditorPage>
|
|||
},
|
||||
child: SafeArea(
|
||||
child: TabBarView(
|
||||
children: tabs.map((t) => t.item2).toList(),
|
||||
children: tabs.map((t) => t.$2).toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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<Tab, Widget>>[
|
||||
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(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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<Tab, Widget>>[
|
||||
Tuple2(
|
||||
final tabs = <(Tab, Widget)>[
|
||||
(
|
||||
Tab(text: l10n.settingsCollectionQuickActionTabBrowsing),
|
||||
QuickActionEditorBody<EntrySetAction>(
|
||||
bannerText: context.l10n.settingsCollectionBrowsingQuickActionEditorBanner,
|
||||
|
@ -27,7 +26,7 @@ class CollectionActionEditorPage extends StatelessWidget {
|
|||
save: (actions) => settings.collectionBrowsingQuickActions = actions,
|
||||
),
|
||||
),
|
||||
Tuple2(
|
||||
(
|
||||
Tab(text: l10n.settingsCollectionQuickActionTabSelecting),
|
||||
QuickActionEditorBody<EntrySetAction>(
|
||||
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(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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<Settings, Tuple2<bool, bool>>(
|
||||
selector: (context, s) => Tuple2(s.showOverlayInfo, s.showOverlayRatingTags),
|
||||
Selector<Settings, (bool, bool)>(
|
||||
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<Settings, Tuple2<bool, bool>>(
|
||||
selector: (context, s) => Tuple2(s.showOverlayInfo, s.showOverlayShootingDetails),
|
||||
Selector<Settings, (bool, bool)>(
|
||||
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<Settings, Tuple2<bool, bool>>(
|
||||
selector: (context, s) => Tuple2(s.showOverlayInfo, s.showOverlayDescription),
|
||||
Selector<Settings, (bool, bool)>(
|
||||
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,
|
||||
|
|
|
@ -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<void> _addShortcut(BuildContext context, AvesEntry targetEntry) async {
|
||||
final result = await showDialog<Tuple2<AvesEntry?, String>>(
|
||||
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);
|
||||
|
|
|
@ -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<Tab, Widget>>[
|
||||
Tuple2(const Tab(text: 'Entry'), _buildEntryTabView()),
|
||||
if (context.select<ValueNotifier<AppMode>, 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<ValueNotifier<AppMode>, 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(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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<Map<String, XmpProp>, List<XmpCardData>?>;
|
||||
typedef XmpExtractedCard = (Map<String, XmpProp>, List<XmpCardData>?);
|
||||
|
||||
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<XmpCard> {
|
|||
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<XmpCard> {
|
|||
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,
|
||||
),
|
||||
);
|
||||
}),
|
||||
|
|
|
@ -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(<String, XmpProp>{}, cards?.map((v) => v.cloneEmpty()).toList()));
|
||||
final _cards = fields.item2;
|
||||
final fields = data.putIfAbsent(null, () => (<String, XmpProp>{}, 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(<String, XmpProp>{}, cards?.map((v) => v.cloneEmpty()).toList()));
|
||||
final _cards = fields.item2;
|
||||
final fields = data.putIfAbsent(index, () => (<String, XmpProp>{}, 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Tuple2<String, String>> get dataProps;
|
||||
List<(String, String)> get dataProps;
|
||||
|
||||
@override
|
||||
Map<String, InfoValueSpanBuilder> linkifyValues(List<XmpProp> 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<Tuple2<String, String>> 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<Tuple2<String, String>> 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<Tuple2<String, String>> 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<Tuple2<String, String>> get dataProps => [
|
||||
Tuple2('${nsPrefix}Data', '${nsPrefix}Mime'),
|
||||
List<(String, String)> get dataProps => [
|
||||
('${nsPrefix}Data', '${nsPrefix}Mime'),
|
||||
];
|
||||
}
|
||||
|
|
|
@ -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<void> _setWallpaper(BuildContext context) async {
|
||||
final l10n = context.l10n;
|
||||
final value = await showDialog<Tuple2<WallpaperTarget, bool>>(
|
||||
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);
|
||||
|
|
|
@ -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<SlideshowPage> {
|
|||
);
|
||||
}
|
||||
|
||||
Tuple2<bool, bool> get collectionSettings => Tuple2(settings.slideshowShuffle, settings.slideshowVideoPlayback == SlideshowVideoPlayback.skip);
|
||||
(bool, bool) get collectionSettings => (settings.slideshowShuffle, settings.slideshowVideoPlayback == SlideshowVideoPlayback.skip);
|
||||
|
||||
Future<void> _showSettings(BuildContext context) async {
|
||||
final oldCollectionSettings = collectionSettings;
|
||||
|
|
|
@ -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<EntryPageView> with SingleTickerProvider
|
|||
final videoDisplaySize = entry.videoDisplaySize(sar);
|
||||
final isPureVideo = entry.isPureVideo;
|
||||
|
||||
return Selector<Settings, Tuple3<bool, bool, bool>>(
|
||||
selector: (context, s) => Tuple3(
|
||||
return Selector<Settings, (bool, bool, bool)>(
|
||||
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;
|
||||
|
|
|
@ -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<RasterImageView> {
|
|||
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<RasterImageView> {
|
|||
return viewOrigin & viewportSize;
|
||||
}
|
||||
|
||||
Tuple2<Rect, Rectangle<int>>? _getTileRects({
|
||||
(Rect tileRect, Rectangle<int> regionRect)? _getTileRects({
|
||||
required int x,
|
||||
required int y,
|
||||
required int regionSide,
|
||||
|
@ -314,7 +314,7 @@ class _RasterImageViewState extends State<RasterImageView> {
|
|||
} else {
|
||||
regionRect = Rectangle<int>(x, y, thisRegionWidth, thisRegionHeight);
|
||||
}
|
||||
return Tuple2<Rect, Rectangle<int>>(tileRect, regionRect);
|
||||
return (tileRect, regionRect);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<VectorImageView> {
|
|||
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<VectorImageView> {
|
|||
return viewOrigin & viewportSize;
|
||||
}
|
||||
|
||||
Tuple2<Rect, Rectangle<double>>? _getTileRects({
|
||||
(Rect tileRect, Rectangle<double> regionRect)? _getTileRects({
|
||||
required double x,
|
||||
required double y,
|
||||
required double regionSide,
|
||||
|
@ -278,7 +278,7 @@ class _VectorImageViewState extends State<VectorImageView> {
|
|||
if (!viewRect.overlaps(tileRect)) return null;
|
||||
|
||||
final regionRect = Rectangle<double>(x, y, thisRegionWidth, thisRegionHeight);
|
||||
return Tuple2<Rect, Rectangle<double>>(tileRect, regionRect);
|
||||
return (tileRect, regionRect);
|
||||
}
|
||||
|
||||
double _imageScaleForViewScale({
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -111,7 +111,6 @@ dependencies:
|
|||
git:
|
||||
url: https://github.com/deckerst/aves_streams_channel.git
|
||||
transparent_image:
|
||||
tuple:
|
||||
url_launcher:
|
||||
vector_math:
|
||||
volume_controller:
|
||||
|
|
Loading…
Reference in a new issue