Skip to content
This repository was archived by the owner on Jun 27, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,5 @@ dependencies {
annotationProcessor 'com.google.dagger:dagger-compiler:2.11'
provided 'org.glassfish:javax.annotation:10.0-b28'
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:cardview-v7:27.1.1'
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import android.view.View
import com.blogspot.e_kanivets.moneytracker.R
import com.blogspot.e_kanivets.moneytracker.activity.base.BaseFragment
import com.blogspot.e_kanivets.moneytracker.adapter.RecordAdapter
import com.blogspot.e_kanivets.moneytracker.controller.FormatController
import com.blogspot.e_kanivets.moneytracker.controller.data.AccountController
import com.blogspot.e_kanivets.moneytracker.controller.data.RecordController
import com.blogspot.e_kanivets.moneytracker.controller.data.TransferController
import com.blogspot.e_kanivets.moneytracker.entity.RecordItem
import com.blogspot.e_kanivets.moneytracker.entity.data.Account
import com.blogspot.e_kanivets.moneytracker.entity.data.Category
import com.blogspot.e_kanivets.moneytracker.entity.data.Record
import com.blogspot.e_kanivets.moneytracker.entity.data.Transfer
import com.blogspot.e_kanivets.moneytracker.util.RecordItemsBuilder
import kotlinx.android.synthetic.main.fragment_account_operations.*
import javax.inject.Inject

Expand All @@ -23,6 +26,8 @@ class AccountOperationsFragment : BaseFragment() {
internal lateinit var recordController: RecordController
@Inject
internal lateinit var transferController: TransferController
@Inject
internal lateinit var formatController: FormatController

private lateinit var account: Account

Expand All @@ -34,17 +39,17 @@ class AccountOperationsFragment : BaseFragment() {
}

override fun initViews(view: View) {
recyclerView.adapter = RecordAdapter(requireContext(), getRecords(), false, null)
recyclerView.adapter = RecordAdapter(requireContext(), getRecordItems(), false, null)
}

private fun getRecords(): List<Record> {
private fun getRecordItems(): List<RecordItem> {
val accountRecords = recordController.getRecordsForAccount(account)
val accountTransfers = transferController.getTransfersForAccount(account)

accountRecords += obtainRecordsFromTransfers(accountTransfers)
accountRecords.sortByDescending { it.time }

return accountRecords
return RecordItemsBuilder().getRecordItems(accountRecords)
}

private fun obtainRecordsFromTransfers(transfers: List<Transfer>): List<Record> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ private boolean addRecord() {
}

private void updateDateAndTime() {
tvDate.setText(formatController.formatDate(timestamp));
tvDate.setText(formatController.formatDateToNumber(timestamp));
tvTime.setText(formatController.formatTime(timestamp));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,20 @@ import com.blogspot.e_kanivets.moneytracker.controller.data.AccountController
import com.blogspot.e_kanivets.moneytracker.controller.data.ExchangeRateController
import com.blogspot.e_kanivets.moneytracker.controller.data.RecordController
import com.blogspot.e_kanivets.moneytracker.entity.Period
import com.blogspot.e_kanivets.moneytracker.entity.RecordItem
import com.blogspot.e_kanivets.moneytracker.entity.data.Record
import com.blogspot.e_kanivets.moneytracker.report.ReportMaker
import com.blogspot.e_kanivets.moneytracker.ui.AppRateDialog
import com.blogspot.e_kanivets.moneytracker.util.AnswersProxy
import com.blogspot.e_kanivets.moneytracker.util.RecordItemsBuilder
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.content_main.*
import javax.inject.Inject

class MainActivity : BaseDrawerActivity() {

private lateinit var recordList: List<Record>
private var recordItems: List<RecordItem> = listOf()
private lateinit var period: Period
private lateinit var recordAdapter: RecordAdapter

Expand Down Expand Up @@ -91,8 +94,7 @@ class MainActivity : BaseDrawerActivity() {
private fun editRecord(position: Int) {
AnswersProxy.get().logButton("Edit Record")

// Minus one because of list view's header view
val record = recordList[position - 1]
val record = recordList[position - 1 - getCountHeadersItems(position - 1)]
startAddRecordActivity(record, AddRecordActivity.Mode.MODE_EDIT, record.type)
}

Expand Down Expand Up @@ -134,17 +136,28 @@ class MainActivity : BaseDrawerActivity() {
override fun update() {
recordList = recordController.getRecordsForPeriod(period)
recordList = recordList.reversed()
recordItems = RecordItemsBuilder().getRecordItems(recordList)

val currency = currencyController.readDefaultCurrency()

val reportMaker = ReportMaker(rateController)
val report = reportMaker.getRecordReport(currency, period, recordList)

recordAdapter.setRecords(recordList, report, currency, reportMaker.currencyNeeded(currency, recordList))
recordAdapter.setRecords(recordItems, report, currency, reportMaker.currencyNeeded(currency, recordList))

fillDefaultAccount()
}

private fun getCountHeadersItems(position: Int): Int {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smart, but I would take one more look on the places where we use getCountHeadersItems. Probably we can get a record without this magic :)

var countHeadersItems = 0
for (inOfData in 0 until position) {
if (recordItems[inOfData] is RecordItem.Header) {
countHeadersItems++
}
}
return countHeadersItems
}

private fun showAppRateDialog() {
AnswersProxy.get().logEvent("Show App Rate Dialog")
val dialog = AppRateDialog(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import android.widget.TextView
import com.blogspot.e_kanivets.moneytracker.MtApp
import com.blogspot.e_kanivets.moneytracker.R
import com.blogspot.e_kanivets.moneytracker.controller.FormatController
import com.blogspot.e_kanivets.moneytracker.entity.data.Record
import com.blogspot.e_kanivets.moneytracker.entity.RecordItem
import com.blogspot.e_kanivets.moneytracker.report.record.IRecordReport
import com.blogspot.e_kanivets.moneytracker.ui.presenter.ShortSummaryPresenter
import kotlinx.android.synthetic.main.view_header_date.view.*
import kotlinx.android.synthetic.main.view_record.view.*
import kotlinx.android.synthetic.main.view_record.view.container
import kotlinx.android.synthetic.main.view_summary_records.view.*
import javax.inject.Inject

Expand All @@ -30,16 +32,16 @@ class RecordAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder> {
private var red: Int
private var green: Int

private var records: List<Record>
private var items: List<RecordItem>
private var context: Context

private var summaryPresenter: ShortSummaryPresenter
private var isHeaderViewNeeded: Boolean = false
private var headerViewHolder: HeaderViewHolder
private var isSummaryViewNeeded: Boolean = false

This comment was marked as resolved.

private var summaryViewHolder: SummaryViewHolder

constructor(context: Context, records: List<Record>, isHeaderViewNeeded: Boolean, itemClickListener: ((Int) -> Unit)?) {
constructor(context: Context, items: List<RecordItem>, isSummaryViewNeeded: Boolean, itemClickListener: ((Int) -> Unit)?) {
this.context = context
this.records = records
this.items = items

MtApp.get().appComponent.inject(this)

Expand All @@ -51,68 +53,71 @@ class RecordAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder> {
summaryPresenter = ShortSummaryPresenter(context)

this.itemClickListener = itemClickListener
this.isHeaderViewNeeded = isHeaderViewNeeded
this.isSummaryViewNeeded = isSummaryViewNeeded

headerViewHolder = HeaderViewHolder(LayoutInflater.from(context).inflate(R.layout.view_summary_records, null), itemClickListener)
summaryPresenter.create(true, headerViewHolder)
summaryViewHolder = SummaryViewHolder(LayoutInflater.from(context).inflate(R.layout.view_summary_records, null), itemClickListener)
summaryPresenter.create(true, summaryViewHolder)
}

override fun getItemCount() = records.size + if (isHeaderViewNeeded) 1 else 0
override fun getItemCount() = items.size + if (isSummaryViewNeeded) 1 else 0

override fun getItemViewType(position: Int): Int = if (position == 0 && isHeaderViewNeeded) {
override fun getItemViewType(position: Int): Int = if (position == 0 && isSummaryViewNeeded) {
TYPE_SUMMARY
} else if (items[position - if (isSummaryViewNeeded) 1 else 0] is RecordItem.Header) {
TYPE_HEADER
} else {
TYPE_ITEM
TYPE_RECORD
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
if (viewType == TYPE_HEADER) {
headerViewHolder
} else {
ViewHolder(LayoutInflater.from(context).inflate(R.layout.view_record, parent, false), itemClickListener)
when (viewType) {
TYPE_RECORD -> RecordViewHolder(LayoutInflater.from(context).inflate(R.layout.view_record, parent, false), itemClickListener)

This comment was marked as resolved.

TYPE_HEADER -> HeaderViewHolder(LayoutInflater.from(context).inflate(R.layout.view_header_date, parent, false))
else -> summaryViewHolder
}

override fun onBindViewHolder(rvViewHolder: RecyclerView.ViewHolder, position: Int) {
if (position == 0 && isHeaderViewNeeded) {
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
if (position == 0 && isSummaryViewNeeded) {
//adapter already bound to view
return
}

val viewHolder = rvViewHolder as ViewHolder
val record: Record = records[position - if (isHeaderViewNeeded) 1 else 0]
viewHolder.container.setBackgroundColor(if (record.isIncome) whiteGreen else whiteRed)
viewHolder.tvPrice.setTextColor(if (record.isIncome) green else red)

viewHolder.tvDateAndTime.text = formatController.formatDateAndTime(record.time)
val price = (if (record.isIncome) record.fullPrice else getNegative(record.fullPrice))
viewHolder.tvPrice.text = formatController.formatSignedAmount(price)
viewHolder.tvTitle.text = record.title
viewHolder.tvCategory.text = record.category?.name
viewHolder.tvCurrency.text = record.currency
if (viewHolder is RecordViewHolder) {
val record = items[position - if (isSummaryViewNeeded) 1 else 0] as RecordItem.Record
viewHolder.tvPrice.setTextColor(if (record.isIncome) green else red)

val price = (if (record.isIncome) record.fullPrice else getNegative(record.fullPrice))
viewHolder.tvPrice.text = formatController.formatSignedAmount(price)
viewHolder.tvTitle.text = record.title
viewHolder.tvCategory.text = record.categoryName
viewHolder.tvCurrency.text = record.currency
} else {
val headerViewHolder = viewHolder as HeaderViewHolder
val header = items[position - if (isSummaryViewNeeded) 1 else 0] as RecordItem.Header
headerViewHolder.tvDate.text = header.date
}
}

private fun getNegative(number: Double): Double {
return -1 * number
}

fun setRecords(recordsList: List<Record>, report: IRecordReport?, currency: String, ratesNeeded: List<String>) {
records = recordsList
fun setRecords(itemsList: List<RecordItem>, report: IRecordReport?, currency: String, ratesNeeded: List<String>) {
items = itemsList
summaryPresenter.update(report, currency, ratesNeeded)
notifyDataSetChanged()
}

class ViewHolder : RecyclerView.ViewHolder {
class RecordViewHolder : RecyclerView.ViewHolder {

var container: LinearLayout
var tvDateAndTime: TextView
var tvPrice: TextView
var tvTitle: TextView
var tvCategory: TextView
var tvCurrency: TextView

constructor(view: View, itemClickListener: ((Int) -> Unit)?) : super(view) {
container = view.container
tvDateAndTime = view.tvDateAndTime
tvPrice = view.tvPrice
tvTitle = view.tvTitle
tvCategory = view.tvCategory
Expand All @@ -124,7 +129,11 @@ class RecordAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder> {
}
}

class HeaderViewHolder : RecyclerView.ViewHolder, ShortSummaryPresenter.SummaryViewInterface {
class HeaderViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val tvDate: TextView = view.tvDate
}

class SummaryViewHolder : RecyclerView.ViewHolder, ShortSummaryPresenter.SummaryViewInterface {

private var tvPeriod: TextView
private var tvTotalIncome: TextView
Expand All @@ -145,15 +154,15 @@ class RecordAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder> {
tvTotalExpense = view.tvTotalExpense
tvTotal = view.tvTotal

view.setOnClickListener {
view.cvSummary.setOnClickListener {
itemClickListener?.invoke(0)
}
}
}

companion object {

private const val TYPE_HEADER = 0
private const val TYPE_ITEM = 1
private const val TYPE_SUMMARY = 0
private const val TYPE_HEADER = 1
private const val TYPE_RECORD = 2
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ public class FormatController {
public static final String PRECISION_NONE = "precision_none";

@SuppressLint("SimpleDateFormat")
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat shortDateFormat = new SimpleDateFormat("yyyy-MM-dd");
@SuppressLint("SimpleDateFormat")
private static final SimpleDateFormat fullDateFormat = new SimpleDateFormat("d MMMM yyyy");
@SuppressLint("SimpleDateFormat")
private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
@SuppressLint("SimpleDateFormat")
Expand Down Expand Up @@ -72,8 +74,12 @@ public String formatExpense(double amount, String currency) {
return (amount > 0 ? "+ " : "- ") + formatAmount(Math.abs(amount)) + " " + currency;
}

public String formatDate(long timestamp) {
return dateFormat.format(new Date(timestamp));
public String formatDateToNumber(long timestamp) {

This comment was marked as resolved.

return shortDateFormat.format(new Date(timestamp));
}

public String formatDateToString(long timestamp) {
return fullDateFormat.format(new Date(timestamp));
}

public String formatTime(long timestamp) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.blogspot.e_kanivets.moneytracker.ui.PeriodSpinner;
import com.blogspot.e_kanivets.moneytracker.ui.presenter.AccountsSummaryPresenter;
import com.blogspot.e_kanivets.moneytracker.ui.presenter.ShortSummaryPresenter;
import com.blogspot.e_kanivets.moneytracker.util.RecordItemsBuilder;

import javax.inject.Singleton;

Expand Down Expand Up @@ -87,4 +88,6 @@ public interface AppComponent {
void inject(EditAccountFragment editAccountFragment);

void inject(AccountOperationsFragment accountRecordsFragment);

void inject(RecordItemsBuilder recordItemsBuilder);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.blogspot.e_kanivets.moneytracker.entity

sealed class RecordItem {

data class Header(val date: String) : RecordItem()

data class Record(val title: String, val categoryName: String, val fullPrice: Double, val currency: String, val isIncome: Boolean) : RecordItem() {
constructor(record: com.blogspot.e_kanivets.moneytracker.entity.data.Record) : this(record.title, record.category?.name?.toString().orEmpty(), record.fullPrice, record.currency, record.isIncome)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ public ShortSummaryPresenter(Context context) {
green = context.getResources().getColor(R.color.green);
}

public View create(boolean shortSummary, RecordAdapter.HeaderViewHolder mainViewHolder) {
public View create(boolean shortSummary, RecordAdapter.SummaryViewHolder mainViewHolder) {
view = layoutInflater.inflate(R.layout.view_summary_records, null);
view.findViewById(R.id.iv_more).setVisibility(shortSummary ? View.VISIBLE : View.INVISIBLE);

view.setEnabled(false);
view.findViewById(R.id.lvSummary).setClickable(false);
view.findViewById(R.id.cvSummary).setClickable(true);
view.setTag(mainViewHolder != null ? mainViewHolder : new ViewHolder(view));

return view;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.blogspot.e_kanivets.moneytracker.util

import com.blogspot.e_kanivets.moneytracker.MtApp
import com.blogspot.e_kanivets.moneytracker.controller.FormatController
import com.blogspot.e_kanivets.moneytracker.entity.RecordItem
import com.blogspot.e_kanivets.moneytracker.entity.data.Record
import javax.inject.Inject

class RecordItemsBuilder {

@Inject
lateinit var formatController: FormatController

constructor() {
MtApp.get().appComponent.inject(this)
}

fun getRecordItems(recordList: List<Record>): List<RecordItem> {
val recordItems: MutableList<RecordItem> = mutableListOf()

var lastDate: String? = null
for (record in recordList) {
if (formatController.formatDateToString(record.time) != lastDate) {
lastDate = formatController.formatDateToString(record.time)
recordItems.add(RecordItem.Header(lastDate))
}

recordItems.add(RecordItem.Record(record))
}

return recordItems
}

}
Loading