Skip to content

Commit

Permalink
Merge pull request #230 from fmasa/pop-window
Browse files Browse the repository at this point in the history
Pop screen to a new window
  • Loading branch information
fmasa authored Nov 17, 2023
2 parents ceace71 + 9cb5a63 commit 765796a
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ val LocalNavigationTransaction = staticCompositionLocalOf<NavigationTransaction>
* This can be e.g. user clicking button multiple times.
*/
class NavigationTransaction(
private val currentScreen: Screen,
val currentScreen: Screen,
private val navigator: Navigator,
) {
val canPop: Boolean get() = navigator.canPop
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package cz.frantisekmasa.wfrp_master.desktop

import androidx.compose.material.DrawerValue
import androidx.compose.material.rememberDrawerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.window.Window
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.Navigator
import cz.frantisekmasa.wfrp_master.common.core.ui.navigation.ProvideNavigationTransaction
import cz.frantisekmasa.wfrp_master.common.core.ui.responsive.ScreenWithBreakpoints
import cz.frantisekmasa.wfrp_master.common.core.ui.scaffolding.KeyboardDispatcher
import cz.frantisekmasa.wfrp_master.common.core.ui.scaffolding.LocalKeyboardDispatcher
import cz.frantisekmasa.wfrp_master.common.core.ui.theme.Theme
import cz.frantisekmasa.wfrp_master.common.localization.FixedStrings
import cz.frantisekmasa.wfrp_master.common.shell.DrawerShell
import cz.frantisekmasa.wfrp_master.common.shell.SnackbarScaffold
import kotlinx.coroutines.launch
import java.util.UUID

@Immutable
data class ApplicationWindowState(
val initialScreen: Screen,
val key: UUID,
val isPrimary: Boolean,
)

@Composable
fun ApplicationWindow(
initialScreen: Screen,
onCloseRequest: () -> Unit,
onNewWindowRequest: (initialScreen: Screen) -> Unit,
) {
val keyboardDispatcher = remember { KeyboardDispatcher() }

CompositionLocalProvider(
LocalKeyboardDispatcher provides keyboardDispatcher,
) {
Window(
title = FixedStrings.appName,
onCloseRequest = onCloseRequest,
onPreviewKeyEvent = {
keyboardDispatcher.dispatch(it, beforeChildren = true)
},
onKeyEvent = {
keyboardDispatcher.dispatch(it, beforeChildren = false)
},
) {
Theme {
SnackbarScaffold {
Startup {
ScreenWithBreakpoints {
val drawerState = rememberDrawerState(DrawerValue.Closed)
val coroutineScope = rememberCoroutineScope()

Navigator(
screens = listOf(initialScreen),
onBackPressed = {
if (drawerState.isOpen) {
coroutineScope.launch { drawerState.close() }
return@Navigator false
}

true
}
) { navigator ->
DrawerShell(drawerState) {
val screen = navigator.lastItem

navigator.saveableState("currentScreen") {
ProvideNavigationTransaction(screen) {
Shortcuts(
onNewWindowRequest = onNewWindowRequest,
)
screen.Content()
}
}
}
}
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cz.frantisekmasa.wfrp_master.desktop

import androidx.compose.runtime.Composable
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.isAltPressed
import androidx.compose.ui.input.key.isCtrlPressed
import androidx.compose.ui.input.key.isShiftPressed
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.type
import cafe.adriel.voyager.core.screen.Screen
import cz.frantisekmasa.wfrp_master.common.core.ui.navigation.LocalNavigationTransaction
import cz.frantisekmasa.wfrp_master.common.core.ui.scaffolding.KeyboardEffect

@Composable
fun Shortcuts(onNewWindowRequest: (initialScreen: Screen) -> Unit) {
val transaction = LocalNavigationTransaction.current

KeyboardEffect("global-shortcuts") {
if (it.type != KeyEventType.KeyDown) {
return@KeyboardEffect false
}

if (it.isAltPressed && it.key == Key.DirectionLeft) {
transaction.goBack(popLast = false)
return@KeyboardEffect true
}

if (it.isCtrlPressed && it.isShiftPressed && it.key == Key.T && transaction.canPop) {
onNewWindowRequest(transaction.currentScreen)
transaction.goBack()

return@KeyboardEffect true
}

return@KeyboardEffect false
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,41 +1,31 @@
package cz.frantisekmasa.wfrp_master.desktop

import androidx.compose.material.DrawerValue
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.rememberDrawerState
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.window.Window
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.window.application
import cafe.adriel.voyager.navigator.Navigator
import cz.frantisekmasa.wfrp_master.common.appModule
import cz.frantisekmasa.wfrp_master.common.core.LocalStaticConfiguration
import cz.frantisekmasa.wfrp_master.common.core.config.Platform
import cz.frantisekmasa.wfrp_master.common.core.config.StaticConfiguration
import cz.frantisekmasa.wfrp_master.common.core.shared.LocalFileChooserFactory
import cz.frantisekmasa.wfrp_master.common.core.shared.LocalFileSaverFactory
import cz.frantisekmasa.wfrp_master.common.core.shared.LocalUrlOpener
import cz.frantisekmasa.wfrp_master.common.core.ui.navigation.ProvideNavigationTransaction
import cz.frantisekmasa.wfrp_master.common.core.ui.responsive.ScreenWithBreakpoints
import cz.frantisekmasa.wfrp_master.common.core.ui.scaffolding.KeyboardDispatcher
import cz.frantisekmasa.wfrp_master.common.core.ui.scaffolding.LocalKeyboardDispatcher
import cz.frantisekmasa.wfrp_master.common.core.ui.theme.Theme
import cz.frantisekmasa.wfrp_master.common.localization.FixedStrings
import cz.frantisekmasa.wfrp_master.common.partyList.PartyListScreen
import cz.frantisekmasa.wfrp_master.common.shell.DrawerShell
import cz.frantisekmasa.wfrp_master.common.shell.SnackbarScaffold
import cz.frantisekmasa.wfrp_master.desktop.interop.DesktopUrlOpener
import cz.frantisekmasa.wfrp_master.desktop.interop.NativeFileChooser
import cz.frantisekmasa.wfrp_master.desktop.interop.NativeFileSaver
import kotlinx.coroutines.launch
import io.github.aakira.napier.Napier
import org.kodein.di.compose.withDI
import java.util.UUID

@ExperimentalMaterialApi
object WfrpMasterApplication {
@JvmStatic
fun main(args: Array<String>) {
val keyboardDispatcher = KeyboardDispatcher()

application {
withDI(appModule) {
val coroutineScope = rememberCoroutineScope()
Expand All @@ -49,49 +39,38 @@ object WfrpMasterApplication {
version = "dev",
platform = Platform.Desktop,
),
LocalKeyboardDispatcher provides keyboardDispatcher,
) {
Window(
title = FixedStrings.appName,
onCloseRequest = ::exitApplication,
onPreviewKeyEvent = {
keyboardDispatcher.dispatch(it, beforeChildren = true)
},
onKeyEvent = {
keyboardDispatcher.dispatch(it, beforeChildren = false)
},
) {
Theme {
SnackbarScaffold {
Startup {
ScreenWithBreakpoints {
val drawerState = rememberDrawerState(DrawerValue.Closed)

Navigator(
screens = listOf(PartyListScreen),
onBackPressed = {
if (drawerState.isOpen) {
coroutineScope.launch { drawerState.close() }
return@Navigator false
}

true
}
) { navigator ->
DrawerShell(drawerState) {
val screen = navigator.lastItem
val windows = rememberSaveable {
mutableStateListOf(
ApplicationWindowState(
initialScreen = PartyListScreen,
key = UUID.randomUUID(),
isPrimary = true,
)
)
}

navigator.saveableState("currentScreen") {
ProvideNavigationTransaction(screen) {
Shortcuts()
screen.Content()
}
}
}
}
windows.forEach { window ->
key(window.key) {
ApplicationWindow(
initialScreen = window.initialScreen,
onNewWindowRequest = { initialScreen ->
windows += ApplicationWindowState(
initialScreen = initialScreen,
key = UUID.randomUUID(),
isPrimary = false,
)
},
onCloseRequest = {
if (window.isPrimary) {
Napier.d("Requested closing of primary window, exiting the app")
exitApplication()
} else {
Napier.d("Closing non-primary window")
windows.removeIf { it.key == window.key }
}
}
}
},
)
}
}
}
Expand Down

0 comments on commit 765796a

Please sign in to comment.