summaryrefslogtreecommitdiffstats
path: root/mobile/android/fenix/docs/architectureexample
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:34:42 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:34:42 +0000
commitda4c7e7ed675c3bf405668739c3012d140856109 (patch)
treecdd868dba063fecba609a1d819de271f0d51b23e /mobile/android/fenix/docs/architectureexample
parentAdding upstream version 125.0.3. (diff)
downloadfirefox-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')
-rw-r--r--mobile/android/fenix/docs/architectureexample/HistoryFragmentExample.kt60
-rw-r--r--mobile/android/fenix/docs/architectureexample/HistoryNavigationMiddlewareExample.kt29
-rw-r--r--mobile/android/fenix/docs/architectureexample/HistoryStorageMiddlewareExample.kt39
-rw-r--r--mobile/android/fenix/docs/architectureexample/HistoryStoreExample.kt64
-rw-r--r--mobile/android/fenix/docs/architectureexample/HistoryTelemetryMiddlewareExample.kt22
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
+ }
+ }
+}