diff options
author | Torsten Grote <t@grobox.de> | 2019-12-27 11:13:19 -0300 |
---|---|---|
committer | Torsten Grote <t@grobox.de> | 2019-12-27 11:13:19 -0300 |
commit | 35ba17db04f48f4ec41f55ac6944051093f7b78b (patch) | |
tree | 4f315cfc5ffe5d386eb7b8d86666ceefbc82fcc4 | |
parent | 89037988ca55cdd68e3be6294125b04ebfc50e77 (diff) | |
download | wallet-android-35ba17db04f48f4ec41f55ac6944051093f7b78b.tar.gz wallet-android-35ba17db04f48f4ec41f55ac6944051093f7b78b.tar.bz2 wallet-android-35ba17db04f48f4ec41f55ac6944051093f7b78b.zip |
Use special layout for withdraw event in wallet history
This is how it could be done for all event types.
9 files changed, 173 insertions, 68 deletions
diff --git a/app/src/main/java/net/taler/wallet/WalletViewModel.kt b/app/src/main/java/net/taler/wallet/WalletViewModel.kt index 291321d..94d2d8a 100644 --- a/app/src/main/java/net/taler/wallet/WalletViewModel.kt +++ b/app/src/main/java/net/taler/wallet/WalletViewModel.kt @@ -20,8 +20,11 @@ import android.app.Application import android.util.Log import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.MutableLiveData +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.KotlinModule +import com.fasterxml.jackson.module.kotlin.readValue import net.taler.wallet.backend.WalletBackendApi -import net.taler.wallet.history.HistoryEntry +import net.taler.wallet.history.History import org.json.JSONObject const val TAG = "taler-wallet" @@ -94,10 +97,6 @@ open class WithdrawStatus { data class Withdrawing(val talerWithdrawUri: String) : WithdrawStatus() } -open class HistoryResult( - val history: List<HistoryEntry> -) - open class PendingOperationInfo( val type: String, val detail: JSONObject @@ -138,6 +137,7 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) { private var currentWithdrawRequestId = 0 private val walletBackendApi = WalletBackendApi(app) + private val mapper = ObjectMapper().registerModule(KotlinModule()) fun init() { if (initialized) { @@ -214,23 +214,14 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) { } } - fun getHistory(cb: (r: HistoryResult) -> Unit) { + fun getHistory(cb: (r: History) -> Unit) { walletBackendApi.sendRequest("getHistory", null) { isError, result -> if (isError) { + // TODO show error message in [WalletHistory] fragment return@sendRequest } - val historyEntries = mutableListOf<HistoryEntry>() - val historyList = result.getJSONArray("history") - for (i in 0 until historyList.length()) { - val h = historyList.getJSONObject(i) - Log.v(TAG, "got history entry $h") - val type = h.getString("type") - Log.v(TAG, "got history entry type $type") - val detail = h - val timestamp = h.getJSONObject("timestamp") - historyEntries.add(HistoryEntry(detail, type, timestamp)) - } - cb(HistoryResult(historyEntries)) + val history: History = mapper.readValue(result.getString("history")) + cb(history) } } diff --git a/app/src/main/java/net/taler/wallet/history/HistoryEvent.kt b/app/src/main/java/net/taler/wallet/history/HistoryEvent.kt index be48ac9..34f3164 100644 --- a/app/src/main/java/net/taler/wallet/history/HistoryEvent.kt +++ b/app/src/main/java/net/taler/wallet/history/HistoryEvent.kt @@ -5,13 +5,6 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY import com.fasterxml.jackson.annotation.JsonSubTypes.Type import com.fasterxml.jackson.annotation.JsonTypeInfo.As.PROPERTY import com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME -import org.json.JSONObject - -open class HistoryEntry( - val detail: JSONObject, - val type: String, - val timestamp: JSONObject -) enum class ReserveType { /** diff --git a/app/src/main/java/net/taler/wallet/history/WalletHistory.kt b/app/src/main/java/net/taler/wallet/history/WalletHistory.kt index 89c6b3f..cdc90ae 100644 --- a/app/src/main/java/net/taler/wallet/history/WalletHistory.kt +++ b/app/src/main/java/net/taler/wallet/history/WalletHistory.kt @@ -24,7 +24,6 @@ import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import net.taler.wallet.HistoryResult import net.taler.wallet.R import net.taler.wallet.WalletViewModel @@ -35,17 +34,13 @@ import net.taler.wallet.WalletViewModel class WalletHistory : Fragment() { lateinit var model: WalletViewModel - lateinit var historyAdapter: WalletHistoryAdapter + private val historyAdapter = WalletHistoryAdapter() lateinit var historyPlaceholder: View override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) - historyAdapter = WalletHistoryAdapter( - HistoryResult(listOf()) - ) - model = activity?.run { ViewModelProviders.of(this)[WalletViewModel::class.java] } ?: throw Exception("Invalid Activity") @@ -68,7 +63,7 @@ class WalletHistory : Fragment() { private fun updateHistory() { model.getHistory { - if (it.history.isEmpty()) { + if (it.isEmpty()) { historyPlaceholder.visibility = View.VISIBLE } historyAdapter.update(it) @@ -81,7 +76,9 @@ class WalletHistory : Fragment() { ): View? { // Inflate the layout for this fragment val view = inflater.inflate(R.layout.fragment_show_history, container, false) - val myLayoutManager = LinearLayoutManager(context) + val myLayoutManager = LinearLayoutManager(context).apply { + reverseLayout = true // show latest events first + } val myItemDecoration = DividerItemDecoration(context, myLayoutManager.orientation) view.findViewById<RecyclerView>(R.id.list_history).apply { layoutManager = myLayoutManager diff --git a/app/src/main/java/net/taler/wallet/history/WalletHistoryAdapter.kt b/app/src/main/java/net/taler/wallet/history/WalletHistoryAdapter.kt index 46bca30..37dc742 100644 --- a/app/src/main/java/net/taler/wallet/history/WalletHistoryAdapter.kt +++ b/app/src/main/java/net/taler/wallet/history/WalletHistoryAdapter.kt @@ -1,41 +1,82 @@ package net.taler.wallet.history +import android.text.format.DateUtils.* import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import net.taler.wallet.HistoryResult +import androidx.annotation.CallSuper +import androidx.recyclerview.widget.RecyclerView.Adapter +import androidx.recyclerview.widget.RecyclerView.ViewHolder import net.taler.wallet.R -class WalletHistoryAdapter(private var myDataset: HistoryResult) : RecyclerView.Adapter<WalletHistoryAdapter.MyViewHolder>() { +internal class WalletHistoryAdapter(private var history: History = History()) : + Adapter<HistoryEventViewHolder>() { init { setHasStableIds(false) } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { - val rowView = LayoutInflater.from(parent.context).inflate(R.layout.history_row, parent, false) - return MyViewHolder(rowView) + override fun getItemViewType(position: Int): Int = when (history[position]) { + is HistoryWithdrawnEvent -> R.layout.history_withdrawn + else -> R.layout.history_row } - override fun getItemCount(): Int { - return myDataset.history.size + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HistoryEventViewHolder { + val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false) + return when (viewType) { + R.layout.history_withdrawn -> HistoryWithdrawnEventViewHolder(view) + else -> HistoryEventViewHolder(view) + } } - override fun onBindViewHolder(holder: MyViewHolder, position: Int) { - val h = myDataset.history[myDataset.history.size - position - 1] - val text = holder.rowView.findViewById<TextView>(R.id.history_text) - val subText = holder.rowView.findViewById<TextView>(R.id.history_subtext) - text.text = h.type - subText.text = h.timestamp.toString() + "\n" + h.detail.toString(1) + override fun getItemCount(): Int = history.size + + override fun onBindViewHolder(holder: HistoryEventViewHolder, position: Int) { + val event = history[position] + holder.bind(event) } - fun update(updatedHistory: HistoryResult) { - this.myDataset = updatedHistory + fun update(updatedHistory: History) { + this.history = updatedHistory this.notifyDataSetChanged() } - class MyViewHolder(val rowView: View) : RecyclerView.ViewHolder(rowView) +} + +internal open class HistoryEventViewHolder(protected val v: View) : ViewHolder(v) { + + protected val title: TextView = v.findViewById(R.id.title) + private val time: TextView = v.findViewById(R.id.time) + + @CallSuper + open fun bind(event: HistoryEvent) { + title.text = event::class.java.simpleName + time.text = getRelativeTime(event.timestamp.ms) + } + + private fun getRelativeTime(timestamp: Long): CharSequence { + val now = System.currentTimeMillis() + return getRelativeTimeSpanString(timestamp, now, MINUTE_IN_MILLIS, FORMAT_ABBREV_RELATIVE) + } + + protected fun getString(resId: Int) = v.context.getString(resId) + +} + +internal class HistoryWithdrawnEventViewHolder(v: View) : HistoryEventViewHolder(v) { + + private val amountWithdrawnRaw: TextView = v.findViewById(R.id.amountWithdrawnRaw) + private val amountWithdrawnEffective: TextView = v.findViewById(R.id.amountWithdrawnEffective) + + override fun bind(event: HistoryEvent) { + super.bind(event) + event as HistoryWithdrawnEvent + + title.text = getString(R.string.history_event_withdrawn) + amountWithdrawnRaw.text = event.amountWithdrawnRaw + amountWithdrawnEffective.text = event.amountWithdrawnEffective + } + } diff --git a/app/src/main/res/drawable/history_withdrawn.xml b/app/src/main/res/drawable/history_withdrawn.xml new file mode 100644 index 0000000..f6bb884 --- /dev/null +++ b/app/src/main/res/drawable/history_withdrawn.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#000" + android:pathData="M3 0V3H0V5H3V8H5V5H8V3H5V0H3M9 3V6H6V9H3V19C3 20.1 3.89 21 5 21H19C20.11 21 21 20.11 21 19V18H12C10.9 18 10 17.11 10 16V8C10 6.9 10.89 6 12 6H21V5C21 3.9 20.11 3 19 3H9M12 8V16H22V8H12M16 10.5C16.83 10.5 17.5 11.17 17.5 12C17.5 12.83 16.83 13.5 16 13.5C15.17 13.5 14.5 12.83 14.5 12C14.5 11.17 15.17 10.5 16 10.5Z" /> +</vector> diff --git a/app/src/main/res/layout/fragment_show_history.xml b/app/src/main/res/layout/fragment_show_history.xml index 4ed11ac..6265a50 100644 --- a/app/src/main/res/layout/fragment_show_history.xml +++ b/app/src/main/res/layout/fragment_show_history.xml @@ -3,8 +3,7 @@ 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_margin="15dp"> + android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" diff --git a/app/src/main/res/layout/history_row.xml b/app/src/main/res/layout/history_row.xml index 669fbd1..2ea6d9d 100644 --- a/app/src/main/res/layout/history_row.xml +++ b/app/src/main/res/layout/history_row.xml @@ -1,22 +1,24 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content"> + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_margin="15dp"> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:id="@+id/history_text" - android:textSize="24sp" tools:text="My History Event"> - </TextView> + <TextView + android:id="@+id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="24sp" + tools:text="My History Event"/> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:id="@+id/history_subtext" - android:textSize="14sp" tools:text="My History Event"> - </TextView> + <TextView + android:id="@+id/time" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="end" + android:textSize="14sp" + tools:text="3 days ago"/> </LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/history_withdrawn.xml b/app/src/main/res/layout/history_withdrawn.xml new file mode 100644 index 0000000..8290c37 --- /dev/null +++ b/app/src/main/res/layout/history_withdrawn.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginTop="8dp" + android:layout_marginEnd="16dp" + android:layout_marginBottom="8dp"> + + <ImageView + android:id="@+id/icon" + android:layout_width="32dp" + android:layout_height="32dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/history_withdrawn" + app:tint="?android:colorControlNormal" + tools:ignore="ContentDescription" /> + + <TextView + android:id="@+id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:text="@string/history_event_withdrawn" + android:textColor="?android:textColorPrimary" + android:textSize="20sp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintStart_toEndOf="@+id/icon" + app:layout_constraintTop_toTopOf="parent" /> + + <TextView + android:id="@+id/amountWithdrawnRaw" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + app:layout_constraintBottom_toBottomOf="@+id/amountWithdrawnEffective" + app:layout_constraintEnd_toStartOf="@+id/amountWithdrawnEffective" + app:layout_constraintHorizontal_bias="1.0" + app:layout_constraintStart_toEndOf="@+id/icon" + app:layout_constraintTop_toTopOf="@+id/amountWithdrawnEffective" + tools:text="TESTKUDOS:10" /> + + <TextView + android:id="@+id/amountWithdrawnEffective" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:textSize="16sp" + android:textColor="?android:textColorPrimary" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/title" + tools:text="TESTKUDOS:9.8" /> + + <TextView + android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:textSize="14sp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/amountWithdrawnEffective" + tools:text="23 min ago" /> + +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cfd2213..82b942b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -16,6 +16,8 @@ <string name="servicedesc">my service</string> <string name="aiddescription">my aid</string> + <string name="history_event_withdrawn">Withdraw</string> + <!-- TODO: Remove or change this placeholder text --> <string name="hello_blank_fragment">Hello blank fragment</string> </resources> |