diff --git a/firka/lib/app/initialization_screen.dart b/firka/lib/app/initialization_screen.dart index 3bf06d1..2b9316f 100644 --- a/firka/lib/app/initialization_screen.dart +++ b/firka/lib/app/initialization_screen.dart @@ -15,6 +15,7 @@ import 'package:firka/core/bloc/theme_cubit.dart'; import 'package:firka/core/firka_bundle.dart'; import 'package:firka/routing/app_router.dart'; import 'package:firka/services/watch_sync_helper.dart'; +import 'package:firka/ui/phone/pages/extras/main_wear_pair.dart'; import 'package:firka/l10n/app_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:go_router/go_router.dart'; @@ -95,17 +96,27 @@ class _InitializationScreenState extends State { case "ping": if (initData.tokens.isNotEmpty) { logger.finest("WatchOS IPC [Phone -> Watch]: pong"); - const watchChannel = MethodChannel('app.firka/watch_sync'); - watchChannel.invokeMethod('sendMessageToWatch', { - "id": "pong", - }); + unawaited( + WatchSyncHelper.sendMessageToWatch({'id': 'pong'}), + ); _router?.go('/home'); + WidgetsBinding.instance.addPostFrameCallback((_) { + final ctx = navigatorKey.currentContext; + if (ctx != null && ctx.mounted) { + showWearBottomSheet( + ctx, + initData, + Platform.isAndroid ? 'Wear OS' : 'Apple Watch', + ); + } + }); } } }; if (Platform.isAndroid) { WatchSyncHelper.watchMessageStream.listen((msg) async { + WatchSyncHelper.onWatchMessage?.call(msg); if (msg['id'] == 'request_sync' && initDone && isWearOsSupportEnabled()) { @@ -114,6 +125,20 @@ class _InitializationScreenState extends State { ); } }); + if (isWearOsSupportEnabled()) { + unawaited(() async { + try { + await WatchSyncHelper.startWearSyncServiceWithFreshCache( + initData.client, + initData.appDir.path, + ); + } catch (e) { + logger.warning( + '[Init] Failed to start Wear sync service on launch: $e', + ); + } + }()); + } } } diff --git a/firka/lib/core/settings.dart b/firka/lib/core/settings.dart index bf22f68..3edae9b 100644 --- a/firka/lib/core/settings.dart +++ b/firka/lib/core/settings.dart @@ -14,9 +14,9 @@ import 'package:majesticons_flutter/majesticons_flutter.dart'; import 'package:firka/app/app_state.dart'; import 'package:firka/app/initialization.dart'; import 'package:firka/app/initialization_screen.dart'; -import 'package:firka/services/wear_sync_cache.dart'; import 'package:firka/services/watch_sync_helper.dart'; import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; const bellRing = 1001; const rounding1 = 1002; @@ -377,15 +377,14 @@ class SettingsStore { if (!Platform.isAndroid) return; final enabled = isWearOsSupportEnabled(); if (enabled && initDone) { - final payload = await buildWearSyncPayload(initData.client); - if (payload != null) { - final path = await getWearSyncCachePath(); - await writeWearSyncCache(path, payload); - await WatchSyncHelper.startWearSyncService( - path, - initData.appDir.path, - ); + final notifStatus = await Permission.notification.status; + if (notifStatus.isDenied || notifStatus.isPermanentlyDenied) { + await Permission.notification.request(); } + await WatchSyncHelper.startWearSyncServiceWithFreshCache( + initData.client, + initData.appDir.path, + ); } else { await WatchSyncHelper.stopWearSyncService(); } diff --git a/firka/lib/services/watch_sync_helper.dart b/firka/lib/services/watch_sync_helper.dart index ec2746d..7a50788 100644 --- a/firka/lib/services/watch_sync_helper.dart +++ b/firka/lib/services/watch_sync_helper.dart @@ -611,6 +611,20 @@ class WatchSyncHelper { ); } + /// Builds fresh sync payload, writes cache, and starts the Wear sync service (Android only). + /// Use when enabling Wear OS support or on app launch when support is already enabled. + static Future startWearSyncServiceWithFreshCache( + KretaClient client, + String appDirPath, + ) async { + if (!Platform.isAndroid) return; + final payload = await buildWearSyncPayload(client); + if (payload == null) return; + final path = await getWearSyncCachePath(); + await writeWearSyncCache(path, payload); + await startWearSyncService(path, appDirPath); + } + /// Sets the method call handler for getLocalizedString (Android). Call once when initData is ready. static void setWearSyncMethodCallHandler() { if (!Platform.isAndroid) return;