setting to show link open prompt
This commit is contained in:
@@ -54,6 +54,10 @@ part of 'routes.dart';
|
||||
name: 'TabTreeRoute',
|
||||
path: 'tab_tree/:rootTabId',
|
||||
),
|
||||
TypedGoRoute<OpenSharedContentRoute>(
|
||||
name: 'OpenSharedContentRoute',
|
||||
path: 'open_content',
|
||||
),
|
||||
],
|
||||
)
|
||||
class BrowserRoute extends GoRouteData with _$BrowserRoute {
|
||||
@@ -75,9 +79,12 @@ class SearchRoute extends GoRouteData with _$SearchRoute {
|
||||
//This should be nullable but isnt allowed by go_router
|
||||
final String searchText;
|
||||
|
||||
final bool $extra;
|
||||
|
||||
const SearchRoute({
|
||||
required this.tabType,
|
||||
this.searchText = SearchRoute.emptySearchText,
|
||||
this.$extra = false,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -87,6 +94,7 @@ class SearchRoute extends GoRouteData with _$SearchRoute {
|
||||
initialSearchText: (searchText.isEmpty || searchText == emptySearchText)
|
||||
? null
|
||||
: searchText,
|
||||
launchedFromIntent: $extra,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -159,3 +167,14 @@ class TabTreeRoute extends GoRouteData with _$TabTreeRoute {
|
||||
return DialogPage(builder: (_) => TabTreeDialog(rootTabId));
|
||||
}
|
||||
}
|
||||
|
||||
class OpenSharedContentRoute extends GoRouteData with _$OpenSharedContentRoute {
|
||||
final Uri $extra;
|
||||
|
||||
const OpenSharedContentRoute(this.$extra);
|
||||
|
||||
@override
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
return DialogPage(builder: (_) => OpenSharedContent(sharedUrl: $extra));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import 'package:weblibre/features/about/presentation/screens/about.dart';
|
||||
import 'package:weblibre/features/bangs/presentation/screens/categories.dart';
|
||||
import 'package:weblibre/features/bangs/presentation/screens/list.dart';
|
||||
import 'package:weblibre/features/bangs/presentation/screens/search.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/dialogs/open_shared_content.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/dialogs/tab_tree.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/screens/browser.dart';
|
||||
import 'package:weblibre/features/geckoview/features/contextmenu/extensions/hit_result.dart';
|
||||
|
||||
@@ -333,6 +333,12 @@ RouteBase get $browserRoute => GoRouteData.$route(
|
||||
|
||||
factory: _$TabTreeRoute._fromState,
|
||||
),
|
||||
GoRouteData.$route(
|
||||
path: 'open_content',
|
||||
name: 'OpenSharedContentRoute',
|
||||
|
||||
factory: _$OpenSharedContentRoute._fromState,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -361,6 +367,7 @@ mixin _$SearchRoute on GoRouteData {
|
||||
tabType: _$TabTypeEnumMap._$fromName(state.pathParameters['tabType']!)!,
|
||||
searchText:
|
||||
state.pathParameters['searchText'] ?? SearchRoute.emptySearchText,
|
||||
$extra: state.extra as bool,
|
||||
);
|
||||
|
||||
SearchRoute get _self => this as SearchRoute;
|
||||
@@ -371,17 +378,19 @@ mixin _$SearchRoute on GoRouteData {
|
||||
);
|
||||
|
||||
@override
|
||||
void go(BuildContext context) => context.go(location);
|
||||
void go(BuildContext context) => context.go(location, extra: _self.$extra);
|
||||
|
||||
@override
|
||||
Future<T?> push<T>(BuildContext context) => context.push<T>(location);
|
||||
Future<T?> push<T>(BuildContext context) =>
|
||||
context.push<T>(location, extra: _self.$extra);
|
||||
|
||||
@override
|
||||
void pushReplacement(BuildContext context) =>
|
||||
context.pushReplacement(location);
|
||||
context.pushReplacement(location, extra: _self.$extra);
|
||||
|
||||
@override
|
||||
void replace(BuildContext context) => context.replace(location);
|
||||
void replace(BuildContext context) =>
|
||||
context.replace(location, extra: _self.$extra);
|
||||
}
|
||||
|
||||
const _$TabTypeEnumMap = {
|
||||
@@ -552,6 +561,31 @@ mixin _$TabTreeRoute on GoRouteData {
|
||||
void replace(BuildContext context) => context.replace(location);
|
||||
}
|
||||
|
||||
mixin _$OpenSharedContentRoute on GoRouteData {
|
||||
static OpenSharedContentRoute _fromState(GoRouterState state) =>
|
||||
OpenSharedContentRoute(state.extra as Uri);
|
||||
|
||||
OpenSharedContentRoute get _self => this as OpenSharedContentRoute;
|
||||
|
||||
@override
|
||||
String get location => GoRouteData.$location('/open_content');
|
||||
|
||||
@override
|
||||
void go(BuildContext context) => context.go(location, extra: _self.$extra);
|
||||
|
||||
@override
|
||||
Future<T?> push<T>(BuildContext context) =>
|
||||
context.push<T>(location, extra: _self.$extra);
|
||||
|
||||
@override
|
||||
void pushReplacement(BuildContext context) =>
|
||||
context.pushReplacement(location, extra: _self.$extra);
|
||||
|
||||
@override
|
||||
void replace(BuildContext context) =>
|
||||
context.replace(location, extra: _self.$extra);
|
||||
}
|
||||
|
||||
extension<T extends Enum> on Map<T, String> {
|
||||
T? _$fromName(String? value) =>
|
||||
entries.where((element) => element.value == value).firstOrNull?.key;
|
||||
|
||||
@@ -25,21 +25,16 @@ import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||
import 'package:nullability/nullability.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:weblibre/core/logger.dart';
|
||||
import 'package:weblibre/core/routing/routes.dart';
|
||||
import 'package:weblibre/features/bangs/domain/providers/bangs.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/entities/states/tab.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/providers.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/providers/selected_tab.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/providers/tab_list.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/providers/tab_state.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/domain/providers.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/domain/providers/intent.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/data/models/container_data.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/data/providers.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/providers/selected_container.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/container.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
|
||||
import 'package:weblibre/features/share_intent/domain/entities/shared_content.dart';
|
||||
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
|
||||
import 'package:weblibre/utils/debouncer.dart';
|
||||
|
||||
part 'tab.g.dart';
|
||||
@@ -68,12 +63,16 @@ class TabRepository extends _$TabRepository {
|
||||
required bool private,
|
||||
HistoryMetadataKey? historyMetadata,
|
||||
Map<String, String>? additionalHeaders,
|
||||
Value<ContainerData?>? container,
|
||||
bool launchedFromIntent = false,
|
||||
}) async {
|
||||
final selectedContainer = await ref
|
||||
.read(selectedContainerProvider.notifier)
|
||||
.fetchData();
|
||||
final assingedContainer =
|
||||
container ??
|
||||
Value<ContainerData?>(
|
||||
await ref.read(selectedContainerProvider.notifier).fetchData(),
|
||||
);
|
||||
|
||||
return ref
|
||||
final newTabId = await ref
|
||||
.read(tabDatabaseProvider)
|
||||
.tabDao
|
||||
.upsertContainerTabTransactional(
|
||||
@@ -84,7 +83,7 @@ class TabRepository extends _$TabRepository {
|
||||
startLoading: startLoading,
|
||||
parentId: parentId,
|
||||
flags: flags,
|
||||
contextId: selectedContainer?.metadata.contextualIdentity,
|
||||
contextId: assingedContainer.value?.metadata.contextualIdentity,
|
||||
source: source,
|
||||
private: private,
|
||||
historyMetadata: historyMetadata,
|
||||
@@ -92,8 +91,14 @@ class TabRepository extends _$TabRepository {
|
||||
);
|
||||
},
|
||||
parentId: Value(parentId),
|
||||
containerId: Value(selectedContainer?.id),
|
||||
containerId: Value(assingedContainer.value?.id),
|
||||
);
|
||||
|
||||
if (launchedFromIntent) {
|
||||
_tabFromIntent.add(newTabId);
|
||||
}
|
||||
|
||||
return newTabId;
|
||||
}
|
||||
|
||||
Future<String> duplicateTab({
|
||||
@@ -371,45 +376,6 @@ class TabRepository extends _$TabRepository {
|
||||
},
|
||||
);
|
||||
|
||||
ref.listen(
|
||||
fireImmediately: true,
|
||||
engineBoundIntentStreamProvider,
|
||||
(previous, next) {
|
||||
next.whenData((value) async {
|
||||
final isPrivate =
|
||||
ref
|
||||
.read(generalSettingsWithDefaultsProvider)
|
||||
.defaultIntentTabType ==
|
||||
TabType.private;
|
||||
|
||||
switch (value) {
|
||||
case SharedUrl():
|
||||
_tabFromIntent.add(
|
||||
await addTab(url: value.url, private: isPrivate),
|
||||
);
|
||||
case SharedText():
|
||||
final defaultSearchBang =
|
||||
ref.read(selectedBangDataProvider()) ??
|
||||
await ref.read(defaultSearchBangDataProvider.future);
|
||||
|
||||
_tabFromIntent.add(
|
||||
await addTab(
|
||||
url: defaultSearchBang?.getTemplateUrl(value.text),
|
||||
private: isPrivate,
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
logger.e(
|
||||
'Error listening to engineBoundIntentStreamProvider',
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
ref.onDispose(() async {
|
||||
tabStateDebouncer.dispose();
|
||||
await tabAddedSub.cancel();
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'tab.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$tabRepositoryHash() => r'4f562c1456eadcda7986ea2048667dd083f37618';
|
||||
String _$tabRepositoryHash() => r'45af26417881bca38973cf702073b1c7857f1cfa';
|
||||
|
||||
/// See also [TabRepository].
|
||||
@ProviderFor(TabRepository)
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/repositories/tab.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/data/models/container_data.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/container_chips.dart';
|
||||
import 'package:weblibre/utils/form_validators.dart';
|
||||
|
||||
class OpenSharedContent extends HookConsumerWidget {
|
||||
final Uri sharedUrl;
|
||||
|
||||
const OpenSharedContent({required this.sharedUrl});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final formKey = useMemoized(() => GlobalKey<FormState>());
|
||||
final textController = useTextEditingController(text: sharedUrl.toString());
|
||||
|
||||
final selectedContainer = useState<ContainerData?>(null);
|
||||
|
||||
Future<void> openTab(bool isPrivate) async {
|
||||
if (formKey.currentState?.validate() == true) {
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.addTab(
|
||||
url: Uri.parse(textController.text),
|
||||
private: isPrivate,
|
||||
container: Value(selectedContainer.value),
|
||||
launchedFromIntent: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Form(
|
||||
key: formKey,
|
||||
child: SimpleDialog(
|
||||
title: const Text('Open URL'),
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsetsDirectional.symmetric(horizontal: 16.0),
|
||||
child: SizedBox(
|
||||
height: 48,
|
||||
width: double.maxFinite,
|
||||
child: ContainerChips(
|
||||
displayMenu: false,
|
||||
selectedContainer: selectedContainer.value,
|
||||
onSelected: (container) {
|
||||
selectedContainer.value = container;
|
||||
},
|
||||
onDeleted: (container) {
|
||||
selectedContainer.value = null;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsetsDirectional.symmetric(horizontal: 16.0),
|
||||
child: TextFormField(
|
||||
controller: textController,
|
||||
keyboardType: TextInputType.url,
|
||||
minLines: 1,
|
||||
maxLines: 10,
|
||||
validator: (value) {
|
||||
return validateUrl(
|
||||
value,
|
||||
onlyHttpProtocol: true,
|
||||
eagerParsing: false,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('Open Regular Tab'),
|
||||
leading: const Icon(MdiIcons.tab),
|
||||
onTap: () async {
|
||||
await openTab(false);
|
||||
if (context.mounted) {
|
||||
context.pop();
|
||||
}
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('Open Private Tab'),
|
||||
leading: const Icon(MdiIcons.tabUnselected),
|
||||
onTap: () async {
|
||||
await openTab(true);
|
||||
if (context.mounted) {
|
||||
context.pop();
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+3
@@ -17,6 +17,7 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import 'package:drift/drift.dart' show Value;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
||||
@@ -242,6 +243,7 @@ class BrowserBottomAppBar extends HookConsumerWidget {
|
||||
.addTab(
|
||||
url: ref.read(docsUriProvider),
|
||||
private: isPrivate,
|
||||
container: const Value(null),
|
||||
);
|
||||
},
|
||||
leadingIcon: const Icon(Icons.help),
|
||||
@@ -301,6 +303,7 @@ class BrowserBottomAppBar extends HookConsumerWidget {
|
||||
.addTab(
|
||||
url: Uri.parse('https://addons.mozilla.org'),
|
||||
private: isPrivate,
|
||||
container: const Value(null),
|
||||
);
|
||||
},
|
||||
leadingIcon: const Icon(MdiIcons.puzzlePlus),
|
||||
|
||||
@@ -44,8 +44,13 @@ import 'package:weblibre/utils/uri_parser.dart' as uri_parser;
|
||||
class SearchScreen extends HookConsumerWidget {
|
||||
final String? initialSearchText;
|
||||
final TabType tabType;
|
||||
final bool launchedFromIntent;
|
||||
|
||||
const SearchScreen({required this.initialSearchText, required this.tabType});
|
||||
const SearchScreen({
|
||||
required this.initialSearchText,
|
||||
required this.tabType,
|
||||
this.launchedFromIntent = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@@ -109,6 +114,7 @@ class SearchScreen extends HookConsumerWidget {
|
||||
parentId: (selectedTabType.value == TabType.child)
|
||||
? ref.read(selectedTabProvider)
|
||||
: null,
|
||||
launchedFromIntent: launchedFromIntent,
|
||||
);
|
||||
|
||||
if (context.mounted) {
|
||||
@@ -212,6 +218,7 @@ class SearchScreen extends HookConsumerWidget {
|
||||
(selectedTabType.value == TabType.child)
|
||||
? ref.read(selectedTabProvider)
|
||||
: null,
|
||||
launchedFromIntent: launchedFromIntent,
|
||||
);
|
||||
|
||||
if (context.mounted) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import 'package:drift/drift.dart' show Value;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
@@ -147,6 +148,7 @@ class OnboardingScreen extends HookConsumerWidget {
|
||||
.addTab(
|
||||
url: ref.read(docsUriProvider),
|
||||
private: false,
|
||||
container: const Value(null),
|
||||
);
|
||||
|
||||
ref.invalidate(routerProvider);
|
||||
|
||||
@@ -175,17 +175,22 @@ class GeneralSettingsScreen extends HookConsumerWidget {
|
||||
showSelectedIcon: false,
|
||||
segments: const [
|
||||
ButtonSegment(
|
||||
value: TabType.regular,
|
||||
value: TabIntentOpenSetting.ask,
|
||||
label: Text('Prompt'),
|
||||
icon: Icon(MdiIcons.messageQuestion),
|
||||
),
|
||||
ButtonSegment(
|
||||
value: TabIntentOpenSetting.regular,
|
||||
label: Text('Regular'),
|
||||
icon: Icon(MdiIcons.tab),
|
||||
),
|
||||
ButtonSegment(
|
||||
value: TabType.private,
|
||||
value: TabIntentOpenSetting.private,
|
||||
label: Text('Private'),
|
||||
icon: Icon(MdiIcons.tabUnselected),
|
||||
),
|
||||
],
|
||||
selected: {generalSettings.defaultIntentTabType},
|
||||
selected: {generalSettings.tabIntentOpenSetting},
|
||||
onSelectionChanged: (value) async {
|
||||
await ref
|
||||
.read(
|
||||
@@ -193,15 +198,16 @@ class GeneralSettingsScreen extends HookConsumerWidget {
|
||||
)
|
||||
.save(
|
||||
(currentSettings) => currentSettings.copyWith
|
||||
.defaultIntentTabType(value.first),
|
||||
.tabIntentOpenSetting(value.first),
|
||||
);
|
||||
},
|
||||
style: switch (generalSettings.defaultIntentTabType) {
|
||||
TabType.regular => null,
|
||||
TabType.private => SegmentedButton.styleFrom(
|
||||
selectedBackgroundColor: const Color(0x648000D7),
|
||||
),
|
||||
TabType.child => null,
|
||||
style: switch (generalSettings.tabIntentOpenSetting) {
|
||||
TabIntentOpenSetting.regular => null,
|
||||
TabIntentOpenSetting.private =>
|
||||
SegmentedButton.styleFrom(
|
||||
selectedBackgroundColor: const Color(0x648000D7),
|
||||
),
|
||||
TabIntentOpenSetting.ask => null,
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
@@ -31,6 +31,8 @@ const _fallbackAutocompleteProvider = SearchSuggestionProviders.none;
|
||||
|
||||
enum TabBarSwipeAction { switchLastOpened, navigateOrderedTabs }
|
||||
|
||||
enum TabIntentOpenSetting { regular, private, ask }
|
||||
|
||||
enum DeleteBrowsingDataType {
|
||||
tabs('Open tabs'),
|
||||
history('Browsing history'),
|
||||
@@ -58,7 +60,7 @@ class GeneralSettings with FastEquatable {
|
||||
final bool showExtensionShortcut;
|
||||
final bool enableLocalAiFeatures;
|
||||
final TabType defaultCreateTabType;
|
||||
final TabType defaultIntentTabType;
|
||||
final TabIntentOpenSetting tabIntentOpenSetting;
|
||||
final bool proxyPrivateTabsTor;
|
||||
final bool autoHideTabBar;
|
||||
final TabBarSwipeAction tabBarSwipeAction;
|
||||
@@ -75,7 +77,7 @@ class GeneralSettings with FastEquatable {
|
||||
required this.showExtensionShortcut,
|
||||
required this.enableLocalAiFeatures,
|
||||
required this.defaultCreateTabType,
|
||||
required this.defaultIntentTabType,
|
||||
required this.tabIntentOpenSetting,
|
||||
required this.autoHideTabBar,
|
||||
required this.tabBarSwipeAction,
|
||||
});
|
||||
@@ -92,7 +94,7 @@ class GeneralSettings with FastEquatable {
|
||||
bool? showExtensionShortcut,
|
||||
bool? enableLocalAiFeatures,
|
||||
TabType? defaultCreateTabType,
|
||||
TabType? defaultIntentTabType,
|
||||
TabIntentOpenSetting? tabIntentOpenSetting,
|
||||
bool? autoHideTabBar,
|
||||
TabBarSwipeAction? tabBarSwipeAction,
|
||||
}) : themeMode = themeMode ?? ThemeMode.dark,
|
||||
@@ -106,7 +108,7 @@ class GeneralSettings with FastEquatable {
|
||||
showExtensionShortcut = showExtensionShortcut ?? false,
|
||||
enableLocalAiFeatures = enableLocalAiFeatures ?? true,
|
||||
defaultCreateTabType = defaultCreateTabType ?? TabType.regular,
|
||||
defaultIntentTabType = defaultIntentTabType ?? TabType.regular,
|
||||
tabIntentOpenSetting = tabIntentOpenSetting ?? TabIntentOpenSetting.ask,
|
||||
autoHideTabBar = autoHideTabBar ?? true,
|
||||
tabBarSwipeAction =
|
||||
tabBarSwipeAction ?? TabBarSwipeAction.switchLastOpened;
|
||||
@@ -128,7 +130,7 @@ class GeneralSettings with FastEquatable {
|
||||
showExtensionShortcut,
|
||||
enableLocalAiFeatures,
|
||||
defaultCreateTabType,
|
||||
defaultIntentTabType,
|
||||
tabIntentOpenSetting,
|
||||
proxyPrivateTabsTor,
|
||||
autoHideTabBar,
|
||||
tabBarSwipeAction,
|
||||
|
||||
@@ -33,7 +33,9 @@ abstract class _$GeneralSettingsCWProxy {
|
||||
|
||||
GeneralSettings defaultCreateTabType(TabType defaultCreateTabType);
|
||||
|
||||
GeneralSettings defaultIntentTabType(TabType defaultIntentTabType);
|
||||
GeneralSettings tabIntentOpenSetting(
|
||||
TabIntentOpenSetting tabIntentOpenSetting,
|
||||
);
|
||||
|
||||
GeneralSettings autoHideTabBar(bool autoHideTabBar);
|
||||
|
||||
@@ -57,7 +59,7 @@ abstract class _$GeneralSettingsCWProxy {
|
||||
bool showExtensionShortcut,
|
||||
bool enableLocalAiFeatures,
|
||||
TabType defaultCreateTabType,
|
||||
TabType defaultIntentTabType,
|
||||
TabIntentOpenSetting tabIntentOpenSetting,
|
||||
bool autoHideTabBar,
|
||||
TabBarSwipeAction tabBarSwipeAction,
|
||||
});
|
||||
@@ -115,8 +117,9 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
|
||||
this(defaultCreateTabType: defaultCreateTabType);
|
||||
|
||||
@override
|
||||
GeneralSettings defaultIntentTabType(TabType defaultIntentTabType) =>
|
||||
this(defaultIntentTabType: defaultIntentTabType);
|
||||
GeneralSettings tabIntentOpenSetting(
|
||||
TabIntentOpenSetting tabIntentOpenSetting,
|
||||
) => this(tabIntentOpenSetting: tabIntentOpenSetting);
|
||||
|
||||
@override
|
||||
GeneralSettings autoHideTabBar(bool autoHideTabBar) =>
|
||||
@@ -145,7 +148,7 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
|
||||
Object? showExtensionShortcut = const $CopyWithPlaceholder(),
|
||||
Object? enableLocalAiFeatures = const $CopyWithPlaceholder(),
|
||||
Object? defaultCreateTabType = const $CopyWithPlaceholder(),
|
||||
Object? defaultIntentTabType = const $CopyWithPlaceholder(),
|
||||
Object? tabIntentOpenSetting = const $CopyWithPlaceholder(),
|
||||
Object? autoHideTabBar = const $CopyWithPlaceholder(),
|
||||
Object? tabBarSwipeAction = const $CopyWithPlaceholder(),
|
||||
}) {
|
||||
@@ -200,10 +203,10 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
|
||||
? _value.defaultCreateTabType
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: defaultCreateTabType as TabType,
|
||||
defaultIntentTabType: defaultIntentTabType == const $CopyWithPlaceholder()
|
||||
? _value.defaultIntentTabType
|
||||
tabIntentOpenSetting: tabIntentOpenSetting == const $CopyWithPlaceholder()
|
||||
? _value.tabIntentOpenSetting
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: defaultIntentTabType as TabType,
|
||||
: tabIntentOpenSetting as TabIntentOpenSetting,
|
||||
autoHideTabBar: autoHideTabBar == const $CopyWithPlaceholder()
|
||||
? _value.autoHideTabBar
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
@@ -248,9 +251,9 @@ GeneralSettings _$GeneralSettingsFromJson(Map<String, dynamic> json) =>
|
||||
_$TabTypeEnumMap,
|
||||
json['defaultCreateTabType'],
|
||||
),
|
||||
defaultIntentTabType: $enumDecodeNullable(
|
||||
_$TabTypeEnumMap,
|
||||
json['defaultIntentTabType'],
|
||||
tabIntentOpenSetting: $enumDecodeNullable(
|
||||
_$TabIntentOpenSettingEnumMap,
|
||||
json['tabIntentOpenSetting'],
|
||||
),
|
||||
autoHideTabBar: json['autoHideTabBar'] as bool?,
|
||||
tabBarSwipeAction: $enumDecodeNullable(
|
||||
@@ -276,7 +279,8 @@ Map<String, dynamic> _$GeneralSettingsToJson(
|
||||
'showExtensionShortcut': instance.showExtensionShortcut,
|
||||
'enableLocalAiFeatures': instance.enableLocalAiFeatures,
|
||||
'defaultCreateTabType': _$TabTypeEnumMap[instance.defaultCreateTabType]!,
|
||||
'defaultIntentTabType': _$TabTypeEnumMap[instance.defaultIntentTabType]!,
|
||||
'tabIntentOpenSetting':
|
||||
_$TabIntentOpenSettingEnumMap[instance.tabIntentOpenSetting]!,
|
||||
'proxyPrivateTabsTor': instance.proxyPrivateTabsTor,
|
||||
'autoHideTabBar': instance.autoHideTabBar,
|
||||
'tabBarSwipeAction': _$TabBarSwipeActionEnumMap[instance.tabBarSwipeAction]!,
|
||||
@@ -311,6 +315,12 @@ const _$TabTypeEnumMap = {
|
||||
TabType.child: 'child',
|
||||
};
|
||||
|
||||
const _$TabIntentOpenSettingEnumMap = {
|
||||
TabIntentOpenSetting.regular: 'regular',
|
||||
TabIntentOpenSetting.private: 'private',
|
||||
TabIntentOpenSetting.ask: 'ask',
|
||||
};
|
||||
|
||||
const _$TabBarSwipeActionEnumMap = {
|
||||
TabBarSwipeAction.switchLastOpened: 'switchLastOpened',
|
||||
TabBarSwipeAction.navigateOrderedTabs: 'navigateOrderedTabs',
|
||||
|
||||
@@ -88,7 +88,7 @@ class GeneralSettingsRepository extends _$GeneralSettingsRepository {
|
||||
DriftSqlType.string,
|
||||
db.typeMapping,
|
||||
),
|
||||
'defaultIntentTabType': settings['defaultIntentTabType']?.readAs(
|
||||
'tabIntentOpenSetting': settings['tabIntentOpenSetting']?.readAs(
|
||||
DriftSqlType.string,
|
||||
db.typeMapping,
|
||||
),
|
||||
|
||||
@@ -27,7 +27,7 @@ final generalSettingsWithDefaultsProvider =
|
||||
typedef GeneralSettingsWithDefaultsRef =
|
||||
AutoDisposeProviderRef<GeneralSettings>;
|
||||
String _$generalSettingsRepositoryHash() =>
|
||||
r'e311760a7773109a90c28275262883fcca348bbb';
|
||||
r'7dd57d726d4bf86e04cb33da9b7a1399d49f7915';
|
||||
|
||||
/// See also [GeneralSettingsRepository].
|
||||
@ProviderFor(GeneralSettingsRepository)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:drift/drift.dart' show Value;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
@@ -205,6 +206,7 @@ class FeedArticleScreen extends HookConsumerWidget {
|
||||
.addTab(
|
||||
url: articleLink.uri,
|
||||
private: isPrivate,
|
||||
container: const Value(null),
|
||||
);
|
||||
|
||||
if (context.mounted) {
|
||||
|
||||
@@ -19,8 +19,18 @@
|
||||
*/
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:weblibre/core/logger.dart';
|
||||
import 'package:weblibre/core/providers/router.dart';
|
||||
import 'package:weblibre/core/routing/routes.dart';
|
||||
import 'package:weblibre/domain/services/app_initialization.dart';
|
||||
import 'package:weblibre/features/bangs/domain/providers/bangs.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/providers/tab_state.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/repositories/tab.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/domain/providers.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/domain/providers/intent.dart';
|
||||
import 'package:weblibre/features/share_intent/domain/entities/shared_content.dart';
|
||||
import 'package:weblibre/features/user/data/models/general_settings.dart';
|
||||
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
|
||||
import 'package:weblibre/presentation/widgets/failure_widget.dart';
|
||||
|
||||
class MainApp extends HookConsumerWidget {
|
||||
@@ -40,6 +50,71 @@ class MainApp extends HookConsumerWidget {
|
||||
final initializationResult = ref.watch(appInitializationServiceProvider);
|
||||
final router = ref.watch(routerProvider);
|
||||
|
||||
ref.listen(
|
||||
engineBoundIntentStreamProvider,
|
||||
(previous, next) {
|
||||
next.whenData((sharedContent) async {
|
||||
final router = await ref.read(routerProvider.future);
|
||||
final settings = ref.read(generalSettingsWithDefaultsProvider);
|
||||
|
||||
switch (settings.tabIntentOpenSetting) {
|
||||
case TabIntentOpenSetting.regular:
|
||||
case TabIntentOpenSetting.private:
|
||||
switch (sharedContent) {
|
||||
case SharedUrl():
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.addTab(
|
||||
url: sharedContent.url,
|
||||
private:
|
||||
settings.tabIntentOpenSetting ==
|
||||
TabIntentOpenSetting.private,
|
||||
launchedFromIntent: true,
|
||||
);
|
||||
case SharedText():
|
||||
final defaultSearchBang =
|
||||
ref.read(selectedBangDataProvider()) ??
|
||||
await ref.read(defaultSearchBangDataProvider.future);
|
||||
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.addTab(
|
||||
url: defaultSearchBang?.getTemplateUrl(
|
||||
sharedContent.text,
|
||||
),
|
||||
private:
|
||||
settings.tabIntentOpenSetting ==
|
||||
TabIntentOpenSetting.private,
|
||||
launchedFromIntent: true,
|
||||
);
|
||||
}
|
||||
case TabIntentOpenSetting.ask:
|
||||
switch (sharedContent) {
|
||||
case SharedUrl():
|
||||
final route = OpenSharedContentRoute(sharedContent.url);
|
||||
await router.push(route.location, extra: route.$extra);
|
||||
case SharedText():
|
||||
final route = SearchRoute(
|
||||
tabType:
|
||||
ref.read(selectedTabTypeProvider) ??
|
||||
settings.defaultCreateTabType,
|
||||
searchText: sharedContent.text,
|
||||
$extra: true, //launched from intent
|
||||
);
|
||||
await router.push(route.location);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
logger.e(
|
||||
'Error listening to engineBoundIntentStreamProvider',
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return initializationResult.fold(
|
||||
(initializationState) {
|
||||
if (!initializationState.initialized) {
|
||||
|
||||
Reference in New Issue
Block a user