diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2017-10-26 01:22:54 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2017-10-26 01:27:02 +0900 |
commit | 7ae78f41164b0333106945dcd611d039646f48e7 (patch) | |
tree | 12d7bd09af4f673e82a42acc640e02a1f5994f30 /app/src/main/java/net/lacolaco | |
parent | 40103f06c8e2798aad8f93c4da1d1b9aea0825f7 (diff) | |
download | SmileEssence-7ae78f41164b0333106945dcd611d039646f48e7.tar.gz |
de-listview
Diffstat (limited to 'app/src/main/java/net/lacolaco')
11 files changed, 206 insertions, 231 deletions
diff --git a/app/src/main/java/net/lacolaco/smileessence/World.kt b/app/src/main/java/net/lacolaco/smileessence/World.kt index 3b9a6c30..5beef673 100644 --- a/app/src/main/java/net/lacolaco/smileessence/World.kt +++ b/app/src/main/java/net/lacolaco/smileessence/World.kt @@ -7,6 +7,7 @@ import android.graphics.drawable.Drawable import android.support.annotation.StringRes import android.support.design.widget.Snackbar import android.view.View +import com.beust.klaxon.* import com.bumptech.glide.Glide import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.target.SimpleTarget @@ -38,7 +39,8 @@ import kotlin.coroutines.experimental.suspendCoroutine */ class World private constructor(private val persistentData: PersistentData) { val id = persistentData.id - val user: User = User.makeSkeletonForInternalUseOnly(id, persistentData.screenName, persistentData.profileImageUrl) + val user: User = User.makeSkeletonForInternalUseOnly(id, persistentData.screenName, + persistentData.profileImageUrl) // XXX: Workaround for a bug in Android var mainActivityIntent: Intent? = null // Timelines @@ -317,13 +319,13 @@ class World private constructor(private val persistentData: PersistentData) { } } - private data class PersistentData( + private class PersistentData( val id: Long, var oauthToken: String, var oauthTokenSecret: String, var screenName: String, var profileImageUrl: String = "https://abs.twimg.com/sticky/default_profile_images/default_profile.png", - var pageInfos: List<PageInfo> = makeDefaultPageInfos(screenName), + var pageInfos: MutableList<PageInfo> = makeDefaultPageInfos(screenName), var themeIndex: Int = 0, var themeColor: Int = 0 ) { @@ -334,16 +336,32 @@ class World private constructor(private val persistentData: PersistentData) { values.put("oauth_token_secret", oauthTokenSecret) values.put("screen_name", screenName) values.put("profile_image_url", profileImageUrl) - Logger.error("pageinfo saving: ${PageInfo.stringifyList(pageInfos)}") - values.put("page_infos", PageInfo.stringifyList(pageInfos)) + values.put("page_infos", stringifyPageInfos()) values.put("theme", themeIndex) values.put("theme_color", themeColor) if (Application.instance.db.replaceOrThrow("profiles", null, values) == -1L) throw RuntimeException("SQLiteDatabase#replaceOrThrow failed") } + private fun stringifyPageInfos(): String { + return json { + array(pageInfos.mapNotNull { + if (it.ephemeral) + return@mapNotNull null + val kind = when (it) { + is PageInfo.ComposePageInfo -> "compose" + is PageInfo.TweetsPageInfo -> "tweets" + is PageInfo.EventsPageInfo -> "events" + is PageInfo.SearchPageInfo -> "search" + is PageInfo.ListPageInfo -> "list" + } + obj("kind" to kind, "data" to it.toJson()) + }) + }.toJsonString() + } + companion object { - private fun makeDefaultPageInfos(screenName: String): List<PageInfo> { + private fun makeDefaultPageInfos(screenName: String): MutableList<PageInfo> { val ret = arrayListOf<PageInfo>() ret.add(PageInfo.EventsPageInfo()) ret.add(PageInfo.ComposePageInfo()) @@ -354,6 +372,26 @@ class World private constructor(private val persistentData: PersistentData) { return ret } + private fun parsePageInfos(input: String): MutableList<PageInfo> { + val parser = Parser() + val json = parser.parse(StringBuilder(input)) as JsonArray<*> + return json.mapNotNull { + it as JsonObject + val kind = it.string("kind")!! + if (kind == "message") + return@mapNotNull null + val data = it.obj("data")!! + when (kind) { + "compose" -> PageInfo.ComposePageInfo(data) + "tweets" -> PageInfo.TweetsPageInfo(data) + "events" -> PageInfo.EventsPageInfo(data) + "search" -> PageInfo.SearchPageInfo(data) + "list" -> PageInfo.ListPageInfo(data) + else -> throw RuntimeException("Recognized PageInfo kind: $kind") + } + }.toMutableList() + } + fun fetchAll(): List<PersistentData> { val ret = arrayListOf<PersistentData>() Application.instance.db.query("profiles", null, null, null, null, null, null).use { cursor -> @@ -369,7 +407,7 @@ class World private constructor(private val persistentData: PersistentData) { cursor.getColumnIndexOrThrow("screen_name")), profileImageUrl = cursor.getString( cursor.getColumnIndexOrThrow("profile_image_url")), - pageInfos = PageInfo.parseList(cursor.getString( + pageInfos = parsePageInfos(cursor.getString( cursor.getColumnIndexOrThrow("page_infos"))), themeIndex = cursor.getInt( cursor.getColumnIndexOrThrow("theme")), diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.kt b/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.kt index 506178ad..265652a0 100644 --- a/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.kt +++ b/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.kt @@ -6,13 +6,72 @@ import android.support.v7.app.AppCompatActivity import android.text.TextUtils import android.view.* import android.widget.AbsListView +import android.widget.BaseAdapter import android.widget.ListView import kotlinx.android.synthetic.main.layout_edit_list.* import kotlinx.android.synthetic.main.list_item_simple_text.view.* import kotlinx.android.synthetic.main.part_edittext.view.* import net.lacolaco.smileessence.R import net.lacolaco.smileessence.data.ExtractionWord -import net.lacolaco.smileessence.view.adapter.UnorderedCustomListAdapter +import net.lacolaco.smileessence.util.UIHandler +import java.util.* + +abstract class CustomListAdapter<out T> : BaseAdapter() { + private var isNotifiable = true + private var frozenList: List<T> = ArrayList() + + fun setNotifiable(notifiable: Boolean) { + isNotifiable = notifiable + } + + override fun getCount(): Int { + return frozenList.size + } + + override fun getItem(position: Int): T { + return frozenList[position] + } + + override fun getItemId(position: Int): Long { + return position.toLong() + } + + override fun notifyDataSetChanged() { + frozenList = Collections.unmodifiableList(list) + super.notifyDataSetChanged() + } + + protected abstract val list: List<T> + + fun update() { + if (isNotifiable) { + updateForce() + } + } + + fun updateForce() { + UIHandler().post { this.notifyDataSetChanged() } + } +} + + +abstract class UnorderedCustomListAdapter<T> constructor(override val list: ArrayList<T> = ArrayList()) : CustomListAdapter<T>() { + init { + update() + } + + @Synchronized + fun add(item: T) = list.add(item) + + @Synchronized + fun addAll(items: Collection<T>) = list.addAll(items) + + @Synchronized + fun clear() = list.clear() + + @Synchronized + fun remove(item: T): Boolean = list.remove(item) +} class EditExtractionActivity : AppCompatActivity() { private val adapter by lazy { diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/ManagePagesActivity.kt b/app/src/main/java/net/lacolaco/smileessence/activity/ManagePagesActivity.kt index 75560f40..11019e72 100644 --- a/app/src/main/java/net/lacolaco/smileessence/activity/ManagePagesActivity.kt +++ b/app/src/main/java/net/lacolaco/smileessence/activity/ManagePagesActivity.kt @@ -20,7 +20,7 @@ class ManagePagesActivity : AppCompatActivity() { private val world by lazy { World[intent.getLongExtra(INTENT_KEY_WORLD_ID, -1)] } - private lateinit var pages: MutableList<PageInfo> + private var changed = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -28,16 +28,14 @@ class ManagePagesActivity : AppCompatActivity() { setContentView(R.layout.activity_page_manage) setSupportActionBar(toolbar) - pages = PageInfo.parseList(if (savedInstanceState == null) - PageInfo.stringifyList(world.pages) - else - savedInstanceState.getString(KEY_SAVED_PAGES) - ).toMutableList() + if (savedInstanceState != null) + changed = savedInstanceState.getBoolean(KEY_IS_CHANGED) fab.setOnClickListener { + changed = true val item = PageInfo.TweetsPageInfo("Tweets", listOf()) - pages.add(item) - recycler_view.adapter.notifyItemInserted(pages.size - 1) + world.pages.add(item) + recycler_view.adapter.notifyItemInserted(world.pages.size - 1) openItemEditor(item) } val helper = ItemTouchHelper(object : ItemTouchHelper.Callback() { @@ -66,15 +64,12 @@ class ManagePagesActivity : AppCompatActivity() { override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - outState.putString(KEY_SAVED_PAGES, PageInfo.stringifyList(pages)) + outState.putBoolean(KEY_IS_CHANGED, changed) } override fun finish() { // MainActivity will restart itself on RESULT_OK - if (PageInfo.stringifyList(world.pages) == PageInfo.stringifyList(pages)) - setResult(RESULT_CANCELED) - else - setResult(RESULT_OK) + setResult(if (changed) RESULT_OK else RESULT_CANCELED) super.finish() } @@ -84,12 +79,12 @@ class ManagePagesActivity : AppCompatActivity() { companion object { val INTENT_KEY_WORLD_ID = "WORLD_ID" - private val KEY_SAVED_PAGES = "SAVED_PAGES" + private val KEY_IS_CHANGED = "IS_CHANGED" } private inner class PagesAdapter : RecyclerView.Adapter<PagesAdapter.ViewHolder>() { override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val item = pages[position] + val item = world.pages[position] val view = holder.itemView view.page_kind_text_view.text = item.name view.page_name_text_view.text = item.describe() @@ -101,7 +96,7 @@ class ManagePagesActivity : AppCompatActivity() { } override fun getItemCount(): Int { - return pages.size + return world.pages.size } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { @@ -109,16 +104,18 @@ class ManagePagesActivity : AppCompatActivity() { } fun move(before: Int, after: Int): Boolean { - val item = pages.removeAt(before) - pages.add(after, item) + changed = true + val item = world.pages.removeAt(before) + world.pages.add(after, item) notifyItemMoved(before, after) return true } fun remove(position: Int) { - pages.removeAt(position) + changed = true + world.pages.removeAt(position) notifyItemRemoved(position) - notifyItemRangeChanged(position, pages.size) + notifyItemRangeChanged(position, world.pages.size) } private inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) diff --git a/app/src/main/java/net/lacolaco/smileessence/data/Pages.kt b/app/src/main/java/net/lacolaco/smileessence/data/Pages.kt index cc3c1ab1..1d898711 100644 --- a/app/src/main/java/net/lacolaco/smileessence/data/Pages.kt +++ b/app/src/main/java/net/lacolaco/smileessence/data/Pages.kt @@ -1,16 +1,21 @@ package net.lacolaco.smileessence.data -import com.beust.klaxon.* -import net.lacolaco.smileessence.Logger +import com.beust.klaxon.JsonObject +import com.beust.klaxon.array +import com.beust.klaxon.json +import com.beust.klaxon.string import net.lacolaco.smileessence.view.page.* sealed class PageInfo(val fragmentClass: Class<out PageFragment<*>>) { abstract val name: String + var ephemeral = false + abstract fun describe(): String abstract fun toJson(): JsonObject class ComposePageInfo() : PageInfo(ComposePageFragment::class.java) { - override val name = "Compose" + override val name + get() = "Compose" override fun describe(): String { return "" @@ -23,8 +28,9 @@ sealed class PageInfo(val fragmentClass: Class<out PageFragment<*>>) { } } - class TweetsPageInfo(override val name: String, val patternStrings: List<String>) : + data class TweetsPageInfo(override val name: String, val patternStrings: List<String>) : PageInfo(TweetsPageFragment::class.java) { + @Transient val patterns = patternStrings.map { Regex(it) } override fun describe(): String { @@ -33,7 +39,8 @@ sealed class PageInfo(val fragmentClass: Class<out PageFragment<*>>) { return sb.toString() } - constructor(json: JsonObject) : this(json.string("name")!!, json.array<String>("patterns")!!.toList()) + constructor(json: JsonObject) + : this(json.string("name")!!, json.array<String>("patterns")!!) override fun toJson() = json { obj("name" to name, "patterns" to array(patternStrings)) @@ -41,7 +48,8 @@ sealed class PageInfo(val fragmentClass: Class<out PageFragment<*>>) { } class EventsPageInfo() : PageInfo(EventsPageFragment::class.java) { - override val name = "Events" + override val name + get() = "Events" override fun describe(): String { return "" @@ -83,41 +91,4 @@ sealed class PageInfo(val fragmentClass: Class<out PageFragment<*>>) { obj("full_name" to fullName) } } - - // XXX: Yucks - companion object { - fun parseList(input: String): List<PageInfo> { - Logger.error("parsing: $input") - val parser = Parser() - val json = parser.parse(StringBuilder(input)) as JsonArray<*> - return json.map { - val data: JsonObject = (it as JsonObject).obj("data")!! - when (it.string("kind")) { - "compose" -> ComposePageInfo(data) - "tweets" -> TweetsPageInfo(data) - "events" -> EventsPageInfo(data) - "search" -> SearchPageInfo(data) - "list" -> ListPageInfo(data) - // FIXME: Remove this - "messages" -> null - else -> throw RuntimeException("invalid kind") - } - }.mapNotNull { it } // FIXME - } - - fun stringifyList(input: List<PageInfo>): String { - return json { - array(input.map { - val kind = when (it) { - is ComposePageInfo -> "compose" - is TweetsPageInfo -> "tweets" - is EventsPageInfo -> "events" - is SearchPageInfo -> "search" - is ListPageInfo -> "list" - } - obj("kind" to kind, "data" to it.toJson()) - }) - }.toJsonString() - } - } } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.kt b/app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.kt deleted file mode 100644 index 612c14e5..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.kt +++ /dev/null @@ -1,43 +0,0 @@ -package net.lacolaco.smileessence.view.adapter - -import android.widget.BaseAdapter -import net.lacolaco.smileessence.util.UIHandler -import java.util.* - -abstract class CustomListAdapter<out T> : BaseAdapter() { - private var isNotifiable = true - private var frozenList: List<T> = ArrayList() - - fun setNotifiable(notifiable: Boolean) { - isNotifiable = notifiable - } - - override fun getCount(): Int { - return frozenList.size - } - - override fun getItem(position: Int): T { - return frozenList[position] - } - - override fun getItemId(position: Int): Long { - return position.toLong() - } - - override fun notifyDataSetChanged() { - frozenList = Collections.unmodifiableList(list) - super.notifyDataSetChanged() - } - - protected abstract val list: List<T> - - fun update() { - if (isNotifiable) { - updateForce() - } - } - - fun updateForce() { - UIHandler().post { this.notifyDataSetChanged() } - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.kt b/app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.kt deleted file mode 100644 index 53b1c824..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.kt +++ /dev/null @@ -1,35 +0,0 @@ -package net.lacolaco.smileessence.view.adapter - -import net.lacolaco.smileessence.entity.IdObject - -import java.util.* - -abstract class OrderedCustomListAdapter<T : IdObject> -constructor(comparator: Comparator<Long> = Comparator { x, y -> java.lang.Long.compare(x, y) }) : CustomListAdapter<T>() { - private val treeMap: MutableMap<Long, T> = TreeMap(Collections.reverseOrder(comparator)) - - override val list: List<T> - @Synchronized get() = ArrayList(treeMap.values) - - @Synchronized - fun add(item: T) { - treeMap.put(item.id, item) - } - - @Synchronized - fun addAll(items: Collection<T>) { - for (item in items) { - treeMap.put(item.id, item) - } - } - - @Synchronized - fun clear() { - treeMap.clear() - } - - @Synchronized - fun remove(item: T): T { - return treeMap.remove(item.id)!! - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.kt b/app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.kt deleted file mode 100644 index f2b640c8..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.kt +++ /dev/null @@ -1,28 +0,0 @@ -package net.lacolaco.smileessence.view.adapter - -import android.app.Activity -import android.view.View -import android.view.ViewGroup -import net.lacolaco.smileessence.World -import net.lacolaco.smileessence.entity.Tweet -import net.lacolaco.smileessence.view.Partials - -class TimelineAdapter(private val activity: Activity, private val world: World) : OrderedCustomListAdapter<Tweet>() { - val lastID: Long - get() = if (count > 0) { - getItem(count - 1).id - } else { - -1 - } - - val topID: Long - get() = if (count > 0) { - getItem(0).id - } else { - -1 - } - - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { - return Partials.getTweetView(getItem(position), world, activity, convertView) - } -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/UnorderedCustomListAdapter.kt b/app/src/main/java/net/lacolaco/smileessence/view/adapter/UnorderedCustomListAdapter.kt deleted file mode 100644 index 46b40681..00000000 --- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/UnorderedCustomListAdapter.kt +++ /dev/null @@ -1,21 +0,0 @@ -package net.lacolaco.smileessence.view.adapter - -import java.util.* - -abstract class UnorderedCustomListAdapter<T> constructor(override val list: ArrayList<T> = ArrayList()) : CustomListAdapter<T>() { - init { - update() - } - - @Synchronized - fun add(item: T) = list.add(item) - - @Synchronized - fun addAll(items: Collection<T>) = list.addAll(items) - - @Synchronized - fun clear() = list.clear() - - @Synchronized - fun remove(item: T): Boolean = list.remove(item) -} diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/AppInfoDialogFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/dialog/AppInfoDialogFragment.kt index 4ebd69f7..247a8cc3 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/AppInfoDialogFragment.kt +++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/AppInfoDialogFragment.kt @@ -9,13 +9,14 @@ import net.lacolaco.smileessence.BuildConfig import net.lacolaco.smileessence.R class AppInfoDialogFragment : StackableDialogFragment() { - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View { return inflater.inflate(R.layout.dialog_app_info, container, false) } override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - application_version.text = "${BuildConfig.VERSION_NAME} (revision ${BuildConfig.VERSION_CODE})" + app_version.text = "${BuildConfig.VERSION_NAME} (revision ${BuildConfig.VERSION_CODE})" web_view.loadUrl("file:///android_asset/licenses.html") } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.kt index d53c887f..d212124f 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.kt +++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.kt @@ -1,6 +1,9 @@ package net.lacolaco.smileessence.view.dialog import android.os.Bundle +import android.support.v7.widget.DividerItemDecoration +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView import android.text.Html import android.text.method.LinkMovementMethod import android.view.LayoutInflater @@ -11,17 +14,18 @@ import com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayoutDirec import kotlinx.android.synthetic.main.dialog_user_detail.* import net.lacolaco.smileessence.R import net.lacolaco.smileessence.activity.MainActivity +import net.lacolaco.smileessence.entity.Tweet import net.lacolaco.smileessence.entity.User import net.lacolaco.smileessence.twitter.TwitterTaskException import net.lacolaco.smileessence.twitter.task.* +import net.lacolaco.smileessence.util.SortedList import net.lacolaco.smileessence.util.browse import net.lacolaco.smileessence.util.launchUi +import net.lacolaco.smileessence.view.Partials import net.lacolaco.smileessence.view.PopupMenu -import net.lacolaco.smileessence.view.adapter.TimelineAdapter import net.lacolaco.smileessence.view.confirm class UserDetailDialogFragment : StackableDialogFragment() { - private val adapter by lazy { TimelineAdapter(activity, world) } private lateinit var user: User private var isFollowedByMe = false private var isFollowingMe = false @@ -61,18 +65,26 @@ class UserDetailDialogFragment : StackableDialogFragment() { user_detail_banner.setOnClickListener { user.profileBannerUrl?.let { browse(it) } } toggle_follow.setOnClickListener { toggleFollowing() } + user_timeline.addItemDecoration( + DividerItemDecoration(activity, DividerItemDecoration.VERTICAL)) + val lm = LinearLayoutManager(activity) + lm.orientation = LinearLayoutManager.VERTICAL + user_timeline.layoutManager = lm + val adapter = UserTimelineAdapter() + user_timeline.adapter = adapter + val refreshLayout = user_detail_refresh_layout refreshLayout.setOnRefreshListener { launchUi { try { if (it == SwipyRefreshLayoutDirection.TOP) { - val tweets = world.getUserTimelineAsync(user.id, sinceId = adapter.topID).await() + val tweets = world.getUserTimelineAsync(user.id, + sinceId = adapter.getMaxIdOrNull()).await() adapter.addAll(tweets) - updateListView(true) } else { - val tweets = world.getUserTimelineAsync(user.id, maxId = adapter.lastID - 1).await() + val tweets = world.getUserTimelineAsync(user.id, + maxId = adapter.getMinIdMinusOneOrNull()).await() adapter.addAll(tweets) - updateListView(false) } } catch (e: TwitterTaskException) { world.notifyError(R.string.notice_error_get_user_timeline) @@ -81,23 +93,20 @@ class UserDetailDialogFragment : StackableDialogFragment() { } } - refresh() updateRelationship() - - // FIXME - listview_user_detail_timeline.adapter = adapter launchUi { try { val tweets = world.getUserTimelineAsync(user.id).await() adapter.addAll(tweets) - adapter.updateForce() } catch (e: TwitterTaskException) { world.notifyError(R.string.notice_error_get_user_timeline) } } + + refreshViews() } - private fun refresh() { + private fun refreshViews() { Glide.with(this).load(user.profileImageUrl).into(user_detail_icon) Glide.with(this).load(user.profileBannerUrl).into(user_detail_banner) user_detail_name.text = user.name @@ -199,23 +208,6 @@ class UserDetailDialogFragment : StackableDialogFragment() { } } - private fun updateListView(addedToTop: Boolean) { - val absListView = listview_user_detail_timeline - val before = adapter.count - adapter.notifyDataSetChanged() // synchronized call (not adapter#updateForce()) - val after = adapter.count - val increments = after - before - if (increments > 0) { - if (addedToTop) { - absListView.setSelection(increments + 1) - absListView.smoothScrollToPositionFromTop(increments, 0) - absListView.setSelection(increments) - } else { - absListView.smoothScrollToPositionFromTop(before, 0) - } - } - } - private fun updateRelationship() { if (user !== world.user) { toggle_follow.isEnabled = false @@ -229,7 +221,7 @@ class UserDetailDialogFragment : StackableDialogFragment() { } catch (e: TwitterTaskException) { world.notifyError("Failed to fetch relationship") } - refresh() + refreshViews() } } } @@ -245,4 +237,45 @@ class UserDetailDialogFragment : StackableDialogFragment() { return obj } } + + private inner class UserTimelineAdapter : + RecyclerView.Adapter<UserTimelineAdapter.ViewHolder>() { + private val sortedList = SortedList<Tweet>( + { position -> notifyItemInserted(position) }, + { position, count -> notifyItemRangeRemoved(position, count) } + ) + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + Partials.getTweetView(sortedList[position], world, activity, holder.itemView) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val layoutInflater = LayoutInflater.from(parent.context) + return ViewHolder(layoutInflater.inflate(R.layout.list_item_status, parent, false)) + } + + override fun getItemCount(): Int { + return sortedList.size + } + + fun addAll(items: Collection<Tweet>) { + sortedList.addAll(items) + } + + fun getMaxIdOrNull(): Long? { + return if (sortedList.size > 0) + sortedList[0].id + else + null + } + + fun getMinIdMinusOneOrNull(): Long? { + return if (sortedList.size > 0) + sortedList[sortedList.size - 1].id - 1 + else + null + } + + private inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) + } } diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.kt index 15ca9449..bd25207f 100644 --- a/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.kt +++ b/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.kt @@ -13,8 +13,11 @@ abstract class PageFragment<out T : PageInfo> : Fragment() { World[arguments.getLong(KEY_WORLD_USER_ID)] } protected val pageInfo by lazy { + val pos = arguments.getInt(KEY_PAGE_POSITION, -2) + if (pos == -2) + throw IllegalStateException("KEY_PAGE_POSITION not specified") @Suppress("UNCHECKED_CAST") - world.pages[arguments.getInt(KEY_PAGE_POSITION)] as T + world.pages[pos] as T } val mainActivity |