Search code examples
kotlinkotlin-coroutinesdesktopandroid-jetpack-compose

Create multiple applicationScope in a jetpack compose/kotlin application


Is it possible to have multiple application scope in a jetpack compose/kotlin ?

I want to manage the first start interface and main interface (with tray) in 2 different application scopes without having mixed code.

I'm thinking about something like that :

suspend fun main() = coroutineScope {
    val repo = MyRepository()
    initDefaultUserConfigIfNeeded(repo)
    startDesktop(repo)
}

suspend fun initDefaultUserConfigIfNeeded(repo: MyRepository) {
    if (repo.isFirstStart()) {
        val defaultPath = getUserConfig(repo)

        repo.addContentRepository(defaultPath)
        repo.markApplicationStartedOnce()
    }
}

suspend fun getUserConfig(repo: MyRepository) = coroutineScope {
    suspendCoroutine { cont ->
        val defaultManagedDir = repo.config.getDefaultManagedDirectory()

        startFirstStartInterface(defaultManagedDir) {
            cont.resume(it)
        }
    }
}

fun startFirstStartInterface(default: String, onSelectedPath: (info: String) -> Unit) {
    application {
        Window(onCloseRequest = { exitApplication() }) {
            Text("here my init interface to select path on first start")
            Button(onClick = { exitApplication(); onSelectedPath("/tmp") } )
        }
    }
}

fun startMainApplication(repo: MyRepository) {
    application {
        val isMainWindowVisible = remember { mutableStateOf(false) }

        Tray(menu = Item("Open", onClick = { isMainWindowVisible.value = true }))

        Window(
            onCloseRequest = { exitApplication() },
            visible = isMainWindowVisible.value,
        ) {
            Text("here my main interface")
        }
    }
}

My problem is the exitApplication method kills the application and not let the code to continue.


Solution

  • Thanks to @Tenfour4 (again), here is how I finally implement that :

    suspend fun main() = coroutineScope {
        val repo = MyRepository()
        initDefaultUserConfigIfNeeded(repo)
        startDesktop(repo)
    }
    
    suspend fun initDefaultUserConfigIfNeeded(repo: MyRepository) {
        if (repo.isFirstStart()) {
            val defaultPath = getUserConfig(repo)
    
            repo.addContentRepository(defaultPath)
            repo.markApplicationStartedOnce()
        }
    }
    
    suspend fun getUserConfig(repo: MyRepository) = coroutineScope {
        var info = String? = null
    
        val defaultManagedDir = repo.config.getDefaultManagedDirectory()
        startFirstStartInterface(
            default = defaultManagedDir,
            onSelectedPath = { info = it; exitApplication() },
            onClose = { exitApplication() },
        )
        info
    }
    
    fun startFirstStartInterface(default: String, onSelectedPath: (info: String) -> Unit) {
        awaitApplication {
            Window(onCloseRequest = { onClose() }) {
                Text("here my init interface to select path on first start")
                Button(onClick = { onSelectedPath("/tmp") } )
            }
        }
    }
    
    fun startMainApplication(repo: MyRepository) {
        application {
            val isMainWindowVisible = remember { mutableStateOf(false) }
    
            Tray(menu = Item("Open", onClick = { isMainWindowVisible.value = true }))
    
            Window(
                onCloseRequest = { exitApplication() },
                visible = isMainWindowVisible.value,
            ) {
                Text("here my main interface")
            }
        }
    }