X-Git-Url: https://git.ktnx.net/?p=mobile-ledger.git;a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fnet%2Fktnx%2Fmobileledger%2Fui%2Factivity%2FMainActivity.java;h=7e9469a296524d706f8fa7adb3cc6e147458a269;hp=ad124667f5b788088a7009e8151c7420fadd94ec;hb=32147725c77f956d37c62a7e50709ec3839586c6;hpb=abc331c02a265be778538a8416766c5d681a031f diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java b/app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java index ad124667..7e9469a2 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java @@ -1,5 +1,5 @@ /* - * Copyright © 2018 Damyan Ivanov. + * Copyright © 2019 Damyan Ivanov. * This file is part of Mobile-Ledger. * Mobile-Ledger is free software: you can distribute it and/or modify it * under the term of the GNU General Public License as published by @@ -18,35 +18,77 @@ package net.ktnx.mobileledger.ui.activity; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.os.Build; import android.os.Bundle; +import android.support.annotation.ColorInt; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentTransaction; +import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.GravityCompat; +import android.support.v4.view.ViewPager; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; -import android.view.ContextMenu; -import android.view.MenuItem; import android.view.View; import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; import net.ktnx.mobileledger.R; +import net.ktnx.mobileledger.async.RefreshDescriptionsTask; +import net.ktnx.mobileledger.async.RetrieveTransactionsTask; +import net.ktnx.mobileledger.model.Data; import net.ktnx.mobileledger.model.LedgerAccount; +import net.ktnx.mobileledger.model.MobileLedgerProfile; +import net.ktnx.mobileledger.ui.MobileLedgerListFragment; import net.ktnx.mobileledger.ui.account_summary.AccountSummaryFragment; import net.ktnx.mobileledger.ui.transaction_list.TransactionListFragment; +import net.ktnx.mobileledger.utils.MLDB; + +import java.lang.ref.WeakReference; +import java.text.DateFormat; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.Observable; +import java.util.Observer; public class MainActivity extends AppCompatActivity { + public MobileLedgerListFragment currentFragment = null; DrawerLayout drawer; private AccountSummaryFragment accountSummaryFragment; private TransactionListFragment transactionListFragment; - private Fragment currentFragment = null; private FragmentManager fragmentManager; + private TextView tvLastUpdate; + private RetrieveTransactionsTask retrieveTransactionsTask; + private View bTransactionListCancelDownload; + private ProgressBar progressBar; + private LinearLayout progressLayout; + private SectionsPagerAdapter mSectionsPagerAdapter; + private ViewPager mViewPager; + + @Override + protected void onStart() { + super.onStart(); + Data.lastUpdateDate.set(null); + updateLastUpdateTextFromDB(); + Date lastUpdate = Data.lastUpdateDate.get(); + + long now = new Date().getTime(); + if ((lastUpdate == null) || (now > (lastUpdate.getTime() + (24 * 3600 * 1000)))) { + if (lastUpdate == null) Log.d("db::", "WEB data never fetched. scheduling a fetch"); + else Log.d("db", + String.format("WEB data last fetched at %1.3f and now is %1.3f. re-fetching", + lastUpdate.getTime() / 1000f, now / 1000f)); + + scheduleTransactionListRetrieval(); + } + } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -54,6 +96,19 @@ public class MainActivity extends AppCompatActivity { Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); + Data.profile.addObserver(new Observer() { + @Override + public void update(Observable o, Object arg) { + MobileLedgerProfile profile = Data.profile.get(); + runOnUiThread(() -> { + if (profile == null) toolbar.setSubtitle(""); + else toolbar.setSubtitle(profile.getName()); + }); + } + }); + + setupProfile(); + drawer = findViewById(R.id.drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, @@ -72,35 +127,106 @@ public class MainActivity extends AppCompatActivity { e.printStackTrace(); } + tvLastUpdate = findViewById(R.id.transactions_last_update); + + bTransactionListCancelDownload = findViewById(R.id.transaction_list_cancel_download); + progressBar = findViewById(R.id.transaction_list_progress_bar); + if (progressBar == null) + throw new RuntimeException("Can't get hold on the transaction value progress bar"); + progressLayout = findViewById(R.id.transaction_progress_layout); + if (progressLayout == null) throw new RuntimeException( + "Can't get hold on the transaction value progress bar layout"); + fragmentManager = getSupportFragmentManager(); + mSectionsPagerAdapter = new SectionsPagerAdapter(fragmentManager); - onAccountSummaryClicked(null); - } + mViewPager = findViewById(R.id.root_frame); + mViewPager.setAdapter(mSectionsPagerAdapter); + mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { + @Override + public void onPageSelected(int position) { + switch (position) { + case 0: + markDrawerItemCurrent(R.id.nav_account_summary); + break; + case 1: + markDrawerItemCurrent(R.id.nav_latest_transactions); + break; + default: + Log.e("MainActivity", String.format("Unexpected page index %d", position)); + } - @Override - protected void onStart() { - super.onStart(); - LinearLayout grp = drawer.findViewById(R.id.nav_actions); - for (int i = 0; i < grp.getChildCount(); i++) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - grp.getChildAt(i).setBackgroundColor( - getResources().getColor(R.color.drawer_background, getTheme())); + super.onPageSelected(position); } - else { - grp.getChildAt(i) - .setBackgroundColor(getResources().getColor(R.color.drawer_background)); + }); + + Data.lastUpdateDate.addObserver((o, arg) -> { + Log.d("main", "lastUpdateDate changed"); + runOnUiThread(() -> { + Date date = Data.lastUpdateDate.get(); + if (date == null) { + tvLastUpdate.setText(R.string.transaction_last_update_never); + } + else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + tvLastUpdate.setText(date.toInstant().atZone(ZoneId.systemDefault()) + .format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); + } + else { + tvLastUpdate.setText(DateFormat.getDateTimeInstance().format(date)); + } + } + }); + }); + } + private void setupProfile() { + Data.profiles.setList(MobileLedgerProfile.loadAllFromDB()); + MobileLedgerProfile profile = null; + + String profileUUID = MLDB.get_option_value(MLDB.OPT_PROFILE_UUID, null); + if (profileUUID == null) { + if (Data.profiles.isEmpty()) { + Data.profiles.setList(MobileLedgerProfile.createInitialProfileList()); + profile = Data.profiles.get(0); + + SharedPreferences backend = getSharedPreferences("backend", MODE_PRIVATE); + Log.d("profiles", "Migrating from preferences to profiles"); + // migration to multiple profiles + if (profile.getUrl().isEmpty()) { + // no legacy config + Intent intent = new Intent(this, ProfileListActivity.class); + startActivity(intent); + } + profile.setUrl(backend.getString("backend_url", "")); + profile.setAuthEnabled(backend.getBoolean("backend_use_http_auth", false)); + profile.setAuthUserName(backend.getString("backend_auth_user", null)); + profile.setAuthPassword(backend.getString("backend_auth_password", null)); + profile.storeInDB(); + SharedPreferences.Editor editor = backend.edit(); + editor.clear(); + editor.apply(); } } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - drawer.findViewById(R.id.nav_account_summary).setBackgroundColor( - getResources().getColor(R.color.table_row_even_bg, getTheme())); - } else { - drawer.findViewById(R.id.nav_account_summary) - .setBackgroundColor(getResources().getColor(R.color.table_row_even_bg)); + profile = MobileLedgerProfile.loadUUIDFromDB(profileUUID); } - } + if (profile == null) profile = Data.profiles.get(0); + + if (profile == null) throw new AssertionError("profile must have a value"); + + Data.profile.set(profile); + MLDB.set_option_value(MLDB.OPT_PROFILE_UUID, profile.getUuid()); + + if (profile.getUrl().isEmpty()) { + Intent intent = new Intent(this, ProfileListActivity.class); + Bundle args = new Bundle(); + args.putInt(ProfileListActivity.ARG_ACTION, ProfileListActivity.ACTION_EDIT_PROFILE); + args.putInt(ProfileListActivity.ARG_PROFILE_INDEX, 0); + intent.putExtras(args); + startActivity(intent, args); + } + } public void fab_new_transaction_clicked(View view) { Intent intent = new Intent(this, NewTransactionActivity.class); startActivity(intent); @@ -115,9 +241,10 @@ public class MainActivity extends AppCompatActivity { public void nav_settings_clicked(View view) { Intent intent = new Intent(this, SettingsActivity.class); startActivity(intent); + drawer.closeDrawers(); } public void markDrawerItemCurrent(int id) { - View item = drawer.findViewById(id); + TextView item = drawer.findViewById(id); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { item.setBackgroundColor(getResources().getColor(R.color.table_row_even_bg, getTheme())); } @@ -125,37 +252,18 @@ public class MainActivity extends AppCompatActivity { item.setBackgroundColor(getResources().getColor(R.color.table_row_even_bg)); } + setTitle(item.getText()); + + @ColorInt int transparent = getResources().getColor(android.R.color.transparent); + LinearLayout actions = drawer.findViewById(R.id.nav_actions); for (int i = 0; i < actions.getChildCount(); i++) { View view = actions.getChildAt(i); if (view.getId() != id) { - view.setBackgroundColor(getResources().getColor(android.R.color.transparent)); + view.setBackgroundColor(transparent); } } } - public void onOptionsMenuClicked(MenuItem menuItem) { - ContextMenu.ContextMenuInfo info = menuItem.getMenuInfo(); - switch (menuItem.getItemId()) { - case R.id.menu_acc_summary_cancel_selection: - if (accountSummaryFragment != null) - accountSummaryFragment.onCancelAccSelection(menuItem); - break; - case R.id.menu_acc_summary_confirm_selection: - if (accountSummaryFragment != null) - accountSummaryFragment.onConfirmAccSelection(menuItem); - break; - case R.id.menu_acc_summary_only_starred: - if (accountSummaryFragment != null) - accountSummaryFragment.onShowOnlyStarredClicked(menuItem); - break; - case R.id.menu_transaction_list_filter: - if (transactionListFragment != null) - transactionListFragment.onShowFilterClick(menuItem); - break; - default: - Log.e("menu", String.format("Menu item %d not handled", menuItem.getItemId())); - } - } public void onViewClicked(View view) { switch (view.getId()) { case R.id.clearAccountNameFilter: @@ -169,45 +277,43 @@ public class MainActivity extends AppCompatActivity { public void onAccountSummaryClicked(View view) { drawer.closeDrawers(); - resetFragmentBackStack(); - showAccountSummaryFragment(); } private void showAccountSummaryFragment() { - FragmentTransaction ft = fragmentManager.beginTransaction(); - accountSummaryFragment = new AccountSummaryFragment(); - ft.replace(R.id.root_frame, accountSummaryFragment); - ft.commit(); - currentFragment = accountSummaryFragment; + mViewPager.setCurrentItem(0, true); +// FragmentTransaction ft = fragmentManager.beginTransaction(); +// accountSummaryFragment = new AccountSummaryFragment(); +// ft.replace(R.id.root_frame, accountSummaryFragment); +// ft.commit(); +// currentFragment = accountSummaryFragment; } public void onLatestTransactionsClicked(View view) { drawer.closeDrawers(); - resetFragmentBackStack(); - showTransactionsFragment(null); } private void resetFragmentBackStack() { // fragmentManager.popBackStack(0, FragmentManager.POP_BACK_STACK_INCLUSIVE); } private void showTransactionsFragment(LedgerAccount account) { - FragmentTransaction ft = fragmentManager.beginTransaction(); - if (transactionListFragment == null) { - Log.d("flow", "MainActivity creating TransactionListFragment"); - transactionListFragment = new TransactionListFragment(); - } - Bundle bundle = new Bundle(); - if (account != null) { - bundle.putString(TransactionListFragment.BUNDLE_KEY_FILTER_ACCOUNT_NAME, - account.getName()); - } - transactionListFragment.setArguments(bundle); - ft.replace(R.id.root_frame, transactionListFragment); - if (account != null) - ft.addToBackStack(getResources().getString(R.string.title_activity_transaction_list)); - ft.commit(); - - currentFragment = transactionListFragment; + mViewPager.setCurrentItem(1, true); +// FragmentTransaction ft = fragmentManager.beginTransaction(); +// if (transactionListFragment == null) { +// Log.d("flow", "MainActivity creating TransactionListFragment"); +// transactionListFragment = new TransactionListFragment(); +// } +// Bundle bundle = new Bundle(); +// if (account != null) { +// bundle.putString(TransactionListFragment.BUNDLE_KEY_FILTER_ACCOUNT_NAME, +// account.getName()); +// } +// transactionListFragment.setArguments(bundle); +// ft.replace(R.id.root_frame, transactionListFragment); +// if (account != null) +// ft.addToBackStack(getResources().getString(R.string.title_activity_transaction_list)); +// ft.commit(); +// +// currentFragment = transactionListFragment; } public void showAccountTransactions(LedgerAccount account) { showTransactionsFragment(account); @@ -225,5 +331,89 @@ public class MainActivity extends AppCompatActivity { super.onBackPressed(); } } + public void updateLastUpdateTextFromDB() { + { + long last_update = Data.profile.get().get_option_value(MLDB.OPT_LAST_SCRAPE, 0L); + + Log.d("transactions", String.format("Last update = %d", last_update)); + if (last_update == 0) { + Data.lastUpdateDate.set(null); + } + else { + Data.lastUpdateDate.set(new Date(last_update)); + } + } + } + public void scheduleTransactionListRetrieval() { + retrieveTransactionsTask = new RetrieveTransactionsTask(new WeakReference<>(this)); + + retrieveTransactionsTask.execute(); + bTransactionListCancelDownload.setEnabled(true); + } + public void onStopTransactionRefreshClick(View view) { + Log.d("interactive", "Cancelling transactions refresh"); + if (retrieveTransactionsTask != null) retrieveTransactionsTask.cancel(false); + bTransactionListCancelDownload.setEnabled(false); + } + public void onRetrieveDone(boolean success) { + progressLayout.setVisibility(View.GONE); + updateLastUpdateTextFromDB(); + + new RefreshDescriptionsTask().execute(); + } + public void onRetrieveStart() { + progressBar.setIndeterminate(true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) progressBar.setProgress(0, false); + else progressBar.setProgress(0); + progressLayout.setVisibility(View.VISIBLE); + } + public void onRetrieveProgress(RetrieveTransactionsTask.Progress progress) { + if ((progress.getTotal() == RetrieveTransactionsTask.Progress.INDETERMINATE) || + (progress.getTotal() == 0)) + { + progressBar.setIndeterminate(true); + } + else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + progressBar.setMin(0); + } + progressBar.setMax(progress.getTotal()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + progressBar.setProgress(progress.getProgress(), true); + } + else progressBar.setProgress(progress.getProgress()); + progressBar.setIndeterminate(false); + } + } + public void nav_profiles_clicked(View view) { + drawer.closeDrawers(); + Intent intent = new Intent(this, ProfileListActivity.class); + startActivity(intent); + } + public class SectionsPagerAdapter extends FragmentPagerAdapter { + + public SectionsPagerAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int position) { + Log.d("main", String.format("Switching to gragment %d", position)); + switch (position) { + case 0: + return new AccountSummaryFragment(); + case 1: + return new TransactionListFragment(); + default: + throw new IllegalStateException( + String.format("Unexpected fragment index: " + "%d", position)); + } + } + + @Override + public int getCount() { + return 2; + } + } }