Skip to content

Commit 6fdeb27

Browse files
author
Mohanraj K.M
committed
Update README
1 parent 4d8d391 commit 6fdeb27

File tree

1 file changed

+204
-1
lines changed

1 file changed

+204
-1
lines changed

README.md

+204-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,204 @@
1-
A declarative router for [ReKotlin](https://github.com/GeoThings/ReKotlin). Allows developers to declare routes in a similar manner as URLs are used on the web.
1+
A declarative router for [ReKotlin](https://github.com/GeoThings/ReKotlin). Allows developers to declare routes in a similar manner as URLs are used on the web.
2+
3+
Using ReKotlinRouter you can navigate your app by defining the target location in the form of a URL-like sequence of identifiers:
4+
5+
```Kotlin
6+
val routes = arrayListOf(loginRoute, repoListRoute, repoDetailRoute)
7+
val actionData = SetRouteSpecificData(route = routes, data = "somedata")
8+
val action = SetRouteAction(route = routes)
9+
mainStore.dispatch(actionData)
10+
mainStore.dispatch(action)
11+
```
12+
13+
# About ReKotlinRouter
14+
15+
16+
When building apps with ReKotlin you should aim to cause **all** state changes through actions - this includes changes to the navigation state.
17+
18+
This requires to store the current navigation state within the app state and to use actions to trigger changes to that state - both is provided ReKotlinRouter.
19+
20+
# Installation
21+
Add the following line along with ReKotlin dependencies in gradle file
22+
23+
```Groovy
24+
implementation 'org.rekotlinrouter:rekotlin-router:0.1.0'
25+
```
26+
27+
# Configuration
28+
29+
Extend your app state to include the navigation state:
30+
31+
```Kotlin
32+
import org.rekotlinrouter.HasNavigationState
33+
import org.rekotlinrouter.NavigationState
34+
import tw.geothings.rekotlin.StateType
35+
36+
data class AppState(override var navigationState: NavigationState,
37+
// other application states such as....
38+
var authenticationState: AuthenticationState,
39+
var repoListState: RepoListState): StateType, HasNavigationState
40+
41+
```
42+
43+
After you've initialized your store, create an instance of `Router`, passing in a reference to the store and to the root `Routable`. Additionally you will need to provide a closure that describes how to access the `navigationState` of your application state:
44+
45+
```Kotlin
46+
router = Router(store = mainStore,
47+
rootRoutable = RootRoutable(context = applicationContext),
48+
stateTransform = { subscription ->
49+
subscription.select { stateType ->
50+
stateType.navigationState
51+
}
52+
})
53+
```
54+
55+
We'll discuss `Routable` in the next main section.
56+
57+
## Calling the Navigation Reducer
58+
59+
The `NavigationReducer` is provided as part of `ReKotlinRouter`. You need to call it from within your top-level reducer. Here's a simple example from the specs:
60+
61+
```Kotlin
62+
63+
fun appReducer(action: Action, oldState: GitHubAppState?) : GitHubAppState {
64+
65+
// if no state has been provided, create the default state
66+
val state = oldState ?: GitHubAppState(
67+
navigationState = NavigationReducer.handleAction(action = action, state = oldState?.navigationState),
68+
// other application state reducers such as....
69+
authenticationState = AuthenticationState(loggedInState = LoggedInState.loggedIn,
70+
userName = ""),
71+
repoListState = RepoListState())
72+
73+
return state.copy(
74+
navigationState = (::navigationReducer)(action, state.navigationState),
75+
// other application state reducers such as....
76+
authenticationState = (::authenticationReducer)(action, state.authenticationState),
77+
repoListState = (::repoListReducer)(action, state.repoListState))
78+
}
79+
80+
fun navigationReducer(action: Action, oldState: NavigationState?): NavigationState {
81+
val state = oldState ?: NavigationReducer.handleAction(action = action, state = oldState)
82+
when (action) {
83+
is SetRouteAction -> {
84+
return NavigationReducer.handleAction(action = action, state = state)
85+
}
86+
87+
is SetRouteSpecificData -> {
88+
return NavigationReducer.handleAction(action = action, state = state)
89+
}
90+
}
91+
return state
92+
}
93+
94+
```
95+
This will make reducer handle all routing relevant actions.
96+
97+
# Implementing `Routable`
98+
99+
ReKotlinRouter works with routes that are defined, similar to URLs, as a sequence of identifiers e.g. `["Home", "User", "UserDetail"]`. It uses `Routable`s to implement that interaction.
100+
101+
Each route segment is mapped to one responsible `Routable`. The `Routable` needs to be able to present a child, hide a child or replace a child with another child.
102+
103+
Here is the `Routable` protocol with the methods you should implement:
104+
105+
```Kotlin
106+
interface Routable {
107+
108+
fun pushRouteSegment(routeElementIdentifier: RouteElementIdentifier,
109+
animated: Boolean,
110+
completionHandler: RoutingCompletionHandler): Routable
111+
112+
fun popRouteSegment(routeElementIdentifier: RouteElementIdentifier,
113+
animated: Boolean,
114+
completionHandler: RoutingCompletionHandler)
115+
116+
fun changeRouteSegment(from: RouteElementIdentifier,
117+
to: RouteElementIdentifier,
118+
animated: Boolean,
119+
completionHandler: RoutingCompletionHandler): Routable
120+
}
121+
```
122+
123+
As part of initializing `Router` you need to pass the first `Routable` as an argument. That root `Routable` will be responsible for the first route segment.
124+
125+
If e.g. you set the route of your application to `["Home"]`, your root `Routable` will be asked to present the view that corresponds to the identifier `"Home"`.
126+
127+
128+
Whenever a `Routable` presents a new route segment, it needs to return a new `Routable` that will be responsible for managing the presented segment. If you want to navigate from `["Home"]` to `["Home", "Users"]` the `Routable` responsible for the `"Home"` segment will be asked to present the `"User"` segment.
129+
130+
If your navigation stack uses a modal presentation for this transition, the implementation of `Routable` for the `"Root"` segment might look like this:
131+
132+
```Kotlin
133+
134+
class RootRoutable(val context: Context): Routable {
135+
override fun popRouteSegment(routeElementIdentifier: RouteElementIdentifier,
136+
animated: Boolean,
137+
completionHandler: RoutingCompletionHandler) {
138+
}
139+
140+
override fun pushRouteSegment(routeElementIdentifier: RouteElementIdentifier,
141+
animated: Boolean,
142+
completionHandler: RoutingCompletionHandler): Routable {
143+
if(routeElementIdentifier == loginRoute) {
144+
return LoginRoutable(context)
145+
} else if (routeElementIdentifier == welcomeRoute) {
146+
return RoutableHelper.createWelcomeRoutable(context)
147+
}
148+
149+
return LoginRoutable(context)
150+
}
151+
152+
override fun changeRouteSegment(from: RouteElementIdentifier,
153+
to: RouteElementIdentifier,
154+
animated: Boolean,
155+
completionHandler: RoutingCompletionHandler): Routable {
156+
TODO("not implemented")
157+
}
158+
159+
}
160+
161+
object RoutableHelper {
162+
163+
fun createWelcomeRoutable(context: Context): WelcomeRoutable {
164+
val welcomeIntent = Intent(context, WelcomeActivity::class.java)
165+
welcomeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
166+
context.startActivity(welcomeIntent)
167+
return WelcomeRoutable(context)
168+
}
169+
}
170+
171+
```
172+
173+
## Calling the Completion Handler within Routables
174+
175+
//TODO:
176+
ReKotlinRouter needs to throttle the navigation actions, since many UI frameworks don't allow to perform multiple navigation steps in parallel. Therefor every method of `Routable` receives a `completionHandler`. The router will not perform any further navigation actions until the completion handler is called.
177+
178+
# Changing the Current Route
179+
180+
Currently the only way to change the current application route is by using the `SetRouteAction` and providing an absolute route. Here's a brief example:
181+
182+
```Kotlin
183+
mEmailSignInButton.setOnClickListener {
184+
mainStore.dispatch(LoginAction(userName = mETEmail.text.toString(),
185+
password = mETPassword.text.toString()))
186+
}
187+
```
188+
As development continues, support for changing individual route segments will be added.
189+
190+
## Bugs and Feedback
191+
192+
For bugs, feature requests, and discussion please use [GitHub Issues][issues].
193+
For general usage questions please use the [mailing list][list] or [StackOverflow][so].
194+
195+
# Contributing
196+
197+
## Compiling & Running tests
198+
199+
To build or test any of the targets, run `gradle assemble`.
200+
201+
## Credits
202+
203+
- Many thanks to [Benjamin Encz](https://github.com/Ben-G) and other ReSwift contributors for buidling original [ReSwift](https://github.com/ReSwift/ReSwift) that we really enjoyed working with.
204+
- Also huge thanks to [Dan Abramov](https://github.com/gaearon) for building [Redux](https://github.com/reactjs/redux) - all ideas in here and many implementation details were provided by his library.

0 commit comments

Comments
 (0)