1
0
Fork 0
fenix/app/src/main/java/org/mozilla/fenix/library/bookmarks/edit/EditBookmarkFragment.kt

226 lines
9.0 KiB
Kotlin
Raw Normal View History

/* 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/. */
package org.mozilla.fenix.library.bookmarks.edit
import android.content.DialogInterface
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.Navigation
import androidx.navigation.fragment.findNavController
2020-02-06 00:33:11 +01:00
import androidx.navigation.fragment.navArgs
2020-02-06 17:14:32 +01:00
import kotlinx.android.synthetic.main.fragment_edit_bookmark.*
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import mozilla.appservices.places.UrlParseFailed
import mozilla.components.concept.storage.BookmarkInfo
import mozilla.components.concept.storage.BookmarkNode
import mozilla.components.concept.storage.BookmarkNodeType
import mozilla.components.support.ktx.android.content.getColorFromAttr
import mozilla.components.support.ktx.android.view.hideKeyboard
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.components.FenixSnackbar
2019-04-17 19:37:36 +02:00
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.getRootView
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.setToolbarColors
import org.mozilla.fenix.ext.toShortUrl
import org.mozilla.fenix.library.bookmarks.BookmarksSharedViewModel
import org.mozilla.fenix.library.bookmarks.DesktopFolders
2019-10-06 19:57:41 +02:00
/**
* Menu to edit the name, URL, and location of a bookmark item.
*/
class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) {
2020-02-06 00:33:11 +01:00
private val args by navArgs<EditBookmarkFragmentArgs>()
private val sharedViewModel: BookmarksSharedViewModel by activityViewModels {
ViewModelProvider.NewInstanceFactory() // this is a workaround for #4652
}
private var bookmarkNode: BookmarkNode? = null
private var bookmarkParent: BookmarkNode? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initToolbar()
lifecycleScope.launch(Main) {
val context = requireContext()
withContext(IO) {
val bookmarksStorage = context.components.core.bookmarksStorage
2020-02-06 00:33:11 +01:00
bookmarkNode = bookmarksStorage.getTree(args.guidToEdit)
bookmarkParent = sharedViewModel.selectedFolder
?: bookmarkNode?.parentGuid
?.let { bookmarksStorage.getTree(it) }
?.let { DesktopFolders(context, showMobileRoot = true).withRootTitle(it) }
}
when (bookmarkNode?.type) {
BookmarkNodeType.FOLDER -> {
activity?.title = getString(R.string.edit_bookmark_folder_fragment_title)
bookmarkUrlEdit.visibility = View.GONE
bookmarkUrlLabel.visibility = View.GONE
}
BookmarkNodeType.ITEM -> {
activity?.title = getString(R.string.edit_bookmark_fragment_title)
}
else -> throw IllegalArgumentException()
}
2019-04-17 19:37:36 +02:00
bookmarkNode?.let { bookmarkNode ->
bookmarkNameEdit.setText(bookmarkNode.title)
bookmarkUrlEdit.setText(bookmarkNode.url)
}
bookmarkParent?.let { node ->
bookmarkParentFolderSelector.text = node.title
bookmarkParentFolderSelector.setOnClickListener {
sharedViewModel.selectedFolder = null
nav(
R.id.bookmarkEditFragment,
EditBookmarkFragmentDirections
.actionBookmarkEditFragmentToBookmarkSelectFolderFragment(null)
)
}
}
}
}
private fun initToolbar() {
val activity = activity as? AppCompatActivity
val actionBar = (activity as HomeActivity).getSupportActionBarAndInflateIfNecessary()
val toolbar = activity.findViewById<Toolbar>(R.id.navigationToolbar)
context?.let {
toolbar?.setToolbarColors(
foreground = it.getColorFromAttr(R.attr.primaryText),
background = it.getColorFromAttr(R.attr.foundation)
)
}
actionBar.show()
}
override fun onPause() {
super.onPause()
bookmarkNameEdit.hideKeyboard()
bookmarkUrlEdit.hideKeyboard()
progress_bar_bookmark.visibility = View.GONE
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.bookmarks_edit, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.delete_bookmark_button -> {
displayDeleteBookmarkDialog()
true
}
R.id.save_bookmark_button -> {
updateBookmarkFromTextChanges()
true
}
else -> super.onOptionsItemSelected(item)
}
}
private fun displayDeleteBookmarkDialog() {
activity?.let { activity ->
AlertDialog.Builder(activity).apply {
setMessage(R.string.bookmark_deletion_confirmation)
setNegativeButton(android.R.string.cancel) { dialog: DialogInterface, _ ->
dialog.cancel()
}
setPositiveButton(R.string.tab_collection_dialog_positive) { dialog: DialogInterface, _ ->
lifecycleScope.launch(IO) {
2020-02-06 00:33:11 +01:00
requireComponents.core.bookmarksStorage.deleteNode(args.guidToEdit)
requireComponents.analytics.metrics.track(Event.RemoveBookmark)
launch(Main) {
Navigation.findNavController(requireActivity(), R.id.container)
.popBackStack()
bookmarkNode?.let { bookmark ->
FenixSnackbar.make(
view = activity.getRootView()!!,
isDisplayedWithBrowserToolbar = true
)
.setText(
getString(
R.string.bookmark_deletion_snackbar_message,
bookmark.url?.toShortUrl(context.components.publicSuffixList)
?: bookmark.title
)
)
.show()
}
}
}
dialog.dismiss()
}
create()
}.show()
}
}
private fun updateBookmarkFromTextChanges() {
progress_bar_bookmark.visibility = View.VISIBLE
val nameText = bookmarkNameEdit.text.toString()
val urlText = bookmarkUrlEdit.text.toString()
updateBookmarkNode(nameText, urlText)
}
private fun updateBookmarkNode(title: String?, url: String?) {
lifecycleScope.launch(IO) {
2019-04-17 19:37:36 +02:00
try {
requireComponents.let { components ->
if (title != bookmarkNode?.title || url != bookmarkNode?.url) {
components.analytics.metrics.track(Event.EditedBookmark)
2019-04-17 19:37:36 +02:00
}
if (sharedViewModel.selectedFolder != null) {
components.analytics.metrics.track(Event.MovedBookmark)
2019-04-17 19:37:36 +02:00
}
components.core.bookmarksStorage.updateNode(
2020-02-06 00:33:11 +01:00
args.guidToEdit,
2019-04-17 19:37:36 +02:00
BookmarkInfo(
sharedViewModel.selectedFolder?.guid ?: bookmarkNode!!.parentGuid,
bookmarkNode?.position,
title,
if (bookmarkNode?.type == BookmarkNodeType.ITEM) url else null
2019-04-17 19:37:36 +02:00
)
)
}
} catch (e: UrlParseFailed) {
withContext(Main) {
bookmarkUrlEdit.error = getString(R.string.bookmark_invalid_url_error)
}
}
}
progress_bar_bookmark.visibility = View.INVISIBLE
findNavController().popBackStack()
}
}