improve tab reorder logic

This commit is contained in:
Fabian Freund
2025-07-17 21:59:33 +02:00
parent d41d56cbaf
commit 3c5bd4a8ad
9 changed files with 83 additions and 12 deletions
+1
View File
@@ -15,6 +15,7 @@ targets:
lexo_rank_next: "text (int, text null)"
lexo_rank_previous: "text (int, text null)"
lexo_rank_reorder_after: "text (text null, text null)"
lexo_rank_reorder_before: "text (text null, text null)"
modules:
- json1
- fts5
@@ -40,6 +40,19 @@ String _reorderAfter(List<Object?> args) {
}
}
String _reorderBefore(List<Object?> args) {
final first = args[0].mapNotNull((arg) => LexoRank.parse(arg as String));
final last = args[1].mapNotNull((arg) => LexoRank.parse(arg as String));
if (first == null) {
throw Exception('Tab not found');
} else if (last == null) {
return first.genPrev().value;
} else {
return last.genBetween(first).value;
}
}
void registerLexorankFunctions(CommonDatabase database) {
database.createFunction(
functionName: 'lexo_rank_next',
@@ -56,4 +69,9 @@ void registerLexorankFunctions(CommonDatabase database) {
argumentCount: const AllowedArgumentCount(2),
function: _reorderAfter,
);
database.createFunction(
functionName: 'lexo_rank_reorder_before',
argumentCount: const AllowedArgumentCount(2),
function: _reorderBefore,
);
}
@@ -300,6 +300,8 @@ class ViewTabsSheetWidget extends HookConsumerWidget {
Expanded(
child: HookConsumer(
builder: (context, ref, child) {
final gridViewKey = useMemoized(() => GlobalKey());
final container = ref.watch(selectedContainerProvider);
final filteredTabEntities = ref.watch(
@@ -387,10 +389,11 @@ class ViewTabsSheetWidget extends HookConsumerWidget {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 4.0),
child: ReorderableBuilder(
child: ReorderableBuilder.builder(
//Rebuild when cross axis count changes
key: ValueKey(crossAxisCount),
scrollController: sheetScrollController,
itemCount: tabs.length,
onDragStarted: (index) {
ref.read(willAcceptDropProvider.notifier).clear();
},
@@ -423,19 +426,27 @@ class ViewTabsSheetWidget extends HookConsumerWidget {
containerId,
);
} else {
final orderAfterIndex = newIndex;
key = await containerRepository.getOrderKeyAfterTab(
filteredTabEntities.value[orderAfterIndex].tabId,
containerId,
);
if (newIndex < oldIndex) {
key = await containerRepository.getOrderKeyAfterTab(
filteredTabEntities.value[newIndex - 1].tabId,
containerId,
);
} else {
key = await containerRepository
.getOrderKeyBeforeTab(
filteredTabEntities.value[newIndex + 1].tabId,
containerId,
);
}
}
await ref
.read(tabDataRepositoryProvider.notifier)
.assignOrderKey(tabId, key);
},
builder: (children) {
childBuilder: (itemBuilder) {
return GridView.builder(
key: gridViewKey,
controller: sheetScrollController,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
//Sync values for itemHeight calculation _calculateItemHeight
@@ -444,11 +455,11 @@ class ViewTabsSheetWidget extends HookConsumerWidget {
crossAxisSpacing: 8.0,
crossAxisCount: crossAxisCount,
),
itemCount: children.length,
itemBuilder: (context, index) => children[index],
itemCount: tabs.length,
itemBuilder: (context, index) =>
itemBuilder(tabs[index], index),
);
},
children: tabs,
),
);
},
@@ -96,4 +96,11 @@ class ContainerDao extends DatabaseAccessor<TabDatabase>
) {
return db.orderKeyAfterTab(containerId: containerId, tabId: tabId);
}
SingleSelectable<String> generateOrderKeyBeforeTabId(
String? containerId,
String tabId,
) {
return db.orderKeyBeforeTab(containerId: containerId, tabId: tabId);
}
}
@@ -118,6 +118,18 @@ orderKeyAfterTab(:tab_id AS TEXT, :container_id AS TEXT OR NULL):
FROM ordered_table
WHERE id = :tab_id;
orderKeyBeforeTab(:tab_id AS TEXT, :container_id AS TEXT OR NULL):
WITH ordered_table AS (
SELECT id,
order_key,
LAG(order_key) OVER (ORDER BY order_key) AS prev_order_key
FROM tab
WHERE container_id IS :container_id
)
SELECT lexo_rank_reorder_before(order_key, prev_order_key)
FROM ordered_table
WHERE id = :tab_id;
queryTabsBasic WITH TabQueryResult:
WITH weights AS (
SELECT
@@ -1165,6 +1165,17 @@ abstract class _$TabDatabase extends GeneratedDatabase {
).map((QueryRow row) => row.read<String>('_c0'));
}
Selectable<String> orderKeyBeforeTab({
String? containerId,
required String tabId,
}) {
return customSelect(
'WITH ordered_table AS (SELECT id, order_key, LAG(order_key)OVER (ORDER BY order_key RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE NO OTHERS) AS prev_order_key FROM tab WHERE container_id IS ?1) SELECT lexo_rank_reorder_before(order_key, prev_order_key) AS _c0 FROM ordered_table WHERE id = ?2',
variables: [Variable<String>(containerId), Variable<String>(tabId)],
readsFrom: {tab},
).map((QueryRow row) => row.read<String>('_c0'));
}
Selectable<TabQueryResult> queryTabsBasic({required String query}) {
return customSelect(
'WITH weights AS (SELECT 10.0 AS title_weight, 5.0 AS url_weight) SELECT t.id, t.title, CAST(t.url AS TEXT) AS url, t.url AS clean_url, bm25(tab_fts, weights.title_weight, weights.url_weight) AS weighted_rank FROM tab_fts AS fts INNER JOIN tab AS t ON t."rowid" = fts."rowid" CROSS JOIN weights WHERE fts.title LIKE ?1 OR fts.url LIKE ?1 ORDER BY weighted_rank ASC, t.timestamp DESC',
@@ -83,6 +83,14 @@ class ContainerRepository extends _$ContainerRepository {
.getSingle();
}
Future<String> getOrderKeyBeforeTab(String tabId, String? containerId) {
return ref
.read(tabDatabaseProvider)
.containerDao
.generateOrderKeyBeforeTabId(containerId, tabId)
.getSingle();
}
Future<Color> unusedRandomContainerColor() async {
final allColors = colorTypes.flattened.toList();
final usedColors = await getDistinctColors();
@@ -7,7 +7,7 @@ part of 'container.dart';
// **************************************************************************
String _$containerRepositoryHash() =>
r'5344ecde33c1c80c1fa2bc8383faca181da91593';
r'af4ccf6cc12eebae2313df6c8f9ca63db842ffe5';
/// See also [ContainerRepository].
@ProviderFor(ContainerRepository)
+4 -1
View File
@@ -24,7 +24,10 @@ dependencies:
flutter_material_design_icons: ^1.1.7447
flutter_mozilla_components:
path: ../packages/flutter_mozilla_components
flutter_reorderable_grid_view: ^5.5.0
flutter_reorderable_grid_view:
git:
url: https://github.com/FaFre/flutter-reorderable-grid-view.git
ref: fix_builder_assert
flutter_secure_storage: ^10.0.0-beta.4
flutter_slidable: ^4.0.0
flutter_svg: ^2.2.0