Skip to content
Draft

Draft #417

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions api/routing-compose.api
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,14 @@ public final class app/softwork/routingcompose/RouteBuilder {

public final class app/softwork/routingcompose/RouteBuilder$NoMatch {
public static final field $stable I
public fun <init> (Ljava/lang/String;Lapp/softwork/routingcompose/Parameters;)V
public final fun getParameters ()Lapp/softwork/routingcompose/Parameters;
public final fun getRemainingPath ()Ljava/lang/String;
public final fun redirect (Ljava/lang/String;ZLandroidx/compose/runtime/Composer;II)V
}

public abstract interface class app/softwork/routingcompose/Router {
public static final field Companion Lapp/softwork/routingcompose/Router$Companion;
public abstract fun getCurrentPath ()Lapp/softwork/routingcompose/Path;
public abstract fun currentPath ()Lapp/softwork/routingcompose/Path;
public abstract fun getPath (Ljava/lang/String;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
public abstract fun navigate (Ljava/lang/String;Z)V
}
Expand All @@ -77,13 +76,13 @@ public final class app/softwork/routingcompose/Router$DefaultImpls {
}

public final class app/softwork/routingcompose/RouterKt {
public static final fun invoke (Lapp/softwork/routingcompose/Router;Ljava/lang/String;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V
public static final fun navigate (Lapp/softwork/routingcompose/Router;Ljava/lang/String;Lapp/softwork/routingcompose/Parameters;Z)V
public static final fun navigate (Lapp/softwork/routingcompose/Router;Ljava/lang/String;Ljava/util/Map;Z)V
public static synthetic fun navigate$default (Lapp/softwork/routingcompose/Router;Ljava/lang/String;Lapp/softwork/routingcompose/Parameters;ZILjava/lang/Object;)V
public static synthetic fun navigate$default (Lapp/softwork/routingcompose/Router;Ljava/lang/String;Ljava/util/Map;ZILjava/lang/Object;)V
public static final fun navigateParameterList (Lapp/softwork/routingcompose/Router;Ljava/lang/String;Ljava/util/Map;Z)V
public static synthetic fun navigateParameterList$default (Lapp/softwork/routingcompose/Router;Ljava/lang/String;Ljava/util/Map;ZILjava/lang/Object;)V
public static final fun route (Lapp/softwork/routingcompose/Router;Ljava/lang/String;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V
}

public abstract interface annotation class app/softwork/routingcompose/Routing : java/lang/annotation/Annotation {
Expand Down
28 changes: 20 additions & 8 deletions api/routing-compose.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ open annotation class app.softwork.routingcompose/Routing : kotlin/Annotation {
}

abstract interface app.softwork.routingcompose/Router { // app.softwork.routingcompose/Router|null[0]
abstract val currentPath // app.softwork.routingcompose/Router.currentPath|{}currentPath[0]
abstract fun <get-currentPath>(): app.softwork.routingcompose/Path // app.softwork.routingcompose/Router.currentPath.<get-currentPath>|<get-currentPath>(){}[0]

abstract fun currentPath(): app.softwork.routingcompose/Path // app.softwork.routingcompose/Router.currentPath|currentPath(){}[0]
abstract fun getPath(kotlin/String, androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.runtime/State<kotlin/String> // app.softwork.routingcompose/Router.getPath|getPath(kotlin.String;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
abstract fun navigate(kotlin/String, kotlin/Boolean = ...) // app.softwork.routingcompose/Router.navigate|navigate(kotlin.String;kotlin.Boolean){}[0]

Expand Down Expand Up @@ -76,8 +74,6 @@ final class app.softwork.routingcompose/RouteBuilder { // app.softwork.routingco
final fun uuid(kotlin/Function4<app.softwork.routingcompose/RouteBuilder, kotlin.uuid/Uuid, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int) // app.softwork.routingcompose/RouteBuilder.uuid|uuid(kotlin.Function4<app.softwork.routingcompose.RouteBuilder,kotlin.uuid.Uuid,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int){}[0]

final class NoMatch { // app.softwork.routingcompose/RouteBuilder.NoMatch|null[0]
constructor <init>(kotlin/String, app.softwork.routingcompose/Parameters?) // app.softwork.routingcompose/RouteBuilder.NoMatch.<init>|<init>(kotlin.String;app.softwork.routingcompose.Parameters?){}[0]

final val parameters // app.softwork.routingcompose/RouteBuilder.NoMatch.parameters|{}parameters[0]
final fun <get-parameters>(): app.softwork.routingcompose/Parameters? // app.softwork.routingcompose/RouteBuilder.NoMatch.parameters.<get-parameters>|<get-parameters>(){}[0]
final val remainingPath // app.softwork.routingcompose/RouteBuilder.NoMatch.remainingPath|{}remainingPath[0]
Expand All @@ -87,6 +83,24 @@ final class app.softwork.routingcompose/RouteBuilder { // app.softwork.routingco
}
}

final object app.softwork.routingcompose/BrowserRouter : app.softwork.routingcompose/Router { // app.softwork.routingcompose/BrowserRouter|null[0]
final fun currentPath(): app.softwork.routingcompose/Path // app.softwork.routingcompose/BrowserRouter.currentPath|currentPath(){}[0]
final fun equals(kotlin/Any?): kotlin/Boolean // app.softwork.routingcompose/BrowserRouter.equals|equals(kotlin.Any?){}[0]
final fun getPath(kotlin/String, androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.runtime/State<kotlin/String> // app.softwork.routingcompose/BrowserRouter.getPath|getPath(kotlin.String;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
final fun hashCode(): kotlin/Int // app.softwork.routingcompose/BrowserRouter.hashCode|hashCode(){}[0]
final fun navigate(kotlin/String, kotlin/Boolean) // app.softwork.routingcompose/BrowserRouter.navigate|navigate(kotlin.String;kotlin.Boolean){}[0]
final fun toString(): kotlin/String // app.softwork.routingcompose/BrowserRouter.toString|toString(){}[0]
}

final object app.softwork.routingcompose/HashRouter : app.softwork.routingcompose/Router { // app.softwork.routingcompose/HashRouter|null[0]
final fun currentPath(): app.softwork.routingcompose/Path // app.softwork.routingcompose/HashRouter.currentPath|currentPath(){}[0]
final fun equals(kotlin/Any?): kotlin/Boolean // app.softwork.routingcompose/HashRouter.equals|equals(kotlin.Any?){}[0]
final fun getPath(kotlin/String, androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.runtime/State<kotlin/String> // app.softwork.routingcompose/HashRouter.getPath|getPath(kotlin.String;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
final fun hashCode(): kotlin/Int // app.softwork.routingcompose/HashRouter.hashCode|hashCode(){}[0]
final fun navigate(kotlin/String, kotlin/Boolean) // app.softwork.routingcompose/HashRouter.navigate|navigate(kotlin.String;kotlin.Boolean){}[0]
final fun toString(): kotlin/String // app.softwork.routingcompose/HashRouter.toString|toString(){}[0]
}

final val app.softwork.routingcompose/app_softwork_routingcompose_BrowserRouter$stableprop // app.softwork.routingcompose/app_softwork_routingcompose_BrowserRouter$stableprop|#static{}app_softwork_routingcompose_BrowserRouter$stableprop[0]
final val app.softwork.routingcompose/app_softwork_routingcompose_DelegateRouter$stableprop // app.softwork.routingcompose/app_softwork_routingcompose_DelegateRouter$stableprop|#static{}app_softwork_routingcompose_DelegateRouter$stableprop[0]
final val app.softwork.routingcompose/app_softwork_routingcompose_HashRouter$stableprop // app.softwork.routingcompose/app_softwork_routingcompose_HashRouter$stableprop|#static{}app_softwork_routingcompose_HashRouter$stableprop[0]
Expand All @@ -95,12 +109,10 @@ final val app.softwork.routingcompose/app_softwork_routingcompose_Path$stablepro
final val app.softwork.routingcompose/app_softwork_routingcompose_RouteBuilder$stableprop // app.softwork.routingcompose/app_softwork_routingcompose_RouteBuilder$stableprop|#static{}app_softwork_routingcompose_RouteBuilder$stableprop[0]
final val app.softwork.routingcompose/app_softwork_routingcompose_RouteBuilder_NoMatch$stableprop // app.softwork.routingcompose/app_softwork_routingcompose_RouteBuilder_NoMatch$stableprop|#static{}app_softwork_routingcompose_RouteBuilder_NoMatch$stableprop[0]

final fun (app.softwork.routingcompose/Router).app.softwork.routingcompose/invoke(kotlin/String, kotlin/Function3<app.softwork.routingcompose/RouteBuilder, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int) // app.softwork.routingcompose/invoke|invoke@app.softwork.routingcompose.Router(kotlin.String;kotlin.Function3<app.softwork.routingcompose.RouteBuilder,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
final fun (app.softwork.routingcompose/Router).app.softwork.routingcompose/navigate(kotlin/String, app.softwork.routingcompose/Parameters, kotlin/Boolean = ...) // app.softwork.routingcompose/navigate|navigate@app.softwork.routingcompose.Router(kotlin.String;app.softwork.routingcompose.Parameters;kotlin.Boolean){}[0]
final fun (app.softwork.routingcompose/Router).app.softwork.routingcompose/navigate(kotlin/String, kotlin.collections/Map<kotlin/String, kotlin.collections/List<kotlin/String>>, kotlin/Boolean = ...) // app.softwork.routingcompose/navigate|navigate@app.softwork.routingcompose.Router(kotlin.String;kotlin.collections.Map<kotlin.String,kotlin.collections.List<kotlin.String>>;kotlin.Boolean){}[0]
final fun (app.softwork.routingcompose/Router).app.softwork.routingcompose/navigate(kotlin/String, kotlin.collections/Map<kotlin/String, kotlin/String>, kotlin/Boolean = ...) // app.softwork.routingcompose/navigate|navigate@app.softwork.routingcompose.Router(kotlin.String;kotlin.collections.Map<kotlin.String,kotlin.String>;kotlin.Boolean){}[0]
final fun (app.softwork.routingcompose/Router).app.softwork.routingcompose/route(kotlin/String, kotlin/Function3<app.softwork.routingcompose/RouteBuilder, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int) // app.softwork.routingcompose/route|route@app.softwork.routingcompose.Router(kotlin.String;kotlin.Function3<app.softwork.routingcompose.RouteBuilder,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
final fun app.softwork.routingcompose/BrowserRouter(kotlin/String, kotlin/Function3<app.softwork.routingcompose/RouteBuilder, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int) // app.softwork.routingcompose/BrowserRouter|BrowserRouter(kotlin.String;kotlin.Function3<app.softwork.routingcompose.RouteBuilder,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
final fun app.softwork.routingcompose/HashRouter(kotlin/String, kotlin/Function3<app.softwork.routingcompose/RouteBuilder, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int) // app.softwork.routingcompose/HashRouter|HashRouter(kotlin.String;kotlin.Function3<app.softwork.routingcompose.RouteBuilder,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
final fun app.softwork.routingcompose/app_softwork_routingcompose_BrowserRouter$stableprop_getter(): kotlin/Int // app.softwork.routingcompose/app_softwork_routingcompose_BrowserRouter$stableprop_getter|app_softwork_routingcompose_BrowserRouter$stableprop_getter(){}[0]
final fun app.softwork.routingcompose/app_softwork_routingcompose_DelegateRouter$stableprop_getter(): kotlin/Int // app.softwork.routingcompose/app_softwork_routingcompose_DelegateRouter$stableprop_getter|app_softwork_routingcompose_DelegateRouter$stableprop_getter(){}[0]
final fun app.softwork.routingcompose/app_softwork_routingcompose_HashRouter$stableprop_getter(): kotlin/Int // app.softwork.routingcompose/app_softwork_routingcompose_HashRouter$stableprop_getter|app_softwork_routingcompose_HashRouter$stableprop_getter(){}[0]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package app.softwork.routingcompose

internal class DelegateRouter(val basePath: String, val router: Router) : Router by router {
internal data class DelegateRouter(val basePath: String, val router: Router) : Router by router {
override fun navigate(to: String, hide: Boolean) {
when {
to.startsWith("/") -> {
Expand All @@ -11,8 +11,8 @@ internal class DelegateRouter(val basePath: String, val router: Router) : Router
router.navigate("/$to", hide)
}

to.startsWith(".") -> {
val newPath = router.currentPath.relative(to)
to.startsWith("./") -> {
val newPath = router.currentPath().relative(to)
router.navigate(newPath.path)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package app.softwork.routingcompose

import androidx.compose.runtime.Immutable
import kotlin.jvm.*

@Immutable
public class Parameters private constructor(public val raw: String, public val map: Map<String, List<String>>) {
public companion object {
private val reservedCharacters = mapOf(
Expand Down
3 changes: 3 additions & 0 deletions src/commonMain/kotlin/app/softwork/routingcompose/Path.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package app.softwork.routingcompose

import androidx.compose.runtime.Immutable

@Immutable
public data class Path(val path: String, val parameters: Parameters?) {
internal fun newPath(currentPath: String) = Path(path = path.removePrefix("/$currentPath"), parameters)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import kotlin.uuid.*
* ```
*/
@Routing
@Stable
public class RouteBuilder internal constructor(private val basePath: String, private val remainingPath: Path) {
public val path: String = remainingPath.path
public val parameters: Parameters? = remainingPath.parameters
Expand Down Expand Up @@ -156,8 +157,9 @@ public class RouteBuilder internal constructor(private val basePath: String, pri
}
}

@Immutable
@Routing
public class NoMatch(public val remainingPath: String, public val parameters: Parameters?) {
public class NoMatch internal constructor(public val remainingPath: String, public val parameters: Parameters?) {
@Routing
@Composable
public fun redirect(target: String, hide: Boolean = false) {
Expand Down
6 changes: 4 additions & 2 deletions src/commonMain/kotlin/app/softwork/routingcompose/Router.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package app.softwork.routingcompose
import androidx.compose.runtime.*
import kotlin.jvm.*

@Stable
public interface Router {
/**
* The current path
*/
public val currentPath: Path
public fun currentPath(): Path

public fun navigate(to: String, hide: Boolean = false)

Expand All @@ -33,8 +34,9 @@ public interface Router {
internal val RouterCompositionLocal: ProvidableCompositionLocal<Router> =
compositionLocalOf { error("Router not defined, cannot provide through RouterCompositionLocal.") }

@Routing
@Composable
public fun Router.route(
public operator fun Router.invoke(
initRoute: String,
routing: @Composable RouteBuilder.() -> Unit
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ package app.softwork.routingcompose
import androidx.compose.runtime.*

class MockRouter : Router {
override val currentPath: Path
get() = Path.from(currentState.value!!)
override fun currentPath() = Path.from(currentState.value!!)

private val currentState = mutableStateOf<String?>(null)

Expand All @@ -16,7 +15,3 @@ class MockRouter : Router {
currentState.value = to
}
}

@Composable
operator fun MockRouter.invoke(initPath: String, routeBuilder: @Composable RouteBuilder.() -> Unit) =
route(initPath, routeBuilder)
2 changes: 1 addition & 1 deletion src/jsMain/kotlin/app/softwork/routingcompose/NavLink.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public fun NavLink(
A(
href = to,
attrs = {
val currentPath = router.currentPath.path
val currentPath = router.currentPath().path
val selected = if (to == "/") {
currentPath == to
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,8 @@ import androidx.compose.runtime.*
* For development environments, see the RoutingCompose Readme
* for full instructions.
*/
@Composable
public fun BrowserRouter(
initPath: String,
routeBuilder: @Composable RouteBuilder.() -> Unit
) {
BrowserRouter().route(initPath, routeBuilder)
}

internal class BrowserRouter : Router {
override val currentPath: Path
get() = Path.from(currentLocation.value)
public data object BrowserRouter : Router {
override fun currentPath(): Path = Path.from(currentLocation.value)

private val currentLocation: MutableState<String> = mutableStateOf(window.location.newPath())

Expand Down
13 changes: 2 additions & 11 deletions src/jsSharedMain/kotlin/app/softwork/routingcompose/HashRouter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,8 @@ import androidx.compose.runtime.*
* Every request will always request `GET /`, so your server needs only to listen and serve this endpoint,
* or using a SaaS `/index.html`.
*/
@Composable
public fun HashRouter(
initPath: String,
routeBuilder: @Composable RouteBuilder.() -> Unit
) {
HashRouter().route(initPath, routeBuilder)
}

internal class HashRouter : Router {
override val currentPath: Path
get() = Path.from(currentHash.value)
public data object HashRouter : Router {
override fun currentPath(): Path = Path.from(currentHash.value)

private val currentHash: MutableState<String> = mutableStateOf(window.location.hash.currentURL() ?: "")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ internal class RouterTest {
fun relativeRoutingTest() = runTest {
var router: Router = MockRouter()
composition {
router.route("/") {
router("/") {
route("foo") {
int {
uuid {
Expand Down
17 changes: 13 additions & 4 deletions src/jvmMain/kotlin/app/softwork/routingcompose/DesktopRouter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ import androidx.compose.runtime.*
*
* To get the current [Router] inside the [navBuilder] `@Composable` tree call [Router.current].
*/
@Routing
@Composable
public fun DesktopRouter(initRoute: String, navBuilder: @Composable RouteBuilder.() -> Unit) {
DesktopRouter().route(initRoute, navBuilder)
DesktopRouter().invoke(initRoute, navBuilder)
}

internal class DesktopRouter : Router {
override val currentPath: Path
get() = Path.from(stack.last().path)
override fun currentPath() = Path.from(stack.last().path)

private data class Entry(val path: String, val hide: Boolean)

Expand All @@ -37,6 +35,17 @@ internal class DesktopRouter : Router {
internal fun navigateBack() {
stack.removeAt(stack.lastIndex)
}

override fun equals(other: Any?): Boolean {
if (other !is DesktopRouter) {
return false
}
return stack == other.stack
}

override fun hashCode(): Int {
return stack.hashCode()
}
}

public fun Router.navigateBack() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class RoutingNodeTest {
val router: Router = DesktopRouter()
var result: String? = null
rule.setContent {
router.route("/") {
router("/") {
int { i ->
result = "$i"
}
Expand All @@ -41,7 +41,7 @@ class RoutingNodeTest {
val router: Router = DesktopRouter()
var result: String? = null
rule.setContent {
router.route("/") {
router("/") {
int { user ->
result = "$user"
int { i ->
Expand Down