add setting to auto clear unassigned tabs after duration
This commit is contained in:
+11
@@ -47,6 +47,7 @@ import 'package:weblibre/features/geckoview/features/browser/domain/services/pro
|
|||||||
import 'package:weblibre/features/geckoview/features/history/domain/repositories/history.dart';
|
import 'package:weblibre/features/geckoview/features/history/domain/repositories/history.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/preferences/data/repositories/preference_observer.dart';
|
import 'package:weblibre/features/geckoview/features/preferences/data/repositories/preference_observer.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/container.dart';
|
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/share_intent/domain/entities/shared_content.dart';
|
import 'package:weblibre/features/share_intent/domain/entities/shared_content.dart';
|
||||||
import 'package:weblibre/features/user/data/models/general_settings.dart';
|
import 'package:weblibre/features/user/data/models/general_settings.dart';
|
||||||
import 'package:weblibre/features/user/domain/repositories/cache.dart';
|
import 'package:weblibre/features/user/domain/repositories/cache.dart';
|
||||||
@@ -117,6 +118,16 @@ class _BrowserViewState extends ConsumerState<BrowserView>
|
|||||||
DateTime.now().subtract(settings.historyAutoCleanInterval),
|
DateTime.now().subtract(settings.historyAutoCleanInterval),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.unassignedTabsAutoCleanInterval > Duration.zero) {
|
||||||
|
await ref
|
||||||
|
.read(tabDataRepositoryProvider.notifier)
|
||||||
|
.deleteUnassignedTabsOlderThan(
|
||||||
|
DateTime.now().subtract(
|
||||||
|
settings.unassignedTabsAutoCleanInterval,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clear data for containers with clearDataOnExit enabled
|
// Clear data for containers with clearDataOnExit enabled
|
||||||
|
|||||||
-1
@@ -33,7 +33,6 @@ import 'package:weblibre/features/geckoview/features/find_in_page/domain/entitie
|
|||||||
import 'package:weblibre/features/geckoview/features/find_in_page/presentation/controllers/find_in_page.dart';
|
import 'package:weblibre/features/geckoview/features/find_in_page/presentation/controllers/find_in_page.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
|
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
|
||||||
import 'package:weblibre/presentation/hooks/menu_controller.dart';
|
import 'package:weblibre/presentation/hooks/menu_controller.dart';
|
||||||
import 'package:weblibre/presentation/widgets/non_focusable.dart';
|
|
||||||
import 'package:weblibre/presentation/widgets/uri_breadcrumb.dart';
|
import 'package:weblibre/presentation/widgets/uri_breadcrumb.dart';
|
||||||
import 'package:weblibre/utils/ui_helper.dart' as ui_helper;
|
import 'package:weblibre/utils/ui_helper.dart' as ui_helper;
|
||||||
|
|
||||||
|
|||||||
@@ -387,4 +387,15 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<String>> getUnassignedTabsOlderThan(DateTime threshold) {
|
||||||
|
final query = selectOnly(db.tab)
|
||||||
|
..addColumns([db.tab.id])
|
||||||
|
..where(
|
||||||
|
db.tab.containerId.isNull() &
|
||||||
|
db.tab.timestamp.isSmallerThanValue(threshold),
|
||||||
|
);
|
||||||
|
|
||||||
|
return query.map((row) => row.read(db.tab.id)!).get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,6 +210,19 @@ class TabDataRepository extends _$TabDataRepository {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<int> deleteUnassignedTabsOlderThan(DateTime threshold) async {
|
||||||
|
final tabIds = await ref
|
||||||
|
.read(tabDatabaseProvider)
|
||||||
|
.tabDao
|
||||||
|
.getUnassignedTabsOlderThan(threshold);
|
||||||
|
|
||||||
|
if (tabIds.isNotEmpty) {
|
||||||
|
await ref.read(tabRepositoryProvider.notifier).closeTabs(tabIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tabIds.length;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void build() {}
|
void build() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ final class TabDataRepositoryProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$tabDataRepositoryHash() => r'a01c38e94aad2145bd26aa0b8ff0bb1bcceb22f5';
|
String _$tabDataRepositoryHash() => r'c3632e0a2d91811103b329659cb0c6d778b14cea';
|
||||||
|
|
||||||
abstract class _$TabDataRepository extends $Notifier<void> {
|
abstract class _$TabDataRepository extends $Notifier<void> {
|
||||||
void build();
|
void build();
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ class _DataManagementSection extends StatelessWidget {
|
|||||||
SettingSection(name: 'Data Management'),
|
SettingSection(name: 'Data Management'),
|
||||||
_DeleteBrowsingDataTile(),
|
_DeleteBrowsingDataTile(),
|
||||||
_AutoClearHistorySection(),
|
_AutoClearHistorySection(),
|
||||||
|
_AutoClearUnassignedTabsSection(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -285,6 +286,7 @@ class _AutoClearHistorySection extends HookConsumerWidget {
|
|||||||
dropdownMenuEntries: const [
|
dropdownMenuEntries: const [
|
||||||
DropdownMenuEntry(value: Duration.zero, label: 'Never'),
|
DropdownMenuEntry(value: Duration.zero, label: 'Never'),
|
||||||
DropdownMenuEntry(value: Duration(days: 1), label: '1 Day'),
|
DropdownMenuEntry(value: Duration(days: 1), label: '1 Day'),
|
||||||
|
DropdownMenuEntry(value: Duration(days: 3), label: '3 Days'),
|
||||||
DropdownMenuEntry(value: Duration(days: 7), label: '1 Week'),
|
DropdownMenuEntry(value: Duration(days: 7), label: '1 Week'),
|
||||||
DropdownMenuEntry(value: Duration(days: 14), label: '2 Weeks'),
|
DropdownMenuEntry(value: Duration(days: 14), label: '2 Weeks'),
|
||||||
DropdownMenuEntry(value: Duration(days: 30), label: '1 Month'),
|
DropdownMenuEntry(value: Duration(days: 30), label: '1 Month'),
|
||||||
@@ -306,6 +308,68 @@ class _AutoClearHistorySection extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _AutoClearUnassignedTabsSection extends HookConsumerWidget {
|
||||||
|
const _AutoClearUnassignedTabsSection();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final unassignedTabsAutoCleanInterval = ref.watch(
|
||||||
|
generalSettingsWithDefaultsProvider.select(
|
||||||
|
(s) => s.unassignedTabsAutoCleanInterval,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const ListTile(
|
||||||
|
title: Text('Auto-Clear Unassigned Tabs'),
|
||||||
|
subtitle: Text(
|
||||||
|
'Automatically close unassigned tabs older than the selected time period',
|
||||||
|
),
|
||||||
|
leading: Icon(MdiIcons.tabRemove),
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 40.0),
|
||||||
|
child: DropdownMenu<Duration>(
|
||||||
|
initialSelection: unassignedTabsAutoCleanInterval,
|
||||||
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
|
prefixIconConstraints: BoxConstraints.tight(
|
||||||
|
const Size.square(24),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
width: double.infinity,
|
||||||
|
dropdownMenuEntries: const [
|
||||||
|
DropdownMenuEntry(value: Duration.zero, label: 'Never'),
|
||||||
|
DropdownMenuEntry(value: Duration(days: 1), label: '1 Day'),
|
||||||
|
DropdownMenuEntry(value: Duration(days: 3), label: '3 Days'),
|
||||||
|
DropdownMenuEntry(value: Duration(days: 7), label: '1 Week'),
|
||||||
|
DropdownMenuEntry(value: Duration(days: 14), label: '2 Weeks'),
|
||||||
|
DropdownMenuEntry(value: Duration(days: 30), label: '1 Month'),
|
||||||
|
DropdownMenuEntry(value: Duration(days: 90), label: '3 Months'),
|
||||||
|
],
|
||||||
|
onSelected: (value) async {
|
||||||
|
await ref
|
||||||
|
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||||
|
.save(
|
||||||
|
(currentSettings) => currentSettings.copyWith
|
||||||
|
.unassignedTabsAutoCleanInterval(
|
||||||
|
value ?? Duration.zero,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _GlobalPrivacyControlTile extends HookConsumerWidget {
|
class _GlobalPrivacyControlTile extends HookConsumerWidget {
|
||||||
const _GlobalPrivacyControlTile();
|
const _GlobalPrivacyControlTile();
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ class GeneralSettings with FastEquatable {
|
|||||||
final QuickTabSwitcherMode quickTabSwitcherMode;
|
final QuickTabSwitcherMode quickTabSwitcherMode;
|
||||||
final bool pullToRefreshEnabled;
|
final bool pullToRefreshEnabled;
|
||||||
final bool doubleBackCloseTab;
|
final bool doubleBackCloseTab;
|
||||||
|
final Duration unassignedTabsAutoCleanInterval;
|
||||||
|
|
||||||
GeneralSettings({
|
GeneralSettings({
|
||||||
required this.themeMode,
|
required this.themeMode,
|
||||||
@@ -106,6 +107,7 @@ class GeneralSettings with FastEquatable {
|
|||||||
required this.quickTabSwitcherMode,
|
required this.quickTabSwitcherMode,
|
||||||
required this.pullToRefreshEnabled,
|
required this.pullToRefreshEnabled,
|
||||||
required this.doubleBackCloseTab,
|
required this.doubleBackCloseTab,
|
||||||
|
required this.unassignedTabsAutoCleanInterval,
|
||||||
});
|
});
|
||||||
|
|
||||||
GeneralSettings.withDefaults({
|
GeneralSettings.withDefaults({
|
||||||
@@ -131,6 +133,7 @@ class GeneralSettings with FastEquatable {
|
|||||||
QuickTabSwitcherMode? quickTabSwitcherMode,
|
QuickTabSwitcherMode? quickTabSwitcherMode,
|
||||||
bool? pullToRefreshEnabled,
|
bool? pullToRefreshEnabled,
|
||||||
bool? doubleBackCloseTab,
|
bool? doubleBackCloseTab,
|
||||||
|
Duration? unassignedTabsAutoCleanInterval,
|
||||||
}) : themeMode = themeMode ?? ThemeMode.dark,
|
}) : themeMode = themeMode ?? ThemeMode.dark,
|
||||||
enableReadability = enableReadability ?? true,
|
enableReadability = enableReadability ?? true,
|
||||||
enforceReadability = enforceReadability ?? false,
|
enforceReadability = enforceReadability ?? false,
|
||||||
@@ -155,7 +158,9 @@ class GeneralSettings with FastEquatable {
|
|||||||
quickTabSwitcherMode =
|
quickTabSwitcherMode =
|
||||||
quickTabSwitcherMode ?? QuickTabSwitcherMode.lastUsedTabs,
|
quickTabSwitcherMode ?? QuickTabSwitcherMode.lastUsedTabs,
|
||||||
pullToRefreshEnabled = pullToRefreshEnabled ?? true,
|
pullToRefreshEnabled = pullToRefreshEnabled ?? true,
|
||||||
doubleBackCloseTab = doubleBackCloseTab ?? true;
|
doubleBackCloseTab = doubleBackCloseTab ?? true,
|
||||||
|
unassignedTabsAutoCleanInterval =
|
||||||
|
unassignedTabsAutoCleanInterval ?? Duration.zero;
|
||||||
|
|
||||||
factory GeneralSettings.fromJson(Map<String, dynamic> json) =>
|
factory GeneralSettings.fromJson(Map<String, dynamic> json) =>
|
||||||
_$GeneralSettingsFromJson(json);
|
_$GeneralSettingsFromJson(json);
|
||||||
@@ -186,5 +191,6 @@ class GeneralSettings with FastEquatable {
|
|||||||
quickTabSwitcherMode,
|
quickTabSwitcherMode,
|
||||||
pullToRefreshEnabled,
|
pullToRefreshEnabled,
|
||||||
doubleBackCloseTab,
|
doubleBackCloseTab,
|
||||||
|
unassignedTabsAutoCleanInterval,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ abstract class _$GeneralSettingsCWProxy {
|
|||||||
|
|
||||||
GeneralSettings doubleBackCloseTab(bool doubleBackCloseTab);
|
GeneralSettings doubleBackCloseTab(bool doubleBackCloseTab);
|
||||||
|
|
||||||
|
GeneralSettings unassignedTabsAutoCleanInterval(
|
||||||
|
Duration unassignedTabsAutoCleanInterval,
|
||||||
|
);
|
||||||
|
|
||||||
/// Creates a new instance with the provided field values.
|
/// Creates a new instance with the provided field values.
|
||||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `GeneralSettings(...).copyWith.fieldName(value)`.
|
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `GeneralSettings(...).copyWith.fieldName(value)`.
|
||||||
///
|
///
|
||||||
@@ -91,6 +95,7 @@ abstract class _$GeneralSettingsCWProxy {
|
|||||||
QuickTabSwitcherMode quickTabSwitcherMode,
|
QuickTabSwitcherMode quickTabSwitcherMode,
|
||||||
bool pullToRefreshEnabled,
|
bool pullToRefreshEnabled,
|
||||||
bool doubleBackCloseTab,
|
bool doubleBackCloseTab,
|
||||||
|
Duration unassignedTabsAutoCleanInterval,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,6 +198,11 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
|
|||||||
GeneralSettings doubleBackCloseTab(bool doubleBackCloseTab) =>
|
GeneralSettings doubleBackCloseTab(bool doubleBackCloseTab) =>
|
||||||
call(doubleBackCloseTab: doubleBackCloseTab);
|
call(doubleBackCloseTab: doubleBackCloseTab);
|
||||||
|
|
||||||
|
@override
|
||||||
|
GeneralSettings unassignedTabsAutoCleanInterval(
|
||||||
|
Duration unassignedTabsAutoCleanInterval,
|
||||||
|
) => call(unassignedTabsAutoCleanInterval: unassignedTabsAutoCleanInterval);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
/// Creates a new instance with the provided field values.
|
/// Creates a new instance with the provided field values.
|
||||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `GeneralSettings(...).copyWith.fieldName(value)`.
|
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `GeneralSettings(...).copyWith.fieldName(value)`.
|
||||||
@@ -224,6 +234,7 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
|
|||||||
Object? quickTabSwitcherMode = const $CopyWithPlaceholder(),
|
Object? quickTabSwitcherMode = const $CopyWithPlaceholder(),
|
||||||
Object? pullToRefreshEnabled = const $CopyWithPlaceholder(),
|
Object? pullToRefreshEnabled = const $CopyWithPlaceholder(),
|
||||||
Object? doubleBackCloseTab = const $CopyWithPlaceholder(),
|
Object? doubleBackCloseTab = const $CopyWithPlaceholder(),
|
||||||
|
Object? unassignedTabsAutoCleanInterval = const $CopyWithPlaceholder(),
|
||||||
}) {
|
}) {
|
||||||
return GeneralSettings(
|
return GeneralSettings(
|
||||||
themeMode: themeMode == const $CopyWithPlaceholder() || themeMode == null
|
themeMode: themeMode == const $CopyWithPlaceholder() || themeMode == null
|
||||||
@@ -354,6 +365,12 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
|
|||||||
? _value.doubleBackCloseTab
|
? _value.doubleBackCloseTab
|
||||||
// ignore: cast_nullable_to_non_nullable
|
// ignore: cast_nullable_to_non_nullable
|
||||||
: doubleBackCloseTab as bool,
|
: doubleBackCloseTab as bool,
|
||||||
|
unassignedTabsAutoCleanInterval:
|
||||||
|
unassignedTabsAutoCleanInterval == const $CopyWithPlaceholder() ||
|
||||||
|
unassignedTabsAutoCleanInterval == null
|
||||||
|
? _value.unassignedTabsAutoCleanInterval
|
||||||
|
// ignore: cast_nullable_to_non_nullable
|
||||||
|
: unassignedTabsAutoCleanInterval as Duration,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -420,6 +437,13 @@ GeneralSettings _$GeneralSettingsFromJson(
|
|||||||
),
|
),
|
||||||
pullToRefreshEnabled: json['pullToRefreshEnabled'] as bool?,
|
pullToRefreshEnabled: json['pullToRefreshEnabled'] as bool?,
|
||||||
doubleBackCloseTab: json['doubleBackCloseTab'] as bool?,
|
doubleBackCloseTab: json['doubleBackCloseTab'] as bool?,
|
||||||
|
unassignedTabsAutoCleanInterval:
|
||||||
|
json['unassignedTabsAutoCleanInterval'] == null
|
||||||
|
? null
|
||||||
|
: Duration(
|
||||||
|
microseconds: (json['unassignedTabsAutoCleanInterval'] as num)
|
||||||
|
.toInt(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$GeneralSettingsToJson(
|
Map<String, dynamic> _$GeneralSettingsToJson(
|
||||||
@@ -455,6 +479,8 @@ Map<String, dynamic> _$GeneralSettingsToJson(
|
|||||||
_$QuickTabSwitcherModeEnumMap[instance.quickTabSwitcherMode]!,
|
_$QuickTabSwitcherModeEnumMap[instance.quickTabSwitcherMode]!,
|
||||||
'pullToRefreshEnabled': instance.pullToRefreshEnabled,
|
'pullToRefreshEnabled': instance.pullToRefreshEnabled,
|
||||||
'doubleBackCloseTab': instance.doubleBackCloseTab,
|
'doubleBackCloseTab': instance.doubleBackCloseTab,
|
||||||
|
'unassignedTabsAutoCleanInterval':
|
||||||
|
instance.unassignedTabsAutoCleanInterval.inMicroseconds,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$ThemeModeEnumMap = {
|
const _$ThemeModeEnumMap = {
|
||||||
|
|||||||
@@ -130,6 +130,11 @@ class GeneralSettingsRepository extends _$GeneralSettingsRepository {
|
|||||||
DriftSqlType.bool,
|
DriftSqlType.bool,
|
||||||
db.typeMapping,
|
db.typeMapping,
|
||||||
),
|
),
|
||||||
|
'unassignedTabsAutoCleanInterval':
|
||||||
|
settings['unassignedTabsAutoCleanInterval']?.readAs(
|
||||||
|
DriftSqlType.int,
|
||||||
|
db.typeMapping,
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ final class GeneralSettingsRepositoryProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _$generalSettingsRepositoryHash() =>
|
String _$generalSettingsRepositoryHash() =>
|
||||||
r'ada58479ceea436f08e22780be200c99e3abedb7';
|
r'08af8820ddd41036ae0d9531c87cf17c9c62db0a';
|
||||||
|
|
||||||
abstract class _$GeneralSettingsRepository
|
abstract class _$GeneralSettingsRepository
|
||||||
extends $StreamNotifier<GeneralSettings> {
|
extends $StreamNotifier<GeneralSettings> {
|
||||||
|
|||||||
Reference in New Issue
Block a user