diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:34:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:34:42 +0000 |
commit | da4c7e7ed675c3bf405668739c3012d140856109 (patch) | |
tree | cdd868dba063fecba609a1d819de271f0d51b23e /mobile/android/fenix/docs/architectureexample | |
parent | Adding upstream version 125.0.3. (diff) | |
download | firefox-da4c7e7ed675c3bf405668739c3012d140856109.tar.xz firefox-da4c7e7ed675c3bf405668739c3012d140856109.zip |
Adding upstream version 126.0.upstream/126.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mobile/android/fenix/docs/architectureexample')
5 files changed, 214 insertions, 0 deletions
diff --git a/mobile/android/fenix/docs/architectureexample/HistoryFragmentExample.kt b/mobile/android/fenix/docs/architectureexample/HistoryFragmentExample.kt new file mode 100644 index 0000000000..f3fa6e3ee5 --- /dev/null +++ b/mobile/android/fenix/docs/architectureexample/HistoryFragmentExample.kt @@ -0,0 +1,60 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This is example code for the 'Simplified Example' section of +// /docs/architecture-overview.md +class HistoryFragment : Fragment() { + + private val store by lazy { + StoreProvider.get(this) { + HistoryStore( + initialState = HistoryState.initial, + middleware = listOf( + HistoryNavigationMiddleware(findNavController()) + HistoryStorageMiddleware(HistoryStorage()), + HistoryTelemetryMiddleware(), + ) + ) + } + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return ComposeView(requireContext()).apply { + setContent { + HistoryScreen(store) + } + } + } +} + +@Composable +private fun HistoryScreen(store: HistoryStore) { + val state = store.observeAsState(initialValue = HistoryState.initial) { state -> state } + val listState = rememberLazyListState() + LazyColumn(listState) { + if (state.selectedItems.isNotEmpty()) { + HistoryMultiSelectHeader( + onDeleteSelectedClick = { + store.dispatch(HistoryAction.DeleteItems(state.selectedItems)) + } + ) + } else { + HistoryHeader( + onDeleteAllClick = { store.dispatch(HistoryAction.DeleteItems(state.items)) } + ) + } + items(items = state.displayItems, key = { item -> item.id } ) { item -> + val isSelected = state.selectedItems.find { selectedItem -> + selectdItem == item + } + HistoryItem( + item = item, + isSelected = isSelected, + onClick = { store.dispatch(HistoryAction.OpenItem(item)) }, + onLongClick = { store.dispatch(HistoryAction.ToggleItemSelection(item)) }, + onDeleteClick = { store.dispatch(HistoryAction.DeleteItems(listOf(item))) }, + ) + } + } +} diff --git a/mobile/android/fenix/docs/architectureexample/HistoryNavigationMiddlewareExample.kt b/mobile/android/fenix/docs/architectureexample/HistoryNavigationMiddlewareExample.kt new file mode 100644 index 0000000000..49f3d42f2b --- /dev/null +++ b/mobile/android/fenix/docs/architectureexample/HistoryNavigationMiddlewareExample.kt @@ -0,0 +1,29 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This is example code for the 'Simplified Example' section of +// /docs/architecture-overview.md +class HistoryNavigationMiddleware( + private val navController: NavController, +) : Middleware<HistoryState, HistoryAction> { + override fun invoke( + context: MiddlewareContext<HistoryState, HistoryAction>, + next: (HistoryAction) -> Unit, + action: HistoryAction, + ) { + // This middleware won't need to manipulate the action, so the action can be passed through + // the middleware chain before the side-effects are initiated + next(action) + when(action) { + is HistoryAction.OpenItem -> { + navController.openToBrowserAndLoad( + searchTermOrURL = item.url, + newTab = true, + from = BrowserDirection.FromHistory, + ) + } + else -> Unit + } + } +} diff --git a/mobile/android/fenix/docs/architectureexample/HistoryStorageMiddlewareExample.kt b/mobile/android/fenix/docs/architectureexample/HistoryStorageMiddlewareExample.kt new file mode 100644 index 0000000000..674adca851 --- /dev/null +++ b/mobile/android/fenix/docs/architectureexample/HistoryStorageMiddlewareExample.kt @@ -0,0 +1,39 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This is example code for the 'Simplified Example' section of +// /docs/architecture-overview.md +class HistoryStorageMiddleware( + private val storage: HistoryStorage + private val scope: CoroutineScope, +) : Middleware<HistoryState, HistoryAction> { + override fun invoke( + context: MiddlewareContext<HistoryState, HistoryAction>, + next: (HistoryAction) -> Unit, + action: HistoryAction, + ) { + // This middleware won't need to manipulate the action, so the action can be passed through + // the middleware chain before the side-effects are initiated + next(action) + when(action) { + is HistoryAction.Init -> { + scope.launch { + val history = storage.load() + context.store.dispatch(HistoryAction.ItemsChanged(history)) + } + } + is HistoryAction.DeleteItems -> { + scope.launch { + val currentItems = context.state.items + if (storage.delete(action.items) is HistoryStorage.Success) { + context.store.dispatch( + HistoryAction.DeleteFinished() + ) + } + } + } + else -> Unit + } + } +} diff --git a/mobile/android/fenix/docs/architectureexample/HistoryStoreExample.kt b/mobile/android/fenix/docs/architectureexample/HistoryStoreExample.kt new file mode 100644 index 0000000000..c53d8d2981 --- /dev/null +++ b/mobile/android/fenix/docs/architectureexample/HistoryStoreExample.kt @@ -0,0 +1,64 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This is example code for the 'Simplified Example' section of +// /docs/architecture-overview.md +class HistoryStore( + private val initialState: HistoryState, + private val middleware: List<Middleware<HistoryState, HistoryAction>> +) : Store<HistoryState, Reducer<HistoryState, HistoryAction>>(initialState, middleware, ::reducer) { + init { + // This will ensure that middlewares can take any actions they need to during initialization + dispatch(HistoryAction.Init) + } +} + +sealed class HistoryAction { + object Init : HistoryAction() + data class ItemsChanged(val items: List<History>) : HistoryAction() + data class DeleteItems(val items: List<History>) : HistoryAction() + data class DeleteFinished() : HistoryAction() + data class ToggleItemSelection(val item: History) : HistoryAction() + data class OpenItem(val item: History) : HistoryAction() +} + +data class HistoryState( + val items: List<History>, + val selectedItems: List<History>, + val itemsBeingDeleted: List<History>, + companion object { + val initial = HistoryState( + items = listOf(), + selectedItems = listOf(), + itemsBeingDeleted = listOf(), + ) + } +) { + val displayItems = items.filter { item -> + item !in itemsBeingDeleted + } +} + +fun reducer(oldState: HistoryState, action: HistoryAction): HistoryState = when (action) { + is HistoryAction.ItemsChanged -> oldState.copy(items = action.items) + is HistoryAction.DeleteItems -> oldState.copy(itemsBeingDeleted = action.items) + is HistoryAction.DeleteFinished -> oldState.copy( + items = oldState.items - oldState.itemsBeingDeleted, + itemsBeingDeleted = listOf(), + ) + is HistoryAction.ToggleItemSelection -> { + if (oldState.selectedItems.contains(action.item)) { + oldState.copy(selectedItems = oldState.selectedItems - action.item) + } else { + oldState.copy(selectedItems = oldState.selectedItems + action.item) + } + } + else -> Unit +} + +data class History( + val id: Int, + val title: String, + val url: Uri, +) diff --git a/mobile/android/fenix/docs/architectureexample/HistoryTelemetryMiddlewareExample.kt b/mobile/android/fenix/docs/architectureexample/HistoryTelemetryMiddlewareExample.kt new file mode 100644 index 0000000000..9bda08ceeb --- /dev/null +++ b/mobile/android/fenix/docs/architectureexample/HistoryTelemetryMiddlewareExample.kt @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This is example code for the 'Simplified Example' section of +// /docs/architecture-overview.md +class HistoryTelemetryMiddleware : Middleware<HistoryState, HistoryAction> { + override fun invoke( + context: MiddlewareContext<HistoryState, HistoryAction>, + next: (HistoryAction) -> Unit, + action: HistoryAction, + ) { + // This middleware won't need to manipulate the action, so the action can be passed through + // the middleware chain before the side-effects are initiated + next(action) + when(action) { + is HistoryAction.DeleteItems -> History.itemsDeleted.record() + is HistoryAction.OpenItem -> History.itemOpened.record() + else -> Unit + } + } +} |