mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-02 03:40:16 +00:00
For #356 - Gives a user the ability to delete their history
This commit is contained in:
parent
6491adf029
commit
00ad9d3f6f
@ -13,8 +13,6 @@ import android.widget.CompoundButton
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.reactivex.Observer
|
||||
import org.mozilla.fenix.R
|
||||
import androidx.core.content.ContextCompat
|
||||
import kotlinx.android.synthetic.main.history_delete.view.*
|
||||
import kotlinx.android.synthetic.main.history_header.view.*
|
||||
import kotlinx.android.synthetic.main.history_list_item.view.*
|
||||
import mozilla.components.browser.menu.BrowserMenu
|
||||
@ -226,48 +224,6 @@ class HistoryAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
class HistoryDeleteViewHolder(
|
||||
view: View,
|
||||
private val actionEmitter: Observer<HistoryAction>
|
||||
) : RecyclerView.ViewHolder(view) {
|
||||
private lateinit var mode: HistoryState.Mode
|
||||
|
||||
private val button = view.delete_history_button.apply {
|
||||
setOnClickListener {
|
||||
val mode = mode
|
||||
if (mode is HistoryState.Mode.Editing && mode.selectedItems.isNotEmpty()) {
|
||||
actionEmitter.onNext(HistoryAction.Delete.Some(mode.selectedItems))
|
||||
} else {
|
||||
actionEmitter.onNext(HistoryAction.Delete.All)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val text = view.delete_history_button_text.apply {
|
||||
val color = ContextCompat.getColor(context, R.color.photonRed60)
|
||||
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_delete)
|
||||
drawable?.setTint(color)
|
||||
this.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)
|
||||
}
|
||||
|
||||
fun bind(mode: HistoryState.Mode) {
|
||||
this.mode = mode
|
||||
|
||||
val text = if (mode is HistoryState.Mode.Editing && mode.selectedItems.isNotEmpty()) {
|
||||
text.context.resources.getString(R.string.history_delete_some, mode.selectedItems.size)
|
||||
} else {
|
||||
text.context.resources.getString(R.string.history_delete_all)
|
||||
}
|
||||
|
||||
button.contentDescription = text
|
||||
this.text.text = text
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val LAYOUT_ID = R.layout.history_delete
|
||||
}
|
||||
}
|
||||
|
||||
private var historyList: HistoryList = HistoryList(emptyList())
|
||||
private var mode: HistoryState.Mode = HistoryState.Mode.Normal
|
||||
|
||||
|
@ -39,7 +39,7 @@ class HistoryComponent(
|
||||
|
||||
override val reducer: (HistoryState, HistoryChange) -> HistoryState = { state, change ->
|
||||
when (change) {
|
||||
is HistoryChange.Change -> state.copy(items = change.list)
|
||||
is HistoryChange.Change -> state.copy(mode = HistoryState.Mode.Normal, items = change.list)
|
||||
is HistoryChange.EnterEditMode -> state.copy(mode = HistoryState.Mode.Editing(listOf(change.item)))
|
||||
is HistoryChange.AddItemForRemoval -> {
|
||||
val mode = state.mode
|
||||
|
@ -17,9 +17,10 @@ import androidx.navigation.NavOptions
|
||||
import androidx.navigation.Navigation
|
||||
import kotlinx.android.synthetic.main.fragment_history.view.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import mozilla.components.support.base.feature.BackHandler
|
||||
import org.mozilla.fenix.utils.ItsNotBrokenSnack
|
||||
import org.mozilla.fenix.R
|
||||
@ -29,6 +30,7 @@ import org.mozilla.fenix.mvi.getAutoDisposeObservable
|
||||
import org.mozilla.fenix.mvi.getManagedEmitter
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
@SuppressWarnings("TooManyFunctions")
|
||||
class HistoryFragment : Fragment(), CoroutineScope, BackHandler {
|
||||
|
||||
private lateinit var job: Job
|
||||
@ -81,18 +83,13 @@ class HistoryFragment : Fragment(), CoroutineScope, BackHandler {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
launch(Dispatchers.IO) {
|
||||
val items = requireComponents.core.historyStorage.getDetailedVisits(0)
|
||||
.asReversed()
|
||||
.mapIndexed { id, item -> HistoryItem(id, item.url, item.visitTime) }
|
||||
|
||||
launch(Dispatchers.Main) {
|
||||
getManagedEmitter<HistoryChange>().onNext(HistoryChange.Change(items))
|
||||
}
|
||||
reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
// This method triggers the complexity warning. However it's actually not that hard to understand.
|
||||
@SuppressWarnings("ComplexMethod")
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
getAutoDisposeObservable<HistoryAction>()
|
||||
@ -107,6 +104,20 @@ class HistoryFragment : Fragment(), CoroutineScope, BackHandler {
|
||||
.onNext(HistoryChange.RemoveItemForRemoval(it.item))
|
||||
is HistoryAction.BackPressed -> getManagedEmitter<HistoryChange>()
|
||||
.onNext(HistoryChange.ExitEditMode)
|
||||
is HistoryAction.Delete.All -> launch(Dispatchers.IO) {
|
||||
requireComponents.core.historyStorage.deleteEverything()
|
||||
reloadData()
|
||||
}
|
||||
is HistoryAction.Delete.One -> launch(Dispatchers.IO) {
|
||||
requireComponents.core.historyStorage.deleteVisit(it.item.url, it.item.visitedAt)
|
||||
reloadData()
|
||||
}
|
||||
is HistoryAction.Delete.Some -> launch(Dispatchers.IO) {
|
||||
it.items.forEach { item ->
|
||||
requireComponents.core.historyStorage.deleteVisit(item.url, item.visitedAt)
|
||||
}
|
||||
reloadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,4 +139,16 @@ class HistoryFragment : Fragment(), CoroutineScope, BackHandler {
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean = (historyComponent.uiView as HistoryUIView).onBackPressed()
|
||||
|
||||
private suspend fun reloadData() {
|
||||
val items = requireComponents.core.historyStorage.getDetailedVisits(0)
|
||||
.asReversed()
|
||||
.mapIndexed { id, item -> HistoryItem(id, item.url, item.visitTime) }
|
||||
|
||||
coroutineScope {
|
||||
launch(Dispatchers.Main) {
|
||||
getManagedEmitter<HistoryChange>().onNext(HistoryChange.Change(items))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,11 +6,12 @@ package org.mozilla.fenix.library.history
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.widget.NestedScrollView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Observer
|
||||
import io.reactivex.functions.Consumer
|
||||
import kotlinx.android.synthetic.main.component_history.view.*
|
||||
import mozilla.components.support.base.feature.BackHandler
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.mvi.UIView
|
||||
@ -26,22 +27,48 @@ class HistoryUIView(
|
||||
var mode: HistoryState.Mode = HistoryState.Mode.Normal
|
||||
private set
|
||||
|
||||
override val view: RecyclerView = LayoutInflater.from(container.context)
|
||||
override val view: NestedScrollView = LayoutInflater.from(container.context)
|
||||
.inflate(R.layout.component_history, container, true)
|
||||
.findViewById(R.id.history_list)
|
||||
.findViewById(R.id.history_wrapper)
|
||||
|
||||
init {
|
||||
view.apply {
|
||||
view.history_list.apply {
|
||||
adapter = HistoryAdapter(actionEmitter)
|
||||
layoutManager = LinearLayoutManager(container.context)
|
||||
}
|
||||
|
||||
view.delete_history_button.setOnClickListener {
|
||||
val mode = mode
|
||||
val action = when (mode) {
|
||||
is HistoryState.Mode.Normal -> HistoryAction.Delete.All
|
||||
is HistoryState.Mode.Editing -> HistoryAction.Delete.Some(mode.selectedItems)
|
||||
}
|
||||
|
||||
actionEmitter.onNext(action)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateView() = Consumer<HistoryState> {
|
||||
mode = it.mode
|
||||
(view.adapter as HistoryAdapter).updateData(it.items, it.mode)
|
||||
updateDeleteButton()
|
||||
(view.history_list.adapter as HistoryAdapter).updateData(it.items, it.mode)
|
||||
}
|
||||
|
||||
private fun updateDeleteButton() {
|
||||
val mode = mode
|
||||
|
||||
val text = if (mode is HistoryState.Mode.Editing && mode.selectedItems.isNotEmpty()) {
|
||||
view.delete_history_button_text.context.resources.getString(
|
||||
R.string.history_delete_some,
|
||||
mode.selectedItems.size
|
||||
)
|
||||
} else {
|
||||
view.delete_history_button_text.context.resources.getString(R.string.history_delete_all)
|
||||
}
|
||||
|
||||
view.delete_history_button.contentDescription = text
|
||||
view.delete_history_button_text.text = text
|
||||
}
|
||||
override fun onBackPressed(): Boolean {
|
||||
if (mode is HistoryState.Mode.Editing) {
|
||||
actionEmitter.onNext(HistoryAction.BackPressed)
|
||||
|
@ -3,8 +3,42 @@
|
||||
- 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/. -->
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/history_list"
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/history_wrapper"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/delete_history_button"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
android:background="@drawable/button_background"
|
||||
android:layout_margin="16dp"
|
||||
android:padding="6dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/delete_history_button_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/history_delete_all"
|
||||
android:textColor="@color/photonRed60"
|
||||
android:drawablePadding="8dp"
|
||||
android:textSize="16sp"
|
||||
android:gravity="center"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:layout_gravity="center" />
|
||||
</FrameLayout>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/history_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/delete_history_button"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
android:background="@drawable/button_background"
|
||||
android:layout_margin="16dp"
|
||||
android:padding="6dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/delete_history_button_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/history_delete_all"
|
||||
android:textColor="@color/photonRed60"
|
||||
android:drawablePadding="8dp"
|
||||
android:textSize="16sp"
|
||||
android:gravity="center"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:layout_gravity="center" />
|
||||
</FrameLayout>
|
Loading…
Reference in New Issue
Block a user