Skip to content

Commit

Permalink
Add NotificationsTab
Browse files Browse the repository at this point in the history
  • Loading branch information
matt-ramotar committed Apr 24, 2024
1 parent 308558a commit 2abcee2
Show file tree
Hide file tree
Showing 18 changed files with 200 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class MainActivity : ComponentActivity() {

val homeTab = remember { coreComponent.screenFactory.homeTab() }
val exploreTab = remember { coreComponent.screenFactory.exploreTab() }
val notificationsTab = remember { coreComponent.screenFactory.notificationsTab()}
val activeScreen = remember { mutableStateOf<Screen>(homeTab) }

OctonautTheme {
Expand Down Expand Up @@ -90,7 +91,9 @@ class MainActivity : ComponentActivity() {
}

IconButton(
onClick = {}
onClick = {
activeScreen.value = notificationsTab
}
) {
Icon(Icons.Default.Notifications, "")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,26 @@ import com.slack.circuit.runtime.Navigator
import com.slack.circuit.runtime.presenter.Presenter
import com.slack.circuit.runtime.screen.Screen
import me.tatarka.inject.annotations.Inject
import org.mobilenativefoundation.sample.octonaut.xplat.feat.NotificationsTabPresenter
import org.mobilenativefoundation.sample.octonaut.xplat.feat.exploreTab.api.ExploreTab
import org.mobilenativefoundation.sample.octonaut.xplat.feat.exploreTab.impl.ExploreTabPresenter
import org.mobilenativefoundation.sample.octonaut.xplat.feat.homeTab.api.HomeTab
import org.mobilenativefoundation.sample.octonaut.xplat.feat.homeTab.impl.HomeTabPresenter
import org.mobilenativefoundation.sample.octonaut.xplat.feat.notificationsTab.api.NotificationsTab
import org.mobilenativefoundation.sample.octonaut.xplat.foundation.di.api.UserScope

@Inject
@UserScope
class OctonautPresenterFactory(
private val homeTabPresenter: HomeTabPresenter,
private val exploreTabPresenter: ExploreTabPresenter
private val exploreTabPresenter: ExploreTabPresenter,
private val notificationsTabPresenter: NotificationsTabPresenter
) : Presenter.Factory {
override fun create(screen: Screen, navigator: Navigator, context: CircuitContext): Presenter<*>? {
return when (screen) {
is HomeTab -> homeTabPresenter
is ExploreTab -> exploreTabPresenter
is NotificationsTab -> notificationsTabPresenter
else -> null
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ package org.mobilenativefoundation.sample.octonaut.android.app.circuit
import me.tatarka.inject.annotations.Inject
import org.mobilenativefoundation.sample.octonaut.xplat.feat.exploreTab.api.ExploreTab
import org.mobilenativefoundation.sample.octonaut.xplat.feat.homeTab.api.HomeTab
import org.mobilenativefoundation.sample.octonaut.xplat.feat.notificationsTab.api.NotificationsTab
import org.mobilenativefoundation.sample.octonaut.xplat.foundation.di.api.UserScope

@Inject
@UserScope
class OctonautScreenFactory(
private val homeTab: HomeTab,
private val exploreTab: ExploreTab
private val exploreTab: ExploreTab,
private val notificationsTab: NotificationsTab
) : ScreenFactory {
override fun homeTab(): HomeTab = homeTab
override fun exploreTab(): ExploreTab = exploreTab
override fun notificationsTab(): NotificationsTab = notificationsTab
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,26 @@ import com.slack.circuit.runtime.CircuitContext
import com.slack.circuit.runtime.screen.Screen
import com.slack.circuit.runtime.ui.Ui
import me.tatarka.inject.annotations.Inject
import org.mobilenativefoundation.sample.octonaut.xplat.feat.NotificationsTabUi
import org.mobilenativefoundation.sample.octonaut.xplat.feat.exploreTab.api.ExploreTab
import org.mobilenativefoundation.sample.octonaut.xplat.feat.exploreTab.impl.ExploreTabUi
import org.mobilenativefoundation.sample.octonaut.xplat.feat.homeTab.api.HomeTab
import org.mobilenativefoundation.sample.octonaut.xplat.feat.homeTab.impl.HomeTabUi
import org.mobilenativefoundation.sample.octonaut.xplat.feat.notificationsTab.api.NotificationsTab
import org.mobilenativefoundation.sample.octonaut.xplat.foundation.di.api.UserScope

@Inject
@UserScope
class OctonautUiFactory(
private val homeTabUi: HomeTabUi,
private val exploreTabUi: ExploreTabUi
private val exploreTabUi: ExploreTabUi,
private val notificationsTabUi: NotificationsTabUi
) : Ui.Factory {
override fun create(screen: Screen, context: CircuitContext): Ui<*>? {
return when (screen) {
is HomeTab -> homeTabUi
is ExploreTab -> exploreTabUi
is NotificationsTab -> notificationsTabUi
else -> null
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package org.mobilenativefoundation.sample.octonaut.android.app.circuit

import org.mobilenativefoundation.sample.octonaut.xplat.feat.exploreTab.api.ExploreTab
import org.mobilenativefoundation.sample.octonaut.xplat.feat.homeTab.api.HomeTab
import org.mobilenativefoundation.sample.octonaut.xplat.feat.notificationsTab.api.NotificationsTab

interface ScreenFactory {
fun homeTab(): HomeTab
fun exploreTab(): ExploreTab
fun notificationsTab(): NotificationsTab
}

Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ import org.mobilenativefoundation.sample.octonaut.xplat.domain.notifications.imp
import org.mobilenativefoundation.sample.octonaut.xplat.domain.user.api.UserStore
import org.mobilenativefoundation.sample.octonaut.xplat.domain.user.api.UserSupplier
import org.mobilenativefoundation.sample.octonaut.xplat.domain.user.impl.UserStoreFactory
import org.mobilenativefoundation.sample.octonaut.xplat.feat.*
import org.mobilenativefoundation.sample.octonaut.xplat.feat.exploreTab.api.ExploreTab
import org.mobilenativefoundation.sample.octonaut.xplat.feat.exploreTab.impl.*
import org.mobilenativefoundation.sample.octonaut.xplat.feat.homeTab.api.HomeTab
import org.mobilenativefoundation.sample.octonaut.xplat.feat.homeTab.impl.*
import org.mobilenativefoundation.sample.octonaut.xplat.feat.notificationsTab.api.NotificationsTab
import org.mobilenativefoundation.sample.octonaut.xplat.foundation.di.api.UserScope
import org.mobilenativefoundation.sample.octonaut.xplat.foundation.networking.api.GetUserQuery
import org.mobilenativefoundation.sample.octonaut.xplat.foundation.networking.api.ListNotificationsResponse
Expand Down Expand Up @@ -221,6 +223,37 @@ abstract class CoreComponent : NetworkingComponent {
fun provideHttpClient(): HttpClient = httpClient()


@Provides
@UserScope
fun provideNotificationsTabWarehouseFactory(
notificationsSupplier: NotificationsSupplier,
warehouseBuilderFactory: WarehouseBuilderFactory
): NotificationsTabWarehouseFactory {
return NotificationsTabWarehouseFactory(notificationsSupplier, warehouseBuilderFactory)
}

@Provides
@UserScope
fun provideNotificationsTabWarehouse(
homeTabWarehouseFactory: NotificationsTabWarehouseFactory
): NotificationsTabWarehouse {
return homeTabWarehouseFactory.create()
}

@Provides
fun provideNotificationsTabPresenter(
warehouse: NotificationsTabWarehouse
): NotificationsTabPresenter {
return NotificationsTabPresenter(warehouse)
}

@Provides
fun provideNotificationsTabUi(): NotificationsTabUi = NotificationsTabUi()

@Provides
fun provideNotificationsTab(): NotificationsTab = RealNotificationsTab


companion object
}

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.mobilenativefoundation.store.store5.Fetcher
import org.mobilenativefoundation.store.store5.StoreBuilder

// TODO: Scheduled reverse paging
// TODO: Scheduled paging

@Inject
class NotificationsStoreFactory(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ kotlin {
api(libs.kotlinInject.runtime)
api(project(":experimental:sample:octonaut:xplat:foundation:networking:api"))
api(project(":experimental:sample:octonaut:xplat:domain:user:api"))
api(project(":experimental:sample:octonaut:xplat:domain:notifications:api"))
api(project(":experimental:sample:octonaut:xplat:foundation:di:api"))
api(project(":store"))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.mobilenativefoundation.sample.octonaut.xplat.feat.notificationsTab.a
import com.slack.circuit.runtime.CircuitUiEvent
import com.slack.circuit.runtime.CircuitUiState
import com.slack.circuit.runtime.screen.Screen
import org.mobilenativefoundation.sample.octonaut.xplat.domain.notifications.api.Notification
import org.mobilenativefoundation.sample.octonaut.xplat.domain.user.api.User
import com.slack.circuit.runtime.presenter.Presenter as CircuitPresenter
import com.slack.circuit.runtime.ui.Ui as CircuitUi
Expand All @@ -11,11 +12,16 @@ interface NotificationsTab : Screen {
sealed interface State : CircuitUiState {
data object Initial : State
data class Loaded(
val user: User,
val notifications: List<Notification>,
val eventSink: (Event) -> Unit
) : State
data object Loading: State

}

sealed interface Event : CircuitUiEvent
sealed interface Event : CircuitUiEvent {
data class MarkDone(val notificationId: String): Event
}

interface Ui : CircuitUi<State>
interface Presenter : CircuitPresenter<State>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ kotlin {

api(project(":experimental:sample:octonaut:xplat:feat:notificationsTab:api"))
api(project(":experimental:sample:octonaut:xplat:foundation:di:api"))
api(project(":experimental:sample:octonaut:xplat:domain:notifications:api"))

api(project(":experimental:market:warehouse"))
api(project(":experimental:sample:octonaut:xplat:common:market"))
implementation(libs.coil.compose)
implementation(libs.coil.network)
implementation(libs.ktor.core)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.mobilenativefoundation.sample.octonaut.xplat.feat

import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import org.mobilenativefoundation.sample.octonaut.xplat.feat.notificationsTab.api.NotificationsTab

@Parcelize
actual object RealNotificationsTab : NotificationsTab, Parcelable
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.mobilenativefoundation.sample.octonaut.xplat.feat

import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import me.tatarka.inject.annotations.Inject
import org.mobilenativefoundation.sample.octonaut.xplat.feat.notificationsTab.api.NotificationsTab

@Inject
class NotificationsTabPresenter(private val warehouse: NotificationsTabWarehouse) : NotificationsTab.Presenter {
private fun on(event: NotificationsTab.Event) {
when (event) {
is NotificationsTab.Event.MarkDone -> warehouse.dispatch(
NotificationsTabWarehouseAction.MarkDone(
event.notificationId
)
)
}
}

@Composable
override fun present(): NotificationsTab.State {
val warehouseState = warehouse.state.collectAsState()

return warehouseState.value.notifications.let {
if (it.isEmpty()) {
NotificationsTab.State.Loading
} else {
NotificationsTab.State.Loaded(it, ::on)
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.mobilenativefoundation.sample.octonaut.xplat.feat

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import me.tatarka.inject.annotations.Inject
import org.mobilenativefoundation.sample.octonaut.xplat.feat.notificationsTab.api.NotificationsTab

@Inject
class NotificationsTabUi : NotificationsTab.Ui {
@Composable
override fun Content(state: NotificationsTab.State, modifier: Modifier) {
Column {
when (state) {
NotificationsTab.State.Initial -> Text("Initial")
is NotificationsTab.State.Loaded -> LoadedContent(state)
is NotificationsTab.State.Loading -> Text("Loading")
}
}
}

@Composable
private fun LoadedContent(state: NotificationsTab.State.Loaded) {

state.notifications.forEach {
Text(it.url)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.mobilenativefoundation.sample.octonaut.xplat.feat

import org.mobilenativefoundation.market.warehouse.Warehouse
import org.mobilenativefoundation.sample.octonaut.xplat.domain.notifications.api.Notification

data class NotificationsTabWarehouseState(
val notifications: List<Notification>
) : Warehouse.State

sealed interface NotificationsTabWarehouseAction : Warehouse.Action {
data class MarkDone(
val notificationId: String
) : NotificationsTabWarehouseAction
}

typealias NotificationsTabWarehouse = Warehouse<NotificationsTabWarehouseState, NotificationsTabWarehouseAction>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.mobilenativefoundation.sample.octonaut.xplat.feat

import me.tatarka.inject.annotations.Inject
import org.mobilenativefoundation.sample.octonaut.xplat.common.market.WarehouseBuilderFactory
import org.mobilenativefoundation.sample.octonaut.xplat.domain.notifications.api.NotificationsSupplier

@Inject
class NotificationsTabWarehouseFactory(
private val notificationsSupplier: NotificationsSupplier,
private val warehouseBuilderFactory: WarehouseBuilderFactory
) {
fun create(): NotificationsTabWarehouse {
val warehouseBuilder =
warehouseBuilderFactory.create<NotificationsTabWarehouseState, NotificationsTabWarehouseAction>()

return warehouseBuilder.extractor { marketState ->
NotificationsTabWarehouseState(marketState.notifications)
}
.actionHandler { action, marketState ->
when (action) {
is NotificationsTabWarehouseAction.MarkDone -> {
// TODO
}
}
}
.build()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.mobilenativefoundation.sample.octonaut.xplat.feat

import org.mobilenativefoundation.sample.octonaut.xplat.feat.notificationsTab.api.NotificationsTab

expect object RealNotificationsTab : NotificationsTab
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.mobilenativefoundation.sample.octonaut.xplat.feat

import org.mobilenativefoundation.sample.octonaut.xplat.feat.notificationsTab.api.NotificationsTab

actual object RealNotificationsTab : NotificationsTab
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.mobilenativefoundation.sample.octonaut.xplat.feat

import org.mobilenativefoundation.sample.octonaut.xplat.feat.notificationsTab.api.NotificationsTab

actual object RealNotificationsTab : NotificationsTab

0 comments on commit 2abcee2

Please sign in to comment.