adding endless scrolling to the search results

This commit is contained in:
tibbi 2023-01-08 21:30:59 +01:00
parent 80234487da
commit a81bf470c0
4 changed files with 110 additions and 33 deletions

View File

@ -34,6 +34,7 @@ import com.simplemobiletools.calendar.pro.helpers.IcsImporter.ImportResult
import com.simplemobiletools.calendar.pro.jobs.CalDAVUpdateListener
import com.simplemobiletools.calendar.pro.models.Event
import com.simplemobiletools.calendar.pro.models.ListEvent
import com.simplemobiletools.calendar.pro.models.ListItem
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.dialogs.FilePickerDialog
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
@ -44,6 +45,8 @@ import com.simplemobiletools.commons.models.FAQItem
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.models.Release
import com.simplemobiletools.commons.models.SimpleContact
import com.simplemobiletools.commons.views.MyLinearLayoutManager
import com.simplemobiletools.commons.views.MyRecyclerView
import kotlinx.android.synthetic.main.activity_main.*
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
@ -77,6 +80,12 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
private var mStoredStartWeekWithCurrentDay = false
private var mStoredHighlightWeekendsColor = 0
// search results have endless scrolling, so reaching the top/bottom fetches further results
private var minFetchedSearchTS = 0L
private var maxFetchedSearchTS = 0L
private var searchResultEvents = ArrayList<Event>()
private var bottomItemAtRefresh: ListItem? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
@ -328,6 +337,10 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
private fun closeSearch() {
main_menu.closeSearch()
minFetchedSearchTS = 0L
maxFetchedSearchTS = 0L
searchResultEvents.clear()
bottomItemAtRefresh = null
}
private fun checkCalDAVUpdateListener() {
@ -1180,35 +1193,19 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
search_holder.fadeIn()
} else if (text.isEmpty()) {
search_holder.fadeOut()
search_results_list.adapter = null
}
search_placeholder_2.beVisibleIf(text.length == 1)
if (text.length >= 2) {
val minFetchedTS = DateTime().minusMinutes(config.displayPastEvents).seconds()
val maxFetchedTS = DateTime().plusMonths(6).seconds()
if (search_results_list.adapter == null) {
minFetchedSearchTS = DateTime().minusMinutes(config.displayPastEvents).seconds()
maxFetchedSearchTS = DateTime().plusMonths(6).seconds()
}
eventsHelper.getEvents(minFetchedTS, maxFetchedTS) { events ->
eventsHelper.getEvents(minFetchedSearchTS, maxFetchedSearchTS) { events ->
if (text == mLatestSearchQuery) {
runOnUiThread {
val filtered = events.filter {
it.title.contains(text, true) || it.location.contains(text, true) || it.description.contains(text, true)
}
search_results_list.beVisibleIf(filtered.isNotEmpty())
search_placeholder.beVisibleIf(filtered.isEmpty())
val listItems = getEventListItems(filtered)
val eventsAdapter = EventListAdapter(this, listItems, true, this, search_results_list) {
hideKeyboard()
if (it is ListEvent) {
Intent(applicationContext, getActivityToOpen(it.isTask)).apply {
putExtra(EVENT_ID, it.id)
startActivity(this)
}
}
}
search_results_list.adapter = eventsAdapter
}
showSearchResultEvents(events, INITIAL_EVENTS)
}
}
} else if (text.length == 1) {
@ -1217,6 +1214,85 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
}
private fun showSearchResultEvents(events: ArrayList<Event>, updateStatus: Int) {
val currentSearchQuery = main_menu.getCurrentQuery()
val filtered = events.filter {
it.title.contains(currentSearchQuery, true) || it.location.contains(currentSearchQuery, true) || it.description.contains(currentSearchQuery, true)
}
searchResultEvents = filtered.toMutableList() as ArrayList<Event>
runOnUiThread {
search_results_list.beVisibleIf(filtered.isNotEmpty())
search_placeholder.beVisibleIf(filtered.isEmpty())
val listItems = getEventListItems(filtered)
val currAdapter = search_results_list.adapter
if (currAdapter == null) {
val eventsAdapter = EventListAdapter(this, listItems, true, this, search_results_list) {
hideKeyboard()
if (it is ListEvent) {
Intent(applicationContext, getActivityToOpen(it.isTask)).apply {
putExtra(EVENT_ID, it.id)
startActivity(this)
}
}
}
search_results_list.adapter = eventsAdapter
search_results_list.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener {
override fun updateTop() {
fetchPreviousPeriod()
}
override fun updateBottom() {
fetchNextPeriod()
}
}
} else {
(currAdapter as EventListAdapter).updateListItems(listItems)
if (updateStatus == UPDATE_TOP) {
val item = listItems.indexOfFirst { it == bottomItemAtRefresh }
if (item != -1) {
search_results_list.scrollToPosition(item)
}
} else if (updateStatus == UPDATE_BOTTOM) {
search_results_list.smoothScrollBy(0, resources.getDimension(R.dimen.endless_scroll_move_height).toInt())
}
}
}
}
private fun fetchPreviousPeriod() {
val lastPosition = (search_results_list.layoutManager as MyLinearLayoutManager).findLastVisibleItemPosition()
bottomItemAtRefresh = (search_results_list.adapter as EventListAdapter).listItems[lastPosition]
val oldMinFetchedTS = minFetchedSearchTS - 1
minFetchedSearchTS -= FETCH_INTERVAL
eventsHelper.getEvents(minFetchedSearchTS, oldMinFetchedTS) { events ->
events.forEach { event ->
if (searchResultEvents.firstOrNull { it.id == event.id && it.startTS == event.startTS } == null) {
searchResultEvents.add(0, event)
}
}
showSearchResultEvents(searchResultEvents, UPDATE_TOP)
}
}
private fun fetchNextPeriod() {
val oldMaxFetchedTS = maxFetchedSearchTS + 1
maxFetchedSearchTS += FETCH_INTERVAL
eventsHelper.getEvents(oldMaxFetchedTS, maxFetchedSearchTS) { events ->
events.forEach { event ->
if (searchResultEvents.firstOrNull { it.id == event.id && it.startTS == event.startTS } == null) {
searchResultEvents.add(0, event)
}
}
showSearchResultEvents(searchResultEvents, UPDATE_BOTTOM)
}
}
private fun checkSwipeRefreshAvailability() {
swipe_refresh_layout.isEnabled = config.caldavSync && config.pullToRefresh && config.storedView != WEEKLY_VIEW
if (!swipe_refresh_layout.isEnabled) {

View File

@ -13,14 +13,12 @@ import com.simplemobiletools.calendar.pro.activities.MainActivity
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.adapters.EventListAdapter
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.helpers.EVENTS_LIST_VIEW
import com.simplemobiletools.calendar.pro.helpers.Formatter
import com.simplemobiletools.calendar.pro.helpers.*
import com.simplemobiletools.calendar.pro.models.Event
import com.simplemobiletools.calendar.pro.models.ListEvent
import com.simplemobiletools.calendar.pro.models.ListItem
import com.simplemobiletools.calendar.pro.models.ListSectionDay
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.MONTH_SECONDS
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.commons.views.MyLinearLayoutManager
import com.simplemobiletools.commons.views.MyRecyclerView
@ -28,11 +26,6 @@ import kotlinx.android.synthetic.main.fragment_event_list.view.*
import org.joda.time.DateTime
class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
private val NOT_UPDATING = 0
private val UPDATE_TOP = 1
private val UPDATE_BOTTOM = 2
private var FETCH_INTERVAL = 3 * MONTH_SECONDS
private var MIN_EVENTS_TRESHOLD = 30
private var mEvents = ArrayList<Event>()
@ -88,7 +81,7 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
requireContext().eventsHelper.getEvents(minFetchedTS, maxFetchedTS) { events ->
if (events.size >= MIN_EVENTS_TRESHOLD) {
receivedEvents(events, NOT_UPDATING)
receivedEvents(events, INITIAL_EVENTS)
} else {
if (!wereInitialEventsAdded) {
maxFetchedTS += FETCH_INTERVAL
@ -96,7 +89,7 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
requireContext().eventsHelper.getEvents(minFetchedTS, maxFetchedTS) {
mEvents = it
receivedEvents(mEvents, NOT_UPDATING, !wereInitialEventsAdded)
receivedEvents(mEvents, INITIAL_EVENTS, !wereInitialEventsAdded)
}
}
wereInitialEventsAdded = true

View File

@ -2,11 +2,18 @@ package com.simplemobiletools.calendar.pro.helpers
import com.simplemobiletools.calendar.pro.activities.EventActivity
import com.simplemobiletools.calendar.pro.activities.TaskActivity
import com.simplemobiletools.commons.helpers.MONTH_SECONDS
const val STORED_LOCALLY_ONLY = 0
const val ROW_COUNT = 6
const val COLUMN_COUNT = 7
const val SCHEDULE_CALDAV_REQUEST_CODE = 10000
const val FETCH_INTERVAL = 1 * MONTH_SECONDS
// endless scrolling updating
const val INITIAL_EVENTS = 0
const val UPDATE_TOP = 1
const val UPDATE_BOTTOM = 2
const val DAY_CODE = "day_code"
const val YEAR_LABEL = "year"

View File

@ -159,6 +159,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:overScrollMode="never"
android:scrollbars="vertical"
app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager" />