diff --git a/app/build.gradle b/app/build.gradle
index 293cfbb..1eac5f3 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -18,15 +18,15 @@ repositories {
}
android {
- compileSdkVersion 27
+ compileSdkVersion 29
buildToolsVersion '27.0.3'
defaultConfig {
applicationId 'com.blogspot.e_kanivets.moneytracker'
- minSdkVersion 17
- targetSdkVersion 26
+ minSdkVersion 21
+ targetSdkVersion 29
- versionCode 31
- versionName '2.0.1'
+ versionCode 32
+ versionName '2.1.0'
}
signingConfigs {
releaseConfig {
@@ -99,4 +99,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'
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0b50798..26d811e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,9 +2,6 @@
-
-
-
+ android:windowSoftInputMode="adjustResize" />
-
-
+
+
+
+
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/ReportActivity.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/ReportActivity.java
deleted file mode 100644
index 667806e..0000000
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/ReportActivity.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package com.blogspot.e_kanivets.moneytracker.activity;
-
-import android.support.v7.widget.AppCompatSpinner;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.ExpandableListView;
-
-import com.blogspot.e_kanivets.moneytracker.R;
-import com.blogspot.e_kanivets.moneytracker.activity.base.BaseBackActivity;
-import com.blogspot.e_kanivets.moneytracker.adapter.ExpandableListReportAdapter;
-import com.blogspot.e_kanivets.moneytracker.controller.CurrencyController;
-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.data.Record;
-import com.blogspot.e_kanivets.moneytracker.report.record.RecordReportConverter;
-import com.blogspot.e_kanivets.moneytracker.report.ReportMaker;
-import com.blogspot.e_kanivets.moneytracker.report.record.IRecordReport;
-import com.blogspot.e_kanivets.moneytracker.ui.presenter.ShortSummaryPresenter;
-
-import java.util.List;
-
-import javax.inject.Inject;
-
-import butterknife.BindView;
-
-public class ReportActivity extends BaseBackActivity {
- @SuppressWarnings("unused")
- private static final String TAG = "ReportActivity";
-
- public static final String KEY_PERIOD = "key_period";
-
- @Inject
- RecordController recordController;
- @Inject
- ExchangeRateController rateController;
- @Inject
- CurrencyController currencyController;
-
- private List recordList;
- private Period period;
-
- private ShortSummaryPresenter shortSummaryPresenter;
-
- @BindView(R.id.spinner_currency)
- AppCompatSpinner spinnerCurrency;
- @BindView(R.id.exp_list_view)
- ExpandableListView expandableListView;
-
- @Override
- protected int getContentViewId() {
- return R.layout.activity_report;
- }
-
- @SuppressWarnings("RedundantIfStatement")
- @Override
- protected boolean initData() {
- super.initData();
- getAppComponent().inject(ReportActivity.this);
-
- period = getIntent().getParcelableExtra(KEY_PERIOD);
- if (period == null) return false;
-
- recordList = recordController.getRecordsForPeriod(period);
-
- return true;
- }
-
- @Override
- protected void initViews() {
- super.initViews();
-
- initSpinnerCurrency();
-
- shortSummaryPresenter = new ShortSummaryPresenter(ReportActivity.this);
- expandableListView.addHeaderView(shortSummaryPresenter.create(false, null));
- }
-
- private void update(String currency) {
- ReportMaker reportMaker = new ReportMaker(rateController);
- IRecordReport report = reportMaker.getRecordReport(currency, period, recordList);
-
- ExpandableListReportAdapter adapter = null;
-
- if (report != null) {
- RecordReportConverter recordReportConverter = new RecordReportConverter(report);
- adapter = new ExpandableListReportAdapter(ReportActivity.this, recordReportConverter);
- }
-
- expandableListView.setAdapter(adapter);
- shortSummaryPresenter.update(report, currency, reportMaker.currencyNeeded(currency, recordList));
- }
-
- private void initSpinnerCurrency() {
- List currencyList = currencyController.readAll();
-
- spinnerCurrency.setAdapter(new ArrayAdapter<>(ReportActivity.this,
- R.layout.view_spinner_item, currencyList));
- spinnerCurrency.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView> parent, View view, int position, long id) {
- update((String) spinnerCurrency.getSelectedItem());
- }
-
- @Override
- public void onNothingSelected(AdapterView> parent) {
-
- }
- });
-
- String currency = currencyController.readDefaultCurrency();
-
- for (int i = 0; i < currencyList.size(); i++) {
- if (currency.equals(currencyList.get(i))) {
- spinnerCurrency.setSelection(i);
- break;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/ReportActivity.kt b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/ReportActivity.kt
new file mode 100644
index 0000000..a8cc845
--- /dev/null
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/ReportActivity.kt
@@ -0,0 +1,136 @@
+package com.blogspot.e_kanivets.moneytracker.activity
+
+import android.view.View
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import com.blogspot.e_kanivets.moneytracker.MtApp
+import com.blogspot.e_kanivets.moneytracker.R
+import com.blogspot.e_kanivets.moneytracker.activity.base.BaseBackActivity
+import com.blogspot.e_kanivets.moneytracker.adapter.RecordReportAdapter
+import com.blogspot.e_kanivets.moneytracker.controller.CurrencyController
+import com.blogspot.e_kanivets.moneytracker.controller.FormatController
+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.RecordReportItem
+import com.blogspot.e_kanivets.moneytracker.entity.data.Record
+import com.blogspot.e_kanivets.moneytracker.report.ReportMaker
+import com.blogspot.e_kanivets.moneytracker.report.record.IRecordReport
+import com.blogspot.e_kanivets.moneytracker.ui.presenter.ShortSummaryPresenter
+import kotlinx.android.synthetic.main.activity_report.*
+import java.util.*
+import javax.inject.Inject
+
+class ReportActivity : BaseBackActivity() {
+
+ @Inject
+ lateinit var recordController: RecordController
+ @Inject
+ lateinit var rateController: ExchangeRateController
+ @Inject
+ lateinit var currencyController: CurrencyController
+
+ private var recordList: List = listOf()
+ private var period: Period? = null
+ private lateinit var adapter: RecordReportAdapter
+ private lateinit var recordReportConverter: RecordReportConverter
+
+ private lateinit var shortSummaryPresenter: ShortSummaryPresenter
+
+ override fun getContentViewId() = R.layout.activity_report
+
+ override fun initData(): Boolean {
+ super.initData()
+ appComponent.inject(this)
+
+ period = intent.getParcelableExtra(KEY_PERIOD)
+ if (period == null) return false
+
+ recordList = recordController.getRecordsForPeriod(period)
+ shortSummaryPresenter = ShortSummaryPresenter(this)
+ adapter = RecordReportAdapter(mutableListOf(), hashMapOf(), this)
+ recordReportConverter = RecordReportConverter()
+
+ return true
+ }
+
+ override fun initViews() {
+ super.initViews()
+
+ initSpinnerCurrency()
+
+ adapter.setSummaryView(shortSummaryPresenter.create(false, null))
+ recyclerView.adapter = adapter
+ }
+
+ private fun update(currency: String) {
+ val reportMaker = ReportMaker(rateController)
+ val report = reportMaker.getRecordReport(currency, period, recordList)
+
+ adapter.setData(recordReportConverter.getItemsFromReport(report), recordReportConverter.getDataFromReport(report))
+ shortSummaryPresenter.update(report, currency, reportMaker.currencyNeeded(currency, recordList))
+ }
+
+ private fun initSpinnerCurrency() {
+ val currencyList = currencyController.readAll()
+
+ spinnerCurrency.adapter = ArrayAdapter(this, R.layout.view_spinner_item, currencyList)
+ spinnerCurrency.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) =
+ update(spinnerCurrency.selectedItem.toString())
+
+ override fun onNothingSelected(p0: AdapterView<*>?) {}
+ }
+
+ val currency = currencyController.readDefaultCurrency()
+
+ spinnerCurrency.setSelection(currencyList.indexOf(currency))
+ }
+
+ class RecordReportConverter {
+
+ @Inject
+ lateinit var formatController: FormatController
+
+ init {
+ MtApp.get().appComponent.inject(this)
+ }
+
+ fun getItemsFromReport(report: IRecordReport?): MutableList {
+ val items: MutableList = mutableListOf()
+
+ if (report == null) return items
+
+ for (categoryRecord in report.summary) {
+ val parentRow = RecordReportItem.ParentRow(categoryRecord.title, formatController.formatSignedAmount(categoryRecord.amount), false)
+ items.add(parentRow)
+ }
+ return items
+ }
+
+ fun getDataFromReport(report: IRecordReport?): HashMap> {
+ val data: HashMap> = hashMapOf()
+
+ if (report == null) return data
+
+ for (categoryRecord in report.summary) {
+ val parentRow = RecordReportItem.ParentRow(categoryRecord.title, formatController.formatSignedAmount(categoryRecord.amount), false)
+ val childRows: MutableList = mutableListOf()
+
+ for (summaryRecord in categoryRecord.summaryRecordList) {
+ val childRow = RecordReportItem.ChildRow(summaryRecord.title, formatController.formatSignedAmount(summaryRecord.amount))
+ childRows.add(childRow)
+ }
+
+ data[parentRow] = childRows
+ }
+ return data
+ }
+
+ }
+
+ companion object {
+
+ const val KEY_PERIOD = "key_period"
+ }
+}
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/SettingsActivity.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/SettingsActivity.java
index eac0415..ee71bfc 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/SettingsActivity.java
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/SettingsActivity.java
@@ -32,7 +32,7 @@ public class SettingsActivity extends BaseBackActivity {
super.initViews();
// Display the fragment as the main content.
- getFragmentManager().beginTransaction().replace(R.id.content, new SettingsFragment()).commit();
+ getFragmentManager().beginTransaction().replace(R.id.contentView, new SettingsFragment()).commit();
}
public static class SettingsFragment extends PreferenceFragment {
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/AccountsActivity.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/AccountsActivity.java
index bbc3692..aa8c50f 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/AccountsActivity.java
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/AccountsActivity.java
@@ -104,9 +104,6 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
break;
case REQUEST_TRANSFER:
- update();
- setResult(RESULT_OK);
- break;
case REQUEST_EDIT_ACCOUNT:
update();
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/AddAccountActivity.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/AddAccountActivity.java
index c61b2b8..706be80 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/AddAccountActivity.java
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/AddAccountActivity.java
@@ -33,9 +33,9 @@ public class AddAccountActivity extends BaseBackActivity {
private IValidator accountValidator;
- @BindView(R.id.content)
+ @BindView(R.id.contentView)
View contentView;
- @BindView(R.id.et_title)
+ @BindView(R.id.etTitle)
EditText etTitle;
@BindView(R.id.et_init_sum)
EditText etInitSum;
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/TransferActivity.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/TransferActivity.java
index f44615b..8ccf29e 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/TransferActivity.java
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/TransferActivity.java
@@ -37,7 +37,7 @@ public class TransferActivity extends BaseBackActivity {
private List accountList;
- @BindView(R.id.content)
+ @BindView(R.id.contentView)
View contentView;
@BindView(R.id.spinner_from)
AppCompatSpinner spinnerFrom;
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/edit/fragment/AccountOperationsFragment.kt b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/edit/fragment/AccountOperationsFragment.kt
index 93d7726..0de51ed 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/edit/fragment/AccountOperationsFragment.kt
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/account/edit/fragment/AccountOperationsFragment.kt
@@ -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
@@ -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
@@ -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)
}
- private fun getRecords(): List {
+ private fun getRecordItems(): List {
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): List {
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/exchange_rate/AddExchangeRateActivity.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/exchange_rate/AddExchangeRateActivity.java
index 47d3f31..bad88bc 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/exchange_rate/AddExchangeRateActivity.java
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/exchange_rate/AddExchangeRateActivity.java
@@ -44,7 +44,7 @@ public class AddExchangeRateActivity extends BaseBackActivity {
@Nullable
private ExchangeRatePair exchangeRatePair;
- @BindView(R.id.content)
+ @BindView(R.id.contentView)
View contentView;
@BindView(R.id.spinner_from_currency)
AppCompatSpinner spinnerFromCurrency;
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/record/AddRecordActivity.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/record/AddRecordActivity.java
deleted file mode 100644
index 6081301..0000000
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/record/AddRecordActivity.java
+++ /dev/null
@@ -1,383 +0,0 @@
-package com.blogspot.e_kanivets.moneytracker.activity.record;
-
-import android.annotation.SuppressLint;
-import android.app.DatePickerDialog;
-import android.app.TimePickerDialog;
-import android.support.annotation.Nullable;
-import android.support.v7.widget.AppCompatSpinner;
-import android.text.InputFilter;
-import android.text.Spanned;
-import android.text.format.DateFormat;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.inputmethod.EditorInfo;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.AutoCompleteTextView;
-import android.widget.DatePicker;
-import android.widget.EditText;
-import android.widget.TextView;
-import android.widget.TimePicker;
-
-import com.blogspot.e_kanivets.moneytracker.R;
-import com.blogspot.e_kanivets.moneytracker.activity.base.BaseBackActivity;
-import com.blogspot.e_kanivets.moneytracker.adapter.CategoryAutoCompleteAdapter;
-import com.blogspot.e_kanivets.moneytracker.controller.FormatController;
-import com.blogspot.e_kanivets.moneytracker.controller.PreferenceController;
-import com.blogspot.e_kanivets.moneytracker.controller.data.AccountController;
-import com.blogspot.e_kanivets.moneytracker.controller.data.CategoryController;
-import com.blogspot.e_kanivets.moneytracker.controller.data.RecordController;
-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.ui.AddRecordUiDecorator;
-import com.blogspot.e_kanivets.moneytracker.util.CrashlyticsProxy;
-import com.blogspot.e_kanivets.moneytracker.util.CategoryAutoCompleter;
-import com.blogspot.e_kanivets.moneytracker.util.validator.IValidator;
-import com.blogspot.e_kanivets.moneytracker.util.validator.RecordValidator;
-
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import butterknife.BindView;
-import butterknife.OnClick;
-
-/**
- * Created on 1/26/16.
- *
- * @author Evgenii Kanivets
- */
-public class AddRecordActivity extends BaseBackActivity {
- @SuppressWarnings("unused")
- private static final String TAG = "AddRecordActivity";
-
- public static final String KEY_RECORD = "key_record";
- public static final String KEY_MODE = "key_mode";
- public static final String KEY_TYPE = "key_type";
-
- @Nullable
- private Record record;
- private Mode mode;
- private int type;
-
- private List accountList;
- private long timestamp;
-
- @Inject
- CategoryController categoryController;
- @Inject
- RecordController recordController;
- @Inject
- AccountController accountController;
- @Inject
- FormatController formatController;
- @Inject
- PreferenceController preferenceController;
-
- private IValidator recordValidator;
- private AddRecordUiDecorator uiDecorator;
- private CategoryAutoCompleter autoCompleter;
-
- @BindView(R.id.content)
- View contentView;
- @BindView(R.id.tv_date)
- TextView tvDate;
- @BindView(R.id.tv_time)
- TextView tvTime;
- @BindView(R.id.et_title)
- EditText etTitle;
- @BindView(R.id.et_category)
- AutoCompleteTextView etCategory;
- @BindView(R.id.et_price)
- EditText etPrice;
- @BindView(R.id.spinner_account)
- AppCompatSpinner spinnerAccount;
-
- @Override
- protected int getContentViewId() {
- return R.layout.activity_add_record;
- }
-
- @Override
- protected boolean initData() {
- super.initData();
- getAppComponent().inject(AddRecordActivity.this);
-
- uiDecorator = new AddRecordUiDecorator(AddRecordActivity.this);
-
- record = getIntent().getParcelableExtra(KEY_RECORD);
- mode = (Mode) getIntent().getSerializableExtra(KEY_MODE);
- type = getIntent().getIntExtra(KEY_TYPE, -1);
- accountList = accountController.readActiveAccounts();
-
- if (mode == Mode.MODE_EDIT && record != null) timestamp = record.getTime();
- else timestamp = new Date().getTime();
-
- return mode != null && (type == Record.TYPE_INCOME || type == Record.TYPE_EXPENSE)
- && (!mode.equals(Mode.MODE_EDIT) || record != null);
- }
-
- @SuppressWarnings("deprecation")
- @SuppressLint("SetTextI18n")
- @Override
- protected void initViews() {
- super.initViews();
-
- recordValidator = new RecordValidator(AddRecordActivity.this, contentView);
- autoCompleter = new CategoryAutoCompleter(categoryController, preferenceController);
-
- // Add texts to dialog if it's edit dialog
- if (mode == Mode.MODE_EDIT) {
- etTitle.setText(record.getTitle());
- if (record.getCategory() != null) etCategory.setText(record.getCategory().getName());
- etPrice.setText(formatController.formatPrecisionNone(record.getFullPrice()));
- }
-
- uiDecorator.decorateActionBar(getSupportActionBar(), mode, type);
- presentSpinnerAccount();
-
-
- final CategoryAutoCompleteAdapter categoryAutoCompleteAdapter = new CategoryAutoCompleteAdapter(
- AddRecordActivity.this, R.layout.view_category_item, autoCompleter);
- etCategory.setAdapter(categoryAutoCompleteAdapter);
- etCategory.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView> parent, View view, int position, long id) {
- etCategory.setText((String) parent.getAdapter().getItem(position));
- etCategory.setSelection(etCategory.getText().length());
- }
- });
- etCategory.setOnEditorActionListener(new TextView.OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- if (actionId == EditorInfo.IME_ACTION_DONE) tryRecord();
- return false;
- }
- });
- etCategory.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View view, boolean hasFocus) {
- if (hasFocus && etCategory.getText().toString().trim().isEmpty()) {
- String title = etTitle.getText().toString().trim();
- String prediction = autoCompleter.completeByRecordTitle(title);
- if (prediction != null) {
- etCategory.setAdapter(null);
- etCategory.setText(prediction);
- etCategory.selectAll();
- etCategory.setAdapter(categoryAutoCompleteAdapter);
- }
- }
- }
- });
-
- // Restrict ';' for input, because it's used as delimiter when exporting
- etTitle.setFilters(new InputFilter[]{new SemicolonInputFilter()});
- etCategory.setFilters(new InputFilter[]{new SemicolonInputFilter()});
-
- updateDateAndTime();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_add_record, menu);
- return true;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- switch (mode) {
- case MODE_ADD:
- menu.removeItem(R.id.action_delete);
- break;
-
- default:
- break;
- }
-
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_done:
- tryRecord();
- return true;
-
- case R.id.action_delete:
- if (recordController.delete(record)) {
- setResult(RESULT_OK);
- finish();
- }
- return true;
-
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- @OnClick(R.id.tv_date)
- public void selectDate() {
- CrashlyticsProxy.get().logButton("Select Date");
- Calendar calendar = Calendar.getInstance();
- calendar.setTimeInMillis(timestamp);
- DatePickerDialog dialog = new DatePickerDialog(AddRecordActivity.this, uiDecorator.getTheme(type),
- new DatePickerDialog.OnDateSetListener() {
- @Override
- public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
- Calendar calendar = Calendar.getInstance();
- calendar.setTimeInMillis(timestamp);
- calendar.set(Calendar.YEAR, year);
- calendar.set(Calendar.MONTH, monthOfYear);
- calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
-
- if (calendar.getTimeInMillis() < new Date().getTime()) {
- timestamp = calendar.getTimeInMillis();
- updateDateAndTime();
- } else {
- showToast(R.string.record_in_future);
- }
- }
- }, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
- calendar.get(Calendar.DAY_OF_MONTH));
- dialog.show();
- }
-
- @OnClick(R.id.tv_time)
- public void selectTime() {
- CrashlyticsProxy.get().logButton("Show Time");
- Calendar calendar = Calendar.getInstance();
- calendar.setTimeInMillis(timestamp);
- TimePickerDialog dialog = new TimePickerDialog(AddRecordActivity.this, uiDecorator.getTheme(type),
- new TimePickerDialog.OnTimeSetListener() {
- @Override
- public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
- Calendar calendar = Calendar.getInstance();
- calendar.setTimeInMillis(timestamp);
- calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
- calendar.set(Calendar.MINUTE, minute);
-
- if (calendar.getTimeInMillis() < new Date().getTime()) {
- timestamp = calendar.getTimeInMillis();
- updateDateAndTime();
- } else {
- showToast(R.string.record_in_future);
- }
- }
- }, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE),
- DateFormat.is24HourFormat(AddRecordActivity.this));
- dialog.show();
- }
-
- private void presentSpinnerAccount() {
- List accounts = new ArrayList<>();
- for (Account account : accountList) {
- accounts.add(account.getTitle());
- }
-
- int selectedAccountIndex = -1;
-
- if (mode == Mode.MODE_EDIT) {
- if (record != null && record.getAccount() != null) {
- for (int i = 0; i < accountList.size(); i++) {
- Account account = accountList.get(i);
- if (account.getId() == record.getAccount().getId()) selectedAccountIndex = i;
- }
- }
- } else if (mode == Mode.MODE_ADD) {
- Account defaultAccount = accountController.readDefaultAccount();
- if (defaultAccount != null) {
- for (int i = 0; i < accountList.size(); i++) {
- Account account = accountList.get(i);
- if (account.getId() == defaultAccount.getId()) selectedAccountIndex = i;
- }
- }
- }
-
- if (selectedAccountIndex == -1) {
- selectedAccountIndex = 0;
- spinnerAccount.setEnabled(false);
-
- if (accounts.size() == 0) {
- accounts.add(getString(R.string.none));
- } else {
- accounts.add(getString(R.string.account_was_removed));
- }
- }
-
- spinnerAccount.setAdapter(new ArrayAdapter<>(AddRecordActivity.this,
- R.layout.view_spinner_item, accounts));
- spinnerAccount.setSelection(selectedAccountIndex);
- }
-
- private void tryRecord() {
- CrashlyticsProxy.get().logButton("Done Record");
- if (addRecord()) {
- CrashlyticsProxy.get().logEvent("Done Record");
- setResult(RESULT_OK);
- finish();
- }
- }
-
- @SuppressWarnings("SimplifiableIfStatement")
- private boolean addRecord() {
- if (recordValidator.validate()) {
- long now = new Date().getTime();
- if (timestamp > now) {
- showToast(R.string.record_in_future);
- return false;
- }
-
- String title = etTitle.getText().toString().trim();
- String category = etCategory.getText().toString().trim();
- double price = Double.parseDouble(etPrice.getText().toString());
- Account account = accountList.get(spinnerAccount.getSelectedItemPosition());
-
- if (title.isEmpty()) {
- title = category;
- }
-
- Record newRecord = null;
-
- if (mode == Mode.MODE_ADD) {
- newRecord = recordController.create(new Record(timestamp, type, title,
- new Category(category), price, account, account.getCurrency()));
- } else if (mode == Mode.MODE_EDIT) {
- long recordId = record == null ? -1 : record.getId();
- newRecord = recordController.update(new Record(recordId, timestamp, type, title,
- new Category(category), price, account, account.getCurrency()));
- }
-
- if (newRecord == null) {
- return false;
- } else {
- autoCompleter.addRecordTitleCategoryPair(title, category);
- return true;
- }
- } else {
- return false;
- }
- }
-
- private void updateDateAndTime() {
- tvDate.setText(formatController.formatDate(timestamp));
- tvTime.setText(formatController.formatTime(timestamp));
- }
-
- public enum Mode {MODE_ADD, MODE_EDIT}
-
- private static class SemicolonInputFilter implements InputFilter {
-
- @Override
- public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
- if (source != null && ";".equals(source.toString())) return "";
- else return null;
- }
- }
-}
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/record/AddRecordActivity.kt b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/record/AddRecordActivity.kt
new file mode 100644
index 0000000..39b87f4
--- /dev/null
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/record/AddRecordActivity.kt
@@ -0,0 +1,306 @@
+package com.blogspot.e_kanivets.moneytracker.activity.record
+
+import android.annotation.SuppressLint
+import android.app.Activity
+import android.app.DatePickerDialog
+import android.app.TimePickerDialog
+import android.content.res.ColorStateList
+import android.support.v4.content.ContextCompat
+import android.text.InputFilter
+import android.text.Spanned
+import android.text.format.DateFormat
+import android.view.Menu
+import android.view.MenuItem
+import android.view.View
+import android.view.inputmethod.EditorInfo
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import com.blogspot.e_kanivets.moneytracker.R
+import com.blogspot.e_kanivets.moneytracker.activity.base.BaseBackActivity
+import com.blogspot.e_kanivets.moneytracker.adapter.CategoryAutoCompleteAdapter
+import com.blogspot.e_kanivets.moneytracker.controller.FormatController
+import com.blogspot.e_kanivets.moneytracker.controller.PreferenceController
+import com.blogspot.e_kanivets.moneytracker.controller.data.AccountController
+import com.blogspot.e_kanivets.moneytracker.controller.data.CategoryController
+import com.blogspot.e_kanivets.moneytracker.controller.data.RecordController
+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.ui.AddRecordUiDecorator
+import com.blogspot.e_kanivets.moneytracker.util.CategoryAutoCompleter
+import com.blogspot.e_kanivets.moneytracker.util.CrashlyticsProxy
+import com.blogspot.e_kanivets.moneytracker.util.validator.IValidator
+import com.blogspot.e_kanivets.moneytracker.util.validator.RecordValidator
+import kotlinx.android.synthetic.main.activity_add_record.*
+import kotlinx.android.synthetic.main.content_add_record.*
+import java.util.*
+import javax.inject.Inject
+
+class AddRecordActivity : BaseBackActivity() {
+
+ private var record: Record? = null
+ private var mode: Mode? = null
+ private var type: Int = 0
+
+ private var accountList: List = listOf()
+ private var timestamp: Long = 0
+
+ @Inject
+ lateinit var categoryController: CategoryController
+ @Inject
+ lateinit var recordController: RecordController
+ @Inject
+ lateinit var accountController: AccountController
+ @Inject
+ lateinit var formatController: FormatController
+ @Inject
+ lateinit var preferenceController: PreferenceController
+
+ private lateinit var recordValidator: IValidator
+ private lateinit var uiDecorator: AddRecordUiDecorator
+ private lateinit var autoCompleter: CategoryAutoCompleter
+
+ override fun getContentViewId() = R.layout.activity_add_record
+
+
+ override fun initData(): Boolean {
+ super.initData()
+ appComponent.inject(this)
+
+ record = intent.getParcelableExtra(KEY_RECORD)
+ mode = intent.getSerializableExtra(KEY_MODE) as Mode
+ type = intent.getIntExtra(KEY_TYPE, -1)
+ accountList = accountController.readActiveAccounts()
+
+ timestamp = record?.time ?: Date().time
+
+ return (mode != null && (type == Record.TYPE_INCOME || type == Record.TYPE_EXPENSE)
+ && ((mode == Mode.MODE_EDIT && record != null) || (mode == Mode.MODE_ADD && record == null)))
+ }
+
+ @SuppressLint("SetTextI18n")
+ override fun initViews() {
+ super.initViews()
+
+ recordValidator = RecordValidator(this, contentView)
+ autoCompleter = CategoryAutoCompleter(categoryController, preferenceController)
+ uiDecorator = AddRecordUiDecorator(this)
+
+ uiDecorator.decorateActionBar(supportActionBar, mode, type)
+
+ if (mode == Mode.MODE_EDIT) {
+ record?.let { record ->
+ etTitle.setText(record.title)
+ etCategory.setText(record.category?.name.orEmpty())
+ etPrice.setText(formatController.formatPrecisionNone(record.fullPrice))
+ }
+ }
+
+ initCategoryAutocomplete()
+ presentSpinnerAccount()
+
+ // Restrict ';' for input, because it's used as delimiter when exporting
+ etTitle.filters = arrayOf(SemicolonInputFilter())
+ etCategory.filters = arrayOf(SemicolonInputFilter())
+
+ tvDate.setOnClickListener { selectDate() }
+ tvTime.setOnClickListener { selectTime() }
+
+ if (type == Record.TYPE_EXPENSE) {
+ fabDone.backgroundTintList = (getColorForFab(R.color.red_light))
+ } else {
+ fabDone.backgroundTintList = (getColorForFab(R.color.green_light))
+ }
+
+ fabDone.setOnClickListener { tryRecord() }
+
+ updateDateAndTime()
+ }
+
+ private fun getColorForFab(color: Int): ColorStateList {
+ return ColorStateList.valueOf(ContextCompat.getColor(this, color))
+ }
+
+ private fun initCategoryAutocomplete() {
+ val categoryAutoCompleteAdapter = CategoryAutoCompleteAdapter(
+ this, R.layout.view_category_item, autoCompleter)
+ etCategory.setAdapter(categoryAutoCompleteAdapter)
+ etCategory.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
+ etCategory.setText(parent.adapter.getItem(position) as String)
+ etCategory.setSelection(etCategory.text.length)
+ }
+ etCategory.setOnEditorActionListener { v, actionId, event ->
+ if (actionId == EditorInfo.IME_ACTION_DONE) tryRecord()
+ false
+ }
+ etCategory.onFocusChangeListener = View.OnFocusChangeListener { view, hasFocus ->
+ if (hasFocus && etCategory.text.toString().trim().isEmpty()) {
+ val title = etTitle.text.toString().trim()
+ autoCompleter.completeByRecordTitle(title)?.let { prediction ->
+ etCategory.setText(prediction)
+ etCategory.selectAll()
+ }
+ }
+ }
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ menuInflater.inflate(R.menu.menu_add_record, menu)
+ return true
+ }
+
+ override fun onPrepareOptionsMenu(menu: Menu): Boolean {
+ when (mode) {
+ Mode.MODE_ADD -> menu.removeItem(R.id.action_delete)
+ else -> {
+ }
+ }
+
+ return true
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ return when (item.itemId) {
+ R.id.action_delete -> {
+ if (recordController.delete(record)) {
+ setResult(Activity.RESULT_OK)
+ finish()
+ }
+ true
+ }
+
+ else -> super.onOptionsItemSelected(item)
+ }
+ }
+
+ private fun selectDate() {
+ CrashlyticsProxy.get().logButton("Select Date")
+ val calendar = Calendar.getInstance()
+ calendar.timeInMillis = timestamp
+ val dialog = DatePickerDialog(this, uiDecorator.getTheme(type),
+ DatePickerDialog.OnDateSetListener { view, year, monthOfYear, dayOfMonth ->
+ val newCalendar = Calendar.getInstance()
+ newCalendar.timeInMillis = timestamp
+ newCalendar.set(Calendar.YEAR, year)
+ newCalendar.set(Calendar.MONTH, monthOfYear)
+ newCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth)
+
+ if (newCalendar.timeInMillis < Date().time) {
+ timestamp = newCalendar.timeInMillis
+ updateDateAndTime()
+ } else {
+ showToast(R.string.record_in_future)
+ }
+ }, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
+ calendar.get(Calendar.DAY_OF_MONTH))
+ dialog.show()
+ }
+
+ private fun selectTime() {
+ CrashlyticsProxy.get().logButton("Show Time")
+ val calendar = Calendar.getInstance()
+ calendar.timeInMillis = timestamp
+ val dialog = TimePickerDialog(this, uiDecorator.getTheme(type),
+ TimePickerDialog.OnTimeSetListener { view, hourOfDay, minute ->
+ val newCalendar = Calendar.getInstance()
+ newCalendar.timeInMillis = timestamp
+ newCalendar.set(Calendar.HOUR_OF_DAY, hourOfDay)
+ newCalendar.set(Calendar.MINUTE, minute)
+
+ if (newCalendar.timeInMillis < Date().time) {
+ timestamp = newCalendar.timeInMillis
+ updateDateAndTime()
+ } else {
+ showToast(R.string.record_in_future)
+ }
+ }, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE),
+ DateFormat.is24HourFormat(this))
+ dialog.show()
+ }
+
+ private fun presentSpinnerAccount() {
+ val accounts = accountList.map { it.title }.toMutableList()
+
+ var selectedAccountIndex = -1
+
+ if (mode == Mode.MODE_EDIT) {
+ if (record?.account != null) {
+ selectedAccountIndex = accountList.indexOf(accountList.find { it.id == record?.account?.id })
+ }
+ } else if (mode == Mode.MODE_ADD) {
+ val defaultAccount = accountController.readDefaultAccount()
+ selectedAccountIndex = accountList.indexOf(accountList.find { it.id == defaultAccount?.id })
+ }
+
+ if (selectedAccountIndex == -1) {
+ spinnerAccount.isEnabled = false
+
+ accounts.clear()
+ accounts.add(getString(R.string.account_removed))
+ }
+
+ spinnerAccount.adapter = ArrayAdapter(this, R.layout.view_spinner_item, accounts)
+ spinnerAccount.setSelection(selectedAccountIndex)
+ }
+
+ private fun tryRecord() {
+ CrashlyticsProxy.get().logButton("Done Record")
+ if (addRecord()) {
+ CrashlyticsProxy.get().logEvent("Done Record")
+ setResult(Activity.RESULT_OK)
+ finish()
+ }
+ }
+
+ private fun addRecord(): Boolean {
+ if (recordValidator.validate()) {
+ val now = Date().time
+ if (timestamp > now) {
+ showToast(R.string.record_in_future)
+ return false
+ }
+
+ var title = etTitle.text.toString().trim()
+ val category = etCategory.text.toString().trim()
+ val price = etPrice.text.toString().toDouble()
+ val account = accountList[spinnerAccount.selectedItemPosition]
+
+ if (title.isEmpty()) {
+ title = category
+ }
+
+ if (mode == Mode.MODE_ADD) {
+ recordController.create(Record(timestamp, type, title,
+ Category(category), price, account, account.currency))
+ } else if (mode == Mode.MODE_EDIT) {
+ recordController.update(Record(record?.id ?: -1,
+ timestamp, type, title, Category(category), price, account, account.currency))
+ }
+
+ autoCompleter.addRecordTitleCategoryPair(title, category)
+ return true
+ } else {
+ return false
+ }
+ }
+
+ private fun updateDateAndTime() {
+ tvDate.text = formatController.formatDateToNumber(timestamp)
+ tvTime.text = formatController.formatTime(timestamp)
+ }
+
+ enum class Mode { MODE_ADD, MODE_EDIT }
+
+ private class SemicolonInputFilter : InputFilter {
+
+ override fun filter(source: CharSequence?, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int): CharSequence? {
+ return if (source != null && ";" == source.toString()) "" else null
+ }
+ }
+
+ companion object {
+ const val KEY_RECORD = "key_record"
+ const val KEY_MODE = "key_mode"
+ const val KEY_TYPE = "key_type"
+ }
+}
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/record/MainActivity.kt b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/record/MainActivity.kt
index fa96f1b..242dbd2 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/record/MainActivity.kt
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/record/MainActivity.kt
@@ -2,6 +2,7 @@ package com.blogspot.e_kanivets.moneytracker.activity.record
import android.content.Intent
import android.support.v7.app.AppCompatActivity
+import android.support.v7.widget.RecyclerView
import android.widget.TextView
import com.blogspot.e_kanivets.moneytracker.R
import com.blogspot.e_kanivets.moneytracker.activity.ReportActivity
@@ -15,10 +16,13 @@ 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.ui.presenter.ShortSummaryPresenter
import com.blogspot.e_kanivets.moneytracker.util.CrashlyticsProxy
+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
@@ -26,6 +30,7 @@ import javax.inject.Inject
class MainActivity : BaseDrawerActivity() {
private lateinit var recordList: List
+ private var recordItems: List = listOf()
private lateinit var period: Period
private lateinit var recordAdapter: RecordAdapter
@@ -47,6 +52,7 @@ class MainActivity : BaseDrawerActivity() {
private lateinit var tvDefaultAccountTitle: TextView
private lateinit var tvDefaultAccountSum: TextView
private lateinit var tvCurrency: TextView
+ private lateinit var summaryPresenter: ShortSummaryPresenter
override fun getContentViewId(): Int = R.layout.activity_main
@@ -70,10 +76,13 @@ class MainActivity : BaseDrawerActivity() {
tvDefaultAccountSum = navigationView.getHeaderView(0).findViewById(R.id.tvDefaultAccountSum)
tvCurrency = navigationView.getHeaderView(0).findViewById(R.id.tvCurrency)
- recordAdapter = RecordAdapter(this, listOf(), true) { position ->
- if (position == 0) showReport()
- else editRecord(position)
- }
+ recordAdapter = RecordAdapter(this, listOf(), true)
+ recordAdapter.itemClickListener = { position -> editRecord(getPositionWithoutSummary(position)) }
+
+ summaryPresenter = ShortSummaryPresenter(this)
+ val summaryViewHolder = summaryPresenter.create(true) { showReport() }.tag as RecyclerView.ViewHolder
+ recordAdapter.summaryViewHolder = summaryViewHolder
+
recyclerView.adapter = recordAdapter
spinner.setPeriodSelectedListener { period ->
@@ -88,11 +97,13 @@ class MainActivity : BaseDrawerActivity() {
btnAddIncome.setOnClickListener { addIncome() }
}
+ private fun getPositionWithoutSummary(position: Int) = position - 1
+
private fun editRecord(position: Int) {
+
CrashlyticsProxy.get().logButton("Edit Record")
+ val record = recordList[getRecordPosition(position)]
- // Minus one because of list view's header view
- val record = recordList[position - 1]
startAddRecordActivity(record, AddRecordActivity.Mode.MODE_EDIT, record.type)
}
@@ -134,17 +145,30 @@ 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))
+ summaryPresenter.update(report, currency, reportMaker.currencyNeeded(currency, recordList))
+ recordAdapter.setRecords(recordItems)
fillDefaultAccount()
}
+ private fun getRecordPosition(position: Int): Int {
+ var recordPosition = 0
+
+ for (indexOfItem in 0 until position) {
+ if (recordItems[indexOfItem] is RecordItem.Record) {
+ recordPosition++
+ }
+ }
+ return recordPosition
+ }
+
private fun showAppRateDialog() {
CrashlyticsProxy.get().logEvent("Show App Rate Dialog")
val dialog = AppRateDialog(this)
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/CategoryAutoCompleteAdapter.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/CategoryAutoCompleteAdapter.java
index a7d0673..8f47160 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/CategoryAutoCompleteAdapter.java
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/CategoryAutoCompleteAdapter.java
@@ -12,6 +12,8 @@
import com.blogspot.e_kanivets.moneytracker.R;
import com.blogspot.e_kanivets.moneytracker.util.CategoryAutoCompleter;
+import org.jetbrains.annotations.NotNull;
+
import java.util.ArrayList;
import java.util.List;
@@ -26,7 +28,6 @@
*/
public class CategoryAutoCompleteAdapter extends ArrayAdapter implements Filterable {
private final CategoryAutoCompleter autoCompleter;
- private List resultList;
public CategoryAutoCompleteAdapter(Context context, int resource, CategoryAutoCompleter autoCompleter) {
super(context, resource);
@@ -34,7 +35,7 @@ public CategoryAutoCompleteAdapter(Context context, int resource, CategoryAutoCo
}
@Override
- public View getView(int position, View convertView, ViewGroup parent) {
+ public View getView(int position, View convertView, @NotNull ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
@@ -43,14 +44,14 @@ public View getView(int position, View convertView, ViewGroup parent) {
convertView.setTag(viewHolder);
} else viewHolder = (ViewHolder) convertView.getTag();
- final String category = resultList.get(position);
+ final String category = getItem(position);
viewHolder.tvCategory.setText(category);
viewHolder.ivCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
autoCompleter.removeFromAutoComplete(category);
- resultList.remove(category);
+ remove(category);
notifyDataSetChanged();
}
});
@@ -58,16 +59,7 @@ public void onClick(View v) {
return convertView;
}
- @Override
- public int getCount() {
- return resultList.size();
- }
-
- @Override
- public String getItem(int index) {
- return resultList.get(index);
- }
-
+ @NotNull
@Override
public Filter getFilter() {
return new Filter() {
@@ -77,7 +69,8 @@ protected FilterResults performFiltering(CharSequence constraint) {
List tempList;
- if (constraint != null) tempList = autoCompleter.completeByPart(constraint.toString());
+ if (constraint != null)
+ tempList = autoCompleter.completeByPart(constraint.toString());
else tempList = new ArrayList<>();
filterResults.values = tempList;
@@ -88,11 +81,14 @@ protected FilterResults performFiltering(CharSequence constraint) {
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
- if (results != null) //noinspection unchecked
- resultList = (List) results.values;
-
- if (results != null && results.count > 0) notifyDataSetChanged();
- else notifyDataSetInvalidated();
+ clear();
+
+ if (results != null && results.count > 0) {
+ addAll((List) results.values);
+ notifyDataSetChanged();
+ } else {
+ notifyDataSetInvalidated();
+ }
}
};
}
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/ExpandableListReportAdapter.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/ExpandableListReportAdapter.java
deleted file mode 100644
index be2caaf..0000000
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/ExpandableListReportAdapter.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package com.blogspot.e_kanivets.moneytracker.adapter;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.SimpleExpandableListAdapter;
-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.report.record.RecordReportConverter;
-
-import java.util.List;
-import java.util.Map;
-
-import javax.inject.Inject;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-
-/**
- * Created on 12/29/14.
- *
- * @author Evgenii Kanivets
- */
-public class ExpandableListReportAdapter extends SimpleExpandableListAdapter {
- @Inject
- FormatController formatController;
-
- private List extends Map> groupData;
- private List extends List extends Map>> childData;
-
- private int whiteRed;
- private int whiteGreen;
- private int white;
- private int red;
- private int green;
-
- public ExpandableListReportAdapter(Context context, RecordReportConverter converter) {
- this(context, converter.getGroupData(), converter.getGroupLayout(),
- converter.getGroupFrom(), converter.getGroupTo(), converter.getChildData(),
- converter.getChildLayout(), converter.getChildFrom(), converter.getChildTo());
- }
-
- @SuppressWarnings("deprecation")
- public ExpandableListReportAdapter(Context context, List extends Map> groupData,
- int groupLayout, String[] groupFrom, int[] groupTo,
- List extends List extends Map>> childData,
- int childLayout, String[] childFrom, int[] childTo) {
- super(context, groupData, groupLayout, groupFrom, groupTo, childData, childLayout, childFrom, childTo);
- MtApp.get().getAppComponent().inject(ExpandableListReportAdapter.this);
-
- this.groupData = groupData;
- this.childData = childData;
-
- whiteRed = context.getResources().getColor(R.color.white_red);
- whiteGreen = context.getResources().getColor(R.color.white_green);
- white = context.getResources().getColor(R.color.white);
- red = context.getResources().getColor(R.color.red);
- green = context.getResources().getColor(R.color.green);
- }
-
- @Override
- public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
- View view = super.getGroupView(groupPosition, isExpanded, convertView, parent);
- customizeView(view, groupData.get(groupPosition), true);
- return view;
- }
-
- @Override
- public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
- View view = super.getChildView(groupPosition, childPosition, isLastChild, convertView, parent);
- customizeView(view, childData.get(groupPosition).get(childPosition), false);
- return view;
- }
-
- @SuppressLint("SetTextI18n")
- private void customizeView(View view, Map values, boolean groupView) {
- ViewHolder viewHolder = (ViewHolder) view.getTag();
- if (viewHolder == null) viewHolder = new ViewHolder(view);
-
- /* Customize view to fit to model and UI */
- Double price = Double.parseDouble(values.get(RecordReportConverter.PRICE_PARAM_NAME));
-
- if (groupView) view.setBackgroundColor(price < 0 ? whiteRed : whiteGreen);
- else view.setBackgroundColor(white);
-
- //Set color of total
- viewHolder.tvTotal.setTextColor(price >= 0 ? green : red);
-
- viewHolder.tvCategory.setText(values.get(RecordReportConverter.TITLE_PARAM_NAME));
- viewHolder.tvTotal.setText(formatController.formatSignedAmount(price));
- }
-
- public static class ViewHolder {
- @BindView(R.id.tvCategory)
- TextView tvCategory;
- @BindView(R.id.tvTotal)
- TextView tvTotal;
-
- public ViewHolder(View view) {
- ButterKnife.bind(this, view);
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/RecordAdapter.kt b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/RecordAdapter.kt
index f07066d..86781ae 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/RecordAdapter.kt
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/RecordAdapter.kt
@@ -6,16 +6,13 @@ import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.widget.LinearLayout
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.report.record.IRecordReport
-import com.blogspot.e_kanivets.moneytracker.ui.presenter.ShortSummaryPresenter
+import com.blogspot.e_kanivets.moneytracker.entity.RecordItem
+import kotlinx.android.synthetic.main.view_header_date.view.*
import kotlinx.android.synthetic.main.view_record.view.*
-import kotlinx.android.synthetic.main.view_summary_records.view.*
import javax.inject.Inject
class RecordAdapter : RecyclerView.Adapter {
@@ -23,23 +20,22 @@ class RecordAdapter : RecyclerView.Adapter {
@Inject
lateinit var formatController: FormatController
- private var itemClickListener: ((Int) -> Unit)? = null
+ var itemClickListener: ((Int) -> Unit)? = null
private var whiteRed: Int
private var whiteGreen: Int
private var red: Int
private var green: Int
- private var records: List
+ private var items: List
private var context: Context
- private var summaryPresenter: ShortSummaryPresenter
- private var isHeaderViewNeeded: Boolean = false
- private var headerViewHolder: HeaderViewHolder
+ private var isSummaryViewNeeded: Boolean = false
+ lateinit var summaryViewHolder: RecyclerView.ViewHolder
- constructor(context: Context, records: List, isHeaderViewNeeded: Boolean, itemClickListener: ((Int) -> Unit)?) {
+ constructor(context: Context, items: List, isSummaryViewNeeded: Boolean) {
this.context = context
- this.records = records
+ this.items = items
MtApp.get().appComponent.inject(this)
@@ -48,71 +44,65 @@ class RecordAdapter : RecyclerView.Adapter {
red = ContextCompat.getColor(context, R.color.red)
green = ContextCompat.getColor(context, R.color.green)
- summaryPresenter = ShortSummaryPresenter(context)
-
- this.itemClickListener = itemClickListener
- this.isHeaderViewNeeded = isHeaderViewNeeded
-
- headerViewHolder = HeaderViewHolder(LayoutInflater.from(context).inflate(R.layout.view_summary_records, null), itemClickListener)
- summaryPresenter.create(true, headerViewHolder)
+ this.isSummaryViewNeeded = isSummaryViewNeeded
}
- 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)
+ 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) {
- //adapter already bound to view
+ override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
+ if (position == 0 && isSummaryViewNeeded) {
+ //view holder 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, report: IRecordReport?, currency: String, ratesNeeded: List) {
- records = recordsList
- summaryPresenter.update(report, currency, ratesNeeded)
+ fun setRecords(itemsList: List) {
+ items = itemsList
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
@@ -124,36 +114,13 @@ class RecordAdapter : RecyclerView.Adapter {
}
}
- class HeaderViewHolder : RecyclerView.ViewHolder, ShortSummaryPresenter.SummaryViewInterface {
-
- private var tvPeriod: TextView
- private var tvTotalIncome: TextView
- private var tvTotalExpense: TextView
- private var tvTotal: TextView
-
- override fun getTvPeriod(): TextView = tvPeriod
-
- override fun getTvTotalIncome(): TextView = tvTotalIncome
-
- override fun getTvTotalExpense(): TextView = tvTotalExpense
-
- override fun getTvTotal(): TextView = tvTotal
-
- constructor(view: View, itemClickListener: ((Int) -> Unit)?) : super(view) {
- tvPeriod = view.tvPeriod
- tvTotalIncome = view.tvTotalIncome
- tvTotalExpense = view.tvTotalExpense
- tvTotal = view.tvTotal
-
- view.setOnClickListener {
- itemClickListener?.invoke(0)
- }
- }
+ class HeaderViewHolder(view: View) : RecyclerView.ViewHolder(view) {
+ val tvDate: TextView = view.tvDate
}
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
}
}
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/RecordReportAdapter.kt b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/RecordReportAdapter.kt
new file mode 100644
index 0000000..cc3f034
--- /dev/null
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/adapter/RecordReportAdapter.kt
@@ -0,0 +1,146 @@
+package com.blogspot.e_kanivets.moneytracker.adapter
+
+import android.content.Context
+import android.support.v4.content.ContextCompat
+import android.support.v7.widget.RecyclerView
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import com.blogspot.e_kanivets.moneytracker.R
+import com.blogspot.e_kanivets.moneytracker.entity.RecordReportItem
+import kotlinx.android.synthetic.main.view_report_item_exp.view.*
+
+class RecordReportAdapter(
+ private var items: MutableList,
+ private var data: HashMap>,
+ private val context: Context
+) : RecyclerView.Adapter() {
+
+ private var red: Int = ContextCompat.getColor(context, R.color.red)
+ private var green: Int = ContextCompat.getColor(context, R.color.green)
+
+ private lateinit var summaryViewHolder: RecyclerView.ViewHolder
+
+ override fun getItemCount() = items.size + 1
+
+ override fun getItemViewType(position: Int): Int = when {
+ position == 0 -> TYPE_SUMMARY
+ items[getPositionWithoutSummary(position)] is RecordReportItem.ChildRow -> TYPE_CHILD
+ else -> TYPE_PARENT
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = when (viewType) {
+ TYPE_PARENT -> ParentViewHolder(LayoutInflater.from(context).inflate(R.layout.view_report_item_exp, parent, false), ::changeItems, context)
+ TYPE_CHILD -> ChildViewHolder(LayoutInflater.from(context).inflate(R.layout.view_report_item, parent, false))
+ else -> summaryViewHolder
+ }
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ val posWithoutSummary = getPositionWithoutSummary(position)
+ if (posWithoutSummary < 0) return
+
+ when (holder) {
+ is ChildViewHolder -> {
+ val row = items[posWithoutSummary] as RecordReportItem.ChildRow
+ holder.tvCategory.text = row.title
+ holder.tvTotal.text = row.amount
+ holder.tvTotal.setTextColor(if (row.amount.first() != '-') green else red)
+ }
+ is ParentViewHolder -> {
+ val row = items[posWithoutSummary] as RecordReportItem.ParentRow
+ holder.tvCategory.text = row.category
+ holder.tvTotal.text = row.totalAmount
+ holder.tvTotal.setTextColor(if (row.totalAmount.first() != '-') green else red)
+ }
+ }
+ }
+
+ fun setData(items: MutableList, data: HashMap>) {
+ this.items = items
+ this.data = data
+ notifyDataSetChanged()
+ }
+
+ fun setSummaryView(summaryView: View) {
+ this.summaryViewHolder = summaryView.tag as RecyclerView.ViewHolder
+ }
+
+ private fun changeItems(position: Int) {
+ val positionWithoutSummary = getPositionWithoutSummary(position)
+ if (items[positionWithoutSummary] is RecordReportItem.ParentRow) {
+ val parentRow = items[positionWithoutSummary] as RecordReportItem.ParentRow
+
+ if (parentRow.isOpen) {
+ closeParentRow(parentRow, positionWithoutSummary)
+ } else {
+ openParentRow(parentRow, positionWithoutSummary)
+ }
+ }
+ }
+
+ private fun closeParentRow(parentRow: RecordReportItem.ParentRow, position: Int) {
+ val item = items.filterIndexed { index, _ -> index > position }
+ .find { it is RecordReportItem.ParentRow }
+
+ val lastChildInd = if (item != null) items.indexOf(item) else items.size
+
+ items.subList(position + 1, lastChildInd).clear()
+ val itemCount = lastChildInd - position - 1
+ notifyItemRangeRemoved(getPositionWithSummary(position + 1), itemCount)
+
+ parentRow.isOpen = false
+ }
+
+ private fun openParentRow(parentRow: RecordReportItem.ParentRow, position: Int) {
+ data[parentRow]?.let { childRows ->
+ var lastChildInd = position + 1
+ for (childRow in childRows) {
+ items.add(lastChildInd, childRow)
+ lastChildInd++
+ }
+ notifyItemRangeInserted(getPositionWithSummary(position + 1), childRows.size)
+ }
+
+ parentRow.isOpen = true
+ }
+
+ private fun getPositionWithSummary(position: Int) = position + 1
+
+ private fun getPositionWithoutSummary(position: Int) = position - 1
+
+ class ParentViewHolder(view: View, changeItems: ((Int) -> Unit), context: Context) : RecyclerView.ViewHolder(view) {
+
+ var tvCategory: TextView = view.tvCategory
+ var tvTotal: TextView = view.tvTotal
+
+ private var isOpen: Boolean = false
+
+ init {
+ view.setOnClickListener {
+ if (isOpen) {
+ view.lowerDivider.visibility = View.GONE
+ view.ivArrow.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_arrow_downward_outline))
+ } else {
+ view.lowerDivider.visibility = View.VISIBLE
+ view.ivArrow.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_arrow_upward_outline))
+ }
+ isOpen = !isOpen
+ changeItems(adapterPosition)
+ }
+ }
+ }
+
+ class ChildViewHolder(view: View) : RecyclerView.ViewHolder(view) {
+ val tvCategory: TextView = view.tvCategory
+ val tvTotal: TextView = view.tvTotal
+ }
+
+ companion object {
+
+ private const val TYPE_SUMMARY = 0
+ private const val TYPE_PARENT = 1
+ private const val TYPE_CHILD = 2
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/controller/FormatController.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/controller/FormatController.java
index 33e73bf..e4e05e9 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/controller/FormatController.java
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/controller/FormatController.java
@@ -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")
@@ -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) {
+ return shortDateFormat.format(new Date(timestamp));
+ }
+
+ public String formatDateToString(long timestamp) {
+ return fullDateFormat.format(new Date(timestamp));
}
public String formatTime(long timestamp) {
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/controller/PeriodController.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/controller/PeriodController.java
index ab947c7..d634e9b 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/controller/PeriodController.java
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/controller/PeriodController.java
@@ -43,7 +43,7 @@ public Period readLastUsedPeriod() {
return allTimePeriod();
case Period.TYPE_CUSTOM:
- return weekPeriod();
+ return customPeriod(first, last);
default:
return weekPeriod();
@@ -58,6 +58,16 @@ public void writeLastUsedPeriod(Period period) {
preferenceController.writePeriodType(period.getType());
}
+ public Period customPeriod(long firstTs, long lastTs) {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(firstTs);
+ Date first = cal.getTime();
+ cal.setTimeInMillis(lastTs);
+ Date last = cal.getTime();
+
+ return new Period(first, last, Period.TYPE_CUSTOM);
+ }
+
public Period dayPeriod() {
Calendar cal = Calendar.getInstance();
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/controller/data/AccountController.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/controller/data/AccountController.java
index f383cd7..e633460 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/controller/data/AccountController.java
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/controller/data/AccountController.java
@@ -21,7 +21,8 @@
* @author Evgenii Kanivets
*/
public class AccountController extends BaseController {
- @SuppressWarnings("unused") private static final String TAG = "AccountController";
+ @SuppressWarnings("unused")
+ private static final String TAG = "AccountController";
private final PreferenceController preferenceController;
@@ -30,11 +31,15 @@ public AccountController(IRepo accountRepo, PreferenceController prefer
this.preferenceController = preferenceController;
}
- @Nullable @Override public Account read(long id) {
+ @Nullable
+ @Override
+ public Account read(long id) {
return substituteCurrency(super.read(id));
}
- @NonNull @Override public List readAll() {
+ @NonNull
+ @Override
+ public List readAll() {
List accountList = super.readAll();
List result = new ArrayList<>();
@@ -45,7 +50,8 @@ public AccountController(IRepo accountRepo, PreferenceController prefer
return result;
}
- @NonNull public List readActiveAccounts() {
+ @NonNull
+ public List readActiveAccounts() {
List result = new ArrayList<>();
for (Account account : readAll()) {
@@ -57,7 +63,8 @@ public AccountController(IRepo accountRepo, PreferenceController prefer
return result;
}
- @NonNull public List readArchivedAccounts() {
+ @NonNull
+ public List readArchivedAccounts() {
List result = new ArrayList<>();
for (Account account : readAll()) {
@@ -69,7 +76,7 @@ public AccountController(IRepo accountRepo, PreferenceController prefer
return result;
}
- public boolean recordAdded(@Nullable Record record) {
+ boolean recordAdded(@Nullable Record record) {
if (record == null || record.getAccount() == null) return false;
Account account = repo.read(record.getAccount().getId());
@@ -93,8 +100,10 @@ public boolean recordAdded(@Nullable Record record) {
return true;
}
- public boolean recordDeleted(@Nullable Record record) {
- if (record == null || record.getAccount() == null) return false;
+ boolean recordDeleted(@Nullable Record record) {
+ if (record == null) return false;
+
+ if (record.getAccount() == null) return true;
Account account = repo.read(record.getAccount().getId());
if (account == null) return false;
@@ -141,7 +150,8 @@ public boolean transferDone(@Nullable Transfer transfer) {
return true;
}
- @Nullable public Account readDefaultAccount() {
+ @Nullable
+ public Account readDefaultAccount() {
long defaultAccountId = preferenceController.readDefaultAccountId();
if (defaultAccountId == -1) {
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/di/AppComponent.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/di/AppComponent.java
index 1f0b100..064033b 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/di/AppComponent.java
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/di/AppComponent.java
@@ -17,7 +17,6 @@
import com.blogspot.e_kanivets.moneytracker.activity.record.MainActivity;
import com.blogspot.e_kanivets.moneytracker.adapter.AccountAdapter;
import com.blogspot.e_kanivets.moneytracker.adapter.ExchangeRateAdapter;
-import com.blogspot.e_kanivets.moneytracker.adapter.ExpandableListReportAdapter;
import com.blogspot.e_kanivets.moneytracker.adapter.MonthSummaryAdapter;
import com.blogspot.e_kanivets.moneytracker.adapter.RecordAdapter;
import com.blogspot.e_kanivets.moneytracker.di.module.repo.CachedRepoModule;
@@ -26,6 +25,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;
@@ -74,8 +74,6 @@ public interface AppComponent {
void inject(AccountAdapter accountAdapter);
- void inject(ExpandableListReportAdapter expandableListReportAdapter);
-
void inject(ShortSummaryPresenter shortSummaryPresenter);
void inject(ExchangeRateAdapter exchangeRateAdapter);
@@ -87,4 +85,8 @@ public interface AppComponent {
void inject(EditAccountFragment editAccountFragment);
void inject(AccountOperationsFragment accountRecordsFragment);
+
+ void inject(RecordItemsBuilder recordItemsBuilder);
+
+ void inject(ReportActivity.RecordReportConverter recordReportConverter);
}
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/entity/RecordItem.kt b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/entity/RecordItem.kt
new file mode 100644
index 0000000..9a4f625
--- /dev/null
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/entity/RecordItem.kt
@@ -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)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/entity/RecordReportItem.kt b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/entity/RecordReportItem.kt
new file mode 100644
index 0000000..7e8ac01
--- /dev/null
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/entity/RecordReportItem.kt
@@ -0,0 +1,9 @@
+package com.blogspot.e_kanivets.moneytracker.entity
+
+sealed class RecordReportItem {
+
+ data class ChildRow(val title: String, val amount: String) : RecordReportItem()
+
+ data class ParentRow(val category: String, val totalAmount: String, var isOpen: Boolean) : RecordReportItem()
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/report/record/RecordReport.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/report/record/RecordReport.java
index c9cf415..1e7dc8a 100644
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/report/record/RecordReport.java
+++ b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/report/record/RecordReport.java
@@ -190,20 +190,7 @@ private SummaryRecord createSummaryRecord(String title, List recordList)
amount += getAmount(record);
}
- SummaryRecord summaryRecord = new SummaryRecord(title, currency, amount);
-
- for (Record record : recordList) {
- summaryRecord.add(record);
- }
-
- Collections.sort(summaryRecord.getRecordList(), new Comparator() {
- @Override
- public int compare(Record lhs, Record rhs) {
- return compareDoubles(getAmount(lhs), getAmount(rhs));
- }
- });
-
- return summaryRecord;
+ return new SummaryRecord(title, currency, amount, recordList.size());
}
private double getAmount(Record record) {
diff --git a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/report/record/RecordReportConverter.java b/app/src/main/java/com/blogspot/e_kanivets/moneytracker/report/record/RecordReportConverter.java
deleted file mode 100644
index 02acc31..0000000
--- a/app/src/main/java/com/blogspot/e_kanivets/moneytracker/report/record/RecordReportConverter.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.blogspot.e_kanivets.moneytracker.report.record;
-
-import android.support.annotation.LayoutRes;
-import android.support.annotation.NonNull;
-
-import com.blogspot.e_kanivets.moneytracker.R;
-import com.blogspot.e_kanivets.moneytracker.report.record.model.CategoryRecord;
-import com.blogspot.e_kanivets.moneytracker.report.record.model.SummaryRecord;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Util class to convert {@link RecordReport} to {@link android.widget.ExpandableListView} input data.
- * Created on 2/26/16.
- *
- * @author Evgenii Kanivets
- */
-public class RecordReportConverter {
- public static final String TITLE_PARAM_NAME = "title";
- public static final String PRICE_PARAM_NAME = "price";
-
- private final IRecordReport report;
-
- public RecordReportConverter(@NonNull IRecordReport report) {
- this.report = report;
- }
-
- public List extends Map> getGroupData() {
- List