Skip to content

Commit a173687

Browse files
author
Patrick Jackson
committed
move to using org.reduxkotlin from maven
1 parent a31c1da commit a173687

23 files changed

+157
-488
lines changed

common/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ kotlin {
3434
implementation "io.ktor:ktor-client-logging:$ktorVersion"
3535
implementation "com.russhwolf:multiplatform-settings:$multiplatformSettingsVersion"
3636
implementation "com.willowtreeapps:fuzzywuzzy-kotlin:0.1.1"
37+
implementation "org.reduxkotlin:redux-kotlin:0.2"
38+
implementation "org.reduxkotlin:redux-kotlin-thunk:0.2"
3739

3840

3941
implementation "io.ktor:ktor-client-core:$ktorVersion"

common/src/commonMain/kotlin/com/beyondeye/reduks/Thunk.kt

Lines changed: 0 additions & 23 deletions
This file was deleted.

common/src/commonMain/kotlin/com/beyondeye/reduks/builders.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ package com.beyondeye.reduks
33
import org.reduxkotlin.Store
44
import org.reduxkotlin.StoreSubscriber
55

6-
class SelectorSubscriberBuilder<S : Any>(val store: Store<S>) {
6+
class SelectorSubscriberBuilder<S : Any>(val store: Store) {
77
val state: S
8-
get() = store.getState()
8+
get() = store.getState() as S
99

1010
var withAnyChangeFun: (() -> Unit)? = null
1111

@@ -35,12 +35,12 @@ class SelectorSubscriberBuilder<S : Any>(val store: Store<S>) {
3535
* }
3636
* }
3737
*/
38-
fun <S : Any> SelectorSubscriberFn(store: Store<S>, selectorSubscriberBuilderInit: SelectorSubscriberBuilder<S>.() -> Unit): StoreSubscriber {
39-
val subBuilder = SelectorSubscriberBuilder(store)
38+
fun <S : Any> SelectorSubscriberFn(store: Store, selectorSubscriberBuilderInit: SelectorSubscriberBuilder<S>.() -> Unit): StoreSubscriber {
39+
val subBuilder = SelectorSubscriberBuilder<S>(store)
4040
subBuilder.selectorSubscriberBuilderInit()
4141
return {
4242
subBuilder.selectorList.forEach { entry ->
43-
entry.key.onChangeIn(store.getState()) { entry.value(store.getState()) }
43+
entry.key.onChangeIn(store.getState() as S) { entry.value(store.getState()) }
4444
}
4545
subBuilder.withAnyChangeFun?.invoke()
4646
}

common/src/commonMain/kotlin/com/willowtreeapps/common/GameEngine.kt

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.willowtreeapps.common
22

33
import org.reduxkotlin.createStore
4-
import com.beyondeye.reduks.createThunkMiddleware
54
import org.reduxkotlin.applyMiddleware
65
import com.willowtreeapps.common.middleware.*
76
import com.willowtreeapps.common.middleware.NavigationMiddleware
@@ -15,6 +14,7 @@ import com.willowtreeapps.common.ui.View
1514
import com.willowtreeapps.common.util.VibrateUtil
1615
import kotlinx.coroutines.CoroutineScope
1716
import kotlinx.coroutines.launch
17+
import org.reduxkotlin.thunk
1818
import kotlin.coroutines.CoroutineContext
1919

2020
class GameEngine(navigator: Navigator,
@@ -28,12 +28,9 @@ class GameEngine(navigator: Navigator,
2828
private val settingsMiddleware by lazy { SettingsMiddleware(LocalStorageSettingsRepository(userSettings(application)), networkContext) }
2929

3030
val appStore by lazy {
31-
createStore(::reducer, AppState.INITIAL_STATE
32-
, applyMiddleware(createThunkMiddleware(),
33-
viewEffectsMiddleware::dispatch,
34-
navigationMiddleware::dispatch,
35-
settingsMiddleware::dispatch,
36-
::loggerMiddleware))
31+
createStore(reducer, AppState.INITIAL_STATE, applyMiddleware(thunk,
32+
navigationMiddleware::dispatch,
33+
settingsMiddleware::dispatch))
3734
}
3835

3936
init {
@@ -49,7 +46,7 @@ class GameEngine(navigator: Navigator,
4946
}
5047

5148
val state: AppState
52-
get() = appStore.state
49+
get() = appStore.state as AppState
5350

5451
fun <T : Presenter<*>> attachView(view: View<T>) = presenterFactory.attachView(view as View<Presenter<*>>)
5552

common/src/commonMain/kotlin/com/willowtreeapps/common/NetworkThunks.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package com.willowtreeapps.common
22

3-
import com.beyondeye.reduks.*
43
import com.willowtreeapps.common.repo.*
54
import kotlinx.coroutines.*
5+
import org.reduxkotlin.Thunk
66
import kotlin.coroutines.CoroutineContext
77

88
/**

common/src/commonMain/kotlin/com/willowtreeapps/common/Reducers.kt

Lines changed: 66 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -4,76 +4,82 @@ import org.reduxkotlin.ActionTypes
44
import com.willowtreeapps.common.Actions.*
55
import com.willowtreeapps.common.util.NO_MATCH
66
import com.willowtreeapps.common.util.match
7+
import org.reduxkotlin.castingReducer
78

89
/**
910
* Reducers and functions used by reducers are in this file. Functions must be pure functions without
1011
* side effects.
1112
*/
12-
fun reducer(state: AppState, action: Any): AppState =
13-
when (action) {
14-
is ActionTypes.INIT -> { AppState.INITIAL_STATE}
15-
is FetchingItemsStartedAction -> state.copy(isLoadingItems = true)
16-
is FetchingItemsSuccessAction -> {
17-
state.copy(isLoadingItems = false,
18-
items = action.itemsHolder.items,
19-
questionTitle = action.itemsHolder.questionTitle,
20-
questions = action.itemsHolder.questions)
21-
}
22-
is FetchingItemsFailedAction -> state.copy(isLoadingItems = false, errorLoadingItems = true, errorMsg = action.message)
23-
is NamePickedAction -> {
24-
val answerName: String?
25-
val status = if (state.currentQuestionItem().equalsDisplayName(action.name)) {
26-
answerName = action.name
27-
Question.Status.CORRECT
28-
} else {
29-
val correctIndex = state.currentQuestion?.choices?.indexOfFirst { it.id == state.currentQuestion?.itemId }
30-
val matchingIndex = match(action.name, state.currentQuestion!!.choices.map { it.displayName() })
31-
when (matchingIndex) {
32-
NO_MATCH -> {
33-
answerName = null
34-
Question.Status.INCORRECT
35-
}
36-
correctIndex -> {
37-
answerName = state.currentQuestion!!.choices[matchingIndex].displayName()
38-
Question.Status.CORRECT
39-
}
40-
else -> {
41-
answerName = state.currentQuestion!!.choices[matchingIndex].displayName()
42-
Question.Status.INCORRECT
43-
}
13+
val reducer= castingReducer { state: AppState, action ->
14+
when (action) {
15+
is ActionTypes.INIT -> {
16+
AppState.INITIAL_STATE
17+
}
18+
is FetchingItemsStartedAction -> state.copy(isLoadingItems = true)
19+
is FetchingItemsSuccessAction -> {
20+
state.copy(isLoadingItems = false,
21+
items = action.itemsHolder.items,
22+
questionTitle = action.itemsHolder.questionTitle,
23+
questions = action.itemsHolder.questions)
24+
}
25+
is FetchingItemsFailedAction -> state.copy(isLoadingItems = false, errorLoadingItems = true, errorMsg = action.message)
26+
is NamePickedAction -> {
27+
val answerName: String?
28+
val status = if (state.currentQuestionItem().equalsDisplayName(action.name)) {
29+
answerName = action.name
30+
Question.Status.CORRECT
31+
} else {
32+
val correctIndex = state.currentQuestion?.choices?.indexOfFirst { it.id == state.currentQuestion?.itemId }
33+
val matchingIndex = match(action.name, state.currentQuestion!!.choices.map { it.displayName() })
34+
when (matchingIndex) {
35+
NO_MATCH -> {
36+
answerName = null
37+
Question.Status.INCORRECT
38+
}
39+
correctIndex -> {
40+
answerName = state.currentQuestion!!.choices[matchingIndex].displayName()
41+
Question.Status.CORRECT
42+
}
43+
else -> {
44+
answerName = state.currentQuestion!!.choices[matchingIndex].displayName()
45+
Question.Status.INCORRECT
4446
}
4547
}
46-
47-
val newQuestions = state.questions.toMutableList()
48-
newQuestions[state.currentQuestionIndex] = newQuestions[state.currentQuestionIndex].copy(answerName = answerName,
49-
status = status,
50-
answerNameInterpretedAs = action.name)
51-
state.copy(questions = newQuestions, waitingForNextQuestion = true)
52-
}
53-
is NextQuestionAction -> state.copy(waitingForNextQuestion = false, currentQuestionIndex = state.currentQuestionIndex + 1)
54-
is GameCompleteAction -> state.copy(waitingForNextQuestion = false, currentQuestionIndex = state.currentQuestionIndex + 1)
55-
is StartOverAction, is ResetGameStateAction -> AppState.INITIAL_STATE.copy(settings = state.settings)
56-
is StartQuestionTimerAction -> state.copy(questionClock = action.initialValue)
57-
is DecrementCountDownAction -> state.copy(questionClock = state.questionClock - 1)
58-
is TimesUpAction -> {
59-
val status = Question.Status.TIMES_UP
60-
val newQuestions = state.questions.toMutableList()
61-
newQuestions[state.currentQuestionIndex] = newQuestions[state.currentQuestionIndex].copy(answerName = "", status = status)
62-
state.copy(questions = newQuestions, waitingForNextQuestion = true, questionClock = -1)
6348
}
6449

65-
is ChangeNumQuestionsSettingsAction -> state.copy(settings = state.settings.copy(numQuestions = action.num))
66-
is ChangeCategorySettingsAction -> state.copy(settings = state.settings.copy(categoryId = action.categoryId))
67-
is ChangeMicrophoneModeSettingsAction -> state.copy(settings = state.settings.copy(microphoneMode = action.enabled))
68-
is SettingsLoadedAction -> state.copy(settings = action.settings)
50+
val newQuestions = state.questions.toMutableList()
51+
newQuestions[state.currentQuestionIndex] = newQuestions[state.currentQuestionIndex].copy(answerName = answerName,
52+
status = status,
53+
answerNameInterpretedAs = action.name)
54+
state.copy(questions = newQuestions, waitingForNextQuestion = true)
55+
}
56+
is NextQuestionAction -> state.copy(waitingForNextQuestion = false, currentQuestionIndex = state.currentQuestionIndex + 1)
57+
is GameCompleteAction -> state.copy(waitingForNextQuestion = false, currentQuestionIndex = state.currentQuestionIndex + 1)
58+
is StartOverAction, is ResetGameStateAction -> AppState.INITIAL_STATE.copy(settings = state.settings)
59+
is StartQuestionTimerAction -> state.copy(questionClock = action.initialValue)
60+
is DecrementCountDownAction -> state.copy(questionClock = state.questionClock - 1)
61+
is TimesUpAction -> {
62+
val status = Question.Status.TIMES_UP
63+
val newQuestions = state.questions.toMutableList()
64+
newQuestions[state.currentQuestionIndex] = newQuestions[state.currentQuestionIndex].copy(answerName = "", status = status)
65+
state.copy(questions = newQuestions, waitingForNextQuestion = true, questionClock = -1)
66+
}
67+
68+
is ChangeNumQuestionsSettingsAction -> state.copy(settings = state.settings.copy(numQuestions = action.num))
69+
is ChangeCategorySettingsAction -> state.copy(settings = state.settings.copy(categoryId = action.categoryId))
70+
is ChangeMicrophoneModeSettingsAction -> state.copy(settings = state.settings.copy(microphoneMode = action.enabled))
71+
is SettingsLoadedAction -> state.copy(settings = action.settings)
6972

70-
is WillowTreeSignInSuccessAction -> state.copy(settings = state.settings.copy(isWillowTree = true))
71-
is WillowTreeSignOutSuccessAction -> state.copy(settings = state.settings.copy(isWillowTree = false))
72-
is LoadAllSettingsAction -> {state}
73+
is WillowTreeSignInSuccessAction -> state.copy(settings = state.settings.copy(isWillowTree = true))
74+
is WillowTreeSignOutSuccessAction -> state.copy(settings = state.settings.copy(isWillowTree = false))
75+
is LoadAllSettingsAction -> {
76+
state
77+
}
7378

74-
else -> {
75-
Logger.d("Action ${action::class.simpleName} not handled")
76-
state
77-
}
79+
else -> {
80+
Logger.d("Action ${action::class.simpleName} not handled")
81+
state
7882
}
83+
}
84+
}
7985

common/src/commonMain/kotlin/com/willowtreeapps/common/TimerThunks.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.willowtreeapps.common
22

3-
import com.beyondeye.reduks.Thunk
43
import kotlinx.coroutines.*
4+
import org.reduxkotlin.Thunk
55
import kotlin.coroutines.CoroutineContext
66

77
class TimerThunks(private val backgroundContext: CoroutineContext) : CoroutineScope {

common/src/commonMain/kotlin/com/willowtreeapps/common/middleware/LoggingMiddleware.kt

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,41 @@ package com.willowtreeapps.common.middleware
33
import org.reduxkotlin.GetState
44
import com.willowtreeapps.common.AppState
55
import com.willowtreeapps.common.Logger
6+
import org.reduxkotlin.Dispatcher
7+
import org.reduxkotlin.Middleware
8+
import org.reduxkotlin.Store
69

7-
fun loggerMiddleware(getState: GetState<AppState>, nextDispatcher: (Any) -> Any, action: Any): Any {
10+
fun loggerMiddleware(getState: GetState, nextDispatcher: (Any) -> Any, action: Any): Any {
811
val result = nextDispatcher(action)
912
Logger.d("DISPATCH action: ${action::class.simpleName}: $action")
1013
return result
1114
}
15+
16+
val loggerMiddleware2: Middleware =
17+
{ store ->
18+
{ next ->
19+
{ action ->
20+
{
21+
val result = next(action)
22+
Logger.d("DISPATCH action: ${action::class.simpleName}: $action")
23+
result
24+
}
25+
}
26+
}
27+
}
28+
29+
val loggerMiddleware3 = middleWare { store, next, action ->
30+
Logger.d("DISPATCH action: ${action::class.simpleName}: $action")
31+
next(action)
32+
}
33+
34+
fun middleWare(dispatch: (Store, Dispatcher, Any) -> Any): Middleware =
35+
{ store ->
36+
{ next ->
37+
{ action: Any ->
38+
{
39+
dispatch(store, next, action)
40+
}
41+
}
42+
}
43+
}
Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
package com.willowtreeapps.common.middleware
22

3-
import org.reduxkotlin.GetState
43
import com.willowtreeapps.common.Actions
5-
import com.willowtreeapps.common.AppState
4+
import org.reduxkotlin.Dispatcher
5+
import org.reduxkotlin.Store
66

77
internal class NavigationMiddleware(private val navigator: Navigator) {
88

9-
fun dispatch(getState: GetState<AppState>, nextDispatcher: (Any) -> Any, action: Any): Any {
10-
val result = nextDispatcher(action)
11-
when (action) {
12-
is Actions.FetchingItemsSuccessAction -> navigator.goto(Screen.QUESTION)
13-
is Actions.GameCompleteAction -> navigator.goto(Screen.GAME_COMPLETE)
14-
is Actions.StartOverAction -> navigator.goto(Screen.START)
15-
is Actions.SettingsTappedAction -> navigator.goto(Screen.SETTINGS)
9+
fun dispatch(store: Store) = { next: Dispatcher ->
10+
{ action: Any ->
11+
when (action) {
12+
is Actions.FetchingItemsSuccessAction -> navigator.goto(Screen.QUESTION)
13+
is Actions.GameCompleteAction -> navigator.goto(Screen.GAME_COMPLETE)
14+
is Actions.StartOverAction -> navigator.goto(Screen.START)
15+
is Actions.SettingsTappedAction -> navigator.goto(Screen.SETTINGS)
16+
}
17+
next(action)
1618
}
17-
return result
1819
}
1920
}
2021

@@ -27,4 +28,4 @@ enum class Screen {
2728

2829
interface Navigator {
2930
fun goto(screen: Screen)
30-
}
31+
}

0 commit comments

Comments
 (0)