feat: Initial Close to system tray implementation #165

This commit is contained in:
Artem Chepurnyi 2024-02-17 23:37:48 +02:00
parent 84565fbcc8
commit 46f337189c
14 changed files with 277 additions and 42 deletions

View File

@ -85,6 +85,8 @@ interface SettingsReadRepository {
fun getUseExternalBrowser(): Flow<Boolean> fun getUseExternalBrowser(): Flow<Boolean>
fun getCloseToTray(): Flow<Boolean>
fun getColors(): Flow<AppColors?> fun getColors(): Flow<AppColors?>
fun getLocale(): Flow<String?> fun getLocale(): Flow<String?>

View File

@ -157,6 +157,10 @@ interface SettingsReadWriteRepository : SettingsReadRepository {
useExternalBrowser: Boolean, useExternalBrowser: Boolean,
): IO<Unit> ): IO<Unit>
fun setCloseToTray(
closeToTray: Boolean,
): IO<Unit>
fun setColors( fun setColors(
colors: AppColors?, colors: AppColors?,
): IO<Unit> ): IO<Unit>

View File

@ -67,6 +67,7 @@ class SettingsRepositoryImpl(
private const val KEY_TWO_PANEL_LAYOUT_LANDSCAPE = "two_panel_layout_landscape" private const val KEY_TWO_PANEL_LAYOUT_LANDSCAPE = "two_panel_layout_landscape"
private const val KEY_TWO_PANEL_LAYOUT_PORTRAIT = "two_panel_layout_portrait" private const val KEY_TWO_PANEL_LAYOUT_PORTRAIT = "two_panel_layout_portrait"
private const val KEY_USE_EXTERNAL_BROWSER = "use_external_browser" private const val KEY_USE_EXTERNAL_BROWSER = "use_external_browser"
private const val KEY_CLOSE_TO_TRAY = "close_to_tray"
private const val KEY_FONT = "font" private const val KEY_FONT = "font"
private const val KEY_THEME = "theme" private const val KEY_THEME = "theme"
private const val KEY_THEME_USE_AMOLED_DARK = "theme_use_amoled_dark" private const val KEY_THEME_USE_AMOLED_DARK = "theme_use_amoled_dark"
@ -166,6 +167,9 @@ class SettingsRepositoryImpl(
private val useExternalBrowserPref = private val useExternalBrowserPref =
store.getBoolean(KEY_USE_EXTERNAL_BROWSER, false) store.getBoolean(KEY_USE_EXTERNAL_BROWSER, false)
private val closeToTrayPref =
store.getBoolean(KEY_CLOSE_TO_TRAY, false)
private val navAnimationPref = private val navAnimationPref =
store.getEnumNullable(KEY_NAV_ANIMATION, lens = NavAnimation::key) store.getEnumNullable(KEY_NAV_ANIMATION, lens = NavAnimation::key)
@ -412,6 +416,13 @@ class SettingsRepositoryImpl(
override fun setUseExternalBrowser(useExternalBrowser: Boolean) = useExternalBrowserPref override fun setUseExternalBrowser(useExternalBrowser: Boolean) = useExternalBrowserPref
.setAndCommit(useExternalBrowser) .setAndCommit(useExternalBrowser)
override fun setCloseToTray(
closeToTray: Boolean,
) = closeToTrayPref
.setAndCommit(closeToTray)
override fun getCloseToTray() = closeToTrayPref
override fun setColors(colors: AppColors?) = colorsPref override fun setColors(colors: AppColors?) = colorsPref
.setAndCommit(colors) .setAndCommit(colors)

View File

@ -0,0 +1,5 @@
package com.artemchep.keyguard.common.usecase
import kotlinx.coroutines.flow.Flow
interface GetCloseToTray : () -> Flow<Boolean>

View File

@ -0,0 +1,5 @@
package com.artemchep.keyguard.common.usecase
import com.artemchep.keyguard.common.io.IO
interface PutCloseToTray : (Boolean) -> IO<Unit>

View File

@ -0,0 +1,20 @@
package com.artemchep.keyguard.common.usecase.impl
import com.artemchep.keyguard.common.service.settings.SettingsReadRepository
import com.artemchep.keyguard.common.usecase.GetCloseToTray
import kotlinx.coroutines.flow.distinctUntilChanged
import org.kodein.di.DirectDI
import org.kodein.di.instance
class GetCloseToTrayImpl(
settingsReadRepository: SettingsReadRepository,
) : GetCloseToTray {
private val sharedFlow = settingsReadRepository.getCloseToTray()
.distinctUntilChanged()
constructor(directDI: DirectDI) : this(
settingsReadRepository = directDI.instance(),
)
override fun invoke() = sharedFlow
}

View File

@ -0,0 +1,18 @@
package com.artemchep.keyguard.common.usecase.impl
import com.artemchep.keyguard.common.io.IO
import com.artemchep.keyguard.common.service.settings.SettingsReadWriteRepository
import com.artemchep.keyguard.common.usecase.PutCloseToTray
import org.kodein.di.DirectDI
import org.kodein.di.instance
class PutCloseToTrayImpl(
private val settingsReadWriteRepository: SettingsReadWriteRepository,
) : PutCloseToTray {
constructor(directDI: DirectDI) : this(
settingsReadWriteRepository = directDI.instance(),
)
override fun invoke(closeToTray: Boolean): IO<Unit> = settingsReadWriteRepository
.setCloseToTray(closeToTray)
}

View File

@ -41,6 +41,7 @@ import com.artemchep.keyguard.feature.home.settings.component.settingClearCache
import com.artemchep.keyguard.feature.home.settings.component.settingClipboardAutoClearProvider import com.artemchep.keyguard.feature.home.settings.component.settingClipboardAutoClearProvider
import com.artemchep.keyguard.feature.home.settings.component.settingClipboardAutoRefreshProvider import com.artemchep.keyguard.feature.home.settings.component.settingClipboardAutoRefreshProvider
import com.artemchep.keyguard.feature.home.settings.component.settingClipboardNotificationSettingsProvider import com.artemchep.keyguard.feature.home.settings.component.settingClipboardNotificationSettingsProvider
import com.artemchep.keyguard.feature.home.settings.component.settingCloseToTrayProvider
import com.artemchep.keyguard.feature.home.settings.component.settingColorAccentProvider import com.artemchep.keyguard.feature.home.settings.component.settingColorAccentProvider
import com.artemchep.keyguard.feature.home.settings.component.settingColorSchemeProvider import com.artemchep.keyguard.feature.home.settings.component.settingColorSchemeProvider
import com.artemchep.keyguard.feature.home.settings.component.settingConcealFieldsProvider import com.artemchep.keyguard.feature.home.settings.component.settingConcealFieldsProvider
@ -166,6 +167,7 @@ object Setting {
const val TWO_PANEL_LAYOUT_LANDSCAPE = "two_panel_layout_landscape" const val TWO_PANEL_LAYOUT_LANDSCAPE = "two_panel_layout_landscape"
const val TWO_PANEL_LAYOUT_PORTRAIT = "two_panel_layout_portrait" const val TWO_PANEL_LAYOUT_PORTRAIT = "two_panel_layout_portrait"
const val USE_EXTERNAL_BROWSER = "use_external_browser" const val USE_EXTERNAL_BROWSER = "use_external_browser"
const val CLOSE_TO_TRAY = "close_to_tray"
const val APP_ICONS = "app_icons" const val APP_ICONS = "app_icons"
const val WEBSITE_ICONS = "website_icons" const val WEBSITE_ICONS = "website_icons"
const val CHECK_PWNED_PASSWORDS = "check_pwned_passwords" const val CHECK_PWNED_PASSWORDS = "check_pwned_passwords"
@ -246,6 +248,7 @@ val hub = mapOf<String, (DirectDI) -> SettingComponent>(
Setting.TWO_PANEL_LAYOUT_LANDSCAPE to ::settingTwoPanelLayoutLandscapeProvider, Setting.TWO_PANEL_LAYOUT_LANDSCAPE to ::settingTwoPanelLayoutLandscapeProvider,
Setting.TWO_PANEL_LAYOUT_PORTRAIT to ::settingTwoPanelLayoutPortraitProvider, Setting.TWO_PANEL_LAYOUT_PORTRAIT to ::settingTwoPanelLayoutPortraitProvider,
Setting.USE_EXTERNAL_BROWSER to ::settingUseExternalBrowserProvider, Setting.USE_EXTERNAL_BROWSER to ::settingUseExternalBrowserProvider,
Setting.CLOSE_TO_TRAY to ::settingCloseToTrayProvider,
Setting.APP_ICONS to ::settingAppIconsProvider, Setting.APP_ICONS to ::settingAppIconsProvider,
Setting.WEBSITE_ICONS to ::settingWebsiteIconsProvider, Setting.WEBSITE_ICONS to ::settingWebsiteIconsProvider,
Setting.CHECK_PWNED_PASSWORDS to ::settingCheckPwnedPasswordsProvider, Setting.CHECK_PWNED_PASSWORDS to ::settingCheckPwnedPasswordsProvider,

View File

@ -0,0 +1,91 @@
package com.artemchep.keyguard.feature.home.settings.component
import androidx.compose.foundation.layout.RowScope
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.CloseFullscreen
import androidx.compose.material3.LocalMinimumInteractiveComponentEnforcement
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import arrow.core.partially1
import com.artemchep.keyguard.common.io.launchIn
import com.artemchep.keyguard.common.usecase.GetCloseToTray
import com.artemchep.keyguard.common.usecase.PutCloseToTray
import com.artemchep.keyguard.common.usecase.WindowCoroutineScope
import com.artemchep.keyguard.platform.CurrentPlatform
import com.artemchep.keyguard.platform.Platform
import com.artemchep.keyguard.res.Res
import com.artemchep.keyguard.ui.FlatItem
import com.artemchep.keyguard.ui.icons.icon
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.coroutines.flow.map
import org.kodein.di.DirectDI
import org.kodein.di.instance
fun settingCloseToTrayProvider(
directDI: DirectDI,
) = settingCloseToTrayProvider(
getCloseToTray = directDI.instance(),
putCloseToTray = directDI.instance(),
windowCoroutineScope = directDI.instance(),
)
fun settingCloseToTrayProvider(
getCloseToTray: GetCloseToTray,
putCloseToTray: PutCloseToTray,
windowCoroutineScope: WindowCoroutineScope,
): SettingComponent = getCloseToTray().map { closeToTray ->
val onCheckedChange = { shouldCloseToTray: Boolean ->
putCloseToTray(shouldCloseToTray)
.launchIn(windowCoroutineScope)
Unit
}
if (CurrentPlatform is Platform.Desktop) {
SettingIi(
search = SettingIi.Search(
group = "ux",
tokens = listOf(
"close",
"tray",
"taskbar",
),
),
) {
SettingCloseToTray(
checked = closeToTray,
onCheckedChange = onCheckedChange,
)
}
} else {
null
}
}
@Composable
private fun SettingCloseToTray(
checked: Boolean,
onCheckedChange: ((Boolean) -> Unit)?,
) {
FlatItem(
leading = icon<RowScope>(Icons.Outlined.CloseFullscreen),
trailing = {
CompositionLocalProvider(
LocalMinimumInteractiveComponentEnforcement provides false,
) {
Switch(
checked = checked,
enabled = onCheckedChange != null,
onCheckedChange = onCheckedChange,
)
}
},
title = {
Text(
text = stringResource(Res.strings.pref_item_close_to_tray_title),
)
},
onClick = onCheckedChange?.partially1(!checked),
)
}

View File

@ -42,6 +42,7 @@ fun UiSettingsScreen() {
list = listOf( list = listOf(
SettingPaneItem.Item(Setting.USE_EXTERNAL_BROWSER), SettingPaneItem.Item(Setting.USE_EXTERNAL_BROWSER),
SettingPaneItem.Item(Setting.KEEP_SCREEN_ON), SettingPaneItem.Item(Setting.KEEP_SCREEN_ON),
SettingPaneItem.Item(Setting.CLOSE_TO_TRAY),
), ),
), ),
SettingPaneItem.Group( SettingPaneItem.Group(

View File

@ -896,6 +896,7 @@
<string name="pref_item_color_scheme_title">Theme</string> <string name="pref_item_color_scheme_title">Theme</string>
<string name="pref_item_color_scheme_amoled_dark_title">Use contrast black theme</string> <string name="pref_item_color_scheme_amoled_dark_title">Use contrast black theme</string>
<string name="pref_item_open_links_in_external_browser_title">Open links in external browser</string> <string name="pref_item_open_links_in_external_browser_title">Open links in external browser</string>
<string name="pref_item_close_to_tray_title">Close to system tray</string>
<string name="pref_item_conceal_fields_title">Conceal fields</string> <string name="pref_item_conceal_fields_title">Conceal fields</string>
<string name="pref_item_conceal_fields_text">Conceal sensitive info, such as passwords and credit card numbers</string> <string name="pref_item_conceal_fields_text">Conceal sensitive info, such as passwords and credit card numbers</string>
<!-- <!--

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -108,6 +108,7 @@ import com.artemchep.keyguard.common.usecase.GetClipboardAutoClear
import com.artemchep.keyguard.common.usecase.GetClipboardAutoClearVariants import com.artemchep.keyguard.common.usecase.GetClipboardAutoClearVariants
import com.artemchep.keyguard.common.usecase.GetClipboardAutoRefresh import com.artemchep.keyguard.common.usecase.GetClipboardAutoRefresh
import com.artemchep.keyguard.common.usecase.GetClipboardAutoRefreshVariants import com.artemchep.keyguard.common.usecase.GetClipboardAutoRefreshVariants
import com.artemchep.keyguard.common.usecase.GetCloseToTray
import com.artemchep.keyguard.common.usecase.GetColors import com.artemchep.keyguard.common.usecase.GetColors
import com.artemchep.keyguard.common.usecase.GetColorsVariants import com.artemchep.keyguard.common.usecase.GetColorsVariants
import com.artemchep.keyguard.common.usecase.GetConcealFields import com.artemchep.keyguard.common.usecase.GetConcealFields
@ -165,6 +166,7 @@ import com.artemchep.keyguard.common.usecase.PutCheckPwnedServices
import com.artemchep.keyguard.common.usecase.PutCheckTwoFA import com.artemchep.keyguard.common.usecase.PutCheckTwoFA
import com.artemchep.keyguard.common.usecase.PutClipboardAutoClear import com.artemchep.keyguard.common.usecase.PutClipboardAutoClear
import com.artemchep.keyguard.common.usecase.PutClipboardAutoRefresh import com.artemchep.keyguard.common.usecase.PutClipboardAutoRefresh
import com.artemchep.keyguard.common.usecase.PutCloseToTray
import com.artemchep.keyguard.common.usecase.PutColors import com.artemchep.keyguard.common.usecase.PutColors
import com.artemchep.keyguard.common.usecase.PutConcealFields import com.artemchep.keyguard.common.usecase.PutConcealFields
import com.artemchep.keyguard.common.usecase.PutDebugPremium import com.artemchep.keyguard.common.usecase.PutDebugPremium
@ -228,6 +230,7 @@ import com.artemchep.keyguard.common.usecase.impl.GetClipboardAutoClearImpl
import com.artemchep.keyguard.common.usecase.impl.GetClipboardAutoClearVariantsImpl import com.artemchep.keyguard.common.usecase.impl.GetClipboardAutoClearVariantsImpl
import com.artemchep.keyguard.common.usecase.impl.GetClipboardAutoRefreshImpl import com.artemchep.keyguard.common.usecase.impl.GetClipboardAutoRefreshImpl
import com.artemchep.keyguard.common.usecase.impl.GetClipboardAutoRefreshVariantsImpl import com.artemchep.keyguard.common.usecase.impl.GetClipboardAutoRefreshVariantsImpl
import com.artemchep.keyguard.common.usecase.impl.GetCloseToTrayImpl
import com.artemchep.keyguard.common.usecase.impl.GetColorsImpl import com.artemchep.keyguard.common.usecase.impl.GetColorsImpl
import com.artemchep.keyguard.common.usecase.impl.GetColorsVariantsImpl import com.artemchep.keyguard.common.usecase.impl.GetColorsVariantsImpl
import com.artemchep.keyguard.common.usecase.impl.GetConcealFieldsImpl import com.artemchep.keyguard.common.usecase.impl.GetConcealFieldsImpl
@ -282,6 +285,7 @@ import com.artemchep.keyguard.common.usecase.impl.PutCheckPwnedServicesImpl
import com.artemchep.keyguard.common.usecase.impl.PutCheckTwoFAImpl import com.artemchep.keyguard.common.usecase.impl.PutCheckTwoFAImpl
import com.artemchep.keyguard.common.usecase.impl.PutClipboardAutoClearImpl import com.artemchep.keyguard.common.usecase.impl.PutClipboardAutoClearImpl
import com.artemchep.keyguard.common.usecase.impl.PutClipboardAutoRefreshImpl import com.artemchep.keyguard.common.usecase.impl.PutClipboardAutoRefreshImpl
import com.artemchep.keyguard.common.usecase.impl.PutCloseToTrayImpl
import com.artemchep.keyguard.common.usecase.impl.PutColorsImpl import com.artemchep.keyguard.common.usecase.impl.PutColorsImpl
import com.artemchep.keyguard.common.usecase.impl.PutConcealFieldsImpl import com.artemchep.keyguard.common.usecase.impl.PutConcealFieldsImpl
import com.artemchep.keyguard.common.usecase.impl.PutDebugPremiumImpl import com.artemchep.keyguard.common.usecase.impl.PutDebugPremiumImpl
@ -617,6 +621,16 @@ fun globalModuleJvm() = DI.Module(
directDI = this, directDI = this,
) )
} }
bindSingleton<GetCloseToTray> {
GetCloseToTrayImpl(
directDI = this,
)
}
bindSingleton<PutCloseToTray> {
PutCloseToTrayImpl(
directDI = this,
)
}
bindSingleton<PutAllowTwoPanelLayoutInLandscape> { bindSingleton<PutAllowTwoPanelLayoutInLandscape> {
PutAllowTwoPanelLayoutInLandscapeImpl( PutAllowTwoPanelLayoutInLandscapeImpl(
directDI = this, directDI = this,

View File

@ -6,11 +6,17 @@ import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.luminance
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.window.ApplicationScope
import androidx.compose.ui.window.Tray
import androidx.compose.ui.window.Window import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application import androidx.compose.ui.window.application
import androidx.compose.ui.window.isTraySupported
import androidx.compose.ui.window.rememberTrayState
import androidx.compose.ui.window.rememberWindowState import androidx.compose.ui.window.rememberWindowState
import com.artemchep.keyguard.common.AppWorker import com.artemchep.keyguard.common.AppWorker
import com.artemchep.keyguard.common.io.bind import com.artemchep.keyguard.common.io.bind
@ -19,6 +25,7 @@ import com.artemchep.keyguard.common.model.PersistedSession
import com.artemchep.keyguard.common.model.ToastMessage import com.artemchep.keyguard.common.model.ToastMessage
import com.artemchep.keyguard.common.service.vault.KeyReadWriteRepository import com.artemchep.keyguard.common.service.vault.KeyReadWriteRepository
import com.artemchep.keyguard.common.usecase.GetAccounts import com.artemchep.keyguard.common.usecase.GetAccounts
import com.artemchep.keyguard.common.usecase.GetCloseToTray
import com.artemchep.keyguard.common.usecase.GetLocale import com.artemchep.keyguard.common.usecase.GetLocale
import com.artemchep.keyguard.common.usecase.GetVaultPersist import com.artemchep.keyguard.common.usecase.GetVaultPersist
import com.artemchep.keyguard.common.usecase.GetVaultSession import com.artemchep.keyguard.common.usecase.GetVaultSession
@ -37,11 +44,12 @@ import com.artemchep.keyguard.feature.navigation.NavigationIntent
import com.artemchep.keyguard.feature.navigation.NavigationNode import com.artemchep.keyguard.feature.navigation.NavigationNode
import com.artemchep.keyguard.feature.navigation.NavigationRouterBackHandler import com.artemchep.keyguard.feature.navigation.NavigationRouterBackHandler
import com.artemchep.keyguard.platform.lifecycle.LeLifecycleState import com.artemchep.keyguard.platform.lifecycle.LeLifecycleState
import com.artemchep.keyguard.res.Res
import com.artemchep.keyguard.ui.LocalComposeWindow import com.artemchep.keyguard.ui.LocalComposeWindow
import com.artemchep.keyguard.ui.surface.LocalSurfaceColor import com.artemchep.keyguard.ui.surface.LocalSurfaceColor
import com.artemchep.keyguard.ui.theme.KeyguardTheme import com.artemchep.keyguard.ui.theme.KeyguardTheme
import com.mayakapps.compose.windowstyler.WindowBackdrop import dev.icerock.moko.resources.compose.painterResource
import com.mayakapps.compose.windowstyler.WindowStyle import dev.icerock.moko.resources.compose.stringResource
import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.resources.desc.StringDesc
import io.kamel.core.config.KamelConfig import io.kamel.core.config.KamelConfig
import io.kamel.core.config.takeFrom import io.kamel.core.config.takeFrom
@ -61,6 +69,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.datetime.Clock import kotlinx.datetime.Clock
import org.kodein.di.DI import org.kodein.di.DI
import org.kodein.di.bindSingleton
import org.kodein.di.compose.rememberInstance import org.kodein.di.compose.rememberInstance
import org.kodein.di.compose.withDI import org.kodein.di.compose.withDI
import org.kodein.di.direct import org.kodein.di.direct
@ -69,13 +78,16 @@ import java.util.Locale
import kotlin.reflect.KClass import kotlin.reflect.KClass
fun main() { fun main() {
val appDi = DI.invoke {
import(diFingerprintRepositoryModule())
}
val kamelConfig = KamelConfig { val kamelConfig = KamelConfig {
this.takeFrom(KamelConfig.Default) this.takeFrom(KamelConfig.Default)
mapper(FaviconUrlMapper) mapper(FaviconUrlMapper)
} }
val appDi = DI.invoke {
import(diFingerprintRepositoryModule())
bindSingleton {
kamelConfig
}
}
val getVaultSession by appDi.di.instance<GetVaultSession>() val getVaultSession by appDi.di.instance<GetVaultSession>()
val getVaultPersist by appDi.di.instance<GetVaultPersist>() val getVaultPersist by appDi.di.instance<GetVaultPersist>()
@ -184,46 +196,94 @@ fun main() {
// } // }
// } // }
val getCloseToTray: GetCloseToTray = appDi.direct.instance()
application(exitProcessOnExit = true) { application(exitProcessOnExit = true) {
withDI(appDi) { withDI(appDi) {
Window( val isWindowOpenState = remember {
::exitApplication, mutableStateOf(true)
state = rememberWindowState(), }
title = "Keyguard",
) {
// this.window.addWindowStateListener {
// println("event $it")
// }
KeyguardTheme {
val containerColor = MaterialTheme.colorScheme.surfaceContainerHighest
val contentColor = contentColorFor(containerColor)
WindowStyle( // Show a tray icon and allow the app to be collapsed into
isDarkTheme = containerColor.luminance() < 0.5f, // the tray on supported platforms.
backdropType = WindowBackdrop.Default, val getCloseToTrayState = if (isTraySupported) {
) remember { getCloseToTray() }
.collectAsState(false)
Surface( } else {
modifier = Modifier.semantics { // If the tray is not supported then we
// Allows to use testTag() for UiAutomator's resource-id. // can never close to it.
// It can be enabled high in the compose hierarchy, remember {
// so that it's enabled for the whole subtree mutableStateOf(false)
// testTagsAsResourceId = true }
}, }
color = containerColor, if (getCloseToTrayState.value) {
contentColor = contentColor, val trayState = rememberTrayState()
) { Tray(
CompositionLocalProvider( icon = painterResource(Res.images.ic_keyguard),
LocalSurfaceColor provides containerColor, state = trayState,
LocalComposeWindow provides this.window, onAction = {
LocalKamelConfig provides kamelConfig, isWindowOpenState.value = true
) { },
Navigation( menu = {
exitApplication = ::exitApplication, Item(
) { stringResource(Res.strings.close),
Content() onClick = ::exitApplication,
} )
},
)
} else {
isWindowOpenState.value = true
}
if (isWindowOpenState.value) {
KeyguardWindow(
onCloseRequest = {
val shouldCloseToTray = getCloseToTrayState.value
if (shouldCloseToTray) {
isWindowOpenState.value = false
} else {
exitApplication()
} }
},
)
}
}
}
}
@Composable
private fun ApplicationScope.KeyguardWindow(
onCloseRequest: () -> Unit,
) {
val windowState = rememberWindowState()
Window(
onCloseRequest = onCloseRequest,
icon = painterResource(Res.images.ic_keyguard),
state = windowState,
title = "Keyguard",
) {
KeyguardTheme {
val containerColor = MaterialTheme.colorScheme.surfaceContainerHighest
val contentColor = contentColorFor(containerColor)
Surface(
modifier = Modifier.semantics {
// Allows to use testTag() for UiAutomator's resource-id.
// It can be enabled high in the compose hierarchy,
// so that it's enabled for the whole subtree
// testTagsAsResourceId = true
},
color = containerColor,
contentColor = contentColor,
) {
val kamelConfig by rememberInstance<KamelConfig>()
CompositionLocalProvider(
LocalSurfaceColor provides containerColor,
LocalComposeWindow provides this.window,
LocalKamelConfig provides kamelConfig,
) {
Navigation(
exitApplication = ::exitApplication,
) {
Content()
} }
} }
} }