Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a3c55d4
Introduce new classes to manage the searching functionality
Feb 9, 2020
57cfc44
Update AppComponent to inject PageParentSearchFragment
Feb 9, 2020
163de54
Update ViewModelModule to for PageParentSearchViewModel
Feb 9, 2020
00f594b
Set up the search on the menu
Feb 9, 2020
b567f8f
Switch in a new xml file for PageParentFragment so it can be adjusted…
Feb 9, 2020
5a483ff
updated to include liveData searchPages
Feb 9, 2020
75c606f
Tie the search all together in the PageParentFragment (initializing, …
Feb 9, 2020
fb3a414
Added view model test for pageparentSearch
Feb 9, 2020
049978c
remove log line from hideSearchList fun
Feb 9, 2020
7af8211
Make sure the search icon shows on back tap
Feb 9, 2020
33aff7c
Fixed klint style errors
Feb 10, 2020
26a5c89
Merge branch 'feature/master-search-in-set-parent-page' into issue/11…
Feb 10, 2020
5f5832b
removed unused variables
Feb 10, 2020
13a5268
Moved pageParentSearchViewModel to the correct package to align with …
Feb 10, 2020
39aff7c
remove the search tap from the onOptionsItemSelected fun
Feb 10, 2020
8f30c21
guard null check with ?.let instead of separate statements
Feb 10, 2020
39bd891
Maintain search text across configuration change
Feb 10, 2020
eb0a0af
Removes the conversion to lowercase and uses contains with ignoreCase…
Feb 10, 2020
e9b4991
adjusted save button and parent selected functionality
Feb 13, 2020
d4000c0
reverting idea-codingStyles-project.xml back to the commit right befo…
Feb 14, 2020
401a294
Merge pull request #11269 from zwarm/issue/11119-search-in-set-parent…
malinajirka Feb 14, 2020
bc517cf
Update release notes
malinajirka Feb 14, 2020
3c27c0b
Merge branch 'develop' into feature/master-search-in-set-parent-page
malinajirka Feb 14, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
14.3
-----
* Added search to set page parent screen


14.2
-----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import org.wordpress.android.ui.notifications.receivers.NotificationsPendingDraftsReceiver;
import org.wordpress.android.ui.pages.PageListFragment;
import org.wordpress.android.ui.pages.PageParentFragment;
import org.wordpress.android.ui.pages.PageParentSearchFragment;
import org.wordpress.android.ui.pages.PagesFragment;
import org.wordpress.android.ui.pages.SearchListFragment;
import org.wordpress.android.ui.people.PeopleInviteFragment;
Expand Down Expand Up @@ -490,6 +491,8 @@ public interface AppComponent extends AndroidInjector<WordPress> {

void inject(AddContentAdapter object);

void inject(PageParentSearchFragment object);

// Allows us to inject the application without having to instantiate any modules, and provides the Application
// in the app graph
@Component.Builder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.wordpress.android.viewmodel.history.HistoryViewModel;
import org.wordpress.android.viewmodel.main.WPMainActivityViewModel;
import org.wordpress.android.viewmodel.pages.PageListViewModel;
import org.wordpress.android.viewmodel.pages.PageParentSearchViewModel;
import org.wordpress.android.viewmodel.pages.PageParentViewModel;
import org.wordpress.android.viewmodel.pages.PagesViewModel;
import org.wordpress.android.viewmodel.pages.SearchListViewModel;
Expand Down Expand Up @@ -282,6 +283,11 @@ abstract class ViewModelModule {
@ViewModelKey(PostSignupInterstitialViewModel.class)
abstract ViewModel postSignupInterstitialViewModel(PostSignupInterstitialViewModel viewModel);

@Binds
@IntoMap
@ViewModelKey(PageParentSearchViewModel.class)
abstract ViewModel pageParentSearchViewModel(PageParentSearchViewModel viewModel);

@Binds
abstract ViewModelProvider.Factory provideViewModelFactory(ViewModelFactory viewModelFactory);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@ import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.MenuItem.OnActionExpandListener
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.pages_list_fragment.*
import kotlinx.android.synthetic.main.page_parent_fragment.*
import kotlinx.android.synthetic.main.pages_list_fragment.recyclerView
import kotlinx.coroutines.CoroutineScope
import org.wordpress.android.R
import org.wordpress.android.WordPress
Expand All @@ -37,8 +42,10 @@ class PageParentFragment : Fragment() {

private var linearLayoutManager: LinearLayoutManager? = null
private var saveButton: MenuItem? = null
private lateinit var searchAction: MenuItem

private var pageId: Long? = null
private var restorePreviousSearch = false

companion object {
fun newInstance(): PageParentFragment {
Expand All @@ -54,6 +61,7 @@ class PageParentFragment : Fragment() {
viewModel.onSaveButtonTapped()
return true
}

return super.onOptionsItemSelected(item)
}

Expand All @@ -76,10 +84,63 @@ class PageParentFragment : Fragment() {

saveButton = menu.findItem(R.id.save_parent)
viewModel.isSaveButtonVisible.value?.let { saveButton?.isVisible = it }
searchAction = checkNotNull(menu.findItem(R.id.action_search)) {
"Menu does not contain mandatory search item"
}

initializeSearchView()
}

private fun initializeSearchView() {
searchAction.setOnActionExpandListener(object : OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
viewModel.onSearchExpanded(restorePreviousSearch)
return true
}

override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
viewModel.onSearchCollapsed()
return true
}
})

val searchView = searchAction.actionView as SearchView
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
viewModel.onSearch(query)
return true
}

override fun onQueryTextChange(newText: String): Boolean {
if (restorePreviousSearch) {
restorePreviousSearch = false
searchView.setQuery(viewModel.lastSearchQuery, false)
} else {
viewModel.onSearch(newText)
}
return true
}
})

val searchEditFrame = searchAction?.actionView.findViewById<LinearLayout>(R.id.search_edit_frame)
(searchEditFrame.layoutParams as LinearLayout.LayoutParams)
.apply { this.leftMargin = DisplayUtils.dpToPx(activity, -8) }

viewModel.isSearchExpanded.observe(this, Observer {
if (it == true) {
showSearchList(searchAction)
} else {
hideSearchList(searchAction)
}
})
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.pages_list_fragment, container, false)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.page_parent_fragment, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
Expand All @@ -92,11 +153,11 @@ class PageParentFragment : Fragment() {

(nonNullActivity.application as? WordPress)?.component()?.inject(this)

initializeViews(savedInstanceState)
initializeViewModels(nonNullPageId, savedInstanceState == null)
initializeViews(nonNullActivity, savedInstanceState)
initializeViewModels(nonNullActivity, nonNullPageId, savedInstanceState == null)
}

private fun initializeViews(savedInstanceState: Bundle?) {
private fun initializeViews(activity: FragmentActivity, savedInstanceState: Bundle?) {
val layoutManager = LinearLayoutManager(activity, RecyclerView.VERTICAL, false)
savedInstanceState?.getParcelable<Parcelable>(listStateKey)?.let {
layoutManager.onRestoreInstanceState(it)
Expand All @@ -105,17 +166,30 @@ class PageParentFragment : Fragment() {
linearLayoutManager = layoutManager
recyclerView.layoutManager = linearLayoutManager
recyclerView.addItemDecoration(RecyclerItemDecoration(0, DisplayUtils.dpToPx(activity, 1)))

val searchFragment = PageParentSearchFragment.newInstance()
activity.supportFragmentManager
.beginTransaction()
.replace(R.id.frameSearch, searchFragment)
.commit()
}

private fun initializeViewModels(pageId: Long, isFirstStart: Boolean) {
viewModel = ViewModelProviders.of(this, viewModelFactory).get(PageParentViewModel::class.java)
private fun initializeViewModels(
activity: FragmentActivity,
pageId: Long,
isFirstStart: Boolean
) {
viewModel = ViewModelProviders.of(activity, viewModelFactory)
.get(PageParentViewModel::class.java)

setupObservers()

if (isFirstStart) {
val site = activity?.intent?.getSerializableExtra(WordPress.SITE) as SiteModel?
val site = activity.intent?.getSerializableExtra(WordPress.SITE) as SiteModel?
val nonNullSite = checkNotNull(site)
viewModel.start(nonNullSite, pageId)
} else {
restorePreviousSearch = true
}
}

Expand Down Expand Up @@ -148,4 +222,24 @@ class PageParentFragment : Fragment() {
}
adapter.update(pages)
}

private fun hideSearchList(myActionMenuItem: MenuItem) {
recyclerView.visibility = View.VISIBLE
frameSearch.visibility = View.GONE
if (myActionMenuItem.isActionViewExpanded) {
myActionMenuItem.collapseActionView()
}
/**Force the recyclerview to redraw if selection has changed while in search mode*/
if (viewModel.currentParent != viewModel.initialParent) {
recyclerView.adapter?.notifyDataSetChanged()
}
}

private fun showSearchList(myActionMenuItem: MenuItem) {
frameSearch.visibility = View.VISIBLE
recyclerView.visibility = View.GONE
if (!myActionMenuItem.isActionViewExpanded) {
myActionMenuItem.expandActionView()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.wordpress.android.ui.pages

import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView.Adapter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.wordpress.android.R.layout
import org.wordpress.android.ui.pages.PageItem.ParentPage
import org.wordpress.android.ui.pages.PageItemViewHolder.EmptyViewHolder
import org.wordpress.android.ui.pages.PageItemViewHolder.PageDividerViewHolder
import org.wordpress.android.ui.pages.PageItemViewHolder.PageParentViewHolder

class PageParentSearchAdapter(
private val onParentSelected: (ParentPage) -> Unit,
private val uiScope: CoroutineScope
) : Adapter<PageItemViewHolder>() {
private val items = mutableListOf<PageItem>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PageItemViewHolder {
return when (viewType) {
PageItem.Type.PARENT.viewType -> PageParentViewHolder(parent,
this::selectParent,
layout.page_parent_list_item)
PageItem.Type.TOP_LEVEL_PARENT.viewType -> PageParentViewHolder(parent,
this::selectParent,
layout.page_parent_top_level_item)
PageItem.Type.DIVIDER.viewType -> PageDividerViewHolder(parent)
PageItem.Type.EMPTY.viewType -> EmptyViewHolder(parent) { }
else -> throw Throwable("Unexpected view type")
}
}

private fun selectParent(parent: ParentPage) {
onParentSelected(parent)
uiScope.launch {
delay(200) // let the selection animation play out before refreshing the list
notifyDataSetChanged()
}
}
override fun getItemCount(): Int = items.size

override fun getItemViewType(position: Int): Int {
return items[position].type.viewType
}

override fun onBindViewHolder(holder: PageItemViewHolder, position: Int) {
holder.onBind(items[position])
}

fun update(result: List<PageItem>) {
val diffResult = DiffUtil.calculateDiff(PageItemDiffUtil(items.toList(), result))
items.clear()
items.addAll(result)
diffResult.dispatchUpdatesTo(this)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package org.wordpress.android.ui.pages

import android.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.pages_list_fragment.*
import kotlinx.coroutines.CoroutineScope
import org.wordpress.android.R
import org.wordpress.android.WordPress
import org.wordpress.android.modules.UI_SCOPE
import org.wordpress.android.util.DisplayUtils
import org.wordpress.android.viewmodel.pages.PageParentSearchViewModel
import org.wordpress.android.viewmodel.pages.PageParentViewModel
import org.wordpress.android.widgets.RecyclerItemDecoration
import javax.inject.Inject
import javax.inject.Named

class PageParentSearchFragment : Fragment() {
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
private lateinit var viewModel: PageParentSearchViewModel
@field:[Inject Named(UI_SCOPE)] lateinit var uiScope: CoroutineScope
private var linearLayoutManager: LinearLayoutManager? = null

private val listStateKey = "list_state"

companion object {
fun newInstance(): PageParentSearchFragment {
return PageParentSearchFragment()
}
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.pages_list_fragment, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val nonNullActivity = checkNotNull(activity)
(nonNullActivity.application as? WordPress)?.component()?.inject(this)

initializeViews(savedInstanceState)
initializeViewModels(nonNullActivity)
}

override fun onSaveInstanceState(outState: Bundle) {
linearLayoutManager?.let {
outState.putParcelable(listStateKey, it.onSaveInstanceState())
}
super.onSaveInstanceState(outState)
}

private fun initializeViewModels(activity: FragmentActivity) {
val pageParentViewModel = ViewModelProviders.of(activity, viewModelFactory)
.get(PageParentViewModel::class.java)

viewModel = ViewModelProviders.of(this, viewModelFactory)
.get(PageParentSearchViewModel::class.java)
viewModel.start(pageParentViewModel)

setupObservers()
}

private fun initializeViews(savedInstanceState: Bundle?) {
val layoutManager = LinearLayoutManager(activity, RecyclerView.VERTICAL, false)
savedInstanceState?.getParcelable<Parcelable>(listStateKey)?.let {
layoutManager.onRestoreInstanceState(it)
}

linearLayoutManager = layoutManager
recyclerView.layoutManager = linearLayoutManager
recyclerView.addItemDecoration(RecyclerItemDecoration(0, DisplayUtils.dpToPx(activity, 1)))
}

private fun setupObservers() {
viewModel.searchResult.observe(this, Observer { data ->
data?.let { setSearchResult(data) }
})
}

private fun setSearchResult(pages: List<PageItem>) {
val adapter: PageParentSearchAdapter
if (recyclerView.adapter == null) {
adapter = PageParentSearchAdapter(
{ page -> viewModel.onParentSelected(page) }, uiScope)
recyclerView.adapter = adapter
} else {
adapter = recyclerView.adapter as PageParentSearchAdapter
}
adapter.update(pages)
}
}
Loading