improve open url dialog opening time

This commit is contained in:
Fabian Freund
2026-04-16 04:32:33 +02:00
parent 1df7f95117
commit 62cc45f607
6 changed files with 70 additions and 40 deletions
@@ -192,6 +192,38 @@ GeckoViewportService viewportService(Ref ref) {
@Riverpod(keepAlive: true) @Riverpod(keepAlive: true)
class EngineReadyState extends _$EngineReadyState { class EngineReadyState extends _$EngineReadyState {
Future<bool> waitUntilReady({
Duration timeout = const Duration(seconds: 3),
}) async {
final eventService = ref.read(eventServiceProvider);
final currentState =
eventService.engineReadyStateEvents.valueOrNull ?? false;
if (currentState) {
return true;
}
try {
final ready = await eventService.engineReadyStateEvents
.firstWhere((value) => value == true)
.timeout(timeout);
if (ref.mounted) {
state = ready;
}
return ready;
} on TimeoutException {
logger.w('Waiting for engine ready state timed out');
if (ref.mounted) {
state = true;
}
return true;
}
}
@override @override
bool build() { bool build() {
final eventService = ref.watch(eventServiceProvider); final eventService = ref.watch(eventServiceProvider);
@@ -200,22 +232,7 @@ class EngineReadyState extends _$EngineReadyState {
eventService.engineReadyStateEvents.valueOrNull ?? false; eventService.engineReadyStateEvents.valueOrNull ?? false;
if (!currentState) { if (!currentState) {
unawaited( unawaited(waitUntilReady());
eventService.engineReadyStateEvents
.firstWhere((value) => value == true)
.timeout(
const Duration(seconds: 3),
onTimeout: () {
logger.w('Waiting for engine ready state timed out');
return true;
},
)
.whenComplete(() {
if (ref.mounted) {
state = true;
}
}),
);
} }
final sub = eventService.engineReadyStateEvents.listen((value) { final sub = eventService.engineReadyStateEvents.listen((value) {
@@ -325,7 +325,7 @@ final class EngineReadyStateProvider
} }
} }
String _$engineReadyStateHash() => r'ab3fe385fbda4d7d8acaf8f5428b3b48b75f3f46'; String _$engineReadyStateHash() => r'0483cc1638d6cc23f7a33b8cb7c52667b07f7eea';
abstract class _$EngineReadyState extends $Notifier<bool> { abstract class _$EngineReadyState extends $Notifier<bool> {
bool build(); bool build();
@@ -26,7 +26,6 @@ import 'package:weblibre/core/logger.dart';
import 'package:weblibre/core/routing/routes.dart'; import 'package:weblibre/core/routing/routes.dart';
import 'package:weblibre/data/models/received_intent_parameter.dart'; import 'package:weblibre/data/models/received_intent_parameter.dart';
import 'package:weblibre/features/app_widget/domain/services/home_widget.dart'; import 'package:weblibre/features/app_widget/domain/services/home_widget.dart';
import 'package:weblibre/features/geckoview/domain/providers.dart';
import 'package:weblibre/features/share_intent/domain/entities/shared_content.dart'; import 'package:weblibre/features/share_intent/domain/entities/shared_content.dart';
import 'package:weblibre/features/share_intent/domain/services/sharing_intent.dart'; import 'package:weblibre/features/share_intent/domain/services/sharing_intent.dart';
@@ -36,10 +35,8 @@ final _contentParserTransformer =
StreamTransformer<ReceivedIntentParameter, SharedContent>.fromHandlers( StreamTransformer<ReceivedIntentParameter, SharedContent>.fromHandlers(
handleData: (parameter, sink) { handleData: (parameter, sink) {
final parsed = parameter.content.mapNotNull( final parsed = parameter.content.mapNotNull(
(content) => SharedContent.parse( (content) =>
content, SharedContent.parse(content, contextId: parameter.contextId),
contextId: parameter.contextId,
),
); );
if (parsed != null) { if (parsed != null) {
@@ -54,11 +51,6 @@ final _contentParserTransformer =
class EngineBoundIntentStream extends _$EngineBoundIntentStream { class EngineBoundIntentStream extends _$EngineBoundIntentStream {
@override @override
Stream<SharedContent> build() { Stream<SharedContent> build() {
final engineReady = ref.watch(engineReadyStateProvider);
if (!engineReady) {
return const Stream.empty();
}
final sharingItentStream = ref.watch(sharingIntentStreamProvider); final sharingItentStream = ref.watch(sharingIntentStreamProvider);
final appWidgetLaunchStream = ref.watch(appWidgetLaunchStreamProvider); final appWidgetLaunchStream = ref.watch(appWidgetLaunchStreamProvider);
@@ -34,7 +34,7 @@ final class EngineBoundIntentStreamProvider
} }
String _$engineBoundIntentStreamHash() => String _$engineBoundIntentStreamHash() =>
r'618eb6431da93989de6f1780cba2993458b0014e'; r'8170f28c2ce69813066780a65205426182a26863';
abstract class _$EngineBoundIntentStream abstract class _$EngineBoundIntentStream
extends $StreamNotifier<SharedContent> { extends $StreamNotifier<SharedContent> {
@@ -221,6 +221,8 @@ class _BrowserViewState extends ConsumerState<BrowserView>
await widget.postInitializationStep?.call(); await widget.postInitializationStep?.call();
if (!_initializationCompleter.isCompleted) { if (!_initializationCompleter.isCompleted) {
_initializationCompleter.complete();
const quickActions = QuickActions(); const quickActions = QuickActions();
//Debounce: https://github.com/flutter/flutter/issues/131121 //Debounce: https://github.com/flutter/flutter/issues/131121
@@ -284,8 +286,6 @@ class _BrowserViewState extends ConsumerState<BrowserView>
localizedTitle: 'New Isolated Tab', localizedTitle: 'New Isolated Tab',
), ),
]); ]);
_initializationCompleter.complete();
} }
}, },
), ),
@@ -349,24 +349,24 @@ class _BrowserViewState extends ConsumerState<BrowserView>
ref.listenManual( ref.listenManual(
engineBoundIntentStreamProvider, engineBoundIntentStreamProvider,
(previous, next) async { (previous, next) {
await _initializationCompleter.future;
next.whenData((sharedContent) async { next.whenData((sharedContent) async {
final router = await ref.read(routerProvider.future);
final settings = ref.read(generalSettingsWithDefaultsProvider); final settings = ref.read(generalSettingsWithDefaultsProvider);
// Resolve container from shortcut intent context ID
final containerSelection = await _resolveContainerSelection(
ref,
sharedContent.contextId,
);
switch (settings.tabIntentOpenSetting) { switch (settings.tabIntentOpenSetting) {
case TabIntentOpenSetting.regular: case TabIntentOpenSetting.regular:
case TabIntentOpenSetting.private: case TabIntentOpenSetting.private:
await ref
.read(engineReadyStateProvider.notifier)
.waitUntilReady();
switch (sharedContent) { switch (sharedContent) {
case SharedUrl(): case SharedUrl():
final containerSelection = await _resolveContainerSelection(
ref,
sharedContent.contextId,
);
await ref await ref
.read(tabRepositoryProvider.notifier) .read(tabRepositoryProvider.notifier)
.addTab( .addTab(
@@ -399,6 +399,8 @@ class _BrowserViewState extends ConsumerState<BrowserView>
); );
} }
case TabIntentOpenSetting.ask: case TabIntentOpenSetting.ask:
final router = await ref.read(routerProvider.future);
switch (sharedContent) { switch (sharedContent) {
case SharedUrl(): case SharedUrl():
final route = OpenSharedContentRoute( final route = OpenSharedContentRoute(
+19
View File
@@ -42,6 +42,7 @@ import 'package:weblibre/core/providers/app_state.dart';
import 'package:weblibre/core/providers/defaults.dart'; import 'package:weblibre/core/providers/defaults.dart';
import 'package:weblibre/core/providers/router.dart'; import 'package:weblibre/core/providers/router.dart';
import 'package:weblibre/domain/services/app_initialization.dart'; import 'package:weblibre/domain/services/app_initialization.dart';
import 'package:weblibre/features/geckoview/features/open_link_tools/domain/services/url_cleaner_catalog_service.dart';
import 'package:weblibre/features/user/domain/repositories/engine_settings.dart'; import 'package:weblibre/features/user/domain/repositories/engine_settings.dart';
import 'package:weblibre/features/user/domain/repositories/general_settings.dart'; import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
import 'package:weblibre/features/web_feed/presentation/controllers/fetch_articles.dart'; import 'package:weblibre/features/web_feed/presentation/controllers/fetch_articles.dart';
@@ -207,6 +208,24 @@ class _MainWidget extends HookConsumerWidget {
await ref.read(appInitializationServiceProvider.notifier).initialize(); await ref.read(appInitializationServiceProvider.notifier).initialize();
Future<void> preloadUrlCleanerCatalog() async {
if (!generalSettings.urlCleanerEnabled) {
return;
}
try {
await ref.read(urlCleanerCatalogServiceProvider.future);
} catch (e, s) {
logger.w(
'Failed preloading URL cleaner catalog',
error: e,
stackTrace: s,
);
}
}
unawaited(preloadUrlCleanerCatalog());
if (!kDebugMode) { if (!kDebugMode) {
await BackgroundFetch.configure( await BackgroundFetch.configure(
BackgroundFetchConfig( BackgroundFetchConfig(