package com.keylesspalace.tusky import android.content.Context import android.content.Intent import android.os.Bundle import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.appcompat.widget.Toolbar import android.view.LayoutInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup import android.widget.ProgressBar import android.widget.TextView import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.entity.MastoList import com.keylesspalace.tusky.fragment.TimelineFragment import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.util.ThemeUtils import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.iconics.IconicsDrawable import retrofit2.Call import retrofit2.Response import java.lang.ref.WeakReference import javax.inject.Inject /** * Created by charlag on 1/4/18. */ interface ListsView { fun update(state: State) fun openTimeline(listId: String) } data class State(val lists: List, val isLoading: Boolean) class ListsViewModel(private val api: MastodonApi) { private var _view: WeakReference? = null private val view: ListsView? get() = _view?.get() private var state = State(listOf(), false) fun attach(view: ListsView) { this._view = WeakReference(view) updateView() loadIfNeeded() } fun detach() { this._view = null } fun didSelectItem(id: String) { view?.openTimeline(id) } private fun loadIfNeeded() { if (state.isLoading || !state.lists.isEmpty()) return updateState(state.copy(isLoading = false)) api.getLists().enqueue(object : retrofit2.Callback> { override fun onResponse(call: Call>, response: Response>) { updateState(state.copy(lists = response.body() ?: listOf(), isLoading = false)) } override fun onFailure(call: Call>, t: Throwable?) { updateState(state.copy(isLoading = false)) } }) } private fun updateState(state: State) { this.state = state view?.update(state) } private fun updateView() { view?.update(state) } } class ListsActivity : BaseActivity(), ListsView, Injectable { companion object { @JvmStatic fun newIntent(context: Context): Intent { return Intent(context, ListsActivity::class.java) } } @Inject lateinit var mastodonApi: MastodonApi private lateinit var recyclerView: RecyclerView private lateinit var progressBar: ProgressBar private lateinit var viewModel: ListsViewModel private val adapter = ListsAdapter() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_lists) val toolbar = findViewById(R.id.toolbar) recyclerView = findViewById(R.id.lists_recycler) progressBar = findViewById(R.id.progress_bar) setSupportActionBar(toolbar) val bar = supportActionBar if (bar != null) { bar.title = getString(R.string.title_lists) bar.setDisplayHomeAsUpEnabled(true) bar.setDisplayShowHomeEnabled(true) } recyclerView.adapter = adapter recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.addItemDecoration( DividerItemDecoration(this, DividerItemDecoration.VERTICAL)) viewModel = lastNonConfigurationInstance as? ListsViewModel ?: ListsViewModel(mastodonApi) viewModel.attach(this) } override fun onDestroy() { viewModel.detach() super.onDestroy() } override fun onRetainCustomNonConfigurationInstance(): Any { return viewModel } override fun update(state: State) { adapter.update(state.lists) progressBar.visibility = if (state.isLoading) View.VISIBLE else View.GONE } override fun openTimeline(listId: String) { startActivityWithSlideInAnimation( ModalTimelineActivity.newIntent(this, TimelineFragment.Kind.LIST, listId)) } override fun onOptionsItemSelected(item: MenuItem): Boolean { if (item.itemId == android.R.id.home) { onBackPressed() return true } return false } private inner class ListsAdapter : RecyclerView.Adapter() { private val items = mutableListOf() fun update(list: List) { this.items.clear() this.items.addAll(list) notifyDataSetChanged() } override fun getItemCount(): Int = items.size override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder { return LayoutInflater.from(parent.context).inflate(R.layout.item_list, parent, false) .let(this::ListViewHolder) .apply { val context = nameTextView.context val icon = IconicsDrawable(context, GoogleMaterial.Icon.gmd_list).sizeDp(20) ThemeUtils.setDrawableTint(context, icon, android.R.attr.textColorTertiary) nameTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null) } } override fun onBindViewHolder(holder: ListViewHolder, position: Int) { holder.nameTextView.text = items[position].title } private inner class ListViewHolder(view: View) : RecyclerView.ViewHolder(view), View.OnClickListener { val nameTextView: TextView = view.findViewById(R.id.list_name_textview) init { view.setOnClickListener(this) } override fun onClick(v: View?) { viewModel.didSelectItem(items[adapterPosition].id) } } } }