Search code examples
kotlintornadofx

How to handle auth while showing loading screen?


How to show a loading screen and handle authorization at the same time?

Can I switch to LoadingView and return back to AuthView in AuthController or I need to move auth logic to LoadingController?

class AuthController : Controller() {
    val authView : AuthView by inject()
    val loadingView : LoadingView by inject()

    fun tryAuth(login: String, password: String) {
        runAsync {
            login == "admin" && password == "admin"
        } ui { successful ->
            authView.replaceWith(loadingView, ViewTransition.Fade(0.5.seconds))

            if (successful) {
                // doesn't work
                loadingView.replaceWith(MainView::class, ViewTransition.Metro(0.5.seconds))
            } else {
                // doesn't work
                loadingView.replaceWith(AuthView::class, ViewTransition.Fade(0.5.seconds))
            }
        }
    }
}

Solution

  • You are replacing the AuthView with the LoadingView and then the LoadingView with the MainView in the same pulse, so that's not going to give you what you want. Normally you'd want to change to the LoadingView on the UI thread before you evaluate the auth information. Using this approach, your code works, but it might not be what you want.

    class AuthController : Controller() {
        val authView : AuthView by inject()
        val loadingView : LoadingView by inject()
    
        fun tryAuth(login: String, password: String) {
            authView.replaceWith(loadingView, ViewTransition.Fade(0.5.seconds))
    
            runAsync {
                // Simulate db access or http call
                Thread.sleep(2000)
                login == "admin" && password == "admin"
            } ui { successful ->
    
                if (successful) {
                    // doesn't work
                    loadingView.replaceWith(MainView::class, ViewTransition.Metro(0.5.seconds))
                } else {
                    // doesn't work
                    loadingView.replaceWith(AuthView::class, ViewTransition.Fade(0.5.seconds))
                }
    
            }
        }
    }
    
    class AuthView : View("Auth") {
        val authController: AuthController by inject()
    
        override val root = stackpane {
            button(title).action {
                authController.tryAuth("admin", "admin")
            }
        }
    }
    
    class LoadingView : View("Loading...") {
        override val root = stackpane {
            label(title)
        }
    }
    
    class MainView : View("Main View") {
        override val root = stackpane {
            label(title)
        }
    }
    

    You must keep in mind that replacing a view will not resize the window (though you could access the stage and ask it to resize to the current view), so you might be better off with opening each view in a separate window instead.