make tab restoration optional

This commit is contained in:
Fabian Freund
2026-01-02 07:44:24 +01:00
parent 43e0930e6d
commit 4fe324c945
2 changed files with 136 additions and 80 deletions
@@ -18,50 +18,100 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
Future<bool?> showClearContainerDataDialog(BuildContext context, int tabCount) {
return showDialog<bool?>(
class ClearContainerDataResult {
final bool confirmed;
final bool reopenTabs;
const ClearContainerDataResult({
required this.confirmed,
required this.reopenTabs,
});
}
Future<ClearContainerDataResult?> showClearContainerDataDialog(
BuildContext context,
int tabCount,
) {
return showDialog<ClearContainerDataResult?>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
icon: const Icon(MdiIcons.databaseRemove),
title: const Text('Clear Container Data?'),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('This will clear all data for this container:'),
const SizedBox(height: 8),
const Text('• Cookies'),
const Text('• Site data'),
const Text('• Cache'),
const Text('• Permissions'),
const SizedBox(height: 8),
Text(
'$tabCount tab(s) will be closed and reopened fresh.',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.tertiary,
),
),
],
),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.pop(context, false);
},
child: const Text('Cancel'),
),
TextButton(
onPressed: () {
Navigator.pop(context, true);
},
child: const Text('Clear Data'),
),
],
);
return _ClearContainerDataDialog(tabCount: tabCount);
},
);
}
class _ClearContainerDataDialog extends HookWidget {
final int tabCount;
const _ClearContainerDataDialog({required this.tabCount});
@override
Widget build(BuildContext context) {
final reopenTabs = useState(false);
return AlertDialog(
icon: const Icon(MdiIcons.databaseRemove),
title: const Text('Clear Container Data'),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('This will clear all data for this container:'),
const SizedBox(height: 8),
const Text('• Cookies'),
const Text('• Site data'),
const Text('• Cache'),
const Text('• Permissions'),
const SizedBox(height: 8),
Text(
'$tabCount tab(s) will be closed.',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.tertiary,
),
),
CheckboxListTile(
value: reopenTabs.value,
onChanged: (value) {
if (value != null) {
reopenTabs.value = value;
}
},
title: const Text('Recreate tabs after clearing'),
contentPadding: EdgeInsets.zero,
controlAffinity: ListTileControlAffinity.trailing,
),
],
),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.pop(
context,
const ClearContainerDataResult(
confirmed: false,
reopenTabs: false,
),
);
},
child: const Text('Cancel'),
),
TextButton(
onPressed: () {
Navigator.pop(
context,
ClearContainerDataResult(
confirmed: true,
reopenTabs: reopenTabs.value,
),
);
},
child: const Text('Clear Data'),
),
],
);
}
}
@@ -378,7 +378,9 @@ class TabViewHeader extends HookConsumerWidget {
tabs.length,
);
if (result == true) {
if (result?.confirmed == true) {
final shouldReopenTabs = result!.reopenTabs;
try {
final closedTabIds = await ref
.read(
@@ -398,52 +400,56 @@ class TabViewHeader extends HookConsumerWidget {
.contextualIdentity!,
);
await ref
.read(
tabRepositoryProvider.notifier,
)
.addMultipleTabs(
tabs: tabs.map((tab) {
var parentId = tab.parentId;
while (parentId != null &&
closedTabIds.contains(
parentId,
)) {
parentId = tabs
.firstWhereOrNull(
(old) =>
old.id == parentId,
)
?.parentId;
}
if (shouldReopenTabs) {
await ref
.read(
tabRepositoryProvider.notifier,
)
.addMultipleTabs(
tabs: tabs.map((tab) {
var parentId = tab.parentId;
while (parentId != null &&
closedTabIds.contains(
parentId,
)) {
parentId = tabs
.firstWhereOrNull(
(old) =>
old.id == parentId,
)
?.parentId;
}
return AddTabParams(
url: tab.url.toString(),
startLoading: true,
parentId: parentId,
private:
tab.isPrivate ?? false,
flags: LoadUrlFlags.NONE
.toValue(),
source: Internal.newTab
.toValue(),
contextId: selectedContainer
.metadata
.contextualIdentity,
);
}).toList(),
container: Value(
selectedContainer,
),
);
return AddTabParams(
url: tab.url.toString(),
startLoading: true,
parentId: parentId,
private:
tab.isPrivate ?? false,
flags: LoadUrlFlags.NONE
.toValue(),
source: Internal.newTab
.toValue(),
contextId: selectedContainer
.metadata
.contextualIdentity,
);
}).toList(),
container: Value(
selectedContainer,
),
);
}
if (context.mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(
const SnackBar(
SnackBar(
content: Text(
'Container data cleared successfully',
shouldReopenTabs
? 'Container data cleared successfully'
: 'Container data cleared. ${tabs.length} tab(s) closed.',
),
),
);