From 5d9dc872392027fa89459fada7783d2e5bf8e4b3 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Sun, 14 Dec 2025 17:48:34 +0900 Subject: [PATCH 01/11] =?UTF-8?q?sharedElement=E3=81=AB=E3=82=88=E3=82=8B?= =?UTF-8?q?=E3=82=A2=E3=83=8B=E3=83=A1=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notificationnotifier/ui/common/AppList.kt | 30 ++++++++- .../ui/screen/app/AppScreen.kt | 67 +++++++++++-------- .../ui/screen/detail/DetailScreen.kt | 44 +++++++++--- .../ui/screen/main/MainScreen.kt | 12 +++- .../ui/screen/target/TargetScreen.kt | 20 +++++- .../notificationnotifier/ui/util/Sample.kt | 17 +++++ 6 files changed, 146 insertions(+), 44 deletions(-) diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppList.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppList.kt index 0ce248d9..aee0f3d7 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppList.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppList.kt @@ -1,5 +1,7 @@ package me.nya_n.notificationnotifier.ui.common +import androidx.compose.animation.AnimatedVisibilityScope +import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box @@ -26,6 +28,8 @@ import me.nya_n.notificationnotifier.ui.theme.AppTheme @Composable fun AppList( + sharedTransitionScope: SharedTransitionScope? = null, + animatedVisibilityScope: AnimatedVisibilityScope? = null, items: List, onAppSelected: (InstalledApp) -> Unit ) { @@ -36,7 +40,14 @@ fun AppList( items( count = items.size, key = { "($it)${items[it]}" }, - itemContent = { AppListItem(app = items[it], onAppSelected = onAppSelected) } + itemContent = { + AppListItem( + sharedTransitionScope = sharedTransitionScope, + animatedVisibilityScope = animatedVisibilityScope, + app = items[it], + onAppSelected = onAppSelected + ) + } ) } } @@ -44,6 +55,8 @@ fun AppList( @Composable fun AppListItem( + sharedTransitionScope: SharedTransitionScope?, + animatedVisibilityScope: AnimatedVisibilityScope?, app: InstalledApp, onAppSelected: (InstalledApp) -> Unit ) { @@ -62,7 +75,20 @@ fun AppListItem( ) { GrayScaleAppIcon( app = app, - modifier = Modifier.size(56.dp), + modifier = Modifier + .size(56.dp) + .then( + if (sharedTransitionScope != null && animatedVisibilityScope != null) { + with(sharedTransitionScope) { + Modifier.sharedElement( + rememberSharedContentState(key = "GrayScaleAppIcon_${app.packageName}"), + animatedVisibilityScope = animatedVisibilityScope + ) + } + } else { + Modifier + } + ), isInListView = true ) Box( diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/app/AppScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/app/AppScreen.kt index 3170eefe..3489697b 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/app/AppScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/app/AppScreen.kt @@ -3,6 +3,7 @@ package me.nya_n.notificationnotifier.ui.screen.app import android.content.Intent import android.provider.Settings import androidx.activity.compose.LocalActivity +import androidx.compose.animation.SharedTransitionLayout import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideOutHorizontally import androidx.compose.runtime.Composable @@ -75,35 +76,45 @@ fun AppScreen( } } - NavHost( - navController = navController, - startDestination = Screen.Main.name, - enterTransition = { - slideInHorizontally(initialOffsetX = { it }) - }, - exitTransition = { - slideOutHorizontally(targetOffsetX = { -it }) - }, - popEnterTransition = { - slideInHorizontally(initialOffsetX = { -it }) - }, - popExitTransition = { - slideOutHorizontally(targetOffsetX = { it }) - }, - ) { - composable(Screen.Main.route) { MainScreen(navController) } - composable(Screen.License.route) { LicenseScreen(navController) } - composable(Screen.Detail.route) { - val app = Gson().fromJson( - it.arguments?.getString("app"), - InstalledApp::class.java - ) - DetailScreen( - navController = navController, - app = app - ) + SharedTransitionLayout { + NavHost( + navController = navController, + startDestination = Screen.Main.name, + enterTransition = { + slideInHorizontally(initialOffsetX = { it }) + }, + exitTransition = { + slideOutHorizontally(targetOffsetX = { -it }) + }, + popEnterTransition = { + slideInHorizontally(initialOffsetX = { -it }) + }, + popExitTransition = { + slideOutHorizontally(targetOffsetX = { it }) + }, + ) { + composable(Screen.Main.route) { + MainScreen( + navController = navController, + sharedTransitionScope = this@SharedTransitionLayout, + animatedVisibilityScope = this@composable + ) + } + composable(Screen.License.route) { LicenseScreen(navController) } + composable(Screen.Detail.route) { + val app = Gson().fromJson( + it.arguments?.getString("app"), + InstalledApp::class.java + ) + DetailScreen( + navController = navController, + sharedTransitionScope = this@SharedTransitionLayout, + animatedVisibilityScope = this@composable, + app = app + ) + } + composable(Screen.About.route) { AboutScreen() } } - composable(Screen.About.route) { AboutScreen() } } } } diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt index debfb038..3fc814ef 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt @@ -1,5 +1,7 @@ package me.nya_n.notificationnotifier.ui.screen.detail +import androidx.compose.animation.AnimatedVisibilityScope +import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -41,7 +43,7 @@ import me.nya_n.notificationnotifier.ui.common.Category import me.nya_n.notificationnotifier.ui.common.GrayScaleAppIcon import me.nya_n.notificationnotifier.ui.common.SnackbarMessage import me.nya_n.notificationnotifier.ui.theme.AppColors -import me.nya_n.notificationnotifier.ui.theme.AppTheme +import me.nya_n.notificationnotifier.ui.util.AppPreview import org.koin.androidx.compose.koinViewModel import org.koin.core.parameter.parametersOf @@ -49,6 +51,8 @@ import org.koin.core.parameter.parametersOf @Composable fun DetailScreen( navController: NavController, + sharedTransitionScope: SharedTransitionScope, + animatedVisibilityScope: AnimatedVisibilityScope, app: InstalledApp, viewModel: DetailViewModel = koinViewModel { parametersOf(app) }, ) { @@ -62,6 +66,8 @@ fun DetailScreen( } DetailContent( snackbarHostState = snackbarHostState, + sharedTransitionScope = sharedTransitionScope, + animatedVisibilityScope = animatedVisibilityScope, app = app, condition = uiState.condition, onBack = { @@ -82,6 +88,8 @@ fun DetailScreen( @Composable fun DetailContent( snackbarHostState: SnackbarHostState, + sharedTransitionScope: SharedTransitionScope, + animatedVisibilityScope: AnimatedVisibilityScope, app: InstalledApp, condition: String, onBack: () -> Unit, @@ -99,7 +107,12 @@ fun DetailContent( .padding(it) .padding(horizontal = 20.dp), ) { - AppInfo(app, onDeleteApp) + AppInfo( + sharedTransitionScope = sharedTransitionScope, + animatedVisibilityScope = animatedVisibilityScope, + app = app, + onDeleteApp = onDeleteApp + ) NotificationSetting(condition, onConditionChanged) } } @@ -110,6 +123,8 @@ fun DetailContent( */ @Composable private fun AppInfo( + sharedTransitionScope: SharedTransitionScope, + animatedVisibilityScope: AnimatedVisibilityScope, app: InstalledApp, onDeleteApp: () -> Unit ) { @@ -118,11 +133,18 @@ private fun AppInfo( modifier = Modifier.padding(vertical = 20.dp) ) { Row { - GrayScaleAppIcon( - app = app, - modifier = Modifier.size(80.dp), - isInListView = false - ) + with(sharedTransitionScope) { + GrayScaleAppIcon( + app = app, + modifier = Modifier + .size(80.dp) + .sharedElement( + rememberSharedContentState(key = "GrayScaleAppIcon_${app.packageName}"), + animatedVisibilityScope = animatedVisibilityScope, + ), + isInListView = false + ) + } Box( modifier = Modifier .fillMaxWidth() @@ -189,9 +211,11 @@ private fun NotificationSetting( @Composable private fun DetailPreview() { val snackbarHostState = remember { SnackbarHostState() } - AppTheme { + AppPreview { sharedTransitionScope, animatedVisibilityScope -> DetailContent( snackbarHostState = snackbarHostState, + sharedTransitionScope = sharedTransitionScope, + animatedVisibilityScope = animatedVisibilityScope, app = InstalledApp("Sample App Name", "example.sample.test"), condition = "^.*$", onBack = { }, @@ -205,9 +229,11 @@ private fun DetailPreview() { @Composable private fun LongAppNameDetailPreview() { val snackbarHostState = remember { SnackbarHostState() } - AppTheme { + AppPreview { sharedTransitionScope, animatedVisibilityScope -> DetailContent( snackbarHostState = snackbarHostState, + sharedTransitionScope = sharedTransitionScope, + animatedVisibilityScope = animatedVisibilityScope, app = InstalledApp( "Sample App Name So Loooooooooooooooooooong", "example.sample.test" diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt index eee4589e..51c56531 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt @@ -2,6 +2,8 @@ package me.nya_n.notificationnotifier.ui.screen.main import androidx.activity.compose.BackHandler import androidx.activity.compose.LocalActivity +import androidx.compose.animation.AnimatedVisibilityScope +import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding @@ -37,7 +39,11 @@ import me.nya_n.notificationnotifier.ui.theme.AppTheme /** メイン画面 */ @Composable -fun MainScreen(navController: NavController) { +fun MainScreen( + navController: NavController, + sharedTransitionScope: SharedTransitionScope, + animatedVisibilityScope: AnimatedVisibilityScope, +) { val snackbarHostState = remember { SnackbarHostState() } val activity = LocalActivity.current val scope = rememberCoroutineScope() @@ -45,7 +51,9 @@ fun MainScreen(navController: NavController) { TabItem(stringResource(id = R.string.targets), Icons.Outlined.NotificationsActive) { TargetScreen( navController = navController, - snackbarHostState = snackbarHostState + snackbarHostState = snackbarHostState, + sharedTransitionScope = sharedTransitionScope, + animatedVisibilityScope = animatedVisibilityScope ) }, TabItem(stringResource(id = R.string.apps), Icons.AutoMirrored.Rounded.List) { diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/target/TargetScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/target/TargetScreen.kt index ec8c9e96..f7a1a1b7 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/target/TargetScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/target/TargetScreen.kt @@ -1,5 +1,7 @@ package me.nya_n.notificationnotifier.ui.screen.target +import androidx.compose.animation.AnimatedVisibilityScope +import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.CircularProgressIndicator @@ -16,7 +18,7 @@ import me.nya_n.notificationnotifier.model.InstalledApp import me.nya_n.notificationnotifier.ui.common.AppList import me.nya_n.notificationnotifier.ui.common.SnackbarMessage import me.nya_n.notificationnotifier.ui.screen.app.Screen -import me.nya_n.notificationnotifier.ui.theme.AppTheme +import me.nya_n.notificationnotifier.ui.util.AppPreview import org.koin.androidx.compose.koinViewModel /** 通知送信ターゲットに追加したアプリリスト */ @@ -24,6 +26,8 @@ import org.koin.androidx.compose.koinViewModel fun TargetScreen( navController: NavController, snackbarHostState: SnackbarHostState, + sharedTransitionScope: SharedTransitionScope, + animatedVisibilityScope: AnimatedVisibilityScope, viewModel: TargetViewModel = koinViewModel() ) { val uiState by viewModel.uiState.collectAsState() @@ -37,6 +41,8 @@ fun TargetScreen( viewModel.messageShown() } TargetContent( + sharedTransitionScope = sharedTransitionScope, + animatedVisibilityScope = animatedVisibilityScope, items = uiState.items, isLoading = uiState.isLoading ) { @@ -46,6 +52,8 @@ fun TargetScreen( @Composable fun TargetContent( + sharedTransitionScope: SharedTransitionScope, + animatedVisibilityScope: AnimatedVisibilityScope, items: List, isLoading: Boolean, onAppSelected: (InstalledApp) -> Unit @@ -59,6 +67,8 @@ fun TargetContent( } } else { AppList( + sharedTransitionScope = sharedTransitionScope, + animatedVisibilityScope = animatedVisibilityScope, items = items, onAppSelected = onAppSelected ) @@ -73,8 +83,10 @@ private fun TargetPreview() { InstalledApp("Sample App", "me.nya_n.notificationnotifier"), InstalledApp("Sample App", "me.nya_n.notificationnotifier"), ) - AppTheme { + AppPreview { sharedTransitionScope, animatedVisibilityScope -> TargetContent( + sharedTransitionScope = sharedTransitionScope, + animatedVisibilityScope = animatedVisibilityScope, items = items, isLoading = false, onAppSelected = { } @@ -85,8 +97,10 @@ private fun TargetPreview() { @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) @Composable private fun LoadingTargetPreview() { - AppTheme { + AppPreview { sharedTransitionScope, animatedVisibilityScope -> TargetContent( + sharedTransitionScope = sharedTransitionScope, + animatedVisibilityScope = animatedVisibilityScope, items = listOf(), isLoading = true, onAppSelected = { } diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/Sample.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/Sample.kt index e63db8cc..63c00c73 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/Sample.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/Sample.kt @@ -1,6 +1,12 @@ package me.nya_n.notificationnotifier.ui.util +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.AnimatedVisibilityScope +import androidx.compose.animation.SharedTransitionLayout +import androidx.compose.animation.SharedTransitionScope +import androidx.compose.runtime.Composable import me.nya_n.notificationnotifier.model.InstalledApp +import me.nya_n.notificationnotifier.ui.theme.AppTheme object Sample { val items: List @@ -9,4 +15,15 @@ object Sample { InstalledApp("Sample App ${it + 1}", "me.nya_n.notificationnotifier") } } +} + +@Composable +fun AppPreview(content: @Composable (SharedTransitionScope, AnimatedVisibilityScope) -> Unit) { + AppTheme { + SharedTransitionLayout { + AnimatedVisibility(visible = true) { + content(this@SharedTransitionLayout, this@AnimatedVisibility) + } + } + } } \ No newline at end of file From 58248c1e957f3d8ab226d50edb606d489797d036 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Sun, 14 Dec 2025 17:59:50 +0900 Subject: [PATCH 02/11] =?UTF-8?q?SharedTransitionScope,=20AnimatedVisibili?= =?UTF-8?q?tyScope=E3=82=92CompositionLocal=E3=81=A7=E6=B8=A1=E3=81=99?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notificationnotifier/ui/common/AppList.kt | 13 ++--- .../ui/screen/app/AppScreen.kt | 29 ++++++---- .../ui/screen/detail/DetailScreen.kt | 57 +++++++++---------- .../ui/screen/main/MainScreen.kt | 12 +--- .../ui/screen/target/TargetScreen.kt | 20 +------ .../ui/util/CompositionLocals.kt | 8 +++ .../notificationnotifier/ui/util/Sample.kt | 17 ------ 7 files changed, 62 insertions(+), 94 deletions(-) create mode 100644 AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/CompositionLocals.kt diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppList.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppList.kt index aee0f3d7..302a015f 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppList.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppList.kt @@ -1,7 +1,5 @@ package me.nya_n.notificationnotifier.ui.common -import androidx.compose.animation.AnimatedVisibilityScope -import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box @@ -25,11 +23,11 @@ import androidx.compose.ui.unit.dp import me.nya_n.notificationnotifier.model.InstalledApp import me.nya_n.notificationnotifier.ui.R import me.nya_n.notificationnotifier.ui.theme.AppTheme +import me.nya_n.notificationnotifier.ui.util.LocalAnimatedVisibilityScope +import me.nya_n.notificationnotifier.ui.util.LocalSharedTransitionScope @Composable fun AppList( - sharedTransitionScope: SharedTransitionScope? = null, - animatedVisibilityScope: AnimatedVisibilityScope? = null, items: List, onAppSelected: (InstalledApp) -> Unit ) { @@ -42,8 +40,6 @@ fun AppList( key = { "($it)${items[it]}" }, itemContent = { AppListItem( - sharedTransitionScope = sharedTransitionScope, - animatedVisibilityScope = animatedVisibilityScope, app = items[it], onAppSelected = onAppSelected ) @@ -55,12 +51,13 @@ fun AppList( @Composable fun AppListItem( - sharedTransitionScope: SharedTransitionScope?, - animatedVisibilityScope: AnimatedVisibilityScope?, app: InstalledApp, onAppSelected: (InstalledApp) -> Unit ) { + val sharedTransitionScope = LocalSharedTransitionScope.current + val animatedVisibilityScope = LocalAnimatedVisibilityScope.current val interactionSource = remember { MutableInteractionSource() } + Box( modifier = Modifier .fillMaxWidth() diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/app/AppScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/app/AppScreen.kt index 3489697b..cd466a89 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/app/AppScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/app/AppScreen.kt @@ -7,6 +7,7 @@ import androidx.compose.animation.SharedTransitionLayout import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideOutHorizontally import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -25,6 +26,8 @@ import me.nya_n.notificationnotifier.ui.screen.detail.DetailScreen import me.nya_n.notificationnotifier.ui.screen.license.LicenseScreen import me.nya_n.notificationnotifier.ui.screen.main.MainScreen import me.nya_n.notificationnotifier.ui.theme.AppTheme +import me.nya_n.notificationnotifier.ui.util.LocalAnimatedVisibilityScope +import me.nya_n.notificationnotifier.ui.util.LocalSharedTransitionScope import org.koin.androidx.compose.koinViewModel import java.net.URLEncoder @@ -94,11 +97,12 @@ fun AppScreen( }, ) { composable(Screen.Main.route) { - MainScreen( - navController = navController, - sharedTransitionScope = this@SharedTransitionLayout, - animatedVisibilityScope = this@composable - ) + CompositionLocalProvider( + LocalSharedTransitionScope provides this@SharedTransitionLayout, + LocalAnimatedVisibilityScope provides this@composable + ) { + MainScreen(navController = navController) + } } composable(Screen.License.route) { LicenseScreen(navController) } composable(Screen.Detail.route) { @@ -106,12 +110,15 @@ fun AppScreen( it.arguments?.getString("app"), InstalledApp::class.java ) - DetailScreen( - navController = navController, - sharedTransitionScope = this@SharedTransitionLayout, - animatedVisibilityScope = this@composable, - app = app - ) + CompositionLocalProvider( + LocalSharedTransitionScope provides this@SharedTransitionLayout, + LocalAnimatedVisibilityScope provides this@composable + ) { + DetailScreen( + navController = navController, + app = app + ) + } } composable(Screen.About.route) { AboutScreen() } } diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt index 3fc814ef..1bb9bbdf 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt @@ -1,7 +1,5 @@ package me.nya_n.notificationnotifier.ui.screen.detail -import androidx.compose.animation.AnimatedVisibilityScope -import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -43,7 +41,9 @@ import me.nya_n.notificationnotifier.ui.common.Category import me.nya_n.notificationnotifier.ui.common.GrayScaleAppIcon import me.nya_n.notificationnotifier.ui.common.SnackbarMessage import me.nya_n.notificationnotifier.ui.theme.AppColors -import me.nya_n.notificationnotifier.ui.util.AppPreview +import me.nya_n.notificationnotifier.ui.theme.AppTheme +import me.nya_n.notificationnotifier.ui.util.LocalAnimatedVisibilityScope +import me.nya_n.notificationnotifier.ui.util.LocalSharedTransitionScope import org.koin.androidx.compose.koinViewModel import org.koin.core.parameter.parametersOf @@ -51,8 +51,6 @@ import org.koin.core.parameter.parametersOf @Composable fun DetailScreen( navController: NavController, - sharedTransitionScope: SharedTransitionScope, - animatedVisibilityScope: AnimatedVisibilityScope, app: InstalledApp, viewModel: DetailViewModel = koinViewModel { parametersOf(app) }, ) { @@ -66,8 +64,6 @@ fun DetailScreen( } DetailContent( snackbarHostState = snackbarHostState, - sharedTransitionScope = sharedTransitionScope, - animatedVisibilityScope = animatedVisibilityScope, app = app, condition = uiState.condition, onBack = { @@ -88,8 +84,6 @@ fun DetailScreen( @Composable fun DetailContent( snackbarHostState: SnackbarHostState, - sharedTransitionScope: SharedTransitionScope, - animatedVisibilityScope: AnimatedVisibilityScope, app: InstalledApp, condition: String, onBack: () -> Unit, @@ -108,8 +102,6 @@ fun DetailContent( .padding(horizontal = 20.dp), ) { AppInfo( - sharedTransitionScope = sharedTransitionScope, - animatedVisibilityScope = animatedVisibilityScope, app = app, onDeleteApp = onDeleteApp ) @@ -123,28 +115,35 @@ fun DetailContent( */ @Composable private fun AppInfo( - sharedTransitionScope: SharedTransitionScope, - animatedVisibilityScope: AnimatedVisibilityScope, app: InstalledApp, onDeleteApp: () -> Unit ) { + val sharedTransitionScope = LocalSharedTransitionScope.current + val animatedVisibilityScope = LocalAnimatedVisibilityScope.current + Category(name = stringResource(id = R.string.app_info)) Box( modifier = Modifier.padding(vertical = 20.dp) ) { Row { - with(sharedTransitionScope) { - GrayScaleAppIcon( - app = app, - modifier = Modifier - .size(80.dp) - .sharedElement( - rememberSharedContentState(key = "GrayScaleAppIcon_${app.packageName}"), - animatedVisibilityScope = animatedVisibilityScope, - ), - isInListView = false - ) - } + GrayScaleAppIcon( + app = app, + modifier = Modifier + .size(80.dp) + .then( + if (sharedTransitionScope != null && animatedVisibilityScope != null) { + with(sharedTransitionScope) { + Modifier.sharedElement( + rememberSharedContentState(key = "GrayScaleAppIcon_${app.packageName}"), + animatedVisibilityScope = animatedVisibilityScope + ) + } + } else { + Modifier + } + ), + isInListView = false + ) Box( modifier = Modifier .fillMaxWidth() @@ -211,11 +210,9 @@ private fun NotificationSetting( @Composable private fun DetailPreview() { val snackbarHostState = remember { SnackbarHostState() } - AppPreview { sharedTransitionScope, animatedVisibilityScope -> + AppTheme { DetailContent( snackbarHostState = snackbarHostState, - sharedTransitionScope = sharedTransitionScope, - animatedVisibilityScope = animatedVisibilityScope, app = InstalledApp("Sample App Name", "example.sample.test"), condition = "^.*$", onBack = { }, @@ -229,11 +226,9 @@ private fun DetailPreview() { @Composable private fun LongAppNameDetailPreview() { val snackbarHostState = remember { SnackbarHostState() } - AppPreview { sharedTransitionScope, animatedVisibilityScope -> + AppTheme { DetailContent( snackbarHostState = snackbarHostState, - sharedTransitionScope = sharedTransitionScope, - animatedVisibilityScope = animatedVisibilityScope, app = InstalledApp( "Sample App Name So Loooooooooooooooooooong", "example.sample.test" diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt index 51c56531..eee4589e 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt @@ -2,8 +2,6 @@ package me.nya_n.notificationnotifier.ui.screen.main import androidx.activity.compose.BackHandler import androidx.activity.compose.LocalActivity -import androidx.compose.animation.AnimatedVisibilityScope -import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding @@ -39,11 +37,7 @@ import me.nya_n.notificationnotifier.ui.theme.AppTheme /** メイン画面 */ @Composable -fun MainScreen( - navController: NavController, - sharedTransitionScope: SharedTransitionScope, - animatedVisibilityScope: AnimatedVisibilityScope, -) { +fun MainScreen(navController: NavController) { val snackbarHostState = remember { SnackbarHostState() } val activity = LocalActivity.current val scope = rememberCoroutineScope() @@ -51,9 +45,7 @@ fun MainScreen( TabItem(stringResource(id = R.string.targets), Icons.Outlined.NotificationsActive) { TargetScreen( navController = navController, - snackbarHostState = snackbarHostState, - sharedTransitionScope = sharedTransitionScope, - animatedVisibilityScope = animatedVisibilityScope + snackbarHostState = snackbarHostState ) }, TabItem(stringResource(id = R.string.apps), Icons.AutoMirrored.Rounded.List) { diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/target/TargetScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/target/TargetScreen.kt index f7a1a1b7..ec8c9e96 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/target/TargetScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/target/TargetScreen.kt @@ -1,7 +1,5 @@ package me.nya_n.notificationnotifier.ui.screen.target -import androidx.compose.animation.AnimatedVisibilityScope -import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.CircularProgressIndicator @@ -18,7 +16,7 @@ import me.nya_n.notificationnotifier.model.InstalledApp import me.nya_n.notificationnotifier.ui.common.AppList import me.nya_n.notificationnotifier.ui.common.SnackbarMessage import me.nya_n.notificationnotifier.ui.screen.app.Screen -import me.nya_n.notificationnotifier.ui.util.AppPreview +import me.nya_n.notificationnotifier.ui.theme.AppTheme import org.koin.androidx.compose.koinViewModel /** 通知送信ターゲットに追加したアプリリスト */ @@ -26,8 +24,6 @@ import org.koin.androidx.compose.koinViewModel fun TargetScreen( navController: NavController, snackbarHostState: SnackbarHostState, - sharedTransitionScope: SharedTransitionScope, - animatedVisibilityScope: AnimatedVisibilityScope, viewModel: TargetViewModel = koinViewModel() ) { val uiState by viewModel.uiState.collectAsState() @@ -41,8 +37,6 @@ fun TargetScreen( viewModel.messageShown() } TargetContent( - sharedTransitionScope = sharedTransitionScope, - animatedVisibilityScope = animatedVisibilityScope, items = uiState.items, isLoading = uiState.isLoading ) { @@ -52,8 +46,6 @@ fun TargetScreen( @Composable fun TargetContent( - sharedTransitionScope: SharedTransitionScope, - animatedVisibilityScope: AnimatedVisibilityScope, items: List, isLoading: Boolean, onAppSelected: (InstalledApp) -> Unit @@ -67,8 +59,6 @@ fun TargetContent( } } else { AppList( - sharedTransitionScope = sharedTransitionScope, - animatedVisibilityScope = animatedVisibilityScope, items = items, onAppSelected = onAppSelected ) @@ -83,10 +73,8 @@ private fun TargetPreview() { InstalledApp("Sample App", "me.nya_n.notificationnotifier"), InstalledApp("Sample App", "me.nya_n.notificationnotifier"), ) - AppPreview { sharedTransitionScope, animatedVisibilityScope -> + AppTheme { TargetContent( - sharedTransitionScope = sharedTransitionScope, - animatedVisibilityScope = animatedVisibilityScope, items = items, isLoading = false, onAppSelected = { } @@ -97,10 +85,8 @@ private fun TargetPreview() { @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) @Composable private fun LoadingTargetPreview() { - AppPreview { sharedTransitionScope, animatedVisibilityScope -> + AppTheme { TargetContent( - sharedTransitionScope = sharedTransitionScope, - animatedVisibilityScope = animatedVisibilityScope, items = listOf(), isLoading = true, onAppSelected = { } diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/CompositionLocals.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/CompositionLocals.kt new file mode 100644 index 00000000..35395a7a --- /dev/null +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/CompositionLocals.kt @@ -0,0 +1,8 @@ +package me.nya_n.notificationnotifier.ui.util + +import androidx.compose.animation.AnimatedVisibilityScope +import androidx.compose.animation.SharedTransitionScope +import androidx.compose.runtime.compositionLocalOf + +val LocalSharedTransitionScope = compositionLocalOf { null } +val LocalAnimatedVisibilityScope = compositionLocalOf { null } \ No newline at end of file diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/Sample.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/Sample.kt index 63c00c73..80aa4262 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/Sample.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/Sample.kt @@ -1,12 +1,6 @@ package me.nya_n.notificationnotifier.ui.util -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.AnimatedVisibilityScope -import androidx.compose.animation.SharedTransitionLayout -import androidx.compose.animation.SharedTransitionScope -import androidx.compose.runtime.Composable import me.nya_n.notificationnotifier.model.InstalledApp -import me.nya_n.notificationnotifier.ui.theme.AppTheme object Sample { val items: List @@ -16,14 +10,3 @@ object Sample { } } } - -@Composable -fun AppPreview(content: @Composable (SharedTransitionScope, AnimatedVisibilityScope) -> Unit) { - AppTheme { - SharedTransitionLayout { - AnimatedVisibility(visible = true) { - content(this@SharedTransitionLayout, this@AnimatedVisibility) - } - } - } -} \ No newline at end of file From a846f058ce544dff0341ba4bf718f5f6ae1c6e5d Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Sun, 14 Dec 2025 18:32:12 +0900 Subject: [PATCH 03/11] =?UTF-8?q?rememberSharedContentState=E3=81=AEkey?= =?UTF-8?q?=E3=82=92=E7=B5=B1=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/me/nya_n/notificationnotifier/ui/common/AppList.kt | 3 ++- .../notificationnotifier/ui/screen/detail/DetailScreen.kt | 3 ++- .../me/nya_n/notificationnotifier/ui/util/Extensions.kt | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppList.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppList.kt index 302a015f..29887544 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppList.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppList.kt @@ -25,6 +25,7 @@ import me.nya_n.notificationnotifier.ui.R import me.nya_n.notificationnotifier.ui.theme.AppTheme import me.nya_n.notificationnotifier.ui.util.LocalAnimatedVisibilityScope import me.nya_n.notificationnotifier.ui.util.LocalSharedTransitionScope +import me.nya_n.notificationnotifier.ui.util.iconSharedTransitionKey @Composable fun AppList( @@ -78,7 +79,7 @@ fun AppListItem( if (sharedTransitionScope != null && animatedVisibilityScope != null) { with(sharedTransitionScope) { Modifier.sharedElement( - rememberSharedContentState(key = "GrayScaleAppIcon_${app.packageName}"), + rememberSharedContentState(key = app.iconSharedTransitionKey), animatedVisibilityScope = animatedVisibilityScope ) } diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt index 1bb9bbdf..17b7478f 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt @@ -44,6 +44,7 @@ import me.nya_n.notificationnotifier.ui.theme.AppColors import me.nya_n.notificationnotifier.ui.theme.AppTheme import me.nya_n.notificationnotifier.ui.util.LocalAnimatedVisibilityScope import me.nya_n.notificationnotifier.ui.util.LocalSharedTransitionScope +import me.nya_n.notificationnotifier.ui.util.iconSharedTransitionKey import org.koin.androidx.compose.koinViewModel import org.koin.core.parameter.parametersOf @@ -134,7 +135,7 @@ private fun AppInfo( if (sharedTransitionScope != null && animatedVisibilityScope != null) { with(sharedTransitionScope) { Modifier.sharedElement( - rememberSharedContentState(key = "GrayScaleAppIcon_${app.packageName}"), + rememberSharedContentState(key = app.iconSharedTransitionKey), animatedVisibilityScope = animatedVisibilityScope ) } diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/Extensions.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/Extensions.kt index ff8ebe4f..9ba46f2e 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/Extensions.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/util/Extensions.kt @@ -2,6 +2,7 @@ package me.nya_n.notificationnotifier.ui.util import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalInspectionMode +import me.nya_n.notificationnotifier.model.InstalledApp /** 現在Preview中か? * - Composableな関数内でのみ使用可能 @@ -13,3 +14,6 @@ fun isInPreview(): Boolean { val isForcePreview = false return LocalInspectionMode.current || isForcePreview } + +val InstalledApp.iconSharedTransitionKey: String + get() = "appIcon_$packageName" From 5c739952370e329ecffd7ad911918b5b6c680afb Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Sun, 14 Dec 2025 23:18:36 +0900 Subject: [PATCH 04/11] =?UTF-8?q?=E8=A9=B3=E7=B4=B0=E3=81=AE=E7=94=BB?= =?UTF-8?q?=E9=9D=A2=E9=81=B7=E7=A7=BB=E3=82=B0=E3=83=A9=E3=83=95=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/screen/app/AppScreen.kt | 26 +++--------- .../ui/screen/main/MainScreen.kt | 41 +++++++++++++++++-- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/app/AppScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/app/AppScreen.kt index cd466a89..b90889ba 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/app/AppScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/app/AppScreen.kt @@ -18,15 +18,12 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import com.google.gson.Gson -import me.nya_n.notificationnotifier.model.InstalledApp import me.nya_n.notificationnotifier.ui.common.RequireNotificationPermissionDialog import me.nya_n.notificationnotifier.ui.common.RequirePackageVisibilityDialog import me.nya_n.notificationnotifier.ui.screen.about.AboutScreen -import me.nya_n.notificationnotifier.ui.screen.detail.DetailScreen import me.nya_n.notificationnotifier.ui.screen.license.LicenseScreen import me.nya_n.notificationnotifier.ui.screen.main.MainScreen import me.nya_n.notificationnotifier.ui.theme.AppTheme -import me.nya_n.notificationnotifier.ui.util.LocalAnimatedVisibilityScope import me.nya_n.notificationnotifier.ui.util.LocalSharedTransitionScope import org.koin.androidx.compose.koinViewModel import java.net.URLEncoder @@ -98,28 +95,12 @@ fun AppScreen( ) { composable(Screen.Main.route) { CompositionLocalProvider( - LocalSharedTransitionScope provides this@SharedTransitionLayout, - LocalAnimatedVisibilityScope provides this@composable + LocalSharedTransitionScope provides this@SharedTransitionLayout ) { MainScreen(navController = navController) } } composable(Screen.License.route) { LicenseScreen(navController) } - composable(Screen.Detail.route) { - val app = Gson().fromJson( - it.arguments?.getString("app"), - InstalledApp::class.java - ) - CompositionLocalProvider( - LocalSharedTransitionScope provides this@SharedTransitionLayout, - LocalAnimatedVisibilityScope provides this@composable - ) { - DetailScreen( - navController = navController, - app = app - ) - } - } composable(Screen.About.route) { AboutScreen() } } } @@ -131,7 +112,10 @@ sealed class Screen( val name: String, private val args: List = emptyList() ) { - data object Main : Screen("main") + data object Main : Screen("main") { + data object Targets : Screen("targets") + data object Detail : Screen("detail", listOf("app")) + } data object License : Screen("license") data object Detail : Screen("detail", listOf("app")) data object About : Screen("about") diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt index eee4589e..b6d4aedc 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt @@ -19,6 +19,7 @@ import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier @@ -26,14 +27,22 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.navigation.NavController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import com.google.gson.Gson import kotlinx.coroutines.launch +import me.nya_n.notificationnotifier.model.InstalledApp import me.nya_n.notificationnotifier.ui.R import me.nya_n.notificationnotifier.ui.common.AppScaffold import me.nya_n.notificationnotifier.ui.common.EmptyView +import me.nya_n.notificationnotifier.ui.screen.app.Screen +import me.nya_n.notificationnotifier.ui.screen.detail.DetailScreen import me.nya_n.notificationnotifier.ui.screen.selection.SelectionScreen import me.nya_n.notificationnotifier.ui.screen.settings.SettingsScreen import me.nya_n.notificationnotifier.ui.screen.target.TargetScreen import me.nya_n.notificationnotifier.ui.theme.AppTheme +import me.nya_n.notificationnotifier.ui.util.LocalAnimatedVisibilityScope /** メイン画面 */ @Composable @@ -43,10 +52,36 @@ fun MainScreen(navController: NavController) { val scope = rememberCoroutineScope() val tabItems = listOf( TabItem(stringResource(id = R.string.targets), Icons.Outlined.NotificationsActive) { - TargetScreen( + val navController = rememberNavController() + NavHost( navController = navController, - snackbarHostState = snackbarHostState - ) + startDestination = Screen.Main.Targets.name + ) { + composable(Screen.Main.Targets.route) { + CompositionLocalProvider( + LocalAnimatedVisibilityScope provides this@composable + ) { + TargetScreen( + navController = navController, + snackbarHostState = snackbarHostState + ) + } + } + composable(Screen.Main.Detail.route) { + val app = Gson().fromJson( + it.arguments?.getString("app"), + InstalledApp::class.java + ) + CompositionLocalProvider( + LocalAnimatedVisibilityScope provides this@composable + ) { + DetailScreen( + navController = navController, + app = app + ) + } + } + } }, TabItem(stringResource(id = R.string.apps), Icons.AutoMirrored.Rounded.List) { SelectionScreen(snackbarHostState = snackbarHostState) From 221d080691547b3f9c40bdf0ec3290f8f57a84b4 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 18 Dec 2025 03:11:55 +0900 Subject: [PATCH 05/11] =?UTF-8?q?=E9=87=8D=E8=A4=87=E3=81=97=E3=81=A6?= =?UTF-8?q?=E3=82=8BScaffold=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/screen/detail/DetailScreen.kt | 38 +++++-------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt index 17b7478f..e109b188 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/detail/DetailScreen.kt @@ -36,7 +36,6 @@ import androidx.navigation.NavController import me.nya_n.notificationnotifier.model.InstalledApp import me.nya_n.notificationnotifier.ui.R import me.nya_n.notificationnotifier.ui.common.AppOutlinedButton -import me.nya_n.notificationnotifier.ui.common.AppScaffold import me.nya_n.notificationnotifier.ui.common.Category import me.nya_n.notificationnotifier.ui.common.GrayScaleAppIcon import me.nya_n.notificationnotifier.ui.common.SnackbarMessage @@ -64,12 +63,8 @@ fun DetailScreen( viewModel.messageShown() } DetailContent( - snackbarHostState = snackbarHostState, app = app, condition = uiState.condition, - onBack = { - navController.popBackStack() - }, onDeleteApp = { viewModel.deleteTarget() navController.previousBackStackEntry?.apply { @@ -84,30 +79,21 @@ fun DetailScreen( /** 詳細画面のコンテンツ本体 */ @Composable fun DetailContent( - snackbarHostState: SnackbarHostState, app: InstalledApp, condition: String, - onBack: () -> Unit, onDeleteApp: () -> Unit, onConditionChanged: (String) -> Unit ) { - AppScaffold( - snackbarHostState = snackbarHostState, - hasBackContent = true, - onBack = onBack + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 20.dp), ) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(it) - .padding(horizontal = 20.dp), - ) { - AppInfo( - app = app, - onDeleteApp = onDeleteApp - ) - NotificationSetting(condition, onConditionChanged) - } + AppInfo( + app = app, + onDeleteApp = onDeleteApp + ) + NotificationSetting(condition, onConditionChanged) } } @@ -210,13 +196,10 @@ private fun NotificationSetting( @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) @Composable private fun DetailPreview() { - val snackbarHostState = remember { SnackbarHostState() } AppTheme { DetailContent( - snackbarHostState = snackbarHostState, app = InstalledApp("Sample App Name", "example.sample.test"), condition = "^.*$", - onBack = { }, onDeleteApp = { }, onConditionChanged = { } ) @@ -226,16 +209,13 @@ private fun DetailPreview() { @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) @Composable private fun LongAppNameDetailPreview() { - val snackbarHostState = remember { SnackbarHostState() } AppTheme { DetailContent( - snackbarHostState = snackbarHostState, app = InstalledApp( "Sample App Name So Loooooooooooooooooooong", "example.sample.test" ), condition = "", - onBack = { }, onDeleteApp = { }, onConditionChanged = { } ) From 79d2ccb802bd02f58211c1c838f5cb6bea14fbe0 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 18 Dec 2025 03:27:59 +0900 Subject: [PATCH 06/11] =?UTF-8?q?hasBackContent=E3=82=92=E3=82=84=E3=82=81?= =?UTF-8?q?=E3=81=A6onBack=E3=81=8Cnull=E3=81=8B=E3=81=A9=E3=81=86?= =?UTF-8?q?=E3=81=8B=E3=81=A7=E5=88=A4=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nya_n/notificationnotifier/ui/common/AppScaffold.kt | 8 ++------ .../me/nya_n/notificationnotifier/ui/common/TopBar.kt | 6 ++---- .../ui/screen/license/LicenseScreen.kt | 1 - .../me/nya_n/notificationnotifier/ScreenshotTest.kt | 1 - 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppScaffold.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppScaffold.kt index a5ff58da..2461eca1 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppScaffold.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/AppScaffold.kt @@ -18,17 +18,13 @@ import me.nya_n.notificationnotifier.ui.theme.AppTheme @Composable fun AppScaffold( snackbarHostState: SnackbarHostState, - hasBackContent: Boolean = false, - onBack: () -> Unit = { }, + onBack: (() -> Unit)? = null, bottomBar: @Composable () -> Unit = { }, content: @Composable (PaddingValues) -> Unit ) { Scaffold( topBar = { - TopBar( - hasBackContent = hasBackContent, - onBack = onBack - ) + TopBar(onBack = onBack) }, bottomBar = bottomBar, containerColor = MaterialTheme.colorScheme.secondary, diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/TopBar.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/TopBar.kt index 4b0c100f..dc663ad3 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/TopBar.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/TopBar.kt @@ -18,8 +18,7 @@ import me.nya_n.notificationnotifier.ui.theme.AppTheme @OptIn(ExperimentalMaterial3Api::class) @Composable fun TopBar( - hasBackContent: Boolean = false, - onBack: () -> Unit = { } + onBack: (() -> Unit)? = null ) { TopAppBar( title = { @@ -29,7 +28,7 @@ fun TopBar( ) }, navigationIcon = { - if (hasBackContent) { + if (onBack != null) { IconButton( onClick = onBack ) { @@ -59,7 +58,6 @@ private fun TopBarPreview() { private fun SubContentTopBarPreview() { AppTheme { TopBar( - hasBackContent = true, onBack = { } ) } diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/license/LicenseScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/license/LicenseScreen.kt index deebbb37..305ec4a6 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/license/LicenseScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/license/LicenseScreen.kt @@ -19,7 +19,6 @@ fun LicenseScreen(navController: NavController) { val snackbarHostState = remember { SnackbarHostState() } AppScaffold( snackbarHostState = snackbarHostState, - hasBackContent = true, onBack = { navController.popBackStack() } diff --git a/AndroidApp/ui/src/screenshotTest/kotlin/me/nya_n/notificationnotifier/ScreenshotTest.kt b/AndroidApp/ui/src/screenshotTest/kotlin/me/nya_n/notificationnotifier/ScreenshotTest.kt index a40f3442..be10f769 100644 --- a/AndroidApp/ui/src/screenshotTest/kotlin/me/nya_n/notificationnotifier/ScreenshotTest.kt +++ b/AndroidApp/ui/src/screenshotTest/kotlin/me/nya_n/notificationnotifier/ScreenshotTest.kt @@ -230,7 +230,6 @@ class ScreenshotTest { fun SubContentTopBarComponentScreenshotTest() { AppTheme { TopBar( - hasBackContent = true, onBack = { } ) } From 8204dd171c0fdfb1d6b5803a2859bfce6880bcde Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 18 Dec 2025 03:50:40 +0900 Subject: [PATCH 07/11] =?UTF-8?q?=E7=89=B9=E5=AE=9A=E3=81=AE=E7=94=BB?= =?UTF-8?q?=E9=9D=A2=E3=81=A7=E2=86=90=E3=83=9C=E3=82=BF=E3=83=B3=E8=A1=A8?= =?UTF-8?q?=E7=A4=BA=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/screen/main/MainScreen.kt | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt index b6d4aedc..79c8ce1f 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt @@ -20,8 +20,11 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource @@ -48,6 +51,7 @@ import me.nya_n.notificationnotifier.ui.util.LocalAnimatedVisibilityScope @Composable fun MainScreen(navController: NavController) { val snackbarHostState = remember { SnackbarHostState() } + var onBack by remember { mutableStateOf<(() -> Unit)?>(null) } val activity = LocalActivity.current val scope = rememberCoroutineScope() val tabItems = listOf( @@ -61,6 +65,7 @@ fun MainScreen(navController: NavController) { CompositionLocalProvider( LocalAnimatedVisibilityScope provides this@composable ) { + onBack = null TargetScreen( navController = navController, snackbarHostState = snackbarHostState @@ -75,6 +80,7 @@ fun MainScreen(navController: NavController) { CompositionLocalProvider( LocalAnimatedVisibilityScope provides this@composable ) { + onBack = { navController.popBackStack() } DetailScreen( navController = navController, app = app @@ -84,9 +90,11 @@ fun MainScreen(navController: NavController) { } }, TabItem(stringResource(id = R.string.apps), Icons.AutoMirrored.Rounded.List) { + onBack = null SelectionScreen(snackbarHostState = snackbarHostState) }, TabItem(stringResource(id = R.string.settings), Icons.Outlined.Settings) { + onBack = null SettingsScreen( navController = navController, snackbarHostState = snackbarHostState @@ -105,11 +113,14 @@ fun MainScreen(navController: NavController) { MainContent( snackbarHostState = snackbarHostState, tabItems = tabItems, - pagerState = pagerState - ) { - snackbarHostState.currentSnackbarData?.dismiss() - scope.launch { pagerState.scrollToPage(it, 0f) } - } + pagerState = pagerState, + onBack = onBack, + onTabSelected = { + snackbarHostState.currentSnackbarData?.dismiss() + scope.launch { pagerState.scrollToPage(it, 0f) } + }, + + ) } /** メイン画面のコンテンツ本体 */ @@ -118,10 +129,12 @@ fun MainContent( snackbarHostState: SnackbarHostState, tabItems: List, pagerState: PagerState, - onTabSelected: (selected: Int) -> Unit + onBack: (() -> Unit)? = null, + onTabSelected: (selected: Int) -> Unit, ) { AppScaffold( snackbarHostState = snackbarHostState, + onBack = onBack, bottomBar = { BottomBar( items = tabItems, @@ -188,8 +201,10 @@ private fun MainPreview() { MainContent( snackbarHostState = snackbarHostState, tabItems = tabItems, - pagerState = pagerState - ) { } + pagerState = pagerState, + onTabSelected = { }, + onBack = null + ) } } From 4dc8a697c9a1319a7cfcbb07f3ea7c910b006332 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 18 Dec 2025 03:53:13 +0900 Subject: [PATCH 08/11] =?UTF-8?q?onBack=E3=81=8Cnull=E3=81=AE=E3=81=A8?= =?UTF-8?q?=E3=81=8D=E3=81=AETopBar=E3=81=AE=E8=A6=8B=E3=81=9F=E7=9B=AE?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../me/nya_n/notificationnotifier/ui/common/TopBar.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/TopBar.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/TopBar.kt index dc663ad3..42ca2f59 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/TopBar.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/TopBar.kt @@ -28,10 +28,10 @@ fun TopBar( ) }, navigationIcon = { - if (onBack != null) { - IconButton( - onClick = onBack - ) { + IconButton( + onClick = onBack ?: { } + ) { + if (onBack != null) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(id = R.string.back) From a54919c2f068558aacf45008df94c1887d6da6e3 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 18 Dec 2025 04:04:44 +0900 Subject: [PATCH 09/11] =?UTF-8?q?onBack=E3=81=AE=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=87=A6=E7=90=86=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/screen/main/MainScreen.kt | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt index 79c8ce1f..f17fcbcc 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/screen/main/MainScreen.kt @@ -20,11 +20,8 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource @@ -32,6 +29,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.navigation.NavController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.google.gson.Gson import kotlinx.coroutines.launch @@ -51,23 +49,21 @@ import me.nya_n.notificationnotifier.ui.util.LocalAnimatedVisibilityScope @Composable fun MainScreen(navController: NavController) { val snackbarHostState = remember { SnackbarHostState() } - var onBack by remember { mutableStateOf<(() -> Unit)?>(null) } + val tab1NavController = rememberNavController() val activity = LocalActivity.current val scope = rememberCoroutineScope() val tabItems = listOf( TabItem(stringResource(id = R.string.targets), Icons.Outlined.NotificationsActive) { - val navController = rememberNavController() NavHost( - navController = navController, + navController = tab1NavController, startDestination = Screen.Main.Targets.name ) { composable(Screen.Main.Targets.route) { CompositionLocalProvider( LocalAnimatedVisibilityScope provides this@composable ) { - onBack = null TargetScreen( - navController = navController, + navController = tab1NavController, snackbarHostState = snackbarHostState ) } @@ -80,9 +76,8 @@ fun MainScreen(navController: NavController) { CompositionLocalProvider( LocalAnimatedVisibilityScope provides this@composable ) { - onBack = { navController.popBackStack() } DetailScreen( - navController = navController, + navController = tab1NavController, app = app ) } @@ -90,11 +85,9 @@ fun MainScreen(navController: NavController) { } }, TabItem(stringResource(id = R.string.apps), Icons.AutoMirrored.Rounded.List) { - onBack = null SelectionScreen(snackbarHostState = snackbarHostState) }, TabItem(stringResource(id = R.string.settings), Icons.Outlined.Settings) { - onBack = null SettingsScreen( navController = navController, snackbarHostState = snackbarHostState @@ -102,6 +95,11 @@ fun MainScreen(navController: NavController) { }, ) val pagerState = rememberPagerState(pageCount = { tabItems.size }) + val isTab1RootScreen = + tab1NavController.currentBackStackEntryAsState().value?.destination?.route == Screen.Main.Targets.route + val onBack: (() -> Unit)? = if (pagerState.currentPage == 0 && !isTab1RootScreen) { + { tab1NavController.popBackStack() } + } else null BackHandler(true) { snackbarHostState.currentSnackbarData?.dismiss() if (pagerState.currentPage == 0) { @@ -118,9 +116,8 @@ fun MainScreen(navController: NavController) { onTabSelected = { snackbarHostState.currentSnackbarData?.dismiss() scope.launch { pagerState.scrollToPage(it, 0f) } - }, - - ) + } + ) } /** メイン画面のコンテンツ本体 */ From 747e7292df71edfcf88444654651aff73335b1b5 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Thu, 18 Dec 2025 04:06:29 +0900 Subject: [PATCH 10/11] =?UTF-8?q?=E2=86=90=E3=81=8C=E8=A1=A8=E7=A4=BA?= =?UTF-8?q?=E3=81=95=E3=82=8C=E3=81=A6=E3=81=AA=E3=81=84=E3=81=A8=E3=81=8D?= =?UTF-8?q?=E3=81=AF=E3=82=BF=E3=83=83=E3=83=97=E3=81=A7=E3=81=8D=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/me/nya_n/notificationnotifier/ui/common/TopBar.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/TopBar.kt b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/TopBar.kt index 42ca2f59..cfe6e221 100644 --- a/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/TopBar.kt +++ b/AndroidApp/ui/src/main/kotlin/me/nya_n/notificationnotifier/ui/common/TopBar.kt @@ -29,7 +29,8 @@ fun TopBar( }, navigationIcon = { IconButton( - onClick = onBack ?: { } + onClick = onBack ?: { }, + enabled = onBack != null ) { if (onBack != null) { Icon( From 4f1d40803e02dda7252e15c61a4d4266c0e87515 Mon Sep 17 00:00:00 2001 From: Takuya Nishizawa Date: Sun, 21 Dec 2025 00:05:36 +0900 Subject: [PATCH 11/11] =?UTF-8?q?ScreenshotTest.kt=E4=B8=80=E6=99=82?= =?UTF-8?q?=E7=9A=84=E3=81=AB=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88=E3=82=A2?= =?UTF-8?q?=E3=82=A6=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notificationnotifier/ScreenshotTest.kt | 478 +++++++++--------- 1 file changed, 239 insertions(+), 239 deletions(-) diff --git a/AndroidApp/ui/src/screenshotTest/kotlin/me/nya_n/notificationnotifier/ScreenshotTest.kt b/AndroidApp/ui/src/screenshotTest/kotlin/me/nya_n/notificationnotifier/ScreenshotTest.kt index be10f769..e878dc25 100644 --- a/AndroidApp/ui/src/screenshotTest/kotlin/me/nya_n/notificationnotifier/ScreenshotTest.kt +++ b/AndroidApp/ui/src/screenshotTest/kotlin/me/nya_n/notificationnotifier/ScreenshotTest.kt @@ -1,239 +1,239 @@ -package me.nya_n.notificationnotifier - -import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.rounded.List -import androidx.compose.material.icons.outlined.NotificationsActive -import androidx.compose.material.icons.outlined.Settings -import androidx.compose.material3.SnackbarHostState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.tooling.preview.Preview -import me.nya_n.notificationnotifier.model.InstalledApp -import me.nya_n.notificationnotifier.ui.common.AppList -import me.nya_n.notificationnotifier.ui.common.AppOutlinedButton -import me.nya_n.notificationnotifier.ui.common.AppScaffold -import me.nya_n.notificationnotifier.ui.common.Category -import me.nya_n.notificationnotifier.ui.common.CommonDialog -import me.nya_n.notificationnotifier.ui.common.EmptyView -import me.nya_n.notificationnotifier.ui.common.RequireNotificationPermissionDialog -import me.nya_n.notificationnotifier.ui.common.RequirePackageVisibilityDialog -import me.nya_n.notificationnotifier.ui.common.TopBar -import me.nya_n.notificationnotifier.ui.screen.detail.DetailContent -import me.nya_n.notificationnotifier.ui.screen.main.MainContent -import me.nya_n.notificationnotifier.ui.screen.main.TabItem -import me.nya_n.notificationnotifier.ui.screen.selection.SelectionContent -import me.nya_n.notificationnotifier.ui.screen.settings.SettingsContent -import me.nya_n.notificationnotifier.ui.screen.target.TargetContent -import me.nya_n.notificationnotifier.ui.theme.AppTheme -import me.nya_n.notificationnotifier.ui.util.Sample - -class ScreenshotTest { - - // region: 画面レベル - - @Preview - @Composable - fun MainContentScreenshotTest() { - val snackbarHostState = remember { SnackbarHostState() } - val tabItems = listOf( - TabItem("タブ1", Icons.Outlined.NotificationsActive), - TabItem("タブ2", Icons.AutoMirrored.Rounded.List), - TabItem("タブ3", Icons.Outlined.Settings), - ) - val pagerState = rememberPagerState(pageCount = { tabItems.size }) - AppTheme { - MainContent( - snackbarHostState = snackbarHostState, - tabItems = tabItems, - pagerState = pagerState - ) { } - } - } - - - @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) - @Composable - fun TargetContentScreenshotTest() { - val items = listOf( - InstalledApp("Sample App", "me.nya_n.notificationnotifier"), - InstalledApp("Sample App", "me.nya_n.notificationnotifier"), - InstalledApp("Sample App", "me.nya_n.notificationnotifier"), - ) - AppTheme { - TargetContent( - items = items, - isLoading = false, - onAppSelected = { } - ) - } - } - - @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) - @Composable - fun DetailContentScreenshotTest() { - val snackbarHostState = remember { SnackbarHostState() } - AppTheme { - DetailContent( - snackbarHostState = snackbarHostState, - app = InstalledApp("Sample App Name", "example.sample.test"), - condition = "^.*$", - onBack = { }, - onDeleteApp = { }, - onConditionChanged = { } - ) - } - } - - @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) - @Composable - fun SelectionContentScreenshotTest() { - AppTheme { - SelectionContent( - items = Sample.items, - isLoading = false, - onAppSelected = { }, - initQuery = "", - onQueryInputted = { } - ) - } - } - - @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) - @Composable - fun SettingsContentScreenshotTest() { - AppTheme { - SettingsContent( - address = "192.168.11.2:5555", - versionCode = 1, - versionName = "1.0", - onValueChange = { }, - onNotifyTest = { }, - onExportData = { }, - onImportData = { }, - onLicense = { }, - onAboutDeveloper = { } - ) - } - } - - // endregion - - // region: コンポーネントレベル - - @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) - @Composable - fun AppListComponentScreenshotTest() { - val items = listOf( - InstalledApp("Sample App", "me.nya_n.notificationnotifier"), - InstalledApp( - "Sample App Name So Looooooooooooooooong", - "me.nya_n.notificationnotifier" - ), - ) - AppTheme { - AppList( - items = items, - onAppSelected = { } - ) - } - } - - @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) - @Composable - fun EmptyAppListComponentScreenshotTest() { - AppTheme { - AppList( - items = emptyList(), - onAppSelected = { } - ) - } - } - - @Preview - @Composable - fun AppOutlinedButtonComponentScreenshotTest() { - AppTheme { - AppOutlinedButton("text") { } - } - } - - @Preview - @Composable - fun AppScaffoldComponentScreenshotTest() { - val snackbarHostState = remember { SnackbarHostState() } - AppTheme { - AppScaffold(snackbarHostState) { } - } - } - - @Preview - @Composable - fun CategoryComponentScreenshotTest() { - AppTheme { - Category("カテゴリ") - } - } - - @Preview - @Composable - fun CommonDialogComponentScreenshotTest() { - AppTheme { - CommonDialog( - message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", - positiveButtonText = "YES", - negativeButtonText = "NO", - onPositiveDismissRequest = { }, - onNegativeDismissRequest = { } - ) - } - } - - @Preview - @Composable - fun RequireNotificationPermissionDialogComponentScreenshotTest() { - AppTheme { - RequireNotificationPermissionDialog( - onDismissRequest = { } - ) - } - } - - @Preview - @Composable - fun RequirePackageVisibilityDialogComponentScreenshotTest() { - AppTheme { - RequirePackageVisibilityDialog( - onDismissRequest = { } - ) - } - } - - @Preview - @Composable - fun EmptyViewComponentScreenshotTest() { - AppTheme { - EmptyView(message = "empty") - } - } - - @Preview - @Composable - fun TopBarComponentScreenshotTest() { - AppTheme { - TopBar() - } - } - - @Preview - @Composable - fun SubContentTopBarComponentScreenshotTest() { - AppTheme { - TopBar( - onBack = { } - ) - } - } - - // endregion -} \ No newline at end of file +//package me.nya_n.notificationnotifier +// +//import androidx.compose.foundation.pager.rememberPagerState +//import androidx.compose.material.icons.Icons +//import androidx.compose.material.icons.automirrored.rounded.List +//import androidx.compose.material.icons.outlined.NotificationsActive +//import androidx.compose.material.icons.outlined.Settings +//import androidx.compose.material3.SnackbarHostState +//import androidx.compose.runtime.Composable +//import androidx.compose.runtime.remember +//import androidx.compose.ui.tooling.preview.Preview +//import me.nya_n.notificationnotifier.model.InstalledApp +//import me.nya_n.notificationnotifier.ui.common.AppList +//import me.nya_n.notificationnotifier.ui.common.AppOutlinedButton +//import me.nya_n.notificationnotifier.ui.common.AppScaffold +//import me.nya_n.notificationnotifier.ui.common.Category +//import me.nya_n.notificationnotifier.ui.common.CommonDialog +//import me.nya_n.notificationnotifier.ui.common.EmptyView +//import me.nya_n.notificationnotifier.ui.common.RequireNotificationPermissionDialog +//import me.nya_n.notificationnotifier.ui.common.RequirePackageVisibilityDialog +//import me.nya_n.notificationnotifier.ui.common.TopBar +//import me.nya_n.notificationnotifier.ui.screen.detail.DetailContent +//import me.nya_n.notificationnotifier.ui.screen.main.MainContent +//import me.nya_n.notificationnotifier.ui.screen.main.TabItem +//import me.nya_n.notificationnotifier.ui.screen.selection.SelectionContent +//import me.nya_n.notificationnotifier.ui.screen.settings.SettingsContent +//import me.nya_n.notificationnotifier.ui.screen.target.TargetContent +//import me.nya_n.notificationnotifier.ui.theme.AppTheme +//import me.nya_n.notificationnotifier.ui.util.Sample +// +//class ScreenshotTest { +// +// // region: 画面レベル +// +// @Preview +// @Composable +// fun MainContentScreenshotTest() { +// val snackbarHostState = remember { SnackbarHostState() } +// val tabItems = listOf( +// TabItem("タブ1", Icons.Outlined.NotificationsActive), +// TabItem("タブ2", Icons.AutoMirrored.Rounded.List), +// TabItem("タブ3", Icons.Outlined.Settings), +// ) +// val pagerState = rememberPagerState(pageCount = { tabItems.size }) +// AppTheme { +// MainContent( +// snackbarHostState = snackbarHostState, +// tabItems = tabItems, +// pagerState = pagerState +// ) { } +// } +// } +// +// +// @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) +// @Composable +// fun TargetContentScreenshotTest() { +// val items = listOf( +// InstalledApp("Sample App", "me.nya_n.notificationnotifier"), +// InstalledApp("Sample App", "me.nya_n.notificationnotifier"), +// InstalledApp("Sample App", "me.nya_n.notificationnotifier"), +// ) +// AppTheme { +// TargetContent( +// items = items, +// isLoading = false, +// onAppSelected = { } +// ) +// } +// } +// +// @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) +// @Composable +// fun DetailContentScreenshotTest() { +// val snackbarHostState = remember { SnackbarHostState() } +// AppTheme { +// DetailContent( +// snackbarHostState = snackbarHostState, +// app = InstalledApp("Sample App Name", "example.sample.test"), +// condition = "^.*$", +// onBack = { }, +// onDeleteApp = { }, +// onConditionChanged = { } +// ) +// } +// } +// +// @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) +// @Composable +// fun SelectionContentScreenshotTest() { +// AppTheme { +// SelectionContent( +// items = Sample.items, +// isLoading = false, +// onAppSelected = { }, +// initQuery = "", +// onQueryInputted = { } +// ) +// } +// } +// +// @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) +// @Composable +// fun SettingsContentScreenshotTest() { +// AppTheme { +// SettingsContent( +// address = "192.168.11.2:5555", +// versionCode = 1, +// versionName = "1.0", +// onValueChange = { }, +// onNotifyTest = { }, +// onExportData = { }, +// onImportData = { }, +// onLicense = { }, +// onAboutDeveloper = { } +// ) +// } +// } +// +// // endregion +// +// // region: コンポーネントレベル +// +// @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) +// @Composable +// fun AppListComponentScreenshotTest() { +// val items = listOf( +// InstalledApp("Sample App", "me.nya_n.notificationnotifier"), +// InstalledApp( +// "Sample App Name So Looooooooooooooooong", +// "me.nya_n.notificationnotifier" +// ), +// ) +// AppTheme { +// AppList( +// items = items, +// onAppSelected = { } +// ) +// } +// } +// +// @Preview(backgroundColor = 0xFFC7B5A8, showBackground = true) +// @Composable +// fun EmptyAppListComponentScreenshotTest() { +// AppTheme { +// AppList( +// items = emptyList(), +// onAppSelected = { } +// ) +// } +// } +// +// @Preview +// @Composable +// fun AppOutlinedButtonComponentScreenshotTest() { +// AppTheme { +// AppOutlinedButton("text") { } +// } +// } +// +// @Preview +// @Composable +// fun AppScaffoldComponentScreenshotTest() { +// val snackbarHostState = remember { SnackbarHostState() } +// AppTheme { +// AppScaffold(snackbarHostState) { } +// } +// } +// +// @Preview +// @Composable +// fun CategoryComponentScreenshotTest() { +// AppTheme { +// Category("カテゴリ") +// } +// } +// +// @Preview +// @Composable +// fun CommonDialogComponentScreenshotTest() { +// AppTheme { +// CommonDialog( +// message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", +// positiveButtonText = "YES", +// negativeButtonText = "NO", +// onPositiveDismissRequest = { }, +// onNegativeDismissRequest = { } +// ) +// } +// } +// +// @Preview +// @Composable +// fun RequireNotificationPermissionDialogComponentScreenshotTest() { +// AppTheme { +// RequireNotificationPermissionDialog( +// onDismissRequest = { } +// ) +// } +// } +// +// @Preview +// @Composable +// fun RequirePackageVisibilityDialogComponentScreenshotTest() { +// AppTheme { +// RequirePackageVisibilityDialog( +// onDismissRequest = { } +// ) +// } +// } +// +// @Preview +// @Composable +// fun EmptyViewComponentScreenshotTest() { +// AppTheme { +// EmptyView(message = "empty") +// } +// } +// +// @Preview +// @Composable +// fun TopBarComponentScreenshotTest() { +// AppTheme { +// TopBar() +// } +// } +// +// @Preview +// @Composable +// fun SubContentTopBarComponentScreenshotTest() { +// AppTheme { +// TopBar( +// onBack = { } +// ) +// } +// } +// +// // endregion +//} \ No newline at end of file