345 lines
14 KiB
Kotlin
345 lines
14 KiB
Kotlin
package org.mariotaku.twidere.fragment.filter
|
|
|
|
import android.annotation.SuppressLint
|
|
import android.app.Activity
|
|
import android.app.Dialog
|
|
import android.content.Context
|
|
import android.content.DialogInterface
|
|
import android.content.Intent
|
|
import android.database.Cursor
|
|
import android.os.Bundle
|
|
import android.support.v4.app.DialogFragment
|
|
import android.support.v4.app.LoaderManager
|
|
import android.support.v4.content.CursorLoader
|
|
import android.support.v4.content.Loader
|
|
import android.support.v4.widget.SimpleCursorAdapter
|
|
import android.support.v7.app.AlertDialog
|
|
import android.view.*
|
|
import android.widget.AbsListView
|
|
import android.widget.ListView
|
|
import android.widget.TextView
|
|
import com.rengwuxian.materialedittext.MaterialEditText
|
|
import kotlinx.android.synthetic.main.layout_list_with_empty_view.*
|
|
import okhttp3.HttpUrl
|
|
import org.mariotaku.abstask.library.TaskStarter
|
|
import org.mariotaku.ktextension.*
|
|
import org.mariotaku.library.objectcursor.ObjectCursor
|
|
import org.mariotaku.sqliteqb.library.Expression
|
|
import org.mariotaku.twidere.R
|
|
import org.mariotaku.twidere.TwidereConstants.REQUEST_PURCHASE_EXTRA_FEATURES
|
|
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACTION
|
|
import org.mariotaku.twidere.constant.IntentConstants.INTENT_PACKAGE_PREFIX
|
|
import org.mariotaku.twidere.extension.*
|
|
import org.mariotaku.twidere.extension.model.getComponentLabel
|
|
import org.mariotaku.twidere.extension.model.instantiateComponent
|
|
import org.mariotaku.twidere.extension.model.setupUrl
|
|
import org.mariotaku.twidere.fragment.BaseDialogFragment
|
|
import org.mariotaku.twidere.fragment.BaseFragment
|
|
import org.mariotaku.twidere.fragment.ExtraFeaturesIntroductionDialogFragment
|
|
import org.mariotaku.twidere.fragment.ProgressDialogFragment
|
|
import org.mariotaku.twidere.model.FiltersSubscription
|
|
import org.mariotaku.twidere.model.analyzer.PurchaseFinished
|
|
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
|
|
import org.mariotaku.twidere.task.filter.RefreshFiltersSubscriptionsTask
|
|
import org.mariotaku.twidere.util.Analyzer
|
|
import org.mariotaku.twidere.util.content.ContentResolverUtils
|
|
import org.mariotaku.twidere.util.premium.ExtraFeaturesService
|
|
import org.mariotaku.twidere.util.view.SimpleTextWatcher
|
|
import java.lang.ref.WeakReference
|
|
|
|
|
|
/**
|
|
* Created by mariotaku on 2016/12/31.
|
|
*/
|
|
class FiltersSubscriptionsFragment : BaseFragment(), LoaderManager.LoaderCallbacks<Cursor>,
|
|
AbsListView.MultiChoiceModeListener {
|
|
|
|
private lateinit var adapter: FilterSubscriptionsAdapter
|
|
private var actionMode: ActionMode? = null
|
|
|
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
|
super.onActivityCreated(savedInstanceState)
|
|
setHasOptionsMenu(true)
|
|
|
|
adapter = FilterSubscriptionsAdapter(context)
|
|
listView.adapter = adapter
|
|
listView.choiceMode = ListView.CHOICE_MODE_MULTIPLE_MODAL
|
|
listView.setMultiChoiceModeListener(this)
|
|
|
|
listContainer.visibility = View.GONE
|
|
progressContainer.visibility = View.VISIBLE
|
|
loaderManager.initLoader(0, null, this)
|
|
|
|
|
|
if (!extraFeaturesService.isSupported()) {
|
|
activity?.finish()
|
|
return
|
|
}
|
|
|
|
if (savedInstanceState == null) {
|
|
when (arguments?.getString(EXTRA_ACTION)) {
|
|
ACTION_ADD_URL_SUBSCRIPTION -> {
|
|
if (!extraFeaturesService.isEnabled(ExtraFeaturesService.FEATURE_FILTERS_SUBSCRIPTION)) {
|
|
val df = ExtraFeaturesIntroductionDialogFragment.show(childFragmentManager,
|
|
ExtraFeaturesService.FEATURE_FILTERS_SUBSCRIPTION)
|
|
df.setTargetFragment(this, REQUEST_ADD_URL_SUBSCRIPTION_PURCHASE)
|
|
} else {
|
|
showAddUrlSubscription()
|
|
}
|
|
}
|
|
else -> {
|
|
if (!extraFeaturesService.isEnabled(ExtraFeaturesService.FEATURE_FILTERS_SUBSCRIPTION)) {
|
|
val df = ExtraFeaturesIntroductionDialogFragment.show(childFragmentManager,
|
|
ExtraFeaturesService.FEATURE_FILTERS_SUBSCRIPTION)
|
|
df.setTargetFragment(this, REQUEST_PURCHASE_EXTRA_FEATURES)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
|
when (requestCode) {
|
|
REQUEST_ADD_URL_SUBSCRIPTION_PURCHASE -> {
|
|
if (resultCode == Activity.RESULT_OK) {
|
|
Analyzer.log(PurchaseFinished.create(data!!))
|
|
executeAfterFragmentResumed { fragment ->
|
|
(fragment as FiltersSubscriptionsFragment).showAddUrlSubscription()
|
|
}
|
|
} else {
|
|
activity?.finish()
|
|
}
|
|
}
|
|
REQUEST_PURCHASE_EXTRA_FEATURES -> {
|
|
if (resultCode == Activity.RESULT_OK) {
|
|
Analyzer.log(PurchaseFinished.create(data!!))
|
|
} else {
|
|
activity?.finish()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
|
inflater.inflate(R.menu.menu_filters_subscriptions, menu)
|
|
}
|
|
|
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
when (item.itemId) {
|
|
R.id.add -> {
|
|
val df = AddUrlSubscriptionDialogFragment()
|
|
df.show(fragmentManager, "add_url_subscription")
|
|
return true
|
|
}
|
|
R.id.refresh -> {
|
|
executeAfterFragmentResumed { fragment ->
|
|
ProgressDialogFragment.show(fragment.childFragmentManager, FRAGMENT_TAG_RREFRESH_FILTERS)
|
|
val task = RefreshFiltersSubscriptionsTask(fragment.context)
|
|
val fragmentRef = WeakReference(fragment)
|
|
task.callback = {
|
|
fragmentRef.get()?.executeAfterFragmentResumed { fragment ->
|
|
val df = fragment.childFragmentManager.findFragmentByTag(FRAGMENT_TAG_RREFRESH_FILTERS) as? DialogFragment
|
|
df?.dismiss()
|
|
}
|
|
}
|
|
TaskStarter.execute(task)
|
|
}
|
|
return true
|
|
}
|
|
else -> return false
|
|
}
|
|
}
|
|
|
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
|
return inflater.inflate(R.layout.layout_list_with_empty_view, container, false)
|
|
}
|
|
|
|
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> {
|
|
val loader = CursorLoader(context)
|
|
loader.uri = Filters.Subscriptions.CONTENT_URI
|
|
loader.projection = Filters.Subscriptions.COLUMNS
|
|
return loader
|
|
}
|
|
|
|
override fun onLoaderReset(loader: Loader<Cursor>) {
|
|
adapter.changeCursor(null)
|
|
}
|
|
|
|
override fun onLoadFinished(loader: Loader<Cursor>, cursor: Cursor) {
|
|
adapter.changeCursor(cursor)
|
|
if (cursor.isEmpty) {
|
|
listView.visibility = View.GONE
|
|
emptyView.visibility = View.VISIBLE
|
|
emptyIcon.setImageResource(R.drawable.ic_info_info_generic)
|
|
emptyText.setText(R.string.hint_empty_filters_subscriptions)
|
|
} else {
|
|
listView.visibility = View.VISIBLE
|
|
emptyView.visibility = View.GONE
|
|
}
|
|
listContainer.visibility = View.VISIBLE
|
|
progressContainer.visibility = View.GONE
|
|
}
|
|
|
|
override fun onItemCheckedStateChanged(mode: ActionMode?, position: Int, id: Long, checked: Boolean) {
|
|
|
|
}
|
|
|
|
|
|
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
|
|
actionMode = mode
|
|
mode.menuInflater.inflate(R.menu.action_multi_select_items, menu)
|
|
menu.setGroupAvailability(R.id.selection_group, true)
|
|
return true
|
|
}
|
|
|
|
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
|
listView.updateSelectionItems(menu)
|
|
return true
|
|
}
|
|
|
|
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
|
when (item.itemId) {
|
|
R.id.delete -> {
|
|
performDeletion()
|
|
mode.finish()
|
|
}
|
|
R.id.select_all -> {
|
|
listView.selectAll()
|
|
}
|
|
R.id.select_none -> {
|
|
listView.selectNone()
|
|
}
|
|
R.id.invert_selection -> {
|
|
listView.invertSelection()
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
override fun onDestroyActionMode(mode: ActionMode) {
|
|
actionMode = null
|
|
}
|
|
|
|
@SuppressLint("Recycle")
|
|
private fun performDeletion() {
|
|
val ids = listView.checkedItemIds
|
|
val resolver = context.contentResolver
|
|
val where = Expression.inArgs(Filters.Subscriptions._ID, ids.size).sql
|
|
val whereArgs = ids.toStringArray()
|
|
resolver.query(Filters.Subscriptions.CONTENT_URI, Filters.Subscriptions.COLUMNS, where,
|
|
whereArgs, null)?.useCursor { cursor ->
|
|
val indices = ObjectCursor.indicesFrom(cursor, FiltersSubscription::class.java)
|
|
cursor.moveToFirst()
|
|
while (!cursor.isAfterLast) {
|
|
val subscription = indices.newObject(cursor)
|
|
subscription.instantiateComponent(context)?.deleteLocalData()
|
|
cursor.moveToNext()
|
|
}
|
|
}
|
|
ContentResolverUtils.bulkDelete(resolver, Filters.Subscriptions.CONTENT_URI, Filters._ID,
|
|
false, ids, null, null)
|
|
ContentResolverUtils.bulkDelete(resolver, Filters.Users.CONTENT_URI, Filters.Users.SOURCE,
|
|
false, ids, null, null)
|
|
ContentResolverUtils.bulkDelete(resolver, Filters.Keywords.CONTENT_URI, Filters.Keywords.SOURCE,
|
|
false, ids, null, null)
|
|
ContentResolverUtils.bulkDelete(resolver, Filters.Sources.CONTENT_URI, Filters.Sources.SOURCE,
|
|
false, ids, null, null)
|
|
ContentResolverUtils.bulkDelete(resolver, Filters.Links.CONTENT_URI, Filters.Links.SOURCE,
|
|
false, ids, null, null)
|
|
}
|
|
|
|
private fun showAddUrlSubscription() {
|
|
val df = AddUrlSubscriptionDialogFragment()
|
|
df.arguments = Bundle {
|
|
this[EXTRA_ADD_SUBSCRIPTION_URL] = arguments?.getString(EXTRA_ADD_SUBSCRIPTION_URL)
|
|
this[EXTRA_ADD_SUBSCRIPTION_NAME] = arguments?.getString(EXTRA_ADD_SUBSCRIPTION_NAME)
|
|
}
|
|
df.show(fragmentManager, "add_url_subscription")
|
|
}
|
|
|
|
class FilterSubscriptionsAdapter(context: Context) : SimpleCursorAdapter(context,
|
|
R.layout.list_item_two_line, null, arrayOf(Filters.Subscriptions.NAME),
|
|
intArrayOf(android.R.id.text1), 0) {
|
|
private var indices: ObjectCursor.CursorIndices<FiltersSubscription>? = null
|
|
private var tempObject: FiltersSubscription = FiltersSubscription()
|
|
|
|
override fun swapCursor(c: Cursor?): Cursor? {
|
|
indices = c?.let { ObjectCursor.indicesFrom(it, FiltersSubscription::class.java) }
|
|
return super.swapCursor(c)
|
|
}
|
|
|
|
override fun bindView(view: View, context: Context, cursor: Cursor) {
|
|
super.bindView(view, context, cursor)
|
|
val indices = this.indices!!
|
|
val iconView = view.findViewById(android.R.id.icon)
|
|
val summaryView = view.findViewById(android.R.id.text2) as TextView
|
|
|
|
indices.parseFields(tempObject, cursor)
|
|
|
|
iconView.visibility = View.GONE
|
|
summaryView.text = tempObject.getComponentLabel(context)
|
|
}
|
|
}
|
|
|
|
class AddUrlSubscriptionDialogFragment : BaseDialogFragment() {
|
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
|
val builder = AlertDialog.Builder(context)
|
|
builder.setView(R.layout.dialog_add_filters_subscription)
|
|
builder.setPositiveButton(R.string.action_add_filters_subscription) { dialog, which ->
|
|
dialog as AlertDialog
|
|
val editName = dialog.findViewById(R.id.name) as MaterialEditText
|
|
val editUrl = dialog.findViewById(R.id.url) as MaterialEditText
|
|
val subscription = FiltersSubscription()
|
|
subscription.name = editName.text.toString()
|
|
subscription.setupUrl(editUrl.text.toString())
|
|
val component = subscription.instantiateComponent(context) ?: return@setPositiveButton
|
|
component.firstAdded()
|
|
val vc = ObjectCursor.valuesCreatorFrom(FiltersSubscription::class.java)
|
|
context.contentResolver.insert(Filters.Subscriptions.CONTENT_URI, vc.create(subscription))
|
|
}
|
|
builder.setNegativeButton(android.R.string.cancel, null)
|
|
val dialog = builder.create()
|
|
dialog.setOnShowListener {
|
|
it as AlertDialog
|
|
it.applyTheme()
|
|
val editName = it.findViewById(R.id.name) as MaterialEditText
|
|
val editUrl = it.findViewById(R.id.url) as MaterialEditText
|
|
val positiveButton = it.getButton(DialogInterface.BUTTON_POSITIVE)
|
|
|
|
fun updateEnableState() {
|
|
val nameValid = !editName.empty
|
|
val urlValid = HttpUrl.parse(editUrl.text.toString()) != null
|
|
positiveButton.isEnabled = nameValid && urlValid
|
|
}
|
|
|
|
val watcher = object : SimpleTextWatcher {
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
|
updateEnableState()
|
|
}
|
|
}
|
|
editName.addTextChangedListener(watcher)
|
|
editUrl.addTextChangedListener(watcher)
|
|
|
|
val args = arguments
|
|
if (savedInstanceState == null && args != null) {
|
|
editName.setText(args.getString(EXTRA_ADD_SUBSCRIPTION_NAME))
|
|
editUrl.setText(args.getString(EXTRA_ADD_SUBSCRIPTION_URL))
|
|
}
|
|
|
|
updateEnableState()
|
|
}
|
|
return dialog
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
const val ACTION_ADD_URL_SUBSCRIPTION = "${INTENT_PACKAGE_PREFIX}ADD_URL_FILTERS_SUBSCRIPTION"
|
|
const val REQUEST_ADD_URL_SUBSCRIPTION_PURCHASE = 101
|
|
const val EXTRA_ADD_SUBSCRIPTION_URL = "add_subscription.url"
|
|
const val EXTRA_ADD_SUBSCRIPTION_NAME = "add_subscription.name"
|
|
private const val FRAGMENT_TAG_RREFRESH_FILTERS = "refresh_filters"
|
|
}
|
|
}
|
|
|
|
|