@@ -19,18 +19,17 @@ import androidx.compose.animation.core.animateFloatAsState
1919import androidx.compose.animation.core.tween
2020import androidx.compose.foundation.layout.Column
2121import androidx.compose.foundation.layout.fillMaxSize
22+ import androidx.compose.foundation.layout.fillMaxWidth
2223import androidx.compose.foundation.layout.statusBarsPadding
23- import androidx.compose.material3.AlertDialog
24- import androidx.compose.material3.ExperimentalMaterial3Api
25- import androidx.compose.material3.Text
26- import androidx.compose.material3.TextButton
24+ import androidx.compose.material3.*
2725import androidx.compose.runtime.*
2826import androidx.compose.runtime.livedata.observeAsState
2927import androidx.compose.runtime.saveable.rememberSaveable
3028import androidx.compose.ui.Modifier
3129import androidx.compose.ui.platform.LocalContext
3230import androidx.compose.ui.platform.LocalView
3331import androidx.compose.ui.res.stringResource
32+ import androidx.compose.ui.text.style.TextAlign
3433import androidx.lifecycle.compose.collectAsStateWithLifecycle
3534import app.morphe.manager.R
3635import app.morphe.manager.domain.installer.InstallerManager
@@ -41,7 +40,10 @@ import app.morphe.manager.ui.screen.patcher.*
4140import app.morphe.manager.ui.screen.patcher.game.MiniGameState
4241import app.morphe.manager.ui.screen.settings.advanced.NotificationPermissionDialog
4342import app.morphe.manager.ui.screen.settings.system.InstallerSelectionDialog
43+ import app.morphe.manager.ui.screen.shared.LocalDialogSecondaryTextColor
4444import app.morphe.manager.ui.screen.shared.MorpheAnimations
45+ import app.morphe.manager.ui.screen.shared.MorpheDialog
46+ import app.morphe.manager.ui.screen.shared.MorpheDialogButtonRow
4547import app.morphe.manager.ui.viewmodel.InstallViewModel
4648import app.morphe.manager.ui.viewmodel.PatcherViewModel
4749import app.morphe.manager.util.APK_MIMETYPE
@@ -72,7 +74,9 @@ fun PatcherScreen(
7274 installViewModel : InstallViewModel = koinViewModel(),
7375 prefs : PreferencesManager = koinInject(),
7476 onBackgroundSpeedChange : (Float ) -> Unit = {},
75- onPatchingCompleted : () -> Unit = {}
77+ onPatchingCompleted : () -> Unit = {},
78+ onStartTour : () -> Unit = {},
79+ onDeclineTour : () -> Unit = {}
7680) {
7781 val context = LocalContext .current
7882 val view = LocalView .current
@@ -281,10 +285,11 @@ fun PatcherScreen(
281285 val errorMessage by remember { derivedStateOf { (installViewModel.installState as ? InstallViewModel .InstallState .Error )?.message } }
282286
283287 val showInstalledSourceConflictDialog = remember { mutableStateOf(false ) }
288+ val shouldPromptTour by patcherViewModel.shouldPromptTour.collectAsStateWithLifecycle()
284289
285290 LaunchedEffect (installState) {
286291 if (installState is InstallViewModel .InstallState .Installed ) {
287- patcherViewModel.triggerNotificationPromptIfNeeded ()
292+ patcherViewModel.triggerPostInstallPromptsIfNeeded ()
288293 }
289294 if (installState is InstallViewModel .InstallState .Conflict && autoHandleConflict) {
290295 showInstalledSourceConflictDialog.value = true
@@ -325,6 +330,41 @@ fun PatcherScreen(
325330 )
326331 }
327332
333+ // Tour prompt dialog shown after first successful install
334+ if (shouldPromptTour) {
335+ MorpheDialog (
336+ onDismissRequest = {
337+ patcherViewModel.consumeTourPrompt()
338+ onDeclineTour()
339+ },
340+ title = stringResource(R .string.tour_prompt_title),
341+ footer = {
342+ MorpheDialogButtonRow (
343+ primaryText = stringResource(R .string.tour_prompt_confirm),
344+ onPrimaryClick = {
345+ patcherViewModel.consumeTourPrompt()
346+ onStartTour()
347+ onBackClick()
348+ },
349+ secondaryText = stringResource(R .string.skip),
350+ onSecondaryClick = {
351+ patcherViewModel.consumeTourPrompt()
352+ onDeclineTour()
353+ onBackClick()
354+ }
355+ )
356+ }
357+ ) {
358+ Text (
359+ text = stringResource(R .string.tour_prompt_desc),
360+ style = MaterialTheme .typography.bodyLarge,
361+ color = LocalDialogSecondaryTextColor .current,
362+ textAlign = TextAlign .Center ,
363+ modifier = Modifier .fillMaxWidth()
364+ )
365+ }
366+ }
367+
328368 // Activity launcher for handling plugin activities or external installs
329369 val activityLauncher = rememberLauncherForActivityResult(
330370 contract = ActivityResultContracts .StartActivityForResult (),
0 commit comments