improved users selector

This commit is contained in:
Mariotaku Lee 2017-01-30 11:29:09 +08:00
parent 3129a25c55
commit 2c1b8b37f2
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
11 changed files with 206 additions and 230 deletions

View File

@ -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";
} }

View File

@ -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"/>

View File

@ -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

View File

@ -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
}
} }

View File

@ -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"
} }
} }

View File

@ -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()
}
}

View File

@ -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>())

View File

@ -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)
} }

View File

@ -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>

View File

@ -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"

View File

@ -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>