0

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.

  • You mean you want to launch two application windows in series, but the first one should wait for all its coroutines to finish before exiting when the user presses the X button? – Tenfour04 Mar 06 '23 at 14:43
  • Yes it can be that, thinking about result of the first window be accessible for the second window or used in a coroutine. – Benjamin Jalon Mar 06 '23 at 22:03
  • I don’t know if an application can have a result, but I think you can use `awaitApplication` to launch them in series. – Tenfour04 Mar 07 '23 at 03:01
  • Again thank you so much... Really hard to fin documentation about that. What is your source of information. There are so little documentations about jetpack compose, I'm interesting of your path. Maybe just the code ? :) – Benjamin Jalon Mar 07 '23 at 07:03
  • Yes, the documentation for desktop Compose is very lacking. I found this by searching the source code. I ctrl+clicked `application` to get to its implementation and documentation. I saw that it indirectly mentioned `awaitApplication` so then I read that documentation. – Tenfour04 Mar 07 '23 at 20:48

1 Answers1

0

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")
        }
    }
}