add setting to control tab insertion position

This commit is contained in:
Fabian Freund
2026-03-13 05:07:48 +01:00
parent 8dc7151c45
commit 8a07d7df1a
10 changed files with 132 additions and 10 deletions
@@ -57,7 +57,7 @@ final class TabSessionProvider extends $NotifierProvider<TabSession, void> {
}
}
String _$tabSessionHash() => r'be44598ad023c2fb23e48d3fa4bf805c4640c599';
String _$tabSessionHash() => r'636f0940425d689ff98fabfc61687de828a8eeb9';
final class TabSessionFamily extends $Family
with $ClassFamilyOverride<TabSession, void, void, void, String?> {
@@ -42,6 +42,8 @@ import 'package:weblibre/features/geckoview/features/tabs/domain/providers/selec
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/container.dart';
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
import 'package:weblibre/features/tor/domain/repositories/tor_proxy.dart';
import 'package:weblibre/features/user/data/models/general_settings.dart';
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
import 'package:weblibre/utils/debouncer.dart';
part 'tab.g.dart';
@@ -66,6 +68,14 @@ class TabRepository extends _$TabRepository {
_tabFromIntent.remove(tabId);
}
NewTabPosition _newTabPositionForParent(String? parentId) {
if (parentId != null) {
return NewTabPosition.first;
}
return ref.read(generalSettingsWithDefaultsProvider).newTabPosition;
}
Future<String?> _resolveParentIdForContext({
required String? parentId,
required String? targetContextId,
@@ -122,6 +132,7 @@ class TabRepository extends _$TabRepository {
final effectiveContextId = tabMode is IsolatedTabMode
? effectiveIsolationContextId
: assignedContainer?.metadata.contextualIdentity;
final newTabPosition = _newTabPositionForParent(validatedParentId);
final newTabId = await tabDao.upsertTabTransactional(
() {
@@ -139,6 +150,7 @@ class TabRepository extends _$TabRepository {
);
},
parentId: Value(validatedParentId),
newTabPosition: newTabPosition,
containerId: Value(assignedContainer?.id),
url: Value(url),
tabMode: Value(tabMode),
@@ -171,7 +183,6 @@ class TabRepository extends _$TabRepository {
tabs: tabs,
selectTabId: selectTabId,
);
// Build sets for validation
final creatingTabIds = createdTabIds.toSet();
final parentIdsToValidate = tabs
@@ -204,6 +215,7 @@ class TabRepository extends _$TabRepository {
tabId,
parentId: Value(validatedParentId),
source: TabSource.manual,
newTabPosition: _newTabPositionForParent(validatedParentId),
containerId: Value(assignedContainer?.id),
url: Value(Uri.tryParse(tab.url)),
tabMode: Value(
@@ -254,6 +266,7 @@ class TabRepository extends _$TabRepository {
);
},
parentId: const Value.absent(),
newTabPosition: _newTabPositionForParent(null),
containerId: Value(containerData?.id),
tabMode: Value(duplicateTabMode),
);
@@ -597,6 +610,7 @@ class TabRepository extends _$TabRepository {
tabId,
parentId: const Value.absent(),
source: TabSource.addedEvent,
newTabPosition: _newTabPositionForParent(null),
containerId: Value(containerId),
);
},
@@ -41,7 +41,7 @@ final class TabRepositoryProvider
}
}
String _$tabRepositoryHash() => r'1c866a1f5b1872ba07ebac82ff92455a7af316a3';
String _$tabRepositoryHash() => r'4dd31901b4d02ca075d3dcec3822f5a2832d164c';
abstract class _$TabRepository extends $Notifier<void> {
void build();
@@ -601,7 +601,7 @@ final class QuickTabSwitcherTabStatesProvider
}
String _$quickTabSwitcherTabStatesHash() =>
r'2627bcd25718472f0c8057e836d76bdaa7317c1c';
r'd83ea34d366238681baaad0b36699ee0742edc3d';
final class QuickTabSwitcherTabStatesFamily extends $Family
with
@@ -30,6 +30,7 @@ import 'package:weblibre/features/geckoview/features/tabs/data/entities/tab_mode
import 'package:weblibre/features/geckoview/features/tabs/data/entities/tab_source.dart';
import 'package:weblibre/features/geckoview/features/tabs/data/models/container_data.dart';
import 'package:weblibre/features/geckoview/features/tabs/data/models/tab_query_result.dart';
import 'package:weblibre/features/user/data/models/general_settings.dart';
class SyncTabsResult {
final Set<String> deletedIsolationContextIds;
@@ -139,6 +140,7 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
Future<String> _generateOrderKey({
required Value<String?> parentId,
required Value<String?> containerId,
required NewTabPosition newTabPosition,
}) async {
if (parentId.value.isNotEmpty) {
return await db.containerDao
@@ -148,15 +150,23 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
.generateLeadingOrderKey(containerId.value)
.getSingle();
} else {
return db.containerDao
.generateLeadingOrderKey(containerId.value)
.getSingle();
return switch (newTabPosition) {
NewTabPosition.first =>
db.containerDao
.generateLeadingOrderKey(containerId.value)
.getSingle(),
NewTabPosition.end =>
db.containerDao
.generateTrailingOrderKey(containerId.value)
.getSingle(),
};
}
}
Future<String> upsertTabTransactional(
Future<String> Function() createTab, {
required Value<String?> parentId,
NewTabPosition newTabPosition = NewTabPosition.first,
Value<String?> containerId = const Value.absent(),
Value<String?> orderKey = const Value.absent(),
Value<Uri?> url = const Value.absent(),
@@ -167,7 +177,11 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
final tabId = await createTab();
final currentOrderKey =
orderKey.value ??
await _generateOrderKey(parentId: parentId, containerId: containerId);
await _generateOrderKey(
parentId: parentId,
containerId: containerId,
newTabPosition: newTabPosition,
);
final Value<TabModeDbValue> persistedTabMode = tabMode.present
? Value(tabMode.value.toDbValue())
: const Value.absent();
@@ -211,6 +225,7 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
String tabId, {
required TabSource source,
required Value<String?> parentId,
NewTabPosition newTabPosition = NewTabPosition.first,
Value<String?> containerId = const Value.absent(),
Value<String?> orderKey = const Value.absent(),
Value<Uri?> url = const Value.absent(),
@@ -220,7 +235,11 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
return db.transaction(() async {
final currentOrderKey =
orderKey.value ??
await _generateOrderKey(parentId: parentId, containerId: containerId);
await _generateOrderKey(
parentId: parentId,
containerId: containerId,
newTabPosition: newTabPosition,
);
final Value<TabModeDbValue> persistedTabMode = tabMode.present
? Value(tabMode.value.toDbValue())
: const Value.absent();