improved users selector
This commit is contained in:
parent
3129a25c55
commit
2c1b8b37f2
|
@ -208,4 +208,5 @@ public interface IntentConstants {
|
||||||
String EXTRA_API_CONFIG = "api_config";
|
String EXTRA_API_CONFIG = "api_config";
|
||||||
String EXTRA_COUNT = "count";
|
String EXTRA_COUNT = "count";
|
||||||
String EXTRA_REQUEST_CODE = "request_code";
|
String EXTRA_REQUEST_CODE = "request_code";
|
||||||
|
String EXTRA_FROM_CACHE = "from_cache";
|
||||||
}
|
}
|
||||||
|
|
|
@ -377,8 +377,9 @@
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.UserSelectorActivity"
|
android:name=".activity.UserSelectorActivity"
|
||||||
android:label="@string/select_user_list"
|
android:label="@string/select_user"
|
||||||
android:theme="@style/Theme.Twidere.Dialog">
|
android:theme="@style/Theme.Twidere.Dialog"
|
||||||
|
android:windowSoftInputMode="adjustResize">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="org.mariotaku.twidere.SELECT_USER"/>
|
<action android:name="org.mariotaku.twidere.SELECT_USER"/>
|
||||||
|
|
||||||
|
@ -387,8 +388,9 @@
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.UserListSelectorActivity"
|
android:name=".activity.UserListSelectorActivity"
|
||||||
android:label="@string/select_user"
|
android:label="@string/select_user_list"
|
||||||
android:theme="@style/Theme.Twidere.Dialog">
|
android:theme="@style/Theme.Twidere.Dialog"
|
||||||
|
android:windowSoftInputMode="adjustResize">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="org.mariotaku.twidere.SELECT_USER_LIST"/>
|
<action android:name="org.mariotaku.twidere.SELECT_USER_LIST"/>
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import android.content.Intent
|
||||||
import android.os.AsyncTask
|
import android.os.AsyncTask
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v4.app.DialogFragment
|
import android.support.v4.app.DialogFragment
|
||||||
|
import android.support.v4.app.LoaderManager
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.text.TextUtils.isEmpty
|
import android.text.TextUtils.isEmpty
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
@ -43,6 +44,7 @@ import org.mariotaku.twidere.adapter.UserAutoCompleteAdapter
|
||||||
import org.mariotaku.twidere.constant.IntentConstants.*
|
import org.mariotaku.twidere.constant.IntentConstants.*
|
||||||
import org.mariotaku.twidere.fragment.CreateUserListDialogFragment
|
import org.mariotaku.twidere.fragment.CreateUserListDialogFragment
|
||||||
import org.mariotaku.twidere.fragment.ProgressDialogFragment
|
import org.mariotaku.twidere.fragment.ProgressDialogFragment
|
||||||
|
import org.mariotaku.twidere.model.ParcelableUser
|
||||||
import org.mariotaku.twidere.model.ParcelableUserList
|
import org.mariotaku.twidere.model.ParcelableUserList
|
||||||
import org.mariotaku.twidere.model.SingleResponse
|
import org.mariotaku.twidere.model.SingleResponse
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
|
|
@ -21,83 +21,63 @@ package org.mariotaku.twidere.activity
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.AsyncTask
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v4.app.DialogFragment
|
import android.support.v4.app.LoaderManager
|
||||||
|
import android.support.v4.content.Loader
|
||||||
import android.text.TextUtils.isEmpty
|
import android.text.TextUtils.isEmpty
|
||||||
import android.util.Log
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.OnClickListener
|
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.AdapterView.OnItemClickListener
|
import android.widget.AdapterView.OnItemClickListener
|
||||||
import android.widget.ListView
|
import android.widget.ListView
|
||||||
import kotlinx.android.synthetic.main.activity_user_selector.*
|
import kotlinx.android.synthetic.main.activity_user_selector.*
|
||||||
import org.mariotaku.microblog.library.MicroBlogException
|
import kotlinx.android.synthetic.main.layout_list_with_empty_view.*
|
||||||
import org.mariotaku.microblog.library.twitter.model.Paging
|
import org.mariotaku.ktextension.Bundle
|
||||||
|
import org.mariotaku.ktextension.isNotNullOrEmpty
|
||||||
|
import org.mariotaku.ktextension.set
|
||||||
import org.mariotaku.twidere.R
|
import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.TwidereConstants.LOGTAG
|
|
||||||
import org.mariotaku.twidere.adapter.SimpleParcelableUsersAdapter
|
import org.mariotaku.twidere.adapter.SimpleParcelableUsersAdapter
|
||||||
import org.mariotaku.twidere.adapter.UserAutoCompleteAdapter
|
|
||||||
import org.mariotaku.twidere.constant.IntentConstants.*
|
import org.mariotaku.twidere.constant.IntentConstants.*
|
||||||
import org.mariotaku.twidere.fragment.CreateUserListDialogFragment
|
import org.mariotaku.twidere.loader.CacheUserSearchLoader
|
||||||
import org.mariotaku.twidere.fragment.ProgressDialogFragment
|
|
||||||
import org.mariotaku.twidere.model.ParcelableUser
|
import org.mariotaku.twidere.model.ParcelableUser
|
||||||
import org.mariotaku.twidere.model.SingleResponse
|
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.model.util.ParcelableUserUtils
|
|
||||||
import org.mariotaku.twidere.util.AsyncTaskUtils
|
|
||||||
import org.mariotaku.twidere.util.MicroBlogAPIFactory
|
|
||||||
import org.mariotaku.twidere.util.ParseUtils
|
import org.mariotaku.twidere.util.ParseUtils
|
||||||
import java.util.*
|
import org.mariotaku.twidere.util.view.SimpleTextWatcher
|
||||||
|
|
||||||
class UserSelectorActivity : BaseActivity(), OnClickListener, OnItemClickListener {
|
class UserSelectorActivity : BaseActivity(), OnItemClickListener, LoaderManager.LoaderCallbacks<List<ParcelableUser>> {
|
||||||
|
|
||||||
private lateinit var usersAdapter: SimpleParcelableUsersAdapter
|
private lateinit var usersAdapter: SimpleParcelableUsersAdapter
|
||||||
|
|
||||||
private var screenName: String? = null
|
private var loaderInitialized: Boolean = false
|
||||||
|
|
||||||
|
private val accountKey: UserKey?
|
||||||
|
get() = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
val intent = intent
|
val accountKey = this.accountKey ?: run {
|
||||||
if (!intent.hasExtra(EXTRA_ACCOUNT_KEY)) {
|
|
||||||
finish()
|
finish()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setContentView(R.layout.activity_user_selector)
|
setContentView(R.layout.activity_user_selector)
|
||||||
|
|
||||||
|
editScreenName.addTextChangedListener(object : SimpleTextWatcher() {
|
||||||
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||||
|
searchUser(accountKey, s.toString(), true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
screenNameConfirm.setOnClickListener {
|
||||||
|
val screenName = ParseUtils.parseString(editScreenName.text)
|
||||||
|
searchUser(accountKey, screenName, false)
|
||||||
|
}
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
screenName = intent.getStringExtra(EXTRA_SCREEN_NAME)
|
editScreenName.setText(intent.getStringExtra(EXTRA_SCREEN_NAME))
|
||||||
} else {
|
|
||||||
screenName = savedInstanceState.getString(EXTRA_SCREEN_NAME)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEmpty(screenName)) {
|
|
||||||
searchUser(screenName!!)
|
|
||||||
}
|
|
||||||
val adapter = UserAutoCompleteAdapter(this)
|
|
||||||
adapter.accountKey = accountKey
|
|
||||||
editScreenName.setAdapter(adapter)
|
|
||||||
editScreenName.setText(screenName)
|
|
||||||
usersAdapter = SimpleParcelableUsersAdapter(this)
|
usersAdapter = SimpleParcelableUsersAdapter(this)
|
||||||
usersList.adapter = usersAdapter
|
listView.adapter = usersAdapter
|
||||||
usersList.onItemClickListener = this
|
listView.onItemClickListener = this
|
||||||
screenNameConfirm.setOnClickListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onClick(v: View) {
|
showSearchHint()
|
||||||
when (v.id) {
|
|
||||||
R.id.screenNameConfirm -> {
|
|
||||||
val screen_name = ParseUtils.parseString(editScreenName.text)
|
|
||||||
if (isEmpty(screen_name)) return
|
|
||||||
searchUser(screen_name)
|
|
||||||
}
|
|
||||||
R.id.createList -> {
|
|
||||||
val f = CreateUserListDialogFragment()
|
|
||||||
val args = Bundle()
|
|
||||||
args.putParcelable(EXTRA_ACCOUNT_KEY, accountKey)
|
|
||||||
f.arguments = args
|
|
||||||
f.show(supportFragmentManager, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClick(view: AdapterView<*>, child: View, position: Int, id: Long) {
|
override fun onItemClick(view: AdapterView<*>, child: View, position: Int, id: Long) {
|
||||||
|
@ -110,93 +90,79 @@ class UserSelectorActivity : BaseActivity(), OnClickListener, OnItemClickListene
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setUsersData(data: List<ParcelableUser>) {
|
override fun onCreateLoader(id: Int, args: Bundle): Loader<List<ParcelableUser>> {
|
||||||
|
val accountKey = args.getParcelable<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||||
|
val query = args.getString(EXTRA_QUERY)
|
||||||
|
val fromCache = args.getBoolean(EXTRA_FROM_CACHE)
|
||||||
|
if (!fromCache) {
|
||||||
|
showProgress()
|
||||||
|
}
|
||||||
|
return CacheUserSearchLoader(this, accountKey, query, fromCache, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLoaderReset(loader: Loader<List<ParcelableUser>>) {
|
||||||
|
usersAdapter.setData(null, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLoadFinished(loader: Loader<List<ParcelableUser>>, data: List<ParcelableUser>?) {
|
||||||
|
progressContainer.visibility = View.GONE
|
||||||
|
listContainer.visibility = View.VISIBLE
|
||||||
usersAdapter.setData(data, true)
|
usersAdapter.setData(data, true)
|
||||||
}
|
loader as CacheUserSearchLoader
|
||||||
|
if (data.isNotNullOrEmpty()) {
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
showList()
|
||||||
super.onSaveInstanceState(outState)
|
} else if (loader.query.isEmpty()) {
|
||||||
outState.putString(EXTRA_SCREEN_NAME, screenName)
|
showSearchHint()
|
||||||
}
|
} else {
|
||||||
|
showNotFound()
|
||||||
private val accountKey: UserKey
|
|
||||||
get() = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)
|
|
||||||
|
|
||||||
|
|
||||||
private fun searchUser(name: String) {
|
|
||||||
val task = SearchUsersTask(this, accountKey, name)
|
|
||||||
AsyncTaskUtils.executeTask(task)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun dismissDialogFragment(tag: String) {
|
|
||||||
executeAfterFragmentResumed { activity ->
|
|
||||||
val fm = activity.supportFragmentManager
|
|
||||||
val f = fm.findFragmentByTag(tag)
|
|
||||||
if (f is DialogFragment) {
|
|
||||||
f.dismiss()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showDialogFragment(df: DialogFragment, tag: String) {
|
private fun searchUser(accountKey: UserKey, query: String, fromCache: Boolean) {
|
||||||
executeAfterFragmentResumed { activity ->
|
if (isEmpty(query)) {
|
||||||
df.show(activity.supportFragmentManager, tag)
|
showSearchHint()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val args = Bundle {
|
||||||
|
this[EXTRA_ACCOUNT_KEY] = accountKey
|
||||||
|
this[EXTRA_QUERY] = query
|
||||||
|
this[EXTRA_FROM_CACHE] = fromCache
|
||||||
|
}
|
||||||
|
if (loaderInitialized) {
|
||||||
|
supportLoaderManager.initLoader(0, args, this)
|
||||||
|
loaderInitialized = true
|
||||||
|
} else {
|
||||||
|
supportLoaderManager.restartLoader(0, args, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
private fun showProgress() {
|
||||||
super.onStart()
|
progressContainer.visibility = View.VISIBLE
|
||||||
bus.register(this)
|
listContainer.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
private fun showSearchHint() {
|
||||||
bus.unregister(this)
|
progressContainer.visibility = View.GONE
|
||||||
super.onStop()
|
listContainer.visibility = View.VISIBLE
|
||||||
|
emptyView.visibility = View.VISIBLE
|
||||||
|
listView.visibility = View.GONE
|
||||||
|
emptyIcon.setImageResource(R.drawable.ic_info_search)
|
||||||
|
emptyText.text = getText(R.string.search_hint_users)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showNotFound() {
|
||||||
private class SearchUsersTask(
|
progressContainer.visibility = View.GONE
|
||||||
private val activity: UserSelectorActivity,
|
listContainer.visibility = View.VISIBLE
|
||||||
private val accountKey: UserKey,
|
emptyView.visibility = View.VISIBLE
|
||||||
private val name: String
|
listView.visibility = View.GONE
|
||||||
) : AsyncTask<Any, Any, SingleResponse<List<ParcelableUser>>>() {
|
emptyIcon.setImageResource(R.drawable.ic_info_search)
|
||||||
|
emptyText.text = getText(R.string.search_hint_users)
|
||||||
override fun doInBackground(vararg params: Any): SingleResponse<List<ParcelableUser>> {
|
|
||||||
val twitter = MicroBlogAPIFactory.getInstance(activity, accountKey) ?: return SingleResponse.getInstance<List<ParcelableUser>>()
|
|
||||||
try {
|
|
||||||
val paging = Paging()
|
|
||||||
val lists = twitter.searchUsers(name, paging)
|
|
||||||
val data = ArrayList<ParcelableUser>()
|
|
||||||
for (item in lists) {
|
|
||||||
data.add(ParcelableUserUtils.fromUser(item, accountKey))
|
|
||||||
}
|
|
||||||
return SingleResponse.getInstance<List<ParcelableUser>>(data)
|
|
||||||
} catch (e: MicroBlogException) {
|
|
||||||
Log.w(LOGTAG, e)
|
|
||||||
return SingleResponse.getInstance<List<ParcelableUser>>(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPostExecute(result: SingleResponse<List<ParcelableUser>>) {
|
|
||||||
activity.dismissDialogFragment(FRAGMENT_TAG_SEARCH_USERS)
|
|
||||||
if (result.data != null) {
|
|
||||||
activity.setUsersData(result.data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPreExecute() {
|
|
||||||
val df = ProgressDialogFragment()
|
|
||||||
df.isCancelable = false
|
|
||||||
activity.showDialogFragment(df, FRAGMENT_TAG_SEARCH_USERS)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
private const val FRAGMENT_TAG_SEARCH_USERS = "search_users"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showList() {
|
||||||
|
progressContainer.visibility = View.GONE
|
||||||
|
listContainer.visibility = View.VISIBLE
|
||||||
|
listView.visibility = View.VISIBLE
|
||||||
|
emptyView.visibility = View.GONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,6 @@ import com.squareup.otto.Subscribe
|
||||||
import kotlinx.android.synthetic.main.fragment_messages_conversation.*
|
import kotlinx.android.synthetic.main.fragment_messages_conversation.*
|
||||||
import kotlinx.android.synthetic.main.layout_actionbar_message_user_picker.view.*
|
import kotlinx.android.synthetic.main.layout_actionbar_message_user_picker.view.*
|
||||||
import me.uucky.colorpicker.internal.EffectViewHelper
|
import me.uucky.colorpicker.internal.EffectViewHelper
|
||||||
import org.mariotaku.sqliteqb.library.Columns.Column
|
|
||||||
import org.mariotaku.sqliteqb.library.Expression
|
import org.mariotaku.sqliteqb.library.Expression
|
||||||
import org.mariotaku.sqliteqb.library.OrderBy
|
import org.mariotaku.sqliteqb.library.OrderBy
|
||||||
import org.mariotaku.twidere.R
|
import org.mariotaku.twidere.R
|
||||||
|
@ -67,12 +66,14 @@ import org.mariotaku.twidere.annotation.CustomTabType
|
||||||
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.ACTION_NAVIGATION_BACK
|
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.ACTION_NAVIGATION_BACK
|
||||||
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.CONTEXT_TAG_NAVIGATION
|
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.CONTEXT_TAG_NAVIGATION
|
||||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants
|
import org.mariotaku.twidere.constant.SharedPreferenceConstants
|
||||||
import org.mariotaku.twidere.loader.UserSearchLoader
|
import org.mariotaku.twidere.loader.CacheUserSearchLoader
|
||||||
import org.mariotaku.twidere.model.*
|
import org.mariotaku.twidere.model.AccountDetails
|
||||||
|
import org.mariotaku.twidere.model.ParcelableDirectMessage
|
||||||
|
import org.mariotaku.twidere.model.ParcelableUser
|
||||||
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.model.message.TaskStateChangedEvent
|
import org.mariotaku.twidere.model.message.TaskStateChangedEvent
|
||||||
import org.mariotaku.twidere.model.util.AccountUtils
|
import org.mariotaku.twidere.model.util.AccountUtils
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore
|
import org.mariotaku.twidere.provider.TwidereDataStore
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers
|
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages
|
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.Conversation
|
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.Conversation
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.ConversationEntries
|
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.ConversationEntries
|
||||||
|
@ -99,8 +100,7 @@ class MessagesConversationFragment : BaseFragment(), LoaderCallbacks<Cursor?>, O
|
||||||
val query = args.getString(EXTRA_QUERY)
|
val query = args.getString(EXTRA_QUERY)
|
||||||
val fromCache = args.getBoolean(EXTRA_FROM_CACHE)
|
val fromCache = args.getBoolean(EXTRA_FROM_CACHE)
|
||||||
val fromUser = args.getBoolean(EXTRA_FROM_USER, false)
|
val fromUser = args.getBoolean(EXTRA_FROM_USER, false)
|
||||||
return CacheUserSearchLoader(this@MessagesConversationFragment, accountKey, query,
|
return CacheUserSearchLoader(context, accountKey, query, fromCache, fromUser)
|
||||||
fromCache, fromUser)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLoadFinished(loader: Loader<List<ParcelableUser>>, data: List<ParcelableUser>?) {
|
override fun onLoadFinished(loader: Loader<List<ParcelableUser>>, data: List<ParcelableUser>?) {
|
||||||
|
@ -706,49 +706,6 @@ class MessagesConversationFragment : BaseFragment(), LoaderCallbacks<Cursor?>, O
|
||||||
// }.executeTask();
|
// }.executeTask();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
class CacheUserSearchLoader(
|
|
||||||
fragment: MessagesConversationFragment,
|
|
||||||
accountKey: UserKey,
|
|
||||||
query: String,
|
|
||||||
private val fromCache: Boolean,
|
|
||||||
fromUser: Boolean
|
|
||||||
) : UserSearchLoader(fragment.context, accountKey, query, 0, null, fromUser) {
|
|
||||||
private val userColorNameManager: UserColorNameManager
|
|
||||||
|
|
||||||
init {
|
|
||||||
userColorNameManager = fragment.userColorNameManager
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun loadInBackground(): List<ParcelableUser> {
|
|
||||||
val query = query
|
|
||||||
if (TextUtils.isEmpty(query)) return emptyList()
|
|
||||||
if (fromCache) {
|
|
||||||
val cachedList = ArrayList<ParcelableUser>()
|
|
||||||
val queryEscaped = query.replace("_", "^_")
|
|
||||||
val nicknameKeys = Utils.getMatchedNicknameKeys(query, userColorNameManager)
|
|
||||||
val selection = Expression.or(Expression.likeRaw(Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"),
|
|
||||||
Expression.likeRaw(Column(CachedUsers.NAME), "?||'%'", "^"),
|
|
||||||
Expression.inArgs(Column(CachedUsers.USER_KEY), nicknameKeys.size))
|
|
||||||
val selectionArgs = arrayOf(queryEscaped, queryEscaped, *nicknameKeys)
|
|
||||||
val order = arrayOf(CachedUsers.LAST_SEEN, CachedUsers.SCREEN_NAME, CachedUsers.NAME)
|
|
||||||
val ascending = booleanArrayOf(false, true, true)
|
|
||||||
val orderBy = OrderBy(order, ascending)
|
|
||||||
val c = context.contentResolver.query(CachedUsers.CONTENT_URI,
|
|
||||||
CachedUsers.BASIC_COLUMNS, selection?.sql,
|
|
||||||
selectionArgs, orderBy.sql)!!
|
|
||||||
val i = ParcelableUserCursorIndices(c)
|
|
||||||
c.moveToFirst()
|
|
||||||
while (!c.isAfterLast) {
|
|
||||||
cachedList.add(i.newObject(c))
|
|
||||||
c.moveToNext()
|
|
||||||
}
|
|
||||||
c.close()
|
|
||||||
return cachedList
|
|
||||||
}
|
|
||||||
return super.loadInBackground()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DeleteConversationConfirmDialogFragment : BaseDialogFragment(), DialogInterface.OnClickListener {
|
class DeleteConversationConfirmDialogFragment : BaseDialogFragment(), DialogInterface.OnClickListener {
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val builder = AlertDialog.Builder(activity)
|
val builder = AlertDialog.Builder(activity)
|
||||||
|
@ -861,6 +818,6 @@ class MessagesConversationFragment : BaseFragment(), LoaderCallbacks<Cursor?>, O
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
private val LOADER_ID_SEARCH_USERS = 1
|
private val LOADER_ID_SEARCH_USERS = 1
|
||||||
private val EXTRA_FROM_CACHE = "from_cache"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package org.mariotaku.twidere.loader
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.text.TextUtils
|
||||||
|
import org.mariotaku.sqliteqb.library.Columns
|
||||||
|
import org.mariotaku.sqliteqb.library.Expression
|
||||||
|
import org.mariotaku.sqliteqb.library.OrderBy
|
||||||
|
import org.mariotaku.twidere.model.ParcelableUser
|
||||||
|
import org.mariotaku.twidere.model.ParcelableUserCursorIndices
|
||||||
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
import org.mariotaku.twidere.provider.TwidereDataStore
|
||||||
|
import org.mariotaku.twidere.util.UserColorNameManager
|
||||||
|
import org.mariotaku.twidere.util.Utils
|
||||||
|
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||||
|
import java.util.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class CacheUserSearchLoader(
|
||||||
|
context: Context,
|
||||||
|
accountKey: UserKey,
|
||||||
|
query: String,
|
||||||
|
private val fromCache: Boolean,
|
||||||
|
fromUser: Boolean
|
||||||
|
) : UserSearchLoader(context, accountKey, query, 0, null, fromUser) {
|
||||||
|
@Inject
|
||||||
|
internal lateinit var userColorNameManager: UserColorNameManager
|
||||||
|
|
||||||
|
init {
|
||||||
|
GeneralComponentHelper.build(context).inject(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadInBackground(): List<ParcelableUser> {
|
||||||
|
if (TextUtils.isEmpty(query)) return emptyList()
|
||||||
|
if (fromCache) {
|
||||||
|
val cachedList = ArrayList<ParcelableUser>()
|
||||||
|
val queryEscaped = query.replace("_", "^_")
|
||||||
|
val nicknameKeys = Utils.getMatchedNicknameKeys(query, userColorNameManager)
|
||||||
|
val selection = Expression.or(Expression.likeRaw(Columns.Column(TwidereDataStore.CachedUsers.SCREEN_NAME), "?||'%'", "^"),
|
||||||
|
Expression.likeRaw(Columns.Column(TwidereDataStore.CachedUsers.NAME), "?||'%'", "^"),
|
||||||
|
Expression.inArgs(Columns.Column(TwidereDataStore.CachedUsers.USER_KEY), nicknameKeys.size))
|
||||||
|
val selectionArgs = arrayOf(queryEscaped, queryEscaped, *nicknameKeys)
|
||||||
|
val order = arrayOf(TwidereDataStore.CachedUsers.LAST_SEEN, TwidereDataStore.CachedUsers.SCREEN_NAME, TwidereDataStore.CachedUsers.NAME)
|
||||||
|
val ascending = booleanArrayOf(false, true, true)
|
||||||
|
val orderBy = OrderBy(order, ascending)
|
||||||
|
val c = context.contentResolver.query(TwidereDataStore.CachedUsers.CONTENT_URI,
|
||||||
|
TwidereDataStore.CachedUsers.BASIC_COLUMNS, selection?.sql,
|
||||||
|
selectionArgs, orderBy.sql)!!
|
||||||
|
val i = ParcelableUserCursorIndices(c)
|
||||||
|
c.moveToFirst()
|
||||||
|
while (!c.isAfterLast) {
|
||||||
|
cachedList.add(i.newObject(c))
|
||||||
|
c.moveToNext()
|
||||||
|
}
|
||||||
|
c.close()
|
||||||
|
return cachedList
|
||||||
|
}
|
||||||
|
return super.loadInBackground()
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,6 @@ package org.mariotaku.twidere.loader
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.support.v4.content.AsyncTaskLoader
|
import android.support.v4.content.AsyncTaskLoader
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import org.mariotaku.twidere.Constants
|
|
||||||
import org.mariotaku.twidere.loader.iface.IExtendedLoader
|
import org.mariotaku.twidere.loader.iface.IExtendedLoader
|
||||||
import org.mariotaku.twidere.model.ParcelableUser
|
import org.mariotaku.twidere.model.ParcelableUser
|
||||||
import org.mariotaku.twidere.util.collection.NoDuplicatesArrayList
|
import org.mariotaku.twidere.util.collection.NoDuplicatesArrayList
|
||||||
|
@ -32,7 +31,7 @@ abstract class ParcelableUsersLoader(
|
||||||
context: Context,
|
context: Context,
|
||||||
data: List<ParcelableUser>?,
|
data: List<ParcelableUser>?,
|
||||||
override var fromUser: Boolean
|
override var fromUser: Boolean
|
||||||
) : AsyncTaskLoader<List<ParcelableUser>>(context), IExtendedLoader, Constants {
|
) : AsyncTaskLoader<List<ParcelableUser>>(context), IExtendedLoader {
|
||||||
|
|
||||||
protected val data: MutableList<ParcelableUser> = Collections.synchronizedList(NoDuplicatesArrayList<ParcelableUser>())
|
protected val data: MutableList<ParcelableUser> = Collections.synchronizedList(NoDuplicatesArrayList<ParcelableUser>())
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.mariotaku.twidere.adapter.*
|
||||||
import org.mariotaku.twidere.app.TwidereApplication
|
import org.mariotaku.twidere.app.TwidereApplication
|
||||||
import org.mariotaku.twidere.fragment.*
|
import org.mariotaku.twidere.fragment.*
|
||||||
import org.mariotaku.twidere.fragment.filter.FilteredUsersFragment
|
import org.mariotaku.twidere.fragment.filter.FilteredUsersFragment
|
||||||
|
import org.mariotaku.twidere.loader.CacheUserSearchLoader
|
||||||
import org.mariotaku.twidere.loader.MicroBlogAPIStatusesLoader
|
import org.mariotaku.twidere.loader.MicroBlogAPIStatusesLoader
|
||||||
import org.mariotaku.twidere.loader.ParcelableStatusLoader
|
import org.mariotaku.twidere.loader.ParcelableStatusLoader
|
||||||
import org.mariotaku.twidere.loader.ParcelableUserLoader
|
import org.mariotaku.twidere.loader.ParcelableUserLoader
|
||||||
|
@ -150,4 +151,6 @@ interface GeneralComponent {
|
||||||
fun inject(provider: UrlFiltersSubscriptionProvider)
|
fun inject(provider: UrlFiltersSubscriptionProvider)
|
||||||
|
|
||||||
fun inject(preference: PremiumEntryPreference)
|
fun inject(preference: PremiumEntryPreference)
|
||||||
|
|
||||||
|
fun inject(loader: CacheUserSearchLoader)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,65 +18,49 @@
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<merge
|
<RelativeLayout
|
||||||
|
android:id="@+id/usersListContainer"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".activity.UserSelectorActivity">
|
tools:context=".activity.UserSelectorActivity">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/usersListContainer"
|
android:id="@+id/searchContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:divider="?android:dividerVertical"
|
android:layout_alignParentTop="true"
|
||||||
android:orientation="vertical"
|
android:gravity="center_vertical"
|
||||||
android:showDividers="middle">
|
android:orientation="horizontal"
|
||||||
|
android:padding="@dimen/element_spacing_normal">
|
||||||
|
|
||||||
<LinearLayout
|
<android.support.v7.widget.AppCompatEditText
|
||||||
|
android:id="@+id/editScreenName"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:layout_weight="1"
|
||||||
|
android:ems="10"
|
||||||
|
android:hint="@string/search_hint_users"
|
||||||
|
android:maxLines="1"
|
||||||
|
app:backgroundTint="?colorAccent"/>
|
||||||
|
|
||||||
<TextView
|
<org.mariotaku.twidere.view.IconActionButton
|
||||||
style="?android:listSeparatorTextViewStyle"
|
android:id="@+id/screenNameConfirm"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="@dimen/minimum_element_size"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="@dimen/minimum_element_size"
|
||||||
android:text="@string/title_user"/>
|
android:layout_weight="0"
|
||||||
|
android:background="?selectableItemBackground"
|
||||||
<LinearLayout
|
android:color="?menuIconColor"
|
||||||
android:layout_width="match_parent"
|
android:contentDescription="@string/search"
|
||||||
android:layout_height="wrap_content"
|
android:src="@drawable/ic_action_search"
|
||||||
android:gravity="center_vertical"
|
tools:tint="?menuIconColor"/>
|
||||||
android:orientation="horizontal"
|
|
||||||
android:padding="@dimen/element_spacing_normal">
|
|
||||||
|
|
||||||
<AutoCompleteTextView
|
|
||||||
android:id="@+id/editScreenName"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:ems="10"
|
|
||||||
android:maxLines="1"/>
|
|
||||||
|
|
||||||
<org.mariotaku.twidere.view.IconActionButton
|
|
||||||
android:id="@+id/screenNameConfirm"
|
|
||||||
android:layout_width="@dimen/minimum_element_size"
|
|
||||||
android:layout_height="@dimen/minimum_element_size"
|
|
||||||
android:layout_weight="0"
|
|
||||||
android:background="?selectableItemBackground"
|
|
||||||
android:color="?menuIconColor"
|
|
||||||
android:contentDescription="@string/search"
|
|
||||||
android:src="@drawable/ic_action_search"
|
|
||||||
tools:tint="?menuIconColor"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ListView
|
|
||||||
android:id="@+id/usersList"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"/>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</merge>
|
<include
|
||||||
|
layout="@layout/layout_list_with_empty_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@+id/searchContainer"/>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
android:id="@+id/emptyView"
|
android:id="@+id/emptyView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:clickable="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:visibility="visible">
|
tools:visibility="visible">
|
||||||
|
@ -63,7 +64,8 @@
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/progressContainer"
|
android:id="@+id/progressContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:clickable="true">
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progressBar"
|
android:id="@+id/progressBar"
|
||||||
|
|
|
@ -1014,6 +1014,7 @@
|
||||||
|
|
||||||
<string name="search">Search</string>
|
<string name="search">Search</string>
|
||||||
<string name="search_hint">Search tweets or users</string>
|
<string name="search_hint">Search tweets or users</string>
|
||||||
|
<string name="search_hint_users">Search users</string>
|
||||||
<string name="search_statuses">Search Tweets</string>
|
<string name="search_statuses">Search Tweets</string>
|
||||||
<string name="search_type_statuses">Tweets</string>
|
<string name="search_type_statuses">Tweets</string>
|
||||||
<string name="search_type_users">Users</string>
|
<string name="search_type_users">Users</string>
|
||||||
|
|
Loading…
Reference in New Issue