mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-17 04:00:48 +01:00
rewriting userlist picker
This commit is contained in:
parent
20c49e727c
commit
4ceaf681c4
@ -209,4 +209,5 @@ public interface IntentConstants {
|
||||
String EXTRA_COUNT = "count";
|
||||
String EXTRA_REQUEST_CODE = "request_code";
|
||||
String EXTRA_FROM_CACHE = "from_cache";
|
||||
String EXTRA_SHOW_MY_LISTS = "show_my_lists";
|
||||
}
|
||||
|
@ -139,7 +139,6 @@ dependencies {
|
||||
compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.6.0'
|
||||
compile 'com.squareup:otto:1.3.8'
|
||||
compile 'dnsjava:dnsjava:2.1.7'
|
||||
compile 'com.commonsware.cwac:merge:1.1.1'
|
||||
compile 'com.commonsware.cwac:layouts:0.4.3'
|
||||
compile 'com.rengwuxian.materialedittext:library:2.1.4'
|
||||
compile 'com.pnikosis:materialish-progress:1.7'
|
||||
|
@ -252,6 +252,12 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable {
|
||||
if (mNotifyOnChange) notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public List<T> getAll() {
|
||||
synchronized (mLock) {
|
||||
return new ArrayList<>(mObjects);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -26,4 +26,9 @@ fun String?.toDouble(def: Double): Double {
|
||||
} catch (e: NumberFormatException) {
|
||||
return def
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.coerceInOr(range: ClosedRange<Int>, or: Int): Int {
|
||||
if (range.isEmpty()) return or
|
||||
return coerceIn(range)
|
||||
}
|
@ -21,128 +21,78 @@ package org.mariotaku.twidere.activity
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.AsyncTask
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.DialogFragment
|
||||
import android.text.TextUtils
|
||||
import android.text.TextUtils.isEmpty
|
||||
import android.util.Log
|
||||
import android.support.v4.app.LoaderManager
|
||||
import android.support.v4.content.Loader
|
||||
import android.view.View
|
||||
import android.view.View.OnClickListener
|
||||
import android.widget.AdapterView
|
||||
import android.widget.AdapterView.OnItemClickListener
|
||||
import android.widget.ListView
|
||||
import com.squareup.otto.Subscribe
|
||||
import kotlinx.android.synthetic.main.activity_user_list_selector.*
|
||||
import org.mariotaku.microblog.library.MicroBlogException
|
||||
import org.mariotaku.microblog.library.twitter.http.HttpResponseCode
|
||||
import android.widget.TextView
|
||||
import kotlinx.android.synthetic.main.layout_list_with_empty_view.*
|
||||
import org.mariotaku.ktextension.Bundle
|
||||
import org.mariotaku.ktextension.set
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.TwidereConstants.LOGTAG
|
||||
import org.mariotaku.twidere.TwidereConstants.REQUEST_SELECT_USER
|
||||
import org.mariotaku.twidere.adapter.SimpleParcelableUserListsAdapter
|
||||
import org.mariotaku.twidere.adapter.UserAutoCompleteAdapter
|
||||
import org.mariotaku.twidere.constant.IntentConstants.*
|
||||
import org.mariotaku.twidere.fragment.CreateUserListDialogFragment
|
||||
import org.mariotaku.twidere.fragment.ProgressDialogFragment
|
||||
import org.mariotaku.twidere.loader.UserListOwnershipsLoader
|
||||
import org.mariotaku.twidere.model.ParcelableUser
|
||||
import org.mariotaku.twidere.model.ParcelableUserList
|
||||
import org.mariotaku.twidere.model.SingleResponse
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.model.message.UserListCreatedEvent
|
||||
import org.mariotaku.twidere.model.util.ParcelableUserListUtils
|
||||
import org.mariotaku.twidere.util.AsyncTaskUtils
|
||||
import org.mariotaku.twidere.util.DataStoreUtils.getAccountScreenName
|
||||
import org.mariotaku.twidere.util.MicroBlogAPIFactory
|
||||
import java.util.*
|
||||
|
||||
class UserListSelectorActivity : BaseActivity(), OnClickListener, OnItemClickListener {
|
||||
class UserListSelectorActivity : BaseActivity(),
|
||||
LoaderManager.LoaderCallbacks<List<ParcelableUserList>> {
|
||||
|
||||
private lateinit var userListsAdapter: SimpleParcelableUserListsAdapter
|
||||
|
||||
private var screenName: String? = null
|
||||
private lateinit var adapter: SimpleParcelableUserListsAdapter
|
||||
|
||||
private val accountKey: UserKey?
|
||||
get() = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||
private val showMyLists: Boolean
|
||||
get() = intent.getBooleanExtra(EXTRA_SHOW_MY_LISTS, false)
|
||||
|
||||
private var userKey: UserKey? = null
|
||||
|
||||
private var loaderInitialized: Boolean = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val intent = intent
|
||||
if (!intent.hasExtra(EXTRA_ACCOUNT_KEY)) {
|
||||
val accountKey = accountKey ?: run {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
setContentView(R.layout.activity_user_list_selector)
|
||||
if (savedInstanceState == null) {
|
||||
screenName = intent.getStringExtra(EXTRA_SCREEN_NAME)
|
||||
|
||||
adapter = SimpleParcelableUserListsAdapter(this)
|
||||
listView.addFooterView(layoutInflater.inflate(R.layout.simple_list_item_activated_1,
|
||||
listView, false).apply {
|
||||
(findViewById(android.R.id.text1) as TextView).setText(R.string.action_select_user)
|
||||
}, SelectUserAction, true)
|
||||
listView.adapter = adapter
|
||||
listView.onItemClickListener = OnItemClickListener { view, child, position, id ->
|
||||
val item = view.getItemAtPosition(position)
|
||||
when (item) {
|
||||
is ParcelableUserList -> {
|
||||
val data = Intent()
|
||||
data.putExtra(EXTRA_USER_LIST, item)
|
||||
setResult(Activity.RESULT_OK, data)
|
||||
finish()
|
||||
}
|
||||
is SelectUserAction -> {
|
||||
selectUser()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val userKey = intent.getParcelableExtra<UserKey>(EXTRA_USER_KEY) ?: if (showMyLists) {
|
||||
accountKey
|
||||
} else {
|
||||
screenName = savedInstanceState.getString(EXTRA_SCREEN_NAME)
|
||||
null
|
||||
}
|
||||
|
||||
if (!isEmpty(screenName)) {
|
||||
getUserLists(screenName)
|
||||
}
|
||||
val adapter = UserAutoCompleteAdapter(this)
|
||||
adapter.accountKey = accountKey
|
||||
userListsAdapter = SimpleParcelableUserListsAdapter(this)
|
||||
userListsList.adapter = userListsAdapter
|
||||
userListsList.onItemClickListener = this
|
||||
createList.setOnClickListener(this)
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
when (v.id) {
|
||||
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) {
|
||||
val list = view as ListView
|
||||
val data = Intent()
|
||||
data.putExtra(EXTRA_USER_LIST, userListsAdapter.getItem(position - list.headerViewsCount))
|
||||
setResult(Activity.RESULT_OK, data)
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putString(EXTRA_SCREEN_NAME, screenName)
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onUserListCreated(event: UserListCreatedEvent) {
|
||||
getUserLists(screenName)
|
||||
}
|
||||
|
||||
private val accountKey: UserKey
|
||||
get() = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||
|
||||
private fun getUserLists(screenName: String?) {
|
||||
if (screenName == null) return
|
||||
this.screenName = screenName
|
||||
val task = GetUserListsTask(this, accountKey, screenName)
|
||||
AsyncTaskUtils.executeTask(task)
|
||||
}
|
||||
|
||||
private fun setUserListsData(data: List<ParcelableUserList>, isMyAccount: Boolean) {
|
||||
userListsAdapter.setData(data, true)
|
||||
userListsContainer.visibility = View.VISIBLE
|
||||
createListContainer.visibility = if (isMyAccount) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
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) {
|
||||
executeAfterFragmentResumed { activity ->
|
||||
df.show(activity.supportFragmentManager, tag)
|
||||
if (userKey != null) {
|
||||
loadUserLists(accountKey, userKey)
|
||||
} else if (savedInstanceState == null) {
|
||||
selectUser()
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,61 +106,68 @@ class UserListSelectorActivity : BaseActivity(), OnClickListener, OnItemClickLis
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
private class GetUserListsTask(
|
||||
private val activity: UserListSelectorActivity,
|
||||
private val accountKey: UserKey,
|
||||
private val screenName: String
|
||||
) : AsyncTask<Any, Any, SingleResponse<List<ParcelableUserList>>>() {
|
||||
|
||||
override fun doInBackground(vararg params: Any): SingleResponse<List<ParcelableUserList>> {
|
||||
val twitter = MicroBlogAPIFactory.getInstance(activity, accountKey) ?: return SingleResponse.getInstance<List<ParcelableUserList>>()
|
||||
try {
|
||||
val lists = twitter.getUserListsByScreenName(screenName, true)
|
||||
val data = ArrayList<ParcelableUserList>()
|
||||
var isMyAccount = screenName.equals(getAccountScreenName(activity,
|
||||
accountKey), ignoreCase = true)
|
||||
for (item in lists) {
|
||||
val user = item.user
|
||||
if (user != null && screenName.equals(user.screenName, ignoreCase = true)) {
|
||||
if (!isMyAccount && TextUtils.equals(user.id, accountKey.id)) {
|
||||
isMyAccount = true
|
||||
}
|
||||
data.add(ParcelableUserListUtils.from(item, accountKey))
|
||||
}
|
||||
}
|
||||
val result = SingleResponse.getInstance<List<ParcelableUserList>>(data)
|
||||
result.extras.putBoolean(EXTRA_IS_MY_ACCOUNT, isMyAccount)
|
||||
return result
|
||||
} catch (e: MicroBlogException) {
|
||||
Log.w(LOGTAG, e)
|
||||
return SingleResponse.getInstance<List<ParcelableUserList>>(e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onPostExecute(result: SingleResponse<List<ParcelableUserList>>) {
|
||||
activity.dismissDialogFragment(FRAGMENT_TAG_GET_USER_LISTS)
|
||||
if (result.data != null) {
|
||||
activity.setUserListsData(result.data, result.extras.getBoolean(EXTRA_IS_MY_ACCOUNT))
|
||||
} else if (result.exception is MicroBlogException) {
|
||||
if (result.exception.statusCode == HttpResponseCode.NOT_FOUND) {
|
||||
// activity.searchUser(screenName)
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
when (requestCode) {
|
||||
REQUEST_SELECT_USER -> {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val user = data.getParcelableExtra<ParcelableUser>(EXTRA_USER)
|
||||
loadUserLists(accountKey!!, user.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPreExecute() {
|
||||
val df = ProgressDialogFragment()
|
||||
df.isCancelable = false
|
||||
activity.showDialogFragment(df, FRAGMENT_TAG_GET_USER_LISTS)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val FRAGMENT_TAG_GET_USER_LISTS = "get_user_lists"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onCreateLoader(id: Int, args: Bundle): Loader<List<ParcelableUserList>> {
|
||||
val accountKey = args.getParcelable<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||
val userKey = args.getParcelable<UserKey>(EXTRA_USER_KEY)
|
||||
return UserListOwnershipsLoader(this, accountKey, userKey, null, adapter.all)
|
||||
}
|
||||
|
||||
override fun onLoaderReset(loader: Loader<List<ParcelableUserList>>?) {
|
||||
adapter.setData(null)
|
||||
}
|
||||
|
||||
override fun onLoadFinished(loader: Loader<List<ParcelableUserList>>?, data: List<ParcelableUserList>?) {
|
||||
adapter.setData(data)
|
||||
showList()
|
||||
}
|
||||
|
||||
private fun loadUserLists(accountKey: UserKey, userKey: UserKey) {
|
||||
if (userKey != this.userKey) {
|
||||
adapter.clear()
|
||||
showProgress()
|
||||
this.userKey = userKey
|
||||
}
|
||||
val args = Bundle {
|
||||
this[EXTRA_ACCOUNT_KEY] = accountKey
|
||||
this[EXTRA_USER_KEY] = userKey
|
||||
}
|
||||
if (!loaderInitialized) {
|
||||
loaderInitialized = true
|
||||
supportLoaderManager.initLoader(0, args, this)
|
||||
} else {
|
||||
supportLoaderManager.restartLoader(0, args, this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showProgress() {
|
||||
progressContainer.visibility = View.VISIBLE
|
||||
listContainer.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun showList() {
|
||||
progressContainer.visibility = View.GONE
|
||||
listContainer.visibility = View.VISIBLE
|
||||
listView.visibility = View.VISIBLE
|
||||
emptyView.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun selectUser() {
|
||||
val selectUserIntent = Intent(this, UserSelectorActivity::class.java)
|
||||
selectUserIntent.putExtra(EXTRA_ACCOUNT_KEY, accountKey)
|
||||
startActivityForResult(selectUserIntent, REQUEST_SELECT_USER)
|
||||
}
|
||||
|
||||
object SelectUserAction
|
||||
|
||||
}
|
||||
|
@ -45,13 +45,13 @@ import org.mariotaku.twidere.util.view.SimpleTextWatcher
|
||||
|
||||
class UserSelectorActivity : BaseActivity(), OnItemClickListener, LoaderManager.LoaderCallbacks<List<ParcelableUser>> {
|
||||
|
||||
private lateinit var usersAdapter: SimpleParcelableUsersAdapter
|
||||
|
||||
private var loaderInitialized: Boolean = false
|
||||
private lateinit var adapter: SimpleParcelableUsersAdapter
|
||||
|
||||
private val accountKey: UserKey?
|
||||
get() = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||
|
||||
private var loaderInitialized: Boolean = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val accountKey = this.accountKey ?: run {
|
||||
@ -73,8 +73,8 @@ class UserSelectorActivity : BaseActivity(), OnItemClickListener, LoaderManager.
|
||||
if (savedInstanceState == null) {
|
||||
editScreenName.setText(intent.getStringExtra(EXTRA_SCREEN_NAME))
|
||||
}
|
||||
usersAdapter = SimpleParcelableUsersAdapter(this)
|
||||
listView.adapter = usersAdapter
|
||||
adapter = SimpleParcelableUsersAdapter(this)
|
||||
listView.adapter = adapter
|
||||
listView.onItemClickListener = this
|
||||
|
||||
showSearchHint()
|
||||
@ -82,7 +82,7 @@ class UserSelectorActivity : BaseActivity(), OnItemClickListener, LoaderManager.
|
||||
|
||||
override fun onItemClick(view: AdapterView<*>, child: View, position: Int, id: Long) {
|
||||
val list = view as ListView
|
||||
val user = usersAdapter.getItem(position - list.headerViewsCount) ?: return
|
||||
val user = adapter.getItem(position - list.headerViewsCount) ?: return
|
||||
val data = Intent()
|
||||
data.setExtrasClassLoader(classLoader)
|
||||
data.putExtra(EXTRA_USER, user)
|
||||
@ -101,13 +101,13 @@ class UserSelectorActivity : BaseActivity(), OnItemClickListener, LoaderManager.
|
||||
}
|
||||
|
||||
override fun onLoaderReset(loader: Loader<List<ParcelableUser>>) {
|
||||
usersAdapter.setData(null, true)
|
||||
adapter.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)
|
||||
adapter.setData(data, true)
|
||||
loader as CacheUserSearchLoader
|
||||
if (data.isNotNullOrEmpty()) {
|
||||
showList()
|
||||
|
@ -24,11 +24,12 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.model.ParcelableUserList
|
||||
import org.mariotaku.twidere.view.holder.TwoLineWithIconViewHolder
|
||||
import org.mariotaku.twidere.util.view.display
|
||||
import org.mariotaku.twidere.view.holder.SimpleUserListViewHolder
|
||||
|
||||
class SimpleParcelableUserListsAdapter(
|
||||
context: Context
|
||||
) : BaseArrayAdapter<ParcelableUserList>(context, R.layout.list_item_two_line) {
|
||||
) : BaseArrayAdapter<ParcelableUserList>(context, R.layout.list_item_simple_user_list) {
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return (if (getItem(position) != null) getItem(position).hashCode() else -1).toLong()
|
||||
@ -37,38 +38,22 @@ class SimpleParcelableUserListsAdapter(
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val view = super.getView(position, convertView, parent)
|
||||
val tag = view.tag
|
||||
val holder: TwoLineWithIconViewHolder
|
||||
if (tag is TwoLineWithIconViewHolder) {
|
||||
holder = tag
|
||||
} else {
|
||||
holder = TwoLineWithIconViewHolder(view)
|
||||
view.tag = holder
|
||||
val holder = tag as? SimpleUserListViewHolder ?: run {
|
||||
val h = SimpleUserListViewHolder(view)
|
||||
view.tag = h
|
||||
return@run h
|
||||
}
|
||||
|
||||
// Clear images in order to prevent images in recycled view shown.
|
||||
holder.icon.setImageDrawable(null)
|
||||
|
||||
val userList = getItem(position)
|
||||
val display_name = userColorNameManager.getDisplayName(userList, nameFirst)
|
||||
holder.text1.text = userList.name
|
||||
holder.text2.text = context.getString(R.string.created_by, display_name)
|
||||
holder.icon.visibility = if (profileImageEnabled) View.VISIBLE else View.GONE
|
||||
if (profileImageEnabled) {
|
||||
mediaLoader.displayProfileImage(holder.icon, userList.user_profile_image_url)
|
||||
} else {
|
||||
mediaLoader.cancelDisplayTask(holder.icon)
|
||||
}
|
||||
holder.display(userList, mediaLoader, userColorNameManager, profileImageEnabled)
|
||||
return view
|
||||
}
|
||||
|
||||
fun setData(data: List<ParcelableUserList>?, clearOld: Boolean) {
|
||||
if (clearOld) {
|
||||
clear()
|
||||
}
|
||||
fun setData(data: List<ParcelableUserList>?) {
|
||||
clear()
|
||||
if (data == null) return
|
||||
for (user in data) {
|
||||
//TODO improve compare
|
||||
if (clearOld || findItemPosition(user.hashCode().toLong()) < 0) {
|
||||
if (findItemPosition(user.hashCode().toLong()) < 0) {
|
||||
add(user)
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import edu.tsinghua.hotmobi.HotMobiLogger
|
||||
import edu.tsinghua.hotmobi.model.MediaEvent
|
||||
import kotlinx.android.synthetic.main.fragment_content_recyclerview.*
|
||||
import org.mariotaku.kpreferences.get
|
||||
import org.mariotaku.ktextension.coerceInOr
|
||||
import org.mariotaku.ktextension.isNullOrEmpty
|
||||
import org.mariotaku.ktextension.rangeOfSize
|
||||
import org.mariotaku.twidere.R
|
||||
@ -225,15 +226,15 @@ abstract class AbsActivitiesFragment protected constructor() :
|
||||
val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
|
||||
val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition()
|
||||
wasAtTop = firstVisibleItemPosition == 0
|
||||
val statusRange = rangeOfSize(adapter.activityStartIndex, adapter.activityCount - 1)
|
||||
val activityRange = rangeOfSize(adapter.activityStartIndex, Math.max(0, adapter.activityCount - 1))
|
||||
val lastReadPosition = if (readFromBottom) {
|
||||
lastVisibleItemPosition
|
||||
} else {
|
||||
firstVisibleItemPosition
|
||||
}.coerceIn(statusRange)
|
||||
}.coerceInOr(activityRange, -1)
|
||||
lastReadId = adapter.getTimestamp(lastReadPosition)
|
||||
lastReadViewTop = layoutManager.findViewByPosition(lastReadPosition)?.top ?: 0
|
||||
loadMore = lastVisibleItemPosition >= statusRange.endInclusive
|
||||
loadMore = activityRange.endInclusive >= 0 && lastVisibleItemPosition >= activityRange.endInclusive
|
||||
} else if (rememberPosition && readPositionTag != null) {
|
||||
lastReadId = readStateManager.getPosition(readPositionTag)
|
||||
lastReadViewTop = 0
|
||||
|
@ -36,6 +36,7 @@ import edu.tsinghua.hotmobi.HotMobiLogger
|
||||
import edu.tsinghua.hotmobi.model.MediaEvent
|
||||
import kotlinx.android.synthetic.main.fragment_content_recyclerview.*
|
||||
import org.mariotaku.kpreferences.get
|
||||
import org.mariotaku.ktextension.coerceInOr
|
||||
import org.mariotaku.ktextension.isNullOrEmpty
|
||||
import org.mariotaku.ktextension.rangeOfSize
|
||||
import org.mariotaku.twidere.R
|
||||
@ -283,14 +284,14 @@ abstract class AbsStatusesFragment protected constructor() :
|
||||
lastVisibleItemPosition
|
||||
} else {
|
||||
firstVisibleItemPosition
|
||||
}.coerceIn(statusRange)
|
||||
}.coerceInOr(statusRange, -1)
|
||||
lastReadId = if (useSortIdAsReadPosition) {
|
||||
adapter.getStatusSortId(lastReadPosition)
|
||||
} else {
|
||||
adapter.getStatusPositionKey(lastReadPosition)
|
||||
}
|
||||
lastReadViewTop = layoutManager.findViewByPosition(lastReadPosition)?.top ?: 0
|
||||
loadMore = lastVisibleItemPosition >= statusRange.endInclusive
|
||||
loadMore = statusRange.endInclusive >= 0 && lastVisibleItemPosition >= statusRange.endInclusive
|
||||
} else if (rememberPosition && readPositionTag != null) {
|
||||
lastReadId = readStateManager.getPosition(readPositionTag)
|
||||
lastReadViewTop = 0
|
||||
|
@ -45,6 +45,7 @@ class UserListExtraConfiguration(key: String) : TabConfiguration.ExtraConfigurat
|
||||
val account = fragment.account ?: return@setOnClickListener
|
||||
val intent = Intent(INTENT_ACTION_SELECT_USER_LIST)
|
||||
intent.putExtra(EXTRA_ACCOUNT_KEY, account.key)
|
||||
intent.putExtra(EXTRA_SHOW_MY_LISTS, true)
|
||||
intent.setClass(context, UserListSelectorActivity::class.java)
|
||||
fragment.startExtraConfigurationActivityForResult(this@UserListExtraConfiguration, intent, 1)
|
||||
}
|
||||
|
@ -12,13 +12,8 @@ import kotlinx.android.synthetic.main.list_item_simple_user_list.view.*
|
||||
|
||||
class SimpleUserListViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
val createdByView: TextView
|
||||
val nameView: TextView
|
||||
val profileImageView: ImageView
|
||||
val createdByView: TextView = itemView.createdBy
|
||||
val nameView: TextView = itemView.name
|
||||
val profileImageView: ImageView = itemView.profileImage
|
||||
|
||||
init {
|
||||
nameView = itemView.name
|
||||
createdByView = itemView.createdBy
|
||||
profileImageView = itemView.profileImage
|
||||
}
|
||||
}
|
||||
|
@ -18,45 +18,16 @@
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<merge
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="@dimen/minimum_width_list_layout_content"
|
||||
tools:context=".activity.UserListSelectorActivity">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/userListsContainer"
|
||||
<include
|
||||
layout="@layout/layout_list_with_empty_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:divider="?android:dividerVertical"
|
||||
android:orientation="vertical"
|
||||
android:showDividers="middle"
|
||||
android:visibility="gone">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/userListsList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/createListContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<Button
|
||||
android:id="@+id/createList"
|
||||
style="?android:borderlessButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/button_bar_height"
|
||||
android:gravity="center"
|
||||
android:text="@string/new_user_list"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</merge>
|
||||
android:layout_height="match_parent"/>
|
||||
</FrameLayout>
|
||||
|
@ -18,20 +18,20 @@
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/usersListContainer"
|
||||
<LinearLayout
|
||||
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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="@dimen/minimum_width_list_layout_content"
|
||||
android:orientation="vertical"
|
||||
tools:context=".activity.UserSelectorActivity">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/searchContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/element_spacing_normal">
|
||||
@ -61,6 +61,5 @@
|
||||
<include
|
||||
layout="@layout/layout_list_with_empty_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/searchContainer"/>
|
||||
</RelativeLayout>
|
||||
android:layout_height="match_parent"/>
|
||||
</LinearLayout>
|
||||
|
@ -27,7 +27,8 @@
|
||||
<FrameLayout
|
||||
android:id="@+id/listContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:minWidth="@dimen/minimum_width_list_layout_content">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/listView"
|
||||
@ -41,6 +42,8 @@
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="true"
|
||||
android:gravity="center"
|
||||
android:minHeight="@dimen/minimum_height_list_layout_content"
|
||||
android:minWidth="@dimen/minimum_width_list_layout_content"
|
||||
android:orientation="vertical"
|
||||
tools:visibility="visible">
|
||||
|
||||
@ -65,7 +68,9 @@
|
||||
android:id="@+id/progressContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="true">
|
||||
android:clickable="true"
|
||||
android:minHeight="@dimen/minimum_height_list_layout_content"
|
||||
android:minWidth="@dimen/minimum_width_list_layout_content">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
|
@ -64,8 +64,8 @@
|
||||
<org.mariotaku.twidere.view.ProfileImageView
|
||||
android:id="@+id/profileImage"
|
||||
style="?profileImageStyle"
|
||||
android:layout_width="@dimen/icon_size_card_list_item"
|
||||
android:layout_height="@dimen/icon_size_card_list_item"
|
||||
android:layout_width="@dimen/icon_size_list_item_small"
|
||||
android:layout_height="@dimen/icon_size_list_item_small"
|
||||
android:layout_marginLeft="@dimen/element_spacing_normal"
|
||||
android:layout_marginStart="@dimen/element_spacing_normal"
|
||||
android:layout_weight="0"
|
||||
|
@ -1,104 +1,109 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<resources>
|
||||
|
||||
<dimen name="element_size_xsmall">16dp</dimen>
|
||||
<dimen name="element_size_small">24dp</dimen>
|
||||
<dimen name="element_size_msmall">36dp</dimen>
|
||||
<dimen name="element_size_normal">48dp</dimen>
|
||||
<dimen name="element_size_mlarge">64dp</dimen>
|
||||
|
||||
|
||||
<dimen name="button_size_content_card">42dp</dimen>
|
||||
<dimen name="button_size_content_card_action">36dp</dimen>
|
||||
|
||||
<!-- Element spacings (padding, margin) -->
|
||||
<dimen name="element_spacing_xsmall">2dp</dimen>
|
||||
<dimen name="element_spacing_small">4dp</dimen>
|
||||
<dimen name="element_spacing_msmall">6dp</dimen>
|
||||
<dimen name="element_spacing_normal">8dp</dimen>
|
||||
<dimen name="element_spacing_mlarge">12dp</dimen>
|
||||
<dimen name="element_spacing_large">16dp</dimen>
|
||||
<dimen name="element_spacing_xlarge">24dp</dimen>
|
||||
<dimen name="element_spacing_minus_xsmall">-2dp</dimen>
|
||||
<dimen name="element_spacing_minus_small">-4dp</dimen>
|
||||
<dimen name="element_spacing_minus_msmall">-6dp</dimen>
|
||||
<dimen name="element_spacing_minus_normal">-8dp</dimen>
|
||||
<dimen name="element_spacing_minus_mlarge">-12dp</dimen>
|
||||
<dimen name="element_spacing_minus_large">-16dp</dimen>
|
||||
<dimen name="element_spacing_minus_xlarge">-24dp</dimen>
|
||||
|
||||
<!-- Preferred size -->
|
||||
<dimen name="preferred_tab_column_width">420dp</dimen>
|
||||
|
||||
<dimen name="icon_size_list_item">56dp</dimen>
|
||||
<dimen name="icon_size_list_item_small">42dp</dimen>
|
||||
<dimen name="icon_size_card_list_item">48dp</dimen>
|
||||
<dimen name="icon_size_card_details">@dimen/element_size_mlarge</dimen>
|
||||
<dimen name="icon_size_user_profile">84dp</dimen>
|
||||
<dimen name="profile_image_size_activity_small">32dp</dimen>
|
||||
<dimen name="default_sliding_menu_shadow_width">8dp</dimen>
|
||||
<dimen name="default_sliding_menu_margin_threshold">16dp</dimen>
|
||||
<dimen name="button_bar_height">52dp</dimen>
|
||||
<dimen name="minimum_element_size">48dp</dimen>
|
||||
<dimen name="drawer_width_home">288dp</dimen>
|
||||
<dimen name="drawer_offset_home">72dp</dimen>
|
||||
<dimen name="float_action_button_size">56dp</dimen>
|
||||
<dimen name="float_action_button_icon_size">24dp</dimen>
|
||||
<dimen name="action_button_size">56dp</dimen>
|
||||
<dimen name="text_size_extra_small">12sp</dimen>
|
||||
|
||||
<!-- Size of icons in the top-level of settings -->
|
||||
<dimen name="header_icon_width">28dp</dimen>
|
||||
|
||||
<!-- Dimensions for color picker -->
|
||||
<dimen name="color_button_width">48dp</dimen>
|
||||
<dimen name="color_button_height">48dp</dimen>
|
||||
|
||||
<!-- Dimensions for compose dialog -->
|
||||
<dimen name="compose_min_width">400dp</dimen>
|
||||
|
||||
<!-- Dimensions for alert dialog -->
|
||||
<dimen name="icon_size_alert_dialog">32dp</dimen>
|
||||
|
||||
<!-- Dimensions for quick menu -->
|
||||
<dimen name="header_height_quick_menu">@dimen/element_size_normal</dimen>
|
||||
|
||||
<!-- Dimensions for buttons -->
|
||||
<dimen name="button_width_content_min">72dp</dimen>
|
||||
<dimen name="action_icon_size">32dp</dimen>
|
||||
<dimen name="unread_indicator_size">16dp</dimen>
|
||||
<dimen name="account_selector_popup_width">180dp</dimen>
|
||||
<dimen name="icon_size_status_profile_image">48dp</dimen>
|
||||
|
||||
<dimen name="icon_size_profile_type">16dp</dimen>
|
||||
<dimen name="icon_size_profile_type_detail">22dp</dimen>
|
||||
<dimen name="icon_size_profile_type_user_profile">26dp</dimen>
|
||||
<dimen name="icon_size_activity_type">16dp</dimen>
|
||||
<dimen name="action_button_size">56dp</dimen>
|
||||
<dimen name="action_icon_size">32dp</dimen>
|
||||
|
||||
<!-- Elevation values -->
|
||||
<dimen name="elevation_card">2dp</dimen>
|
||||
<dimen name="corner_radius_card">2dp</dimen>
|
||||
|
||||
|
||||
<dimen name="padding_profile_image_detail_page">@dimen/element_spacing_small</dimen>
|
||||
<dimen name="padding_profile_image_list_item">@dimen/element_spacing_small</dimen>
|
||||
<dimen name="icon_size_profile_image_dashboard_current">72dp</dimen>
|
||||
<dimen name="elevation_settings_item">0dp</dimen>
|
||||
<dimen name="popup_width_account_selector">160dp</dimen>
|
||||
|
||||
<dimen name="line_width_compose_account_profile_image">2dp</dimen>
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
|
||||
<dimen name="height_player_control_panel">40dp</dimen>
|
||||
<dimen name="toolbar_elevation">8dp</dimen>
|
||||
<dimen name="button_bar_height">52dp</dimen>
|
||||
<dimen name="button_size_content_card">42dp</dimen>
|
||||
<dimen name="button_size_content_card_action">36dp</dimen>
|
||||
<!-- Dimensions for buttons -->
|
||||
<dimen name="button_width_content_min">72dp</dimen>
|
||||
|
||||
<dimen name="color_button_height">48dp</dimen>
|
||||
<!-- Dimensions for color picker -->
|
||||
<dimen name="color_button_width">48dp</dimen>
|
||||
|
||||
<!-- Dimensions for compose dialog -->
|
||||
<dimen name="compose_min_width">400dp</dimen>
|
||||
|
||||
<dimen name="corner_radius_card">2dp</dimen>
|
||||
|
||||
<dimen name="default_sliding_menu_margin_threshold">16dp</dimen>
|
||||
<dimen name="default_sliding_menu_shadow_width">8dp</dimen>
|
||||
|
||||
<dimen name="drawer_offset_home">72dp</dimen>
|
||||
<dimen name="drawer_width_home">288dp</dimen>
|
||||
|
||||
<dimen name="element_size_mlarge">64dp</dimen>
|
||||
<dimen name="element_size_msmall">36dp</dimen>
|
||||
<dimen name="element_size_normal">48dp</dimen>
|
||||
<dimen name="element_size_quick_search_bar_item_icon">40dp</dimen>
|
||||
<dimen name="element_size_small">24dp</dimen>
|
||||
<dimen name="element_size_xsmall">16dp</dimen>
|
||||
<dimen name="element_spacing_large">16dp</dimen>
|
||||
<dimen name="element_spacing_minus_large">-16dp</dimen>
|
||||
<dimen name="element_spacing_minus_mlarge">-12dp</dimen>
|
||||
<dimen name="element_spacing_minus_msmall">-6dp</dimen>
|
||||
<dimen name="element_spacing_minus_normal">-8dp</dimen>
|
||||
<dimen name="element_spacing_minus_small">-4dp</dimen>
|
||||
<dimen name="element_spacing_minus_xlarge">-24dp</dimen>
|
||||
<dimen name="element_spacing_minus_xsmall">-2dp</dimen>
|
||||
<dimen name="element_spacing_mlarge">12dp</dimen>
|
||||
<dimen name="element_spacing_msmall">6dp</dimen>
|
||||
<dimen name="element_spacing_normal">8dp</dimen>
|
||||
<dimen name="element_spacing_small">4dp</dimen>
|
||||
<dimen name="element_spacing_xlarge">24dp</dimen>
|
||||
<!-- Element spacings (padding, margin) -->
|
||||
<dimen name="element_spacing_xsmall">2dp</dimen>
|
||||
|
||||
<!-- Elevation values -->
|
||||
<dimen name="elevation_card">2dp</dimen>
|
||||
<dimen name="elevation_settings_item">0dp</dimen>
|
||||
|
||||
<dimen name="float_action_button_icon_size">24dp</dimen>
|
||||
<dimen name="float_action_button_size">56dp</dimen>
|
||||
|
||||
<!-- Dimensions for quick menu -->
|
||||
<dimen name="header_height_quick_menu">@dimen/element_size_normal</dimen>
|
||||
<!-- Size of icons in the top-level of settings -->
|
||||
<dimen name="header_icon_width">28dp</dimen>
|
||||
|
||||
<dimen name="height_player_control_panel">40dp</dimen>
|
||||
|
||||
<dimen name="home_page_margin">1dp</dimen>
|
||||
|
||||
<dimen name="settings_panel_width_entries">240dp</dimen>
|
||||
<dimen name="settings_panel_margin_start_details">@dimen/element_size_normal</dimen>
|
||||
<dimen name="icon_size_activity_type">16dp</dimen>
|
||||
<!-- Dimensions for alert dialog -->
|
||||
<dimen name="icon_size_alert_dialog">32dp</dimen>
|
||||
<dimen name="icon_size_card_details">@dimen/element_size_mlarge</dimen>
|
||||
<dimen name="icon_size_card_list_item">48dp</dimen>
|
||||
<dimen name="icon_size_list_item">56dp</dimen>
|
||||
<dimen name="icon_size_list_item_small">42dp</dimen>
|
||||
<dimen name="icon_size_profile_image_dashboard_current">72dp</dimen>
|
||||
<dimen name="icon_size_profile_type">16dp</dimen>
|
||||
<dimen name="icon_size_profile_type_detail">22dp</dimen>
|
||||
<dimen name="icon_size_profile_type_user_profile">26dp</dimen>
|
||||
<dimen name="icon_size_status_profile_image">48dp</dimen>
|
||||
<dimen name="icon_size_user_profile">84dp</dimen>
|
||||
|
||||
</resources>
|
||||
<dimen name="line_width_compose_account_profile_image">2dp</dimen>
|
||||
|
||||
<dimen name="minimum_element_size">48dp</dimen>
|
||||
<dimen name="minimum_height_list_layout_content">300dp</dimen>
|
||||
<dimen name="minimum_width_list_layout_content">300dp</dimen>
|
||||
|
||||
<dimen name="padding_profile_image_detail_page">@dimen/element_spacing_small</dimen>
|
||||
<dimen name="padding_profile_image_list_item">@dimen/element_spacing_small</dimen>
|
||||
|
||||
<dimen name="popup_width_account_selector">160dp</dimen>
|
||||
|
||||
<!-- Preferred size -->
|
||||
<dimen name="preferred_tab_column_width">420dp</dimen>
|
||||
|
||||
<dimen name="profile_image_size_activity_small">32dp</dimen>
|
||||
|
||||
<dimen name="settings_panel_margin_start_details">@dimen/element_size_normal</dimen>
|
||||
<dimen name="settings_panel_width_entries">240dp</dimen>
|
||||
|
||||
<dimen name="text_size_extra_small">12sp</dimen>
|
||||
|
||||
<dimen name="toolbar_elevation">8dp</dimen>
|
||||
|
||||
<dimen name="unread_indicator_size">16dp</dimen>
|
||||
</resources>
|
||||
|
@ -82,6 +82,7 @@
|
||||
<string name="action_saving_search">saving search</string>
|
||||
<string name="action_select_all">Select all</string>
|
||||
<string name="action_select_none">Select none</string>
|
||||
<string name="action_select_user">Select user</string>
|
||||
<!-- [verb] Send tweet/message -->
|
||||
<string name="action_send">Send</string>
|
||||
<string name="action_sending_direct_message">sending direct message</string>
|
||||
@ -486,9 +487,6 @@
|
||||
<string name="following_you">Following you</string>
|
||||
|
||||
<string name="follows">Follows</string>
|
||||
<string name="title_user_list_subscriptions">Subscriptions</string>
|
||||
<string name="title_user_list_memberships">Belongs to</string>
|
||||
<string name="title_user_list_ownerships">Created</string>
|
||||
|
||||
<string name="font">Font</string>
|
||||
<string name="font_family">Font family</string>
|
||||
@ -1219,6 +1217,9 @@
|
||||
<string name="title_sync_settings">Sync settings</string>
|
||||
<string name="title_user">User</string>
|
||||
<string name="title_user_colors">User colors</string>
|
||||
<string name="title_user_list_memberships">Belongs to</string>
|
||||
<string name="title_user_list_ownerships">Created</string>
|
||||
<string name="title_user_list_subscriptions">Subscriptions</string>
|
||||
<string name="title_users_favorited_this">Users favorited this</string>
|
||||
<string name="title_users_liked_this">Users liked this</string>
|
||||
<string name="title_users_retweeted_this">Users retweeted this</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user