applying filter in real time
This commit is contained in:
parent
a44d772852
commit
b27ec2ce4e
|
@ -84,7 +84,7 @@ subprojects {
|
||||||
Room : '1.1.0',
|
Room : '1.1.0',
|
||||||
ConstraintLayout : '1.1.0',
|
ConstraintLayout : '1.1.0',
|
||||||
MessageBubbleView : '2.4',
|
MessageBubbleView : '2.4',
|
||||||
WorkManager : '1.0.0-alpha01',
|
WorkManager : '1.0.0-alpha02',
|
||||||
]
|
]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,12 +44,20 @@ class CursorObjectDataSourceFactory<T : Any>(
|
||||||
val processor: DataSourceItemProcessor<T>? = null
|
val processor: DataSourceItemProcessor<T>? = null
|
||||||
) : DataSource.Factory<Int, T>() {
|
) : DataSource.Factory<Int, T>() {
|
||||||
|
|
||||||
|
private val observerInfo = mutableListOf<ObserverInfo>()
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
override fun create(): DataSource<Int, T> {
|
override fun create(): DataSource<Int, T> {
|
||||||
return CursorObjectDataSource(resolver, uri, projection, selection, selectionArgs,
|
return CursorObjectDataSource(resolver, uri, projection, selection, selectionArgs,
|
||||||
sortOrder, cls, processor)
|
sortOrder, cls, processor, observerInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun registerContentObserver(uri: Uri, notifyForDescendants: Boolean) {
|
||||||
|
observerInfo.add(ObserverInfo(uri, notifyForDescendants))
|
||||||
|
}
|
||||||
|
|
||||||
|
private data class ObserverInfo(val uri: Uri, val notifyForDescendants: Boolean)
|
||||||
|
|
||||||
private class CursorObjectDataSource<T : Any>(
|
private class CursorObjectDataSource<T : Any>(
|
||||||
val resolver: ContentResolver,
|
val resolver: ContentResolver,
|
||||||
val uri: Uri,
|
val uri: Uri,
|
||||||
|
@ -58,7 +66,8 @@ class CursorObjectDataSourceFactory<T : Any>(
|
||||||
val selectionArgs: Array<String>? = null,
|
val selectionArgs: Array<String>? = null,
|
||||||
val sortOrder: String? = null,
|
val sortOrder: String? = null,
|
||||||
val cls: Class<T>,
|
val cls: Class<T>,
|
||||||
val processor: DataSourceItemProcessor<T>?
|
val processor: DataSourceItemProcessor<T>?,
|
||||||
|
val observerInfo: List<ObserverInfo>
|
||||||
) : PositionalDataSource<T>() {
|
) : PositionalDataSource<T>() {
|
||||||
|
|
||||||
private val totalCount: Int by lazy { resolver.queryCount(uri, selection, selectionArgs) }
|
private val totalCount: Int by lazy { resolver.queryCount(uri, selection, selectionArgs) }
|
||||||
|
@ -69,10 +78,16 @@ class CursorObjectDataSourceFactory<T : Any>(
|
||||||
val observer: ContentObserver = object : ContentObserver(MainHandler) {
|
val observer: ContentObserver = object : ContentObserver(MainHandler) {
|
||||||
override fun onChange(selfChange: Boolean) {
|
override fun onChange(selfChange: Boolean) {
|
||||||
resolver.unregisterContentObserver(this)
|
resolver.unregisterContentObserver(this)
|
||||||
|
observerInfo.forEach {
|
||||||
|
resolver.unregisterContentObserver(this)
|
||||||
|
}
|
||||||
weakThis?.invalidate()
|
weakThis?.invalidate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resolver.registerContentObserver(uri, false, observer)
|
resolver.registerContentObserver(uri, false, observer)
|
||||||
|
observerInfo.forEach {
|
||||||
|
resolver.registerContentObserver(it.uri, it.notifyForDescendants, observer)
|
||||||
|
}
|
||||||
processor?.init(resolver)
|
processor?.init(resolver)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +133,7 @@ class CursorObjectDataSourceFactory<T : Any>(
|
||||||
"$offset,$limit", cls) ?: return false
|
"$offset,$limit", cls) ?: return false
|
||||||
DebugLog.d(msg = "Querying $uri:$startPosition,$count took ${System.currentTimeMillis() - start} ms.")
|
DebugLog.d(msg = "Querying $uri:$startPosition,$count took ${System.currentTimeMillis() - start} ms.")
|
||||||
val reachedEnd = list.size < count
|
val reachedEnd = list.size < count
|
||||||
list.mapIndexedNotNullTo(result) lambda@ { index, item ->
|
list.mapIndexedNotNullTo(result) lambda@{ index, item ->
|
||||||
val processed = processor.process(item)
|
val processed = processor.process(item)
|
||||||
filterStates[offset + index] = processed != null
|
filterStates[offset + index] = processed != null
|
||||||
return@lambda processed
|
return@lambda processed
|
||||||
|
|
|
@ -79,6 +79,7 @@ import org.mariotaku.twidere.model.pagination.SinceMaxPagination
|
||||||
import org.mariotaku.twidere.model.refresh.BaseContentRefreshParam
|
import org.mariotaku.twidere.model.refresh.BaseContentRefreshParam
|
||||||
import org.mariotaku.twidere.model.refresh.ContentRefreshParam
|
import org.mariotaku.twidere.model.refresh.ContentRefreshParam
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Activities
|
import org.mariotaku.twidere.provider.TwidereDataStore.Activities
|
||||||
|
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
|
||||||
import org.mariotaku.twidere.singleton.BusSingleton
|
import org.mariotaku.twidere.singleton.BusSingleton
|
||||||
import org.mariotaku.twidere.singleton.PreferencesSingleton
|
import org.mariotaku.twidere.singleton.PreferencesSingleton
|
||||||
import org.mariotaku.twidere.task.statuses.GetStatusesTask
|
import org.mariotaku.twidere.task.statuses.GetStatusesTask
|
||||||
|
@ -381,6 +382,7 @@ abstract class AbsActivitiesFragment : AbsContentRecyclerViewFragment<Parcelable
|
||||||
activityColumnsLite, Expression.and(*expressions.toTypedArray()).sql,
|
activityColumnsLite, Expression.and(*expressions.toTypedArray()).sql,
|
||||||
expressionArgs.toTypedArray(), Activities.DEFAULT_SORT_ORDER,
|
expressionArgs.toTypedArray(), Activities.DEFAULT_SORT_ORDER,
|
||||||
ParcelableActivity::class.java, onCreateCursorObjectProcessor())
|
ParcelableActivity::class.java, onCreateCursorObjectProcessor())
|
||||||
|
factory.registerContentObserver(Filters.CONTENT_URI, true)
|
||||||
// dataController = factory.obtainDataController()
|
// dataController = factory.obtainDataController()
|
||||||
return LivePagedListBuilder(factory, AbsTimelineFragment.databasePagedListConfig).build()
|
return LivePagedListBuilder(factory, AbsTimelineFragment.databasePagedListConfig).build()
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,7 @@ import org.mariotaku.twidere.model.refresh.ContentRefreshParam
|
||||||
import org.mariotaku.twidere.model.tab.extra.TimelineTabExtras
|
import org.mariotaku.twidere.model.tab.extra.TimelineTabExtras
|
||||||
import org.mariotaku.twidere.model.timeline.TimelineFilter
|
import org.mariotaku.twidere.model.timeline.TimelineFilter
|
||||||
import org.mariotaku.twidere.promise.StatusPromises
|
import org.mariotaku.twidere.promise.StatusPromises
|
||||||
|
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses
|
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses
|
||||||
import org.mariotaku.twidere.singleton.BusSingleton
|
import org.mariotaku.twidere.singleton.BusSingleton
|
||||||
import org.mariotaku.twidere.singleton.PreferencesSingleton
|
import org.mariotaku.twidere.singleton.PreferencesSingleton
|
||||||
|
@ -458,6 +459,7 @@ abstract class AbsTimelineFragment : AbsContentRecyclerViewFragment<ParcelableSt
|
||||||
statusColumnsLite, Expression.and(*expressions.toTypedArray()).sql,
|
statusColumnsLite, Expression.and(*expressions.toTypedArray()).sql,
|
||||||
expressionArgs.toTypedArray(), Statuses.DEFAULT_SORT_ORDER,
|
expressionArgs.toTypedArray(), Statuses.DEFAULT_SORT_ORDER,
|
||||||
ParcelableStatus::class.java, processor)
|
ParcelableStatus::class.java, processor)
|
||||||
|
factory.registerContentObserver(Filters.CONTENT_URI, true)
|
||||||
// dataController = factory.obtainDataController()
|
// dataController = factory.obtainDataController()
|
||||||
return ExceptionLiveData.wrap(LivePagedListBuilder(factory, databasePagedListConfig)
|
return ExceptionLiveData.wrap(LivePagedListBuilder(factory, databasePagedListConfig)
|
||||||
.setBoundaryCallback(timelineBoundaryCallback).build())
|
.setBoundaryCallback(timelineBoundaryCallback).build())
|
||||||
|
|
|
@ -32,7 +32,7 @@ import org.mariotaku.twidere.util.ErrorInfoStore
|
||||||
class GetListTimelineTask(context: Context) : GetStatusesTask<ListTimelineContentRefreshParam>(context) {
|
class GetListTimelineTask(context: Context) : GetStatusesTask<ListTimelineContentRefreshParam>(context) {
|
||||||
|
|
||||||
override val contentUri: Uri
|
override val contentUri: Uri
|
||||||
get() = Statuses.GroupTimeline.CONTENT_URI.withAppendedPath(params.tabId)
|
get() = Statuses.ListTimeline.CONTENT_URI.withAppendedPath(params.tabId)
|
||||||
|
|
||||||
override val filterScopes: Int = FilterScope.LIST_GROUP_TIMELINE
|
override val filterScopes: Int = FilterScope.LIST_GROUP_TIMELINE
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,11 @@ class MediaContainerHelper(context: Context, attrs: AttributeSet?) : ConstraintH
|
||||||
val referencedCount: Int
|
val referencedCount: Int
|
||||||
get() = mCount
|
get() = mCount
|
||||||
|
|
||||||
|
fun hideAll() {
|
||||||
|
for (i in 0 until mCount) {
|
||||||
|
getReferencedViewAt(i).setVisible(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("SwitchIntDef")
|
@SuppressLint("SwitchIntDef")
|
||||||
fun layout1(@PreviewStyle style: Int, item: ParcelableMedia) {
|
fun layout1(@PreviewStyle style: Int, item: ParcelableMedia) {
|
||||||
|
|
|
@ -24,6 +24,7 @@ import android.view.View
|
||||||
import kotlinx.android.synthetic.main.layout_content_item_attachment_media.view.*
|
import kotlinx.android.synthetic.main.layout_content_item_attachment_media.view.*
|
||||||
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter
|
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter
|
||||||
import org.mariotaku.twidere.annotation.PreviewStyle
|
import org.mariotaku.twidere.annotation.PreviewStyle
|
||||||
|
import org.mariotaku.twidere.extension.setVisible
|
||||||
import org.mariotaku.twidere.model.ParcelableMedia
|
import org.mariotaku.twidere.model.ParcelableMedia
|
||||||
import org.mariotaku.twidere.model.ParcelableStatus
|
import org.mariotaku.twidere.model.ParcelableStatus
|
||||||
import org.mariotaku.twidere.util.glide.GlideApp
|
import org.mariotaku.twidere.util.glide.GlideApp
|
||||||
|
@ -33,11 +34,14 @@ import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
|
||||||
class MediaAttachmentHolder(parent: StatusViewHolder, view: ConstraintLayout) : StatusViewHolder.AttachmentHolder(parent, view) {
|
class MediaAttachmentHolder(parent: StatusViewHolder, view: ConstraintLayout) : StatusViewHolder.AttachmentHolder(parent, view) {
|
||||||
|
|
||||||
private var mediaPreviewStyle: Int = PreviewStyle.CROP
|
private var mediaPreviewStyle: Int = PreviewStyle.CROP
|
||||||
|
private var mediaPreviewEnabled: Boolean = false
|
||||||
|
|
||||||
private val mediaContainerHelper = view.mediaContainerHelper
|
private val mediaContainerHelper = view.mediaContainerHelper
|
||||||
|
private val mediaPreviewIndicator = view.mediaPreviewIndicator
|
||||||
|
|
||||||
override fun setupViewOptions(adapter: IStatusesAdapter) {
|
override fun setupViewOptions(adapter: IStatusesAdapter) {
|
||||||
mediaPreviewStyle = adapter.mediaPreviewStyle
|
mediaPreviewStyle = adapter.mediaPreviewStyle
|
||||||
|
mediaPreviewEnabled = adapter.mediaPreviewEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setTextSize(textSize: Float) {
|
override fun setTextSize(textSize: Float) {
|
||||||
|
@ -45,6 +49,12 @@ class MediaAttachmentHolder(parent: StatusViewHolder, view: ConstraintLayout) :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun display(status: ParcelableStatus) {
|
override fun display(status: ParcelableStatus) {
|
||||||
|
if (!mediaPreviewEnabled) {
|
||||||
|
mediaPreviewIndicator.setVisible(true)
|
||||||
|
mediaContainerHelper.hideAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mediaPreviewIndicator.setVisible(false)
|
||||||
val media = status.attachment!!.media!!
|
val media = status.attachment!!.media!!
|
||||||
when (media.size) {
|
when (media.size) {
|
||||||
1 -> mediaContainerHelper.layout1(mediaPreviewStyle, media.first())
|
1 -> mediaContainerHelper.layout1(mediaPreviewStyle, media.first())
|
||||||
|
|
|
@ -24,6 +24,15 @@
|
||||||
tools:layout_width="match_parent"
|
tools:layout_width="match_parent"
|
||||||
tools:parentTag="android.support.constraint.ConstraintLayout">
|
tools:parentTag="android.support.constraint.ConstraintLayout">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/mediaPreviewIndicator"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/label_media"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<org.mariotaku.twidere.view.MediaPreviewImageView
|
<org.mariotaku.twidere.view.MediaPreviewImageView
|
||||||
android:id="@+id/mediaPreviewItem0"
|
android:id="@+id/mediaPreviewItem0"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
|
Loading…
Reference in New Issue