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