Twidere-App-Android-Twitter.../twidere/src/main/kotlin/org/mariotaku/twidere/fragment/filter/FiltersSubscriptionsFragmen...

345 lines
14 KiB
Kotlin
Raw Normal View History

package org.mariotaku.twidere.fragment.filter
import android.annotation.SuppressLint
2017-01-18 18:48:29 +01:00
import android.app.Activity
2017-01-12 17:26:44 +01:00
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
2017-01-18 18:48:29 +01:00
import android.content.Intent
2017-01-12 17:26:44 +01:00
import android.database.Cursor
import android.os.Bundle
2017-01-18 18:48:29 +01:00
import android.support.v4.app.DialogFragment
2017-01-12 17:26:44 +01:00
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
2017-01-12 18:08:10 +01:00
import android.widget.TextView
2017-01-12 17:26:44 +01:00
import com.rengwuxian.materialedittext.MaterialEditText
import kotlinx.android.synthetic.main.layout_list_with_empty_view.*
import okhttp3.HttpUrl
2017-01-12 17:26:44 +01:00
import org.mariotaku.abstask.library.TaskStarter
import org.mariotaku.ktextension.*
2017-03-05 09:08:09 +01:00
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.Expression
2017-01-12 17:26:44 +01:00
import org.mariotaku.twidere.R
2017-01-18 18:48:29 +01:00
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
2017-02-05 14:42:20 +01:00
import org.mariotaku.twidere.extension.*
2017-01-12 18:08:10 +01:00
import org.mariotaku.twidere.extension.model.getComponentLabel
import org.mariotaku.twidere.extension.model.instantiateComponent
2017-01-12 17:26:44 +01:00
import org.mariotaku.twidere.extension.model.setupUrl
import org.mariotaku.twidere.fragment.BaseDialogFragment
import org.mariotaku.twidere.fragment.BaseFragment
2017-01-18 18:48:29 +01:00
import org.mariotaku.twidere.fragment.ExtraFeaturesIntroductionDialogFragment
2017-01-12 17:26:44 +01:00
import org.mariotaku.twidere.fragment.ProgressDialogFragment
import org.mariotaku.twidere.model.FiltersSubscription
2017-01-18 18:48:29 +01:00
import org.mariotaku.twidere.model.analyzer.PurchaseFinished
2017-01-12 17:26:44 +01:00
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
import org.mariotaku.twidere.task.filter.RefreshFiltersSubscriptionsTask
2017-01-18 18:48:29 +01:00
import org.mariotaku.twidere.util.Analyzer
import org.mariotaku.twidere.util.content.ContentResolverUtils
2017-01-18 18:48:29 +01:00
import org.mariotaku.twidere.util.premium.ExtraFeaturesService
2017-01-12 17:26:44 +01:00
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 {
2017-01-12 17:26:44 +01:00
private lateinit var adapter: FilterSubscriptionsAdapter
private var actionMode: ActionMode? = null
2017-01-12 17:26:44 +01:00
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
2017-01-12 17:26:44 +01:00
setHasOptionsMenu(true)
adapter = FilterSubscriptionsAdapter(context)
listView.adapter = adapter
listView.choiceMode = ListView.CHOICE_MODE_MULTIPLE_MODAL
listView.setMultiChoiceModeListener(this)
2017-01-12 17:26:44 +01:00
listContainer.visibility = View.GONE
progressContainer.visibility = View.VISIBLE
loaderManager.initLoader(0, null, this)
2017-01-18 18:48:29 +01:00
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)) {
2017-01-18 18:48:29 +01:00
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)
}
2017-01-18 18:48:29 +01:00
}
}
}
}
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()
}
}
}
2017-01-12 17:26:44 +01:00
}
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 -> {
2017-01-18 18:48:29 +01:00
executeAfterFragmentResumed { fragment ->
ProgressDialogFragment.show(fragment.childFragmentManager, FRAGMENT_TAG_RREFRESH_FILTERS)
2017-01-18 18:48:29 +01:00
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
2017-01-18 18:48:29 +01:00
df?.dismiss()
}
}
TaskStarter.execute(task)
2017-01-12 17:26:44 +01:00
}
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)
}
2017-01-12 17:26:44 +01:00
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
}
2017-01-12 17:26:44 +01:00
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 ->
2017-03-05 09:08:09 +01:00
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,
2017-02-13 14:33:45 +01:00
false, ids, null, null)
ContentResolverUtils.bulkDelete(resolver, Filters.Users.CONTENT_URI, Filters.Users.SOURCE,
2017-02-13 14:33:45 +01:00
false, ids, null, null)
ContentResolverUtils.bulkDelete(resolver, Filters.Keywords.CONTENT_URI, Filters.Keywords.SOURCE,
2017-02-13 14:33:45 +01:00
false, ids, null, null)
ContentResolverUtils.bulkDelete(resolver, Filters.Sources.CONTENT_URI, Filters.Sources.SOURCE,
2017-02-13 14:33:45 +01:00
false, ids, null, null)
ContentResolverUtils.bulkDelete(resolver, Filters.Links.CONTENT_URI, Filters.Links.SOURCE,
2017-02-13 14:33:45 +01:00
false, ids, null, null)
}
2017-01-18 18:48:29 +01:00
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")
}
2017-01-12 17:26:44 +01:00
class FilterSubscriptionsAdapter(context: Context) : SimpleCursorAdapter(context,
2017-01-12 18:08:10 +01:00
R.layout.list_item_two_line, null, arrayOf(Filters.Subscriptions.NAME),
2017-01-12 17:26:44 +01:00
intArrayOf(android.R.id.text1), 0) {
2017-03-05 09:08:09 +01:00
private var indices: ObjectCursor.CursorIndices<FiltersSubscription>? = null
2017-01-12 18:08:10 +01:00
private var tempObject: FiltersSubscription = FiltersSubscription()
override fun swapCursor(c: Cursor?): Cursor? {
2017-03-05 09:08:09 +01:00
indices = c?.let { ObjectCursor.indicesFrom(it, FiltersSubscription::class.java) }
2017-01-12 18:08:10 +01:00
return super.swapCursor(c)
}
2017-01-12 17:26:44 +01:00
override fun bindView(view: View, context: Context, cursor: Cursor) {
super.bindView(view, context, cursor)
2017-01-12 18:08:10 +01:00
val indices = this.indices!!
2017-01-12 17:26:44 +01:00
val iconView = view.findViewById(android.R.id.icon)
2017-01-12 18:08:10 +01:00
val summaryView = view.findViewById(android.R.id.text2) as TextView
indices.parseFields(tempObject, cursor)
2017-01-12 17:26:44 +01:00
iconView.visibility = View.GONE
2017-01-12 18:08:10 +01:00
summaryView.text = tempObject.getComponentLabel(context)
2017-01-12 17:26:44 +01:00
}
}
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()
2017-03-05 09:08:09 +01:00
val vc = ObjectCursor.valuesCreatorFrom(FiltersSubscription::class.java)
context.contentResolver.insert(Filters.Subscriptions.CONTENT_URI, vc.create(subscription))
2017-01-12 17:26:44 +01:00
}
builder.setNegativeButton(android.R.string.cancel, null)
val dialog = builder.create()
2017-02-05 14:42:20 +01:00
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)
2017-01-12 17:26:44 +01:00
fun updateEnableState() {
val nameValid = !editName.empty
val urlValid = HttpUrl.parse(editUrl.text.toString()) != null
positiveButton.isEnabled = nameValid && urlValid
2017-01-12 17:26:44 +01:00
}
2017-02-15 14:45:59 +01:00
val watcher = object : SimpleTextWatcher {
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
2017-01-12 17:26:44 +01:00
updateEnableState()
}
}
editName.addTextChangedListener(watcher)
editUrl.addTextChangedListener(watcher)
2017-01-18 18:48:29 +01:00
val args = arguments
if (savedInstanceState == null && args != null) {
editName.setText(args.getString(EXTRA_ADD_SUBSCRIPTION_NAME))
editUrl.setText(args.getString(EXTRA_ADD_SUBSCRIPTION_URL))
}
2017-01-12 17:26:44 +01:00
updateEnableState()
}
return dialog
}
}
2017-01-18 18:48:29 +01:00
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"
2017-01-18 18:48:29 +01:00
}
2017-01-12 17:26:44 +01:00
}
2017-01-12 18:08:10 +01:00