-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Switch to Redux style view presentation in ItemDetailView.
- Loading branch information
Showing
5 changed files
with
126 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 84 additions & 26 deletions
110
presentation/src/main/kotlin/clean/news/presentation/model/item/ItemDetailViewModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,112 @@ | ||
package clean.news.presentation.model.item | ||
|
||
import clean.news.app.usecase.item.GetChildren | ||
import clean.news.app.usecase.item.GetChildren.Request | ||
import clean.news.core.entity.Item | ||
import clean.news.presentation.collections.StreamMap | ||
import clean.news.presentation.collections.streamMapOf | ||
import clean.news.presentation.inject.ScreenScope | ||
import clean.news.presentation.model.Model | ||
import clean.news.presentation.model.item.ItemDetailViewModel.Sinks | ||
import clean.news.presentation.model.item.ItemDetailViewModel.Sources | ||
import clean.news.presentation.model.item.ItemDetailViewModel.Action.GoBack | ||
import clean.news.presentation.model.item.ItemDetailViewModel.Action.GoToUrl | ||
import clean.news.presentation.model.item.ItemDetailViewModel.Action.Share | ||
import clean.news.presentation.model.item.ItemDetailViewModel.Action.ShowChildren | ||
import clean.news.presentation.navigation.NavigationFactory | ||
import clean.news.presentation.navigation.NavigationFactory.ItemDetailScreen | ||
import clean.news.presentation.navigation.NavigationService | ||
import redux.Dispatcher | ||
import redux.Middleware | ||
import redux.Reducer | ||
import redux.Store | ||
import redux.logger.Logger | ||
import redux.logger.Logger.Event | ||
import redux.logger.LoggerMiddleware | ||
import redux.observable.Epic | ||
import redux.observable.EpicMiddleware | ||
import rx.Observable | ||
import rx.Scheduler | ||
import javax.inject.Inject | ||
|
||
@ScreenScope(ItemDetailScreen::class) | ||
class ItemDetailViewModel @Inject constructor( | ||
private val observeScheduler: Scheduler, | ||
private val navService: NavigationService, | ||
private val navFactory: NavigationFactory, | ||
private val getChildren: GetChildren, | ||
private val item: Item) : Model<Sources, Sinks>() { | ||
item: Item) { | ||
|
||
private val children = getChildren.execute(Request(item)) | ||
.map { it.items } | ||
.replay(1) | ||
.autoConnect() | ||
// State | ||
|
||
override fun bind(sources: StreamMap<Sources>): StreamMap<Sinks> { | ||
Sources.BACK_CLICKS<Unit>(sources) | ||
.subscribe { navService.goBack() } | ||
data class State( | ||
val item: Item, | ||
val children: List<Item>, | ||
val loading: Boolean) | ||
|
||
Sources.URL_CLICKS<Unit>(sources) | ||
.subscribe { navService.replaceTo(navFactory.url(item)) } | ||
private val initialState = State(item, listOf(item), false) | ||
|
||
Sources.SHARE_CLICKS<Unit>(sources) | ||
.subscribe { navService.goTo(navFactory.shareDetail(item)) } | ||
// Actions | ||
|
||
return streamMapOf( | ||
Sinks.ITEM to Observable.just(item), | ||
Sinks.CHILDREN to children | ||
) | ||
sealed class Action { | ||
class GetChildren(val item: Item) : Action() | ||
class ShowChildren(val children: List<Item>) : Action() | ||
class GoBack() : Action() | ||
class GoToUrl() : Action() | ||
class Share() : Action() | ||
} | ||
|
||
enum class Sources : Key { | ||
BACK_CLICKS, URL_CLICKS, SHARE_CLICKS | ||
// Reducer | ||
|
||
private val reducer = object : Reducer<State> { | ||
override fun reduce(state: State, action: Any): State { | ||
return when (action) { | ||
is ShowChildren -> state.copy(children = action.children) | ||
else -> state | ||
} | ||
} | ||
} | ||
|
||
// Middleware | ||
|
||
private val logger = object : Logger<State> { | ||
override fun log(event: Event, action: Any, state: State) { | ||
|
||
} | ||
} | ||
private val epic = object : Epic<State> { | ||
override fun map(actions: Observable<out Any>, store: Store<State>): Observable<out Any> { | ||
return actions.ofType(Action.GetChildren::class.java) | ||
.flatMap { | ||
getChildren.execute(GetChildren.Request(it.item)) | ||
.observeOn(observeScheduler) | ||
} | ||
.map { Action.ShowChildren(it.items) } | ||
} | ||
} | ||
|
||
enum class Sinks : Key { | ||
ITEM, CHILDREN | ||
private val loggerMiddleware = LoggerMiddleware.create(logger) | ||
private val epicMiddleware = EpicMiddleware.create(epic) | ||
private val navigationMiddleware = object : Middleware<State> { | ||
override fun dispatch(store: Store<State>, action: Any, next: Dispatcher): Any { | ||
when (action) { | ||
is GoBack -> navService.goBack() | ||
is GoToUrl -> navService.goTo(navFactory.url(item)) | ||
is Share -> navService.goTo(navFactory.shareDetail(item)) | ||
} | ||
return action | ||
} | ||
|
||
} | ||
|
||
// Store | ||
|
||
val store = Store.create( | ||
reducer, | ||
initialState, | ||
Middleware.apply( | ||
loggerMiddleware, | ||
epicMiddleware, | ||
navigationMiddleware | ||
) | ||
) | ||
|
||
init { | ||
store.dispatch(Action.GetChildren(item)) | ||
} | ||
|
||
} |