O'Shane McKenzie
04/06/2025, 2:58 AMturansky
04/06/2025, 4:50 PMKonstantin Tskhovrebov
04/06/2025, 5:09 PMO'Shane McKenzie
07/03/2025, 3:26 PMexternal interface JsPageState {
val id: String
}
class Navigator(private val defaultPage:String = "") {
private val currentPage = mutableStateOf(defaultPage)
private val pageHistory = mutableMapOf<String, Any?>()
private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
init {
// Set up listener for browser back/forward buttons
window.addEventListener("popstate") {
try {
val state = window.history.state
val pageId = if (state != null) {
(state as JsPageState).id
} else {
val hash = window.location.hash
if (hash.isNotEmpty()) hash.removePrefix("#") else defaultPage
}
currentPage.value = pageId
} catch (e: Throwable) {
currentPage.value = defaultPage
}
}
}
fun getCurrentPage(): String {
return currentPage.value
}
fun getCurrentPageState(): MutableState<String> {
return currentPage
}
fun navigate(pageId: String, pageData: Any? = null, updateHistory: Boolean = true) {
scope.launch {
try{// Store any associated data
pageHistory[pageId] = pageData
// Convert pageId to JS value before passing to history API
val jsPageId = createJsState(pageId)
// Update browser history if requested
if (updateHistory) {
// Add new entry to history with hashtag
window.history.pushState(jsPageId, "", "#$pageId")
} else {
// Replace current history entry with new pageId
window.history.replaceState(jsPageId, "", "#$pageId")
}
// Update current page state
withContext(Dispatchers.Main){
currentPage.value = pageId
}
}catch (e:Exception){
e.printStackTrace()
}
}
}
fun getPageData(pageId: String): Any? {
return pageHistory[pageId]
}
}
O'Shane McKenzie
07/03/2025, 3:28 PMO'Shane McKenzie
07/03/2025, 3:31 PMobject Pages {
const val HOME = "home"
const val ACCOUNT = "account"
const val SIGNIN = "signin"
const val SIGNUP = "signup"
const val DETAIL = "detail"
const val DASHBOARD = "dashboard"
}
val currentPage by navigator.getCurrentPageState()
when (currentPage) {
Pages.HOME -> {
SimpleAnimator(
modifier = Modifier.matchParentSize(),
style = AnimationStyle.LEFT,
isVisible = currentPage == Pages.HOME
) {
Home(modifier = Modifier.matchParentSize())
}
}
Pages.DETAIL -> {
SimpleAnimator(
modifier = Modifier.matchParentSize(),
style = AnimationStyle.RIGHT,
isVisible = currentPage == Pages.DETAIL
) {
Detail(modifier = Modifier.matchParentSize())
}
}
Pages.DASHBOARD-> {
SimpleAnimator(
modifier = Modifier.matchParentSize(),
style = AnimationStyle.RIGHT,
isVisible = currentPage == Pages.DASHBOARD
) {
Dashboard(modifier = Modifier.matchParentSize())
}
}
Pages.SIGNIN -> {
SimpleAnimator(
modifier = Modifier.matchParentSize(),
style = AnimationStyle.RIGHT,
isVisible = currentPage == Pages.SIGNIN
) {
Signin(modifier = Modifier.matchParentSize())
}
}
}