fix formatting
This commit is contained in:
@@ -25,8 +25,8 @@ class EquatableImage {
|
||||
bool _isDisposed = false;
|
||||
|
||||
EquatableImage(Image value, {required int hash})
|
||||
: _value = value,
|
||||
_imageHash = hash;
|
||||
: _value = value,
|
||||
_imageHash = hash;
|
||||
|
||||
/// The underlying ui.Image. Returns null if disposed.
|
||||
Image? get value => _isDisposed ? null : _value;
|
||||
|
||||
@@ -90,10 +90,7 @@ class GenericWebsiteService extends _$GenericWebsiteService {
|
||||
|
||||
GenericWebsiteService()
|
||||
: _iconsService = GeckoIconService(),
|
||||
_browserIconCache = LRUCache(
|
||||
50,
|
||||
onEvict: (icon) => icon.image.dispose(),
|
||||
);
|
||||
_browserIconCache = LRUCache(50, onEvict: (icon) => icon.image.dispose());
|
||||
|
||||
@override
|
||||
void build() {
|
||||
|
||||
@@ -460,14 +460,17 @@ class TabRepository extends _$TabRepository {
|
||||
.read(tabDataRepositoryProvider.notifier)
|
||||
.getTabContainerData(tabState.id);
|
||||
|
||||
final contextChanging = containerData.metadata.contextualIdentity !=
|
||||
final contextChanging =
|
||||
containerData.metadata.contextualIdentity !=
|
||||
currentContainerData?.metadata.contextualIdentity;
|
||||
|
||||
await addTab(
|
||||
url: uri,
|
||||
private: tabState.isPrivate,
|
||||
container: Value(containerData),
|
||||
parentId: contextChanging ? null : tabState.id, // Break parent chain if context changes
|
||||
parentId: contextChanging
|
||||
? null
|
||||
: tabState.id, // Break parent chain if context changes
|
||||
selectTab: true,
|
||||
);
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ part 'bookmarks.g.dart';
|
||||
bool _isEmptyRootFolder(BookmarkFolder folder) {
|
||||
if (folder.children == null) return true;
|
||||
// A root folder is empty if it has no children, or only contains other root folders
|
||||
return folder.children!.every((child) => bookmarkRootIds.contains(child.guid));
|
||||
return folder.children!.every(
|
||||
(child) => bookmarkRootIds.contains(child.guid),
|
||||
);
|
||||
}
|
||||
|
||||
T? _selectChildRecursive<T extends BookmarkItem>(
|
||||
@@ -152,10 +154,12 @@ AsyncValue<T?> bookmarks<T extends BookmarkItem>(
|
||||
entryGuid == BookmarkRoot.root.id &&
|
||||
result is BookmarkFolder) {
|
||||
final filteredChildren = result.children
|
||||
?.where((child) =>
|
||||
child is! BookmarkFolder ||
|
||||
child.guid == BookmarkRoot.mobile.id ||
|
||||
!_isEmptyRootFolder(child))
|
||||
?.where(
|
||||
(child) =>
|
||||
child is! BookmarkFolder ||
|
||||
child.guid == BookmarkRoot.mobile.id ||
|
||||
!_isEmptyRootFolder(child),
|
||||
)
|
||||
.toList();
|
||||
result = result.copyWith.children(filteredChildren) as T;
|
||||
}
|
||||
@@ -187,8 +191,16 @@ class SeamlessBookmarks extends _$SeamlessBookmarks {
|
||||
}
|
||||
|
||||
@override
|
||||
AsyncValue<BookmarkItem?> build(String entryGuid, {bool hideEmptyRoots = false}) {
|
||||
final bookmarks = ref.watch(bookmarksProvider<BookmarkItem>(entryGuid, hideEmptyRoots: hideEmptyRoots));
|
||||
AsyncValue<BookmarkItem?> build(
|
||||
String entryGuid, {
|
||||
bool hideEmptyRoots = false,
|
||||
}) {
|
||||
final bookmarks = ref.watch(
|
||||
bookmarksProvider<BookmarkItem>(
|
||||
entryGuid,
|
||||
hideEmptyRoots: hideEmptyRoots,
|
||||
),
|
||||
);
|
||||
|
||||
if (_hasSearch) {
|
||||
final filterGuids = ref.watch(bookmarksSearchProvider);
|
||||
|
||||
+26
-9
@@ -49,15 +49,30 @@ class BookmarkListScreen extends HookConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final treeKey = useMemoized(() => GlobalKey<TreeViewState>());
|
||||
final hideEmptyRoots = useState(true);
|
||||
final bookmarkList = ref.watch(seamlessBookmarksProvider(entryGuid, hideEmptyRoots: hideEmptyRoots.value));
|
||||
final bookmarkList = ref.watch(
|
||||
seamlessBookmarksProvider(
|
||||
entryGuid,
|
||||
hideEmptyRoots: hideEmptyRoots.value,
|
||||
),
|
||||
);
|
||||
|
||||
final textFilterEnabled = useState(false);
|
||||
final textFilterController = useTextEditingController();
|
||||
|
||||
useOnListenableChange(textFilterController, () {
|
||||
if (ref.exists(seamlessBookmarksProvider(entryGuid, hideEmptyRoots: hideEmptyRoots.value))) {
|
||||
if (ref.exists(
|
||||
seamlessBookmarksProvider(
|
||||
entryGuid,
|
||||
hideEmptyRoots: hideEmptyRoots.value,
|
||||
),
|
||||
)) {
|
||||
ref
|
||||
.read(seamlessBookmarksProvider(entryGuid, hideEmptyRoots: hideEmptyRoots.value).notifier)
|
||||
.read(
|
||||
seamlessBookmarksProvider(
|
||||
entryGuid,
|
||||
hideEmptyRoots: hideEmptyRoots.value,
|
||||
).notifier,
|
||||
)
|
||||
.search(textFilterController.text);
|
||||
}
|
||||
});
|
||||
@@ -109,12 +124,14 @@ class BookmarkListScreen extends HookConsumerWidget {
|
||||
),
|
||||
if (entryGuid == BookmarkRoot.root.id)
|
||||
MenuItemButton(
|
||||
leadingIcon: Icon(hideEmptyRoots.value
|
||||
? MdiIcons.eyeOff
|
||||
: MdiIcons.eye),
|
||||
child: Text(hideEmptyRoots.value
|
||||
? 'Show Empty Root Folders'
|
||||
: 'Hide Empty Root Folders'),
|
||||
leadingIcon: Icon(
|
||||
hideEmptyRoots.value ? MdiIcons.eyeOff : MdiIcons.eye,
|
||||
),
|
||||
child: Text(
|
||||
hideEmptyRoots.value
|
||||
? 'Show Empty Root Folders'
|
||||
: 'Hide Empty Root Folders',
|
||||
),
|
||||
onPressed: () {
|
||||
hideEmptyRoots.value = !hideEmptyRoots.value;
|
||||
},
|
||||
|
||||
+1
-4
@@ -128,10 +128,7 @@ class BrowserBottomAppBar extends HookConsumerWidget {
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(bottom: bottomPadding),
|
||||
child: SizedBox(
|
||||
height: _size.height,
|
||||
child: _tabBar,
|
||||
),
|
||||
child: SizedBox(height: _size.height, child: _tabBar),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
+3
-1
@@ -319,7 +319,9 @@ class ListTabPreview extends HookConsumerWidget {
|
||||
child: UriBreadcrumb(
|
||||
uri: tabState.url,
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: tabState.isPrivate ? colorScheme.onSurface : null,
|
||||
color: tabState.isPrivate
|
||||
? colorScheme.onSurface
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
+3
-1
@@ -184,7 +184,9 @@ class ViewTabTreesWidget extends HookConsumerWidget {
|
||||
searchPartition: TabSearchPartition.preview,
|
||||
// ignore: document_ignores using fast equatable
|
||||
// ignore: provider_parameters
|
||||
containerFilter: ContainerFilterById(containerId: containerId),
|
||||
containerFilter: ContainerFilterById(
|
||||
containerId: containerId,
|
||||
),
|
||||
groupTrees: true,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -260,7 +260,8 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
|
||||
for (final state in next.values) {
|
||||
final previousState = previous?[state.id];
|
||||
|
||||
if (previousState?.parentId != state.parentId && state.parentId != null) {
|
||||
if (previousState?.parentId != state.parentId &&
|
||||
state.parentId != null) {
|
||||
if (next.containsKey(state.parentId)) {
|
||||
// Parent exists in current state
|
||||
validatedParentIds[state.id] = state.parentId;
|
||||
@@ -272,8 +273,9 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
|
||||
}
|
||||
|
||||
// Batch validate parent IDs that aren't in the current state
|
||||
final existingParentIds =
|
||||
await getExistingTabIds(parentIdsToValidate).get().then((ids) => ids.toSet());
|
||||
final existingParentIds = await getExistingTabIds(
|
||||
parentIdsToValidate,
|
||||
).get().then((ids) => ids.toSet());
|
||||
|
||||
// Complete validation map
|
||||
for (final state in next.values) {
|
||||
@@ -282,7 +284,8 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
|
||||
if (previousState?.parentId != state.parentId) {
|
||||
if (!validatedParentIds.containsKey(state.id)) {
|
||||
// This parent ID needed database validation
|
||||
if (state.parentId != null && existingParentIds.contains(state.parentId)) {
|
||||
if (state.parentId != null &&
|
||||
existingParentIds.contains(state.parentId)) {
|
||||
validatedParentIds[state.id] = state.parentId;
|
||||
} else {
|
||||
validatedParentIds[state.id] = null;
|
||||
|
||||
@@ -51,17 +51,17 @@ class AdvancedSettingsScreen extends StatelessWidget {
|
||||
child: FadingScroll(
|
||||
fadingSize: 25,
|
||||
builder: (context, controller) {
|
||||
return ListView(
|
||||
controller: controller,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
children: const [
|
||||
_ContentBehaviorSection(),
|
||||
_StorageDebuggingSection(),
|
||||
_ResetSection(),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
return ListView(
|
||||
controller: controller,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
children: const [
|
||||
_ContentBehaviorSection(),
|
||||
_StorageDebuggingSection(),
|
||||
_ResetSection(),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -119,9 +119,7 @@ class _JavaScriptTile extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final javascriptEnabled = ref.watch(
|
||||
engineSettingsWithDefaultsProvider.select(
|
||||
(s) => s.javascriptEnabled,
|
||||
),
|
||||
engineSettingsWithDefaultsProvider.select((s) => s.javascriptEnabled),
|
||||
);
|
||||
|
||||
return SwitchListTile.adaptive(
|
||||
|
||||
@@ -111,10 +111,7 @@ class _ThemeSection extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -146,9 +143,7 @@ class _ThemeSection extends HookConsumerWidget {
|
||||
selected: {themeMode},
|
||||
onSelectionChanged: (value) async {
|
||||
await ref
|
||||
.read(
|
||||
saveGeneralSettingsControllerProvider.notifier,
|
||||
)
|
||||
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.themeMode(value.first),
|
||||
@@ -172,10 +167,7 @@ class _TabBarPositionSection extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -190,9 +182,7 @@ class _TabBarPositionSection extends HookConsumerWidget {
|
||||
onChanged: (value) async {
|
||||
if (value != null) {
|
||||
await ref
|
||||
.read(
|
||||
saveGeneralSettingsControllerProvider.notifier,
|
||||
)
|
||||
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.tabBarPosition(value),
|
||||
@@ -204,9 +194,7 @@ class _TabBarPositionSection extends HookConsumerWidget {
|
||||
RadioListTile.adaptive(
|
||||
value: TabBarPosition.top,
|
||||
title: Text('Top'),
|
||||
subtitle: Text(
|
||||
'Persistent tab bar without auto-hide',
|
||||
),
|
||||
subtitle: Text('Persistent tab bar without auto-hide'),
|
||||
),
|
||||
RadioListTile.adaptive(
|
||||
value: TabBarPosition.bottom,
|
||||
@@ -228,8 +216,9 @@ class _ShowContextualTabBarTile extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final tabBarShowContextualBar = ref.watch(
|
||||
generalSettingsWithDefaultsProvider
|
||||
.select((s) => s.tabBarShowContextualBar),
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
(s) => s.tabBarShowContextualBar,
|
||||
),
|
||||
);
|
||||
|
||||
return SwitchListTile.adaptive(
|
||||
@@ -257,8 +246,9 @@ class _ShowQuickTabSwitcherBarTile extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final tabBarShowQuickTabSwitcherBar = ref.watch(
|
||||
generalSettingsWithDefaultsProvider
|
||||
.select((s) => s.tabBarShowQuickTabSwitcherBar),
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
(s) => s.tabBarShowQuickTabSwitcherBar,
|
||||
),
|
||||
);
|
||||
|
||||
return SwitchListTile.adaptive(
|
||||
@@ -272,8 +262,8 @@ class _ShowQuickTabSwitcherBarTile extends HookConsumerWidget {
|
||||
await ref
|
||||
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.tabBarShowQuickTabSwitcherBar(value),
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.tabBarShowQuickTabSwitcherBar(value),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -290,10 +280,7 @@ class _QuickTabSwitcherModeSection extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -308,12 +295,10 @@ class _QuickTabSwitcherModeSection extends HookConsumerWidget {
|
||||
onChanged: (value) async {
|
||||
if (value != null) {
|
||||
await ref
|
||||
.read(
|
||||
saveGeneralSettingsControllerProvider.notifier,
|
||||
)
|
||||
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.quickTabSwitcherMode(value),
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.quickTabSwitcherMode(value),
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -322,16 +307,12 @@ class _QuickTabSwitcherModeSection extends HookConsumerWidget {
|
||||
RadioListTile.adaptive(
|
||||
value: QuickTabSwitcherMode.lastUsedTabs,
|
||||
title: Text('Recently Used Tabs'),
|
||||
subtitle: Text(
|
||||
'Recently used tabs across all containers',
|
||||
),
|
||||
subtitle: Text('Recently used tabs across all containers'),
|
||||
),
|
||||
RadioListTile.adaptive(
|
||||
value: QuickTabSwitcherMode.containerTabs,
|
||||
title: Text('Container Tabs'),
|
||||
subtitle: Text(
|
||||
'Ordered tabs of the selected container',
|
||||
),
|
||||
subtitle: Text('Ordered tabs of the selected container'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -34,17 +34,17 @@ class FingerprintingSettingsScreen extends StatelessWidget {
|
||||
child: FadingScroll(
|
||||
fadingSize: 25,
|
||||
builder: (context, controller) {
|
||||
return ListView(
|
||||
controller: controller,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
children: const [
|
||||
_MainProtectionSection(),
|
||||
_IdentitySection(),
|
||||
_AdvancedSection(),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
return ListView(
|
||||
controller: controller,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
children: const [
|
||||
_MainProtectionSection(),
|
||||
_IdentitySection(),
|
||||
_AdvancedSection(),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -120,9 +120,7 @@ class _FingerprintProtectionTile extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
title: const Text('Fingerprint Protection'),
|
||||
subtitle: const Text(
|
||||
'Granular control over browser fingerprinting',
|
||||
),
|
||||
subtitle: const Text('Granular control over browser fingerprinting'),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
horizontal: 16.0,
|
||||
@@ -143,9 +141,7 @@ class _ResistFingerprintingTile extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
title: const Text('Resist Fingerprinting'),
|
||||
subtitle: const Text(
|
||||
'Advanced fingerprinting protection hardening',
|
||||
),
|
||||
subtitle: const Text('Advanced fingerprinting protection hardening'),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
horizontal: 16.0,
|
||||
|
||||
@@ -43,19 +43,19 @@ class PrivacySecuritySettingsScreen extends StatelessWidget {
|
||||
child: FadingScroll(
|
||||
fadingSize: 25,
|
||||
builder: (context, controller) {
|
||||
return ListView(
|
||||
controller: controller,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
children: const [
|
||||
_PrivacyModesSection(),
|
||||
_TrackingProtectionSection(),
|
||||
_ConnectionSecuritySection(),
|
||||
_DataManagementSection(),
|
||||
_AdvancedSection(),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
return ListView(
|
||||
controller: controller,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
children: const [
|
||||
_PrivacyModesSection(),
|
||||
_TrackingProtectionSection(),
|
||||
_ConnectionSecuritySection(),
|
||||
_DataManagementSection(),
|
||||
_AdvancedSection(),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -161,19 +161,13 @@ class _IncognitoModeSection extends HookConsumerWidget {
|
||||
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) => value
|
||||
? currentSettings.copyWith.deleteBrowsingDataOnQuit(
|
||||
{},
|
||||
)
|
||||
: currentSettings.copyWith.deleteBrowsingDataOnQuit(
|
||||
null,
|
||||
),
|
||||
? currentSettings.copyWith.deleteBrowsingDataOnQuit({})
|
||||
: currentSettings.copyWith.deleteBrowsingDataOnQuit(null),
|
||||
);
|
||||
},
|
||||
),
|
||||
if (deleteBrowsingDataOnQuit != null)
|
||||
_DeleteBrowsingDataTypes(
|
||||
selectedTypes: deleteBrowsingDataOnQuit,
|
||||
),
|
||||
_DeleteBrowsingDataTypes(selectedTypes: deleteBrowsingDataOnQuit),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -187,10 +181,7 @@ class _DeleteBrowsingDataTypes extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Column(
|
||||
children: [
|
||||
for (final type in DeleteBrowsingDataType.values)
|
||||
@@ -208,20 +199,19 @@ class _DeleteBrowsingDataTypes extends HookConsumerWidget {
|
||||
|
||||
if (value == true) {
|
||||
await notifier.save(
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.deleteBrowsingDataOnQuit({
|
||||
...currentSettings.deleteBrowsingDataOnQuit!,
|
||||
type,
|
||||
}),
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.deleteBrowsingDataOnQuit({
|
||||
...currentSettings.deleteBrowsingDataOnQuit!,
|
||||
type,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
await notifier.save(
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.deleteBrowsingDataOnQuit(
|
||||
{
|
||||
...currentSettings.deleteBrowsingDataOnQuit!,
|
||||
}..remove(type),
|
||||
),
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.deleteBrowsingDataOnQuit(
|
||||
{...currentSettings.deleteBrowsingDataOnQuit!}
|
||||
..remove(type),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -269,10 +259,7 @@ class _AutoClearHistorySection extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -296,41 +283,19 @@ class _AutoClearHistorySection extends HookConsumerWidget {
|
||||
),
|
||||
width: double.infinity,
|
||||
dropdownMenuEntries: const [
|
||||
DropdownMenuEntry(
|
||||
value: Duration.zero,
|
||||
label: 'Never',
|
||||
),
|
||||
DropdownMenuEntry(
|
||||
value: Duration(days: 1),
|
||||
label: '1 Day',
|
||||
),
|
||||
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',
|
||||
),
|
||||
DropdownMenuEntry(value: Duration.zero, label: 'Never'),
|
||||
DropdownMenuEntry(value: Duration(days: 1), label: '1 Day'),
|
||||
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,
|
||||
)
|
||||
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.historyAutoCleanInterval(
|
||||
value ?? Duration.zero,
|
||||
),
|
||||
.historyAutoCleanInterval(value ?? Duration.zero),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -378,10 +343,7 @@ class _HttpsOnlyModeSection extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -410,9 +372,7 @@ class _HttpsOnlyModeSection extends HookConsumerWidget {
|
||||
selected: {httpsOnlyMode},
|
||||
onSelectionChanged: (value) async {
|
||||
await ref
|
||||
.read(
|
||||
saveEngineSettingsControllerProvider.notifier,
|
||||
)
|
||||
.read(saveEngineSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.httpsOnlyMode(value.first),
|
||||
@@ -458,10 +418,7 @@ class _EnhancedTrackingProtectionSection extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -477,8 +434,8 @@ class _EnhancedTrackingProtectionSection extends HookConsumerWidget {
|
||||
await ref
|
||||
.read(saveEngineSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.trackingProtectionPolicy(value),
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.trackingProtectionPolicy(value),
|
||||
);
|
||||
},
|
||||
child: const Column(
|
||||
@@ -504,9 +461,7 @@ class _EnhancedTrackingProtectionSection extends HookConsumerWidget {
|
||||
RadioListTile<TrackingProtectionPolicy>.adaptive(
|
||||
value: TrackingProtectionPolicy.custom,
|
||||
title: Text('Custom'),
|
||||
subtitle: Text(
|
||||
'Choose which trackers and scripts to block.',
|
||||
),
|
||||
subtitle: Text('Choose which trackers and scripts to block.'),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -546,8 +501,8 @@ class _BounceTrackingProtectionTile extends HookConsumerWidget {
|
||||
await ref
|
||||
.read(saveEngineSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.bounceTrackingProtectionMode(
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.bounceTrackingProtectionMode(
|
||||
value
|
||||
? BounceTrackingProtectionMode.enabled
|
||||
: BounceTrackingProtectionMode.disabled,
|
||||
@@ -570,10 +525,7 @@ class _QueryParameterStrippingSection extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -605,12 +557,10 @@ class _QueryParameterStrippingSection extends HookConsumerWidget {
|
||||
selected: {queryParameterStripping},
|
||||
onSelectionChanged: (value) async {
|
||||
await ref
|
||||
.read(
|
||||
saveEngineSettingsControllerProvider.notifier,
|
||||
)
|
||||
.read(saveEngineSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.queryParameterStripping(value.first),
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.queryParameterStripping(value.first),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -44,18 +44,18 @@ class SearchContentSettingsScreen extends StatelessWidget {
|
||||
child: FadingScroll(
|
||||
fadingSize: 25,
|
||||
builder: (context, controller) {
|
||||
return ListView(
|
||||
controller: controller,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
children: const [
|
||||
_SearchSection(),
|
||||
_ContentViewingSection(),
|
||||
_ContentEnhancementSection(),
|
||||
_ExtensionsSection(),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
return ListView(
|
||||
controller: controller,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
children: const [
|
||||
_SearchSection(),
|
||||
_ContentViewingSection(),
|
||||
_ContentEnhancementSection(),
|
||||
_ExtensionsSection(),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -154,16 +154,14 @@ class _AutocompleteProviderSection extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final defaultSearchSuggestionsProvider = ref.watch(
|
||||
generalSettingsWithDefaultsProvider
|
||||
.select((s) => s.defaultSearchSuggestionsProvider),
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
(s) => s.defaultSearchSuggestionsProvider,
|
||||
),
|
||||
);
|
||||
final relatedBang = defaultSearchSuggestionsProvider.relatedBang;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -183,28 +181,27 @@ class _AutocompleteProviderSection extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
width: double.infinity,
|
||||
leadingIcon:
|
||||
relatedBang.mapNotNull((trigger) => BangIcon(trigger: trigger)),
|
||||
dropdownMenuEntries: SearchSuggestionProviders.values
|
||||
.map((provider) {
|
||||
return DropdownMenuEntry(
|
||||
value: provider,
|
||||
label: provider.label,
|
||||
leadingIcon: provider.relatedBang.mapNotNull(
|
||||
(trigger) => BangIcon(trigger: trigger),
|
||||
),
|
||||
);
|
||||
})
|
||||
.toList(),
|
||||
leadingIcon: relatedBang.mapNotNull(
|
||||
(trigger) => BangIcon(trigger: trigger),
|
||||
),
|
||||
dropdownMenuEntries: SearchSuggestionProviders.values.map((
|
||||
provider,
|
||||
) {
|
||||
return DropdownMenuEntry(
|
||||
value: provider,
|
||||
label: provider.label,
|
||||
leadingIcon: provider.relatedBang.mapNotNull(
|
||||
(trigger) => BangIcon(trigger: trigger),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
onSelected: (value) async {
|
||||
if (value != null) {
|
||||
await ref
|
||||
.read(
|
||||
saveGeneralSettingsControllerProvider.notifier,
|
||||
)
|
||||
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.defaultSearchSuggestionsProvider(value),
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.defaultSearchSuggestionsProvider(value),
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -243,7 +240,9 @@ class _OnDeviceAiTile extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final enableLocalAiFeatures = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select((s) => s.enableLocalAiFeatures),
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
(s) => s.enableLocalAiFeatures,
|
||||
),
|
||||
);
|
||||
|
||||
return SwitchListTile.adaptive(
|
||||
@@ -315,9 +314,7 @@ class _EnforceReaderModeTile extends HookConsumerWidget {
|
||||
onChanged: enableReadability
|
||||
? (value) async {
|
||||
await ref
|
||||
.read(
|
||||
saveGeneralSettingsControllerProvider.notifier,
|
||||
)
|
||||
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.enforceReadability(value),
|
||||
|
||||
@@ -39,17 +39,17 @@ class TabsBehaviorSettingsScreen extends StatelessWidget {
|
||||
child: FadingScroll(
|
||||
fadingSize: 25,
|
||||
builder: (context, controller) {
|
||||
return ListView(
|
||||
controller: controller,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
children: const [
|
||||
_TabCreationSection(),
|
||||
_TabOrganizationSection(),
|
||||
_TabInteractionSection(),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
return ListView(
|
||||
controller: controller,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
children: const [
|
||||
_TabCreationSection(),
|
||||
_TabOrganizationSection(),
|
||||
_TabInteractionSection(),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -110,19 +110,14 @@ class _NewTabDefaultSection extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const ListTile(
|
||||
title: Text('New Tab Default'),
|
||||
subtitle: Text(
|
||||
'Choose the default type for manually created tabs',
|
||||
),
|
||||
subtitle: Text('Choose the default type for manually created tabs'),
|
||||
leading: Icon(MdiIcons.tab),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
@@ -144,12 +139,10 @@ class _NewTabDefaultSection extends HookConsumerWidget {
|
||||
selected: {defaultCreateTabType},
|
||||
onSelectionChanged: (value) async {
|
||||
await ref
|
||||
.read(
|
||||
saveGeneralSettingsControllerProvider.notifier,
|
||||
)
|
||||
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.defaultCreateTabType(value.first),
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.defaultCreateTabType(value.first),
|
||||
);
|
||||
},
|
||||
style: switch (defaultCreateTabType) {
|
||||
@@ -178,19 +171,14 @@ class _ExternalLinkHandlingSection extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const ListTile(
|
||||
title: Text('External Link Handling'),
|
||||
subtitle: Text(
|
||||
'Choose how external links open in WebLibre',
|
||||
),
|
||||
subtitle: Text('Choose how external links open in WebLibre'),
|
||||
leading: Icon(MdiIcons.tabPlus),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
),
|
||||
@@ -217,12 +205,10 @@ class _ExternalLinkHandlingSection extends HookConsumerWidget {
|
||||
selected: {tabIntentOpenSetting},
|
||||
onSelectionChanged: (value) async {
|
||||
await ref
|
||||
.read(
|
||||
saveGeneralSettingsControllerProvider.notifier,
|
||||
)
|
||||
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.tabIntentOpenSetting(value.first),
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.tabIntentOpenSetting(value.first),
|
||||
);
|
||||
},
|
||||
style: switch (tabIntentOpenSetting) {
|
||||
@@ -246,7 +232,9 @@ class _CreateChildTabsTile extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final createChildTabsOption = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select((s) => s.createChildTabsOption),
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
(s) => s.createChildTabsOption,
|
||||
),
|
||||
);
|
||||
|
||||
return SwitchListTile.adaptive(
|
||||
@@ -274,14 +262,14 @@ class _ShowExtensionShortcutTile extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final showExtensionShortcut = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select((s) => s.showExtensionShortcut),
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
(s) => s.showExtensionShortcut,
|
||||
),
|
||||
);
|
||||
|
||||
return SwitchListTile.adaptive(
|
||||
title: const Text('Show Extension Shortcut'),
|
||||
subtitle: const Text(
|
||||
'Display an extension menu directly on the tab bar',
|
||||
),
|
||||
subtitle: const Text('Display an extension menu directly on the tab bar'),
|
||||
secondary: const Icon(MdiIcons.puzzleHeart),
|
||||
value: showExtensionShortcut,
|
||||
onChanged: (value) async {
|
||||
@@ -306,10 +294,7 @@ class _TabBarSwipeBehaviorSection extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -324,9 +309,7 @@ class _TabBarSwipeBehaviorSection extends HookConsumerWidget {
|
||||
onChanged: (value) async {
|
||||
if (value != null) {
|
||||
await ref
|
||||
.read(
|
||||
saveGeneralSettingsControllerProvider.notifier,
|
||||
)
|
||||
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||
.save(
|
||||
(currentSettings) =>
|
||||
currentSettings.copyWith.tabBarSwipeAction(value),
|
||||
|
||||
@@ -10,11 +10,7 @@ import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart';
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
|
||||
/// Keyboard visibility event data
|
||||
typedef KeyboardEvent = ({
|
||||
int heightPx,
|
||||
bool isVisible,
|
||||
bool isAnimating,
|
||||
});
|
||||
typedef KeyboardEvent = ({int heightPx, bool isVisible, bool isAnimating});
|
||||
|
||||
/// Service for controlling GeckoView's viewport behavior.
|
||||
///
|
||||
@@ -57,9 +53,9 @@ class GeckoViewportService extends GeckoViewportEvents {
|
||||
BinaryMessenger? binaryMessenger,
|
||||
String messageChannelSuffix = '',
|
||||
}) : _api = GeckoViewportApi(
|
||||
binaryMessenger: binaryMessenger,
|
||||
messageChannelSuffix: messageChannelSuffix,
|
||||
);
|
||||
binaryMessenger: binaryMessenger,
|
||||
messageChannelSuffix: messageChannelSuffix,
|
||||
);
|
||||
|
||||
/// Sets up the service to receive events from native.
|
||||
///
|
||||
@@ -110,15 +106,11 @@ class GeckoViewportService extends GeckoViewportEvents {
|
||||
bool isVisible,
|
||||
bool isAnimating,
|
||||
) {
|
||||
_keyboardSubject.addWhenMoreRecent(
|
||||
timestamp,
|
||||
null,
|
||||
(
|
||||
heightPx: heightPx,
|
||||
isVisible: isVisible,
|
||||
isAnimating: isAnimating,
|
||||
),
|
||||
);
|
||||
_keyboardSubject.addWhenMoreRecent(timestamp, null, (
|
||||
heightPx: heightPx,
|
||||
isVisible: isVisible,
|
||||
isAnimating: isAnimating,
|
||||
));
|
||||
}
|
||||
|
||||
/// Disposes the service and closes all streams.
|
||||
|
||||
@@ -18,8 +18,8 @@ void main() {
|
||||
// Verify that platform version is retrieved.
|
||||
expect(
|
||||
find.byWidgetPredicate(
|
||||
(Widget widget) => widget is Text &&
|
||||
widget.data!.startsWith('Running on:'),
|
||||
(Widget widget) =>
|
||||
widget is Text && widget.data!.startsWith('Running on:'),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
// For more information about Flutter integration tests, please see
|
||||
// https://flutter.dev/to/integration-testing
|
||||
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
|
||||
@@ -84,11 +84,7 @@ class _MyAppState extends State<MyApp> {
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.mic,
|
||||
size: 80,
|
||||
color: Colors.blue,
|
||||
),
|
||||
const Icon(Icons.mic, size: 80, color: Colors.blue),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
_recognizedText,
|
||||
|
||||
@@ -18,8 +18,8 @@ void main() {
|
||||
// Verify that platform version is retrieved.
|
||||
expect(
|
||||
find.byWidgetPredicate(
|
||||
(Widget widget) => widget is Text &&
|
||||
widget.data!.startsWith('Running on:'),
|
||||
(Widget widget) =>
|
||||
widget is Text && widget.data!.startsWith('Running on:'),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
|
||||
@@ -48,11 +48,9 @@ class SpeechToTextDialog implements SpeechToTextEvents {
|
||||
///
|
||||
/// Optionally provide a custom [api] for testing or dependency injection.
|
||||
/// If [binaryMessenger] is provided, it will be used for Pigeon communication.
|
||||
SpeechToTextDialog({
|
||||
SpeechToTextApi? api,
|
||||
BinaryMessenger? binaryMessenger,
|
||||
}) : _api = api ?? SpeechToTextApi(binaryMessenger: binaryMessenger),
|
||||
_binaryMessenger = binaryMessenger {
|
||||
SpeechToTextDialog({SpeechToTextApi? api, BinaryMessenger? binaryMessenger})
|
||||
: _api = api ?? SpeechToTextApi(binaryMessenger: binaryMessenger),
|
||||
_binaryMessenger = binaryMessenger {
|
||||
// Set up the event handler
|
||||
SpeechToTextEvents.setUp(this, binaryMessenger: binaryMessenger);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import 'package:pigeon/pigeon.dart';
|
||||
dartPackageName: 'speech_to_text_dialog',
|
||||
),
|
||||
)
|
||||
|
||||
/// Host API - methods called from Flutter to native Android.
|
||||
@HostApi()
|
||||
abstract class SpeechToTextApi {
|
||||
|
||||
Reference in New Issue
Block a user