#1045 stack RAW and JPEG with same file names
This commit is contained in:
parent
44eecd2e55
commit
d890d9d9ae
16 changed files with 125 additions and 48 deletions
|
@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## <a id="unreleased"></a>[Unreleased]
|
## <a id="unreleased"></a>[Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Collection: stack RAW and JPEG with same file names
|
||||||
|
|
||||||
## <a id="v1.11.3"></a>[v1.11.3] - 2024-06-17
|
## <a id="v1.11.3"></a>[v1.11.3] - 2024-06-17
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -44,7 +44,8 @@ class AvesEntry with AvesEntryBase {
|
||||||
AddressDetails? _addressDetails;
|
AddressDetails? _addressDetails;
|
||||||
TrashDetails? trashDetails;
|
TrashDetails? trashDetails;
|
||||||
|
|
||||||
List<AvesEntry>? burstEntries;
|
// synthetic stack of related entries, e.g. burst shots or raw/developed pairs
|
||||||
|
List<AvesEntry>? stackedEntries;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final AChangeNotifier visualChangeNotifier = AChangeNotifier();
|
final AChangeNotifier visualChangeNotifier = AChangeNotifier();
|
||||||
|
@ -69,7 +70,7 @@ class AvesEntry with AvesEntryBase {
|
||||||
required int? durationMillis,
|
required int? durationMillis,
|
||||||
required this.trashed,
|
required this.trashed,
|
||||||
required this.origin,
|
required this.origin,
|
||||||
this.burstEntries,
|
this.stackedEntries,
|
||||||
}) : id = id ?? 0 {
|
}) : id = id ?? 0 {
|
||||||
if (kFlutterMemoryAllocationsEnabled) {
|
if (kFlutterMemoryAllocationsEnabled) {
|
||||||
FlutterMemoryAllocations.instance.dispatchObjectCreated(
|
FlutterMemoryAllocations.instance.dispatchObjectCreated(
|
||||||
|
@ -93,7 +94,7 @@ class AvesEntry with AvesEntryBase {
|
||||||
int? dateAddedSecs,
|
int? dateAddedSecs,
|
||||||
int? dateModifiedSecs,
|
int? dateModifiedSecs,
|
||||||
int? origin,
|
int? origin,
|
||||||
List<AvesEntry>? burstEntries,
|
List<AvesEntry>? stackedEntries,
|
||||||
}) {
|
}) {
|
||||||
final copyEntryId = id ?? this.id;
|
final copyEntryId = id ?? this.id;
|
||||||
final copied = AvesEntry(
|
final copied = AvesEntry(
|
||||||
|
@ -114,7 +115,7 @@ class AvesEntry with AvesEntryBase {
|
||||||
durationMillis: durationMillis,
|
durationMillis: durationMillis,
|
||||||
trashed: trashed,
|
trashed: trashed,
|
||||||
origin: origin ?? this.origin,
|
origin: origin ?? this.origin,
|
||||||
burstEntries: burstEntries ?? this.burstEntries,
|
stackedEntries: stackedEntries ?? this.stackedEntries,
|
||||||
)
|
)
|
||||||
..catalogMetadata = _catalogMetadata?.copyWith(id: copyEntryId)
|
..catalogMetadata = _catalogMetadata?.copyWith(id: copyEntryId)
|
||||||
..addressDetails = _addressDetails?.copyWith(id: copyEntryId)
|
..addressDetails = _addressDetails?.copyWith(id: copyEntryId)
|
||||||
|
|
|
@ -7,9 +7,9 @@ import 'package:aves/services/common/services.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
|
|
||||||
extension ExtraAvesEntryMultipage on AvesEntry {
|
extension ExtraAvesEntryMultipage on AvesEntry {
|
||||||
bool get isMultiPage => isBurst || ((catalogMetadata?.isMultiPage ?? false) && (isMotionPhoto || !isHdr));
|
bool get isMultiPage => isStack || ((catalogMetadata?.isMultiPage ?? false) && (isMotionPhoto || !isHdr));
|
||||||
|
|
||||||
bool get isBurst => burstEntries?.isNotEmpty == true;
|
bool get isStack => stackedEntries?.isNotEmpty == true;
|
||||||
|
|
||||||
bool get isMotionPhoto => catalogMetadata?.isMotionPhoto ?? false;
|
bool get isMotionPhoto => catalogMetadata?.isMotionPhoto ?? false;
|
||||||
|
|
||||||
|
@ -19,10 +19,10 @@ extension ExtraAvesEntryMultipage on AvesEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<MultiPageInfo?> getMultiPageInfo() async {
|
Future<MultiPageInfo?> getMultiPageInfo() async {
|
||||||
if (isBurst) {
|
if (isStack) {
|
||||||
return MultiPageInfo(
|
return MultiPageInfo(
|
||||||
mainEntry: this,
|
mainEntry: this,
|
||||||
pages: burstEntries!
|
pages: stackedEntries!
|
||||||
.mapIndexed((index, entry) => SinglePageInfo(
|
.mapIndexed((index, entry) => SinglePageInfo(
|
||||||
index: index,
|
index: index,
|
||||||
pageId: entry.id,
|
pageId: entry.id,
|
||||||
|
|
|
@ -32,10 +32,10 @@ class MultiPageInfo {
|
||||||
_pages.insert(0, firstPage.copyWith(isDefault: true));
|
_pages.insert(0, firstPage.copyWith(isDefault: true));
|
||||||
}
|
}
|
||||||
|
|
||||||
final burstEntries = mainEntry.burstEntries;
|
final stackedEntries = mainEntry.stackedEntries;
|
||||||
if (burstEntries != null) {
|
if (stackedEntries != null) {
|
||||||
_pageEntries.addEntries(pages.map((pageInfo) {
|
_pageEntries.addEntries(pages.map((pageInfo) {
|
||||||
final pageEntry = burstEntries.firstWhere((entry) => entry.uri == pageInfo.uri);
|
final pageEntry = stackedEntries.firstWhere((entry) => entry.uri == pageInfo.uri);
|
||||||
return MapEntry(pageInfo, pageEntry);
|
return MapEntry(pageInfo, pageEntry);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,15 +9,18 @@ import 'package:aves/model/filters/album.dart';
|
||||||
import 'package:aves/model/filters/favourite.dart';
|
import 'package:aves/model/filters/favourite.dart';
|
||||||
import 'package:aves/model/filters/filters.dart';
|
import 'package:aves/model/filters/filters.dart';
|
||||||
import 'package:aves/model/filters/location.dart';
|
import 'package:aves/model/filters/location.dart';
|
||||||
|
import 'package:aves/model/filters/mime.dart';
|
||||||
import 'package:aves/model/filters/query.dart';
|
import 'package:aves/model/filters/query.dart';
|
||||||
import 'package:aves/model/filters/rating.dart';
|
import 'package:aves/model/filters/rating.dart';
|
||||||
import 'package:aves/model/filters/trash.dart';
|
import 'package:aves/model/filters/trash.dart';
|
||||||
|
import 'package:aves/model/filters/type.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/model/source/events.dart';
|
import 'package:aves/model/source/events.dart';
|
||||||
import 'package:aves/model/source/location/location.dart';
|
import 'package:aves/model/source/location/location.dart';
|
||||||
import 'package:aves/model/source/section_keys.dart';
|
import 'package:aves/model/source/section_keys.dart';
|
||||||
import 'package:aves/model/source/tag.dart';
|
import 'package:aves/model/source/tag.dart';
|
||||||
|
import 'package:aves/ref/mime_types.dart';
|
||||||
import 'package:aves/utils/collection_utils.dart';
|
import 'package:aves/utils/collection_utils.dart';
|
||||||
import 'package:aves_model/aves_model.dart';
|
import 'package:aves_model/aves_model.dart';
|
||||||
import 'package:aves_utils/aves_utils.dart';
|
import 'package:aves_utils/aves_utils.dart';
|
||||||
|
@ -34,7 +37,7 @@ class CollectionLens with ChangeNotifier {
|
||||||
final AChangeNotifier filterChangeNotifier = AChangeNotifier(), sortSectionChangeNotifier = AChangeNotifier();
|
final AChangeNotifier filterChangeNotifier = AChangeNotifier(), sortSectionChangeNotifier = AChangeNotifier();
|
||||||
final List<StreamSubscription> _subscriptions = [];
|
final List<StreamSubscription> _subscriptions = [];
|
||||||
int? id;
|
int? id;
|
||||||
bool listenToSource, groupBursts, fixedSort;
|
bool listenToSource, stackBursts, stackDevelopedRaws, fixedSort;
|
||||||
List<AvesEntry>? fixedSelection;
|
List<AvesEntry>? fixedSelection;
|
||||||
|
|
||||||
final Set<AvesEntry> _syntheticEntries = {};
|
final Set<AvesEntry> _syntheticEntries = {};
|
||||||
|
@ -47,7 +50,8 @@ class CollectionLens with ChangeNotifier {
|
||||||
Set<CollectionFilter?>? filters,
|
Set<CollectionFilter?>? filters,
|
||||||
this.id,
|
this.id,
|
||||||
this.listenToSource = true,
|
this.listenToSource = true,
|
||||||
this.groupBursts = true,
|
this.stackBursts = true,
|
||||||
|
this.stackDevelopedRaws = true,
|
||||||
this.fixedSort = false,
|
this.fixedSort = false,
|
||||||
this.fixedSelection,
|
this.fixedSelection,
|
||||||
}) : filters = (filters ?? {}).whereNotNull().toSet(),
|
}) : filters = (filters ?? {}).whereNotNull().toSet(),
|
||||||
|
@ -192,30 +196,59 @@ class CollectionLens with ChangeNotifier {
|
||||||
_disposeSyntheticEntries();
|
_disposeSyntheticEntries();
|
||||||
_filteredSortedEntries = List.of(filters.isEmpty ? entries : entries.where((entry) => filters.every((filter) => filter.test(entry))));
|
_filteredSortedEntries = List.of(filters.isEmpty ? entries : entries.where((entry) => filters.every((filter) => filter.test(entry))));
|
||||||
|
|
||||||
if (groupBursts) {
|
if (stackBursts) {
|
||||||
_groupBursts();
|
_stackBursts();
|
||||||
|
}
|
||||||
|
if (stackDevelopedRaws) {
|
||||||
|
_stackDevelopedRaws();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _groupBursts() {
|
void _stackBursts() {
|
||||||
final byBurstKey = groupBy<AvesEntry, String?>(_filteredSortedEntries, (entry) => entry.getBurstKey(burstPatterns)).whereNotNullKey();
|
final byBurstKey = groupBy<AvesEntry, String?>(_filteredSortedEntries, (entry) => entry.getBurstKey(burstPatterns)).whereNotNullKey();
|
||||||
byBurstKey.forEach((burstKey, entries) {
|
byBurstKey.forEach((burstKey, entries) {
|
||||||
if (entries.length > 1) {
|
if (entries.length > 1) {
|
||||||
entries.sort(AvesEntrySort.compareByName);
|
entries.sort(AvesEntrySort.compareByName);
|
||||||
final mainEntry = entries.first;
|
final mainEntry = entries.first;
|
||||||
final burstEntry = mainEntry.copyWith(burstEntries: entries);
|
final stackEntry = mainEntry.copyWith(stackedEntries: entries);
|
||||||
_syntheticEntries.add(burstEntry);
|
_syntheticEntries.add(stackEntry);
|
||||||
|
|
||||||
entries.skip(1).toList().forEach((subEntry) {
|
entries.skip(1).forEach((subEntry) {
|
||||||
_filteredSortedEntries.remove(subEntry);
|
_filteredSortedEntries.remove(subEntry);
|
||||||
});
|
});
|
||||||
final index = _filteredSortedEntries.indexOf(mainEntry);
|
final index = _filteredSortedEntries.indexOf(mainEntry);
|
||||||
_filteredSortedEntries.removeAt(index);
|
_filteredSortedEntries.removeAt(index);
|
||||||
_filteredSortedEntries.insert(index, burstEntry);
|
_filteredSortedEntries.insert(index, stackEntry);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _stackDevelopedRaws() {
|
||||||
|
final allRawEntries = _filteredSortedEntries.where(TypeFilter.raw.test).toSet();
|
||||||
|
if (allRawEntries.isNotEmpty) {
|
||||||
|
final allDevelopedEntries = _filteredSortedEntries.where(MimeFilter(MimeTypes.jpeg).test).toSet();
|
||||||
|
final rawEntriesByDir = groupBy<AvesEntry, String?>(allRawEntries, (entry) => entry.directory);
|
||||||
|
rawEntriesByDir.forEach((dir, dirRawEntries) {
|
||||||
|
if (dir != null) {
|
||||||
|
final dirDevelopedEntries = allDevelopedEntries.where((entry) => entry.directory == dir).toSet();
|
||||||
|
for (final rawEntry in dirRawEntries) {
|
||||||
|
final rawFilename = rawEntry.filenameWithoutExtension;
|
||||||
|
final developedEntry = dirDevelopedEntries.firstWhereOrNull((entry) => entry.filenameWithoutExtension == rawFilename);
|
||||||
|
if (developedEntry != null) {
|
||||||
|
final stackEntry = rawEntry.copyWith(stackedEntries: [rawEntry, developedEntry]);
|
||||||
|
_syntheticEntries.add(stackEntry);
|
||||||
|
|
||||||
|
_filteredSortedEntries.remove(developedEntry);
|
||||||
|
final index = _filteredSortedEntries.indexOf(rawEntry);
|
||||||
|
_filteredSortedEntries.removeAt(index);
|
||||||
|
_filteredSortedEntries.insert(0, stackEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _applySort() {
|
void _applySort() {
|
||||||
if (fixedSort) return;
|
if (fixedSort) return;
|
||||||
|
|
||||||
|
@ -322,23 +355,52 @@ class CollectionLens with ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onEntryRemoved(Set<AvesEntry> entries) {
|
void _onEntryRemoved(Set<AvesEntry> entries) {
|
||||||
if (groupBursts) {
|
if (_syntheticEntries.isNotEmpty) {
|
||||||
// find impacted burst groups
|
// find impacted stacks
|
||||||
final obsoleteBurstEntries = <AvesEntry>{};
|
final obsoleteStacks = <AvesEntry>{};
|
||||||
final burstKeys = entries.map((entry) => entry.getBurstKey(burstPatterns)).whereNotNull().toSet();
|
|
||||||
if (burstKeys.isNotEmpty) {
|
void _replaceStack(AvesEntry stackEntry, AvesEntry entry) {
|
||||||
_filteredSortedEntries.where((entry) => entry.isBurst && burstKeys.contains(entry.getBurstKey(burstPatterns))).forEach((mainEntry) {
|
obsoleteStacks.add(stackEntry);
|
||||||
final subEntries = mainEntry.burstEntries!;
|
fixedSelection?.replace(stackEntry, entry);
|
||||||
|
_filteredSortedEntries.replace(stackEntry, entry);
|
||||||
|
_sortedEntries?.replace(stackEntry, entry);
|
||||||
|
sections.forEach((key, sectionEntries) => sectionEntries.replace(stackEntry, entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
final stacks = _filteredSortedEntries.where((entry) => entry.isStack).toSet();
|
||||||
|
stacks.forEach((stackEntry) {
|
||||||
|
final subEntries = stackEntry.stackedEntries!;
|
||||||
|
if (subEntries.any(entries.contains)) {
|
||||||
|
final mainEntry = subEntries.first;
|
||||||
|
|
||||||
// remove the deleted sub-entries
|
// remove the deleted sub-entries
|
||||||
subEntries.removeWhere(entries.contains);
|
subEntries.removeWhere(entries.contains);
|
||||||
if (subEntries.isEmpty) {
|
|
||||||
// remove the burst entry itself
|
switch (subEntries.length) {
|
||||||
obsoleteBurstEntries.add(mainEntry);
|
case 0:
|
||||||
|
// remove the stack itself
|
||||||
|
obsoleteStacks.add(stackEntry);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// replace the stack by the last remaining sub-entry
|
||||||
|
_replaceStack(stackEntry, subEntries.first);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// keep the stack with the remaining sub-entries
|
||||||
|
if (!subEntries.contains(mainEntry)) {
|
||||||
|
// recreate the stack with the correct main entry
|
||||||
|
_replaceStack(stackEntry, subEntries.first.copyWith(stackedEntries: subEntries));
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// TODO TLAD [burst] recreate the burst main entry if the first sub-entry got deleted
|
}
|
||||||
});
|
});
|
||||||
entries.addAll(obsoleteBurstEntries);
|
|
||||||
}
|
obsoleteStacks.forEach((stackEntry) {
|
||||||
|
_syntheticEntries.remove(stackEntry);
|
||||||
|
stackEntry.dispose();
|
||||||
|
});
|
||||||
|
entries.addAll(obsoleteStacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we should remove obsolete entries and sections
|
// we should remove obsolete entries and sections
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
|
|
||||||
|
extension ExtraList<E> on List<E> {
|
||||||
|
bool replace(E old, E newItem) {
|
||||||
|
final index = indexOf(old);
|
||||||
|
if (index == -1) return false;
|
||||||
|
|
||||||
|
this[index] = newItem;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension ExtraMapNullableKey<K extends Object, V> on Map<K?, V> {
|
extension ExtraMapNullableKey<K extends Object, V> on Map<K?, V> {
|
||||||
Map<K, V> whereNotNullKey() => <K, V>{for (var v in keys.whereNotNull()) v: this[v] as V};
|
Map<K, V> whereNotNullKey() => <K, V>{for (var v in keys.whereNotNull()) v: this[v] as V};
|
||||||
}
|
}
|
||||||
|
|
|
@ -444,7 +444,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<AvesEntry> _getExpandedSelectedItems(Selection<AvesEntry> selection) {
|
Set<AvesEntry> _getExpandedSelectedItems(Selection<AvesEntry> selection) {
|
||||||
return selection.selectedItems.expand((entry) => entry.burstEntries ?? {entry}).toSet();
|
return selection.selectedItems.expand((entry) => entry.stackedEntries ?? {entry}).toSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
// key is expected by test driver (e.g. 'menu-configureView', 'menu-map')
|
// key is expected by test driver (e.g. 'menu-configureView', 'menu-map')
|
||||||
|
|
|
@ -237,7 +237,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
||||||
Set<AvesEntry> _getTargetItems(BuildContext context) {
|
Set<AvesEntry> _getTargetItems(BuildContext context) {
|
||||||
final selection = context.read<Selection<AvesEntry>>();
|
final selection = context.read<Selection<AvesEntry>>();
|
||||||
final groupedEntries = (selection.isSelecting ? selection.selectedItems : context.read<CollectionLens>().sortedEntries);
|
final groupedEntries = (selection.isSelecting ? selection.selectedItems : context.read<CollectionLens>().sortedEntries);
|
||||||
return groupedEntries.expand((entry) => entry.burstEntries ?? {entry}).toSet();
|
return groupedEntries.expand((entry) => entry.stackedEntries ?? {entry}).toSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _share(BuildContext context) async {
|
Future<void> _share(BuildContext context) async {
|
||||||
|
|
|
@ -80,7 +80,7 @@ class EntryListDetails extends StatelessWidget {
|
||||||
final date = entry.bestDate;
|
final date = entry.bestDate;
|
||||||
final dateText = date != null ? formatDateTime(date, locale, use24hour) : AText.valueNotAvailable;
|
final dateText = date != null ? formatDateTime(date, locale, use24hour) : AText.valueNotAvailable;
|
||||||
|
|
||||||
final size = entry.burstEntries?.map((v) => v.sizeBytes).sum ?? entry.sizeBytes;
|
final size = entry.stackedEntries?.map((v) => v.sizeBytes).sum ?? entry.sizeBytes;
|
||||||
final sizeText = size != null ? formatFileSize(locale, size) : AText.valueNotAvailable;
|
final sizeText = size != null ? formatFileSize(locale, size) : AText.valueNotAvailable;
|
||||||
|
|
||||||
return Wrap(
|
return Wrap(
|
||||||
|
|
|
@ -181,8 +181,8 @@ class MultiPageIcon extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String? text;
|
String? text;
|
||||||
if (entry.isBurst) {
|
if (entry.isStack) {
|
||||||
text = '${entry.burstEntries?.length}';
|
text = '${entry.stackedEntries?.length}';
|
||||||
}
|
}
|
||||||
final child = OverlayIcon(
|
final child = OverlayIcon(
|
||||||
icon: AIcons.multiPage,
|
icon: AIcons.multiPage,
|
||||||
|
|
|
@ -300,7 +300,7 @@ class _HomePageState extends State<HomePage> {
|
||||||
// if we group bursts, opening a burst sub-entry should:
|
// if we group bursts, opening a burst sub-entry should:
|
||||||
// - identify and select the containing main entry,
|
// - identify and select the containing main entry,
|
||||||
// - select the sub-entry in the Viewer page.
|
// - select the sub-entry in the Viewer page.
|
||||||
groupBursts: false,
|
stackBursts: false,
|
||||||
);
|
);
|
||||||
final viewerEntryPath = viewerEntry.path;
|
final viewerEntryPath = viewerEntry.path;
|
||||||
final collectionEntry = collection.sortedEntries.firstWhereOrNull((entry) => entry.path == viewerEntryPath);
|
final collectionEntry = collection.sortedEntries.firstWhereOrNull((entry) => entry.path == viewerEntryPath);
|
||||||
|
|
|
@ -163,7 +163,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
||||||
}
|
}
|
||||||
|
|
||||||
AvesEntry _getTargetEntry(BuildContext context, EntryAction action) {
|
AvesEntry _getTargetEntry(BuildContext context, EntryAction action) {
|
||||||
if (mainEntry.isMultiPage && (mainEntry.isBurst || EntryActions.pageActions.contains(action))) {
|
if (mainEntry.isMultiPage && (mainEntry.isStack || EntryActions.pageActions.contains(action))) {
|
||||||
final multiPageController = context.read<MultiPageConductor>().getController(mainEntry);
|
final multiPageController = context.read<MultiPageConductor>().getController(mainEntry);
|
||||||
if (multiPageController != null) {
|
if (multiPageController != null) {
|
||||||
final multiPageInfo = multiPageController.info;
|
final multiPageInfo = multiPageController.info;
|
||||||
|
|
|
@ -795,11 +795,11 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
||||||
if (collectionEntries.remove(removedEntry)) return;
|
if (collectionEntries.remove(removedEntry)) return;
|
||||||
|
|
||||||
// remove from burst
|
// remove from burst
|
||||||
final mainEntry = collectionEntries.firstWhereOrNull((entry) => entry.burstEntries?.contains(removedEntry) == true);
|
final mainEntry = collectionEntries.firstWhereOrNull((entry) => entry.stackedEntries?.contains(removedEntry) == true);
|
||||||
if (mainEntry != null) {
|
if (mainEntry != null) {
|
||||||
final multiPageController = context.read<MultiPageConductor>().getController(mainEntry);
|
final multiPageController = context.read<MultiPageConductor>().getController(mainEntry);
|
||||||
if (multiPageController != null) {
|
if (multiPageController != null) {
|
||||||
mainEntry.burstEntries!.remove(removedEntry);
|
mainEntry.stackedEntries!.remove(removedEntry);
|
||||||
multiPageController.reset();
|
multiPageController.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ class _InfoPageState extends State<InfoPage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mainEntry.isBurst
|
return mainEntry.isStack
|
||||||
? PageEntryBuilder(
|
? PageEntryBuilder(
|
||||||
multiPageController: context.read<MultiPageConductor>().getController(mainEntry),
|
multiPageController: context.read<MultiPageConductor>().getController(mainEntry),
|
||||||
builder: (pageEntry) => _buildContent(pageEntry: pageEntry),
|
builder: (pageEntry) => _buildContent(pageEntry: pageEntry),
|
||||||
|
|
|
@ -181,7 +181,7 @@ class _TvButtonRowContent extends StatelessWidget {
|
||||||
}) {
|
}) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case EntryAction.toggleFavourite:
|
case EntryAction.toggleFavourite:
|
||||||
final favouriteTargetEntry = mainEntry.isBurst ? pageEntry : mainEntry;
|
final favouriteTargetEntry = mainEntry.isStack ? pageEntry : mainEntry;
|
||||||
return FavouriteTogglerCaption(
|
return FavouriteTogglerCaption(
|
||||||
entries: {favouriteTargetEntry},
|
entries: {favouriteTargetEntry},
|
||||||
enabled: enabled,
|
enabled: enabled,
|
||||||
|
@ -236,7 +236,7 @@ class _ViewerButtonRowContentState extends State<ViewerButtonRowContent> {
|
||||||
|
|
||||||
AvesEntry get pageEntry => widget.pageEntry;
|
AvesEntry get pageEntry => widget.pageEntry;
|
||||||
|
|
||||||
AvesEntry get favouriteTargetEntry => mainEntry.isBurst ? pageEntry : mainEntry;
|
AvesEntry get favouriteTargetEntry => mainEntry.isStack ? pageEntry : mainEntry;
|
||||||
|
|
||||||
static const double padding = ViewerButtonRowContent.padding;
|
static const double padding = ViewerButtonRowContent.padding;
|
||||||
|
|
||||||
|
@ -487,7 +487,7 @@ class _ViewerButtonRowContentState extends State<ViewerButtonRowContent> {
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
);
|
);
|
||||||
case EntryAction.toggleFavourite:
|
case EntryAction.toggleFavourite:
|
||||||
final favouriteTargetEntry = mainEntry.isBurst ? pageEntry : mainEntry;
|
final favouriteTargetEntry = mainEntry.isStack ? pageEntry : mainEntry;
|
||||||
child = FavouriteToggler(
|
child = FavouriteToggler(
|
||||||
entries: {favouriteTargetEntry},
|
entries: {favouriteTargetEntry},
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
|
|
|
@ -71,7 +71,7 @@ class ViewStateConductor {
|
||||||
void reset(AvesEntry entry) {
|
void reset(AvesEntry entry) {
|
||||||
final uris = <AvesEntry>{
|
final uris = <AvesEntry>{
|
||||||
entry,
|
entry,
|
||||||
...?entry.burstEntries,
|
...?entry.stackedEntries,
|
||||||
}.map((v) => v.uri).toSet();
|
}.map((v) => v.uri).toSet();
|
||||||
final entryControllers = _controllers.where((v) => uris.contains(v.entry.uri)).toSet();
|
final entryControllers = _controllers.where((v) => uris.contains(v.entry.uri)).toSet();
|
||||||
entryControllers.forEach((controller) {
|
entryControllers.forEach((controller) {
|
||||||
|
|
Loading…
Reference in a new issue