support reordering with tab pinning active
This commit is contained in:
@@ -60,13 +60,7 @@ bool canManualTabReorder(Ref ref) {
|
|||||||
).select((value) => (value.value?.query ?? '').isNotEmpty),
|
).select((value) => (value.value?.query ?? '').isNotEmpty),
|
||||||
);
|
);
|
||||||
|
|
||||||
// sortPinnedFirst partitions the rendered list into pinned/unpinned
|
return !filterOptions.hasActiveFilter && !hasActiveSearch;
|
||||||
// sections that don't reflect storage order_key ordering. A drag would
|
|
||||||
// compute anchors across the partition boundary and silently snap the
|
|
||||||
// moved tab into the wrong section once the stream re-renders.
|
|
||||||
return !filterOptions.hasActiveFilter &&
|
|
||||||
!hasActiveSearch &&
|
|
||||||
!filterOptions.sortPinnedFirst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Riverpod(keepAlive: true)
|
@Riverpod(keepAlive: true)
|
||||||
|
|||||||
+45
-6
@@ -38,10 +38,12 @@ TabViewReorderResult? buildTabViewReorderResult({
|
|||||||
required List<TabViewItem> visibleItems,
|
required List<TabViewItem> visibleItems,
|
||||||
required List<TabsWithRootAndDepthResult> treeRows,
|
required List<TabsWithRootAndDepthResult> treeRows,
|
||||||
required Set<String> collapsedGroups,
|
required Set<String> collapsedGroups,
|
||||||
|
required Set<String> pinnedTabIds,
|
||||||
required int oldIndex,
|
required int oldIndex,
|
||||||
required int newIndex,
|
required int newIndex,
|
||||||
required TabListDirection tabListDirection,
|
required TabListDirection tabListDirection,
|
||||||
required bool hierarchical,
|
required bool hierarchical,
|
||||||
|
required bool sortPinnedFirst,
|
||||||
}) {
|
}) {
|
||||||
if (oldIndex < 0 || oldIndex >= visibleItems.length) {
|
if (oldIndex < 0 || oldIndex >= visibleItems.length) {
|
||||||
logger.t(
|
logger.t(
|
||||||
@@ -65,11 +67,14 @@ TabViewReorderResult? buildTabViewReorderResult({
|
|||||||
final ordered = reordered.map((item) => item.tabId).toList();
|
final ordered = reordered.map((item) => item.tabId).toList();
|
||||||
return _resultFromOrderedIds(
|
return _resultFromOrderedIds(
|
||||||
movingTabIds: [movingItem.tabId],
|
movingTabIds: [movingItem.tabId],
|
||||||
orderedTabIds: tabListDirection == TabListDirection.newestFirst
|
orderedTabIds: _orderedIdsForStorageAnchors(
|
||||||
// Rendering flips root group order for newest-first; convert the
|
ordered,
|
||||||
// display order back to storage order before choosing anchors.
|
tabListDirection: tabListDirection,
|
||||||
? ordered.reversed.toList()
|
pinnedTabIds: pinnedTabIds,
|
||||||
: ordered,
|
parentById: const {},
|
||||||
|
movingPartitionRootId: movingItem.tabId,
|
||||||
|
sortPinnedFirst: sortPinnedFirst,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,10 +200,44 @@ TabViewReorderResult? buildTabViewReorderResult({
|
|||||||
|
|
||||||
return _resultFromOrderedIds(
|
return _resultFromOrderedIds(
|
||||||
movingTabIds: moveBlock,
|
movingTabIds: moveBlock,
|
||||||
orderedTabIds: orderedTabIds,
|
orderedTabIds: _orderedIdsForStorageAnchors(
|
||||||
|
orderedTabIds,
|
||||||
|
tabListDirection: tabListDirection,
|
||||||
|
pinnedTabIds: pinnedTabIds,
|
||||||
|
parentById: parentById,
|
||||||
|
movingPartitionRootId: _rootIdFor(movingItem.tabId, parentById),
|
||||||
|
sortPinnedFirst: sortPinnedFirst,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> _orderedIdsForStorageAnchors(
|
||||||
|
List<String> orderedTabIds, {
|
||||||
|
required TabListDirection tabListDirection,
|
||||||
|
required Set<String> pinnedTabIds,
|
||||||
|
required Map<String, String?> parentById,
|
||||||
|
required String movingPartitionRootId,
|
||||||
|
required bool sortPinnedFirst,
|
||||||
|
}) {
|
||||||
|
var storageOrderedIds = tabListDirection == TabListDirection.newestFirst
|
||||||
|
// Rendering flips root group order for newest-first; convert the
|
||||||
|
// display order back to storage order before choosing anchors.
|
||||||
|
? orderedTabIds.reversed.toList()
|
||||||
|
: orderedTabIds;
|
||||||
|
|
||||||
|
if (!sortPinnedFirst || pinnedTabIds.isEmpty) {
|
||||||
|
return storageOrderedIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pinned-first is a render-only partition, so choose DB anchors only from
|
||||||
|
// the moving tab's own partition to avoid snapping across the boundary.
|
||||||
|
final movingPinned = pinnedTabIds.contains(movingPartitionRootId);
|
||||||
|
return storageOrderedIds.where((tabId) {
|
||||||
|
final rootId = _rootIdFor(tabId, parentById);
|
||||||
|
return pinnedTabIds.contains(rootId) == movingPinned;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
TabViewReorderResult? _resultFromOrderedIds({
|
TabViewReorderResult? _resultFromOrderedIds({
|
||||||
required List<String> movingTabIds,
|
required List<String> movingTabIds,
|
||||||
required List<String> orderedTabIds,
|
required List<String> orderedTabIds,
|
||||||
|
|||||||
+7
@@ -184,6 +184,11 @@ class _TabGridView extends HookConsumerWidget {
|
|||||||
final tabListDirection = ref.watch(
|
final tabListDirection = ref.watch(
|
||||||
generalSettingsWithDefaultsProvider.select((s) => s.tabListDirection),
|
generalSettingsWithDefaultsProvider.select((s) => s.tabListDirection),
|
||||||
);
|
);
|
||||||
|
final pinnedTabIds = ref.watch(
|
||||||
|
watchPinnedTabIdsProvider.select(
|
||||||
|
(value) => value.value ?? const <String>{},
|
||||||
|
),
|
||||||
|
);
|
||||||
final collapsedGroups = ref.watch(collapsedGroupsProvider);
|
final collapsedGroups = ref.watch(collapsedGroupsProvider);
|
||||||
final List<TabsWithRootAndDepthResult> treeRows = showHierarchicalTabs
|
final List<TabsWithRootAndDepthResult> treeRows = showHierarchicalTabs
|
||||||
? ref.watch(
|
? ref.watch(
|
||||||
@@ -384,10 +389,12 @@ class _TabGridView extends HookConsumerWidget {
|
|||||||
visibleItems: primaryRows,
|
visibleItems: primaryRows,
|
||||||
treeRows: treeRows,
|
treeRows: treeRows,
|
||||||
collapsedGroups: collapsedGroups,
|
collapsedGroups: collapsedGroups,
|
||||||
|
pinnedTabIds: pinnedTabIds,
|
||||||
oldIndex: oldIndex,
|
oldIndex: oldIndex,
|
||||||
newIndex: newIndex,
|
newIndex: newIndex,
|
||||||
tabListDirection: tabListDirection,
|
tabListDirection: tabListDirection,
|
||||||
hierarchical: showHierarchicalTabs && !hasActiveSearch,
|
hierarchical: showHierarchicalTabs && !hasActiveSearch,
|
||||||
|
sortPinnedFirst: filterOptions.sortPinnedFirst,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
|
|||||||
+7
@@ -241,6 +241,11 @@ class _TabListView extends HookConsumerWidget {
|
|||||||
final canManualReorder = ref.watch(canManualTabReorderProvider);
|
final canManualReorder = ref.watch(canManualTabReorderProvider);
|
||||||
final reorderEnabled = tabsReorderable && canManualReorder;
|
final reorderEnabled = tabsReorderable && canManualReorder;
|
||||||
final filterOptions = ref.watch(tabViewFilterControllerProvider);
|
final filterOptions = ref.watch(tabViewFilterControllerProvider);
|
||||||
|
final pinnedTabIds = ref.watch(
|
||||||
|
watchPinnedTabIdsProvider.select(
|
||||||
|
(value) => value.value ?? const <String>{},
|
||||||
|
),
|
||||||
|
);
|
||||||
final showHierarchicalTabs = filterOptions.showHierarchicalTabs;
|
final showHierarchicalTabs = filterOptions.showHierarchicalTabs;
|
||||||
final tabListDirection = ref.watch(
|
final tabListDirection = ref.watch(
|
||||||
generalSettingsWithDefaultsProvider.select((s) => s.tabListDirection),
|
generalSettingsWithDefaultsProvider.select((s) => s.tabListDirection),
|
||||||
@@ -447,10 +452,12 @@ class _TabListView extends HookConsumerWidget {
|
|||||||
visibleItems: primaryRows,
|
visibleItems: primaryRows,
|
||||||
treeRows: treeRows,
|
treeRows: treeRows,
|
||||||
collapsedGroups: collapsedGroups,
|
collapsedGroups: collapsedGroups,
|
||||||
|
pinnedTabIds: pinnedTabIds,
|
||||||
oldIndex: oldIndex,
|
oldIndex: oldIndex,
|
||||||
newIndex: newIndex,
|
newIndex: newIndex,
|
||||||
tabListDirection: tabListDirection,
|
tabListDirection: tabListDirection,
|
||||||
hierarchical: showHierarchicalTabs && !hasActiveSearch,
|
hierarchical: showHierarchicalTabs && !hasActiveSearch,
|
||||||
|
sortPinnedFirst: filterOptions.sortPinnedFirst,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user