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),
|
||||
);
|
||||
|
||||
// sortPinnedFirst partitions the rendered list into pinned/unpinned
|
||||
// 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;
|
||||
return !filterOptions.hasActiveFilter && !hasActiveSearch;
|
||||
}
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
|
||||
+45
-6
@@ -38,10 +38,12 @@ TabViewReorderResult? buildTabViewReorderResult({
|
||||
required List<TabViewItem> visibleItems,
|
||||
required List<TabsWithRootAndDepthResult> treeRows,
|
||||
required Set<String> collapsedGroups,
|
||||
required Set<String> pinnedTabIds,
|
||||
required int oldIndex,
|
||||
required int newIndex,
|
||||
required TabListDirection tabListDirection,
|
||||
required bool hierarchical,
|
||||
required bool sortPinnedFirst,
|
||||
}) {
|
||||
if (oldIndex < 0 || oldIndex >= visibleItems.length) {
|
||||
logger.t(
|
||||
@@ -65,11 +67,14 @@ TabViewReorderResult? buildTabViewReorderResult({
|
||||
final ordered = reordered.map((item) => item.tabId).toList();
|
||||
return _resultFromOrderedIds(
|
||||
movingTabIds: [movingItem.tabId],
|
||||
orderedTabIds: tabListDirection == TabListDirection.newestFirst
|
||||
// Rendering flips root group order for newest-first; convert the
|
||||
// display order back to storage order before choosing anchors.
|
||||
? ordered.reversed.toList()
|
||||
: ordered,
|
||||
orderedTabIds: _orderedIdsForStorageAnchors(
|
||||
ordered,
|
||||
tabListDirection: tabListDirection,
|
||||
pinnedTabIds: pinnedTabIds,
|
||||
parentById: const {},
|
||||
movingPartitionRootId: movingItem.tabId,
|
||||
sortPinnedFirst: sortPinnedFirst,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -195,10 +200,44 @@ TabViewReorderResult? buildTabViewReorderResult({
|
||||
|
||||
return _resultFromOrderedIds(
|
||||
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({
|
||||
required List<String> movingTabIds,
|
||||
required List<String> orderedTabIds,
|
||||
|
||||
+7
@@ -184,6 +184,11 @@ class _TabGridView extends HookConsumerWidget {
|
||||
final tabListDirection = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select((s) => s.tabListDirection),
|
||||
);
|
||||
final pinnedTabIds = ref.watch(
|
||||
watchPinnedTabIdsProvider.select(
|
||||
(value) => value.value ?? const <String>{},
|
||||
),
|
||||
);
|
||||
final collapsedGroups = ref.watch(collapsedGroupsProvider);
|
||||
final List<TabsWithRootAndDepthResult> treeRows = showHierarchicalTabs
|
||||
? ref.watch(
|
||||
@@ -384,10 +389,12 @@ class _TabGridView extends HookConsumerWidget {
|
||||
visibleItems: primaryRows,
|
||||
treeRows: treeRows,
|
||||
collapsedGroups: collapsedGroups,
|
||||
pinnedTabIds: pinnedTabIds,
|
||||
oldIndex: oldIndex,
|
||||
newIndex: newIndex,
|
||||
tabListDirection: tabListDirection,
|
||||
hierarchical: showHierarchicalTabs && !hasActiveSearch,
|
||||
sortPinnedFirst: filterOptions.sortPinnedFirst,
|
||||
);
|
||||
|
||||
if (result == null) return;
|
||||
|
||||
+7
@@ -241,6 +241,11 @@ class _TabListView extends HookConsumerWidget {
|
||||
final canManualReorder = ref.watch(canManualTabReorderProvider);
|
||||
final reorderEnabled = tabsReorderable && canManualReorder;
|
||||
final filterOptions = ref.watch(tabViewFilterControllerProvider);
|
||||
final pinnedTabIds = ref.watch(
|
||||
watchPinnedTabIdsProvider.select(
|
||||
(value) => value.value ?? const <String>{},
|
||||
),
|
||||
);
|
||||
final showHierarchicalTabs = filterOptions.showHierarchicalTabs;
|
||||
final tabListDirection = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select((s) => s.tabListDirection),
|
||||
@@ -447,10 +452,12 @@ class _TabListView extends HookConsumerWidget {
|
||||
visibleItems: primaryRows,
|
||||
treeRows: treeRows,
|
||||
collapsedGroups: collapsedGroups,
|
||||
pinnedTabIds: pinnedTabIds,
|
||||
oldIndex: oldIndex,
|
||||
newIndex: newIndex,
|
||||
tabListDirection: tabListDirection,
|
||||
hierarchical: showHierarchicalTabs && !hasActiveSearch,
|
||||
sortPinnedFirst: filterOptions.sortPinnedFirst,
|
||||
);
|
||||
|
||||
if (result == null) return;
|
||||
|
||||
Reference in New Issue
Block a user