import net.ktnx.mobileledger.model.Data;
import net.ktnx.mobileledger.model.LedgerTransaction;
+import net.ktnx.mobileledger.model.MobileLedgerProfile;
import net.ktnx.mobileledger.model.TransactionListItem;
import net.ktnx.mobileledger.utils.Globals;
import net.ktnx.mobileledger.utils.MLDB;
public class UpdateTransactionsTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String[] filterAccName) {
Data.backgroundTaskCount.incrementAndGet();
- String profile_uuid = Data.profile.get().getUuid();
+ final MobileLedgerProfile profile = Data.profile.get();
+ if (profile == null) return "Profile not configured";
+
+ String profile_uuid = profile.getUuid();
try {
ArrayList<TransactionListItem> newList = new ArrayList<>();
import java.util.ArrayList;
import java.util.Date;
+import java.util.List;
public final class Data {
public static TransactionList transactions = new TransactionList();
MLDB.setOption(MLDB.OPT_PROFILE_UUID, newProfile.getUuid());
profile.set(newProfile);
}
+ public static int getProfileIndex(MobileLedgerProfile profile) {
+ List<MobileLedgerProfile> list = profiles.getList();
+
+ for (int i = 0; i < list.size(); i++) {
+ MobileLedgerProfile p = list.get(i);
+ if (p.equals(profile)) return i;
+ }
+
+ return -1;
+ }
}
new CommitAccountsTaskParams(Data.accounts.get(), Data.optShowOnlyStarred.get()));
}
void scheduleAccountListReload() {
+ if (Data.profile.get() == null) return;
+
UAT task = new UAT();
task.execute();
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;
});
});
- setupProfile();
-
drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle =
new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open,
}
});
});
+
+ findViewById(R.id.btn_no_profiles_add).setOnClickListener(v -> startAddProfileActivity());
+ }
+ @Override
+ protected void onResume() {
+ super.onResume();
+ setupProfile();
+ }
+ private void startAddProfileActivity() {
+ 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, ProfileListActivity.PROFILE_INDEX_NONE);
+ intent.putExtras(args);
+ startActivity(intent, args);
}
private void setupProfile() {
String profileUUID = MLDB.getOption(MLDB.OPT_PROFILE_UUID, null);
MobileLedgerProfile profile;
- 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();
- }
- else profile = Data.profiles.get(0);
- }
- else {
- profile = MobileLedgerProfile.loadAllFromDB(profileUUID);
+ profile = MobileLedgerProfile.loadAllFromDB(profileUUID);
+
+ if (Data.profiles.getList().isEmpty()) {
+ findViewById(R.id.no_profiles_layout).setVisibility(View.VISIBLE);
+ findViewById(R.id.pager_layout).setVisibility(View.GONE);
+ return;
}
+ findViewById(R.id.pager_layout).setVisibility(View.VISIBLE);
+ findViewById(R.id.no_profiles_layout).setVisibility(View.GONE);
+
if (profile == null) profile = Data.profiles.get(0);
if (profile == null) throw new AssertionError("profile must have a value");
Data.setCurrentProfile(profile);
-
- 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 fabNewTransactionClicked(View view) {
Intent intent = new Intent(this, NewTransactionActivity.class);
}
public void updateLastUpdateTextFromDB() {
{
- long last_update = Data.profile.get().getLongOption(MLDB.OPT_LAST_SCRAPE, 0L);
+ final MobileLedgerProfile profile = Data.profile.get();
+ long last_update =
+ (profile != null) ? profile.getLongOption(MLDB.OPT_LAST_SCRAPE, 0L) : 0;
Log.d("transactions", String.format("Last update = %d", last_update));
if (last_update == 0) {
}
}
public void scheduleTransactionListRetrieval() {
+ if (Data.profile.get() == null) return;
+
retrieveTransactionsTask = new RetrieveTransactionsTask(new WeakReference<>(this));
retrieveTransactionsTask.execute();
@Override
public Fragment getItem(int position) {
- Log.d("main", String.format("Switching to gragment %d", position));
+ Log.d("main", String.format("Switching to fragment %d", position));
switch (position) {
case 0:
return new AccountSummaryFragment();
public class ProfileListActivity extends AppCompatActivity {
public static final String ARG_ACTION = "action";
- public static final String ARG_PROFILE_INDEX = "profile_uuid";
+ public static final String ARG_PROFILE_INDEX = "profile_index";
+ public static final int PROFILE_INDEX_NONE = -1;
public static final int ACTION_EDIT_PROFILE = 1;
public static final int ACTION_INVALID = -1;
/**
int action = getIntent().getIntExtra(ARG_ACTION, ACTION_INVALID);
if (action == ACTION_EDIT_PROFILE) {
Log.d("profiles", "got edit profile action");
- int index = getIntent().getIntExtra(ARG_PROFILE_INDEX, -1);
- if (index >= 0) {
- MobileLedgerProfile profile = Data.profiles.get(index);
- ProfilesRecyclerViewAdapter adapter =
- (ProfilesRecyclerViewAdapter) recyclerView.getAdapter();
- if (adapter != null) adapter.editProfile(recyclerView, profile);
+ int index = getIntent().getIntExtra(ARG_PROFILE_INDEX, PROFILE_INDEX_NONE);
+
+ MobileLedgerProfile profile = (index >= 0) ? Data.profiles.get(index) : null;
+ ProfilesRecyclerViewAdapter adapter =
+ (ProfilesRecyclerViewAdapter) recyclerView.getAdapter();
+ if (adapter != null) {
+ adapter.editProfile(recyclerView, profile);
+
+ // if invoked from the initial screen, get out so that when the new profile
+ // activity finishes the user i navigated to the main activity
+ if ((profile == null) && Data.profiles.getList().isEmpty()) finish();
}
}
}
else {
Context context = view.getContext();
Intent intent = new Intent(context, ProfileDetailActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION);
if (index != -1) intent.putExtra(ProfileDetailFragment.ARG_ITEM_ID, index);
context.startActivity(intent);
final MobileLedgerProfile profile = Data.profiles.get(position);
final MobileLedgerProfile currentProfile = Data.profile.get();
Log.d("profiles", String.format("pos %d: %s, current: %s", position, profile.getUuid(),
- currentProfile.getUuid()));
+ (currentProfile == null) ? "<NULL>" : currentProfile.getUuid()));
holder.itemView.setTag(profile);
holder.mTitle.setText(profile.getName());
holder.mSubTitle.setText(profile.getUrl());
package net.ktnx.mobileledger.ui.profiles;
import android.app.Activity;
-import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
}
}
}
-
@Override
- public void onAttach(Context context) {
- super.onAttach(context);
- fab = ((Activity) context).findViewById(R.id.fab);
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ Activity context = getActivity();
+ if (context == null) return;
+
+ fab = context.findViewById(R.id.fab);
fab.setOnClickListener(v -> {
if (mProfile != null) {
mProfile.setName(profileName.getText());
public static ObservableValue<String> updateError = new ObservableValue<>();
public static void scheduleTransactionListReload() {
+ if (Data.profile.get() == null) return;
+
String filter = TransactionListFragment.accountFilter.get();
AsyncTask<String, Void, String> task = new UTT();
task.execute(filter);
android:layout_width="match_parent"
android:layout_height="match_parent">
- <android.support.design.widget.FloatingActionButton
- android:id="@+id/btn_add_transaction"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom|end"
- android:layout_margin="@dimen/fab_margin"
- android:onClick="fabNewTransactionClicked"
- app:backgroundTint="@color/colorPrimary"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:srcCompat="@drawable/svg_thick_plus_white" />
-
- <LinearLayout
- android:id="@+id/main_header"
+ <android.support.constraint.ConstraintLayout
+ android:id="@+id/pager_layout"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:theme="@style/AppTheme"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent">
+ android:layout_height="match_parent">
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/btn_add_transaction"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|end"
+ android:layout_margin="@dimen/fab_margin"
+ android:onClick="fabNewTransactionClicked"
+ app:backgroundTint="@color/colorPrimary"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:srcCompat="@drawable/svg_thick_plus_white" />
<LinearLayout
- android:id="@+id/transaction_list_account_name_filter"
+ android:id="@+id/main_header"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:visibility="gone">
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:theme="@style/AppTheme"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@drawable/ic_filter_list_black_24dp" />
+ <LinearLayout
+ android:id="@+id/transaction_list_account_name_filter"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:visibility="gone">
- <AutoCompleteTextView
- android:id="@+id/transaction_filter_account_name"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1" />
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/ic_filter_list_black_24dp" />
- <TextView
- android:id="@+id/clearAccountNameFilter"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@drawable/ic_clear_black_24dp"
- android:clickable="true"
- android:focusable="true" />
+ <AutoCompleteTextView
+ android:id="@+id/transaction_filter_account_name"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
- </LinearLayout>
+ <TextView
+ android:id="@+id/clearAccountNameFilter"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/ic_clear_black_24dp"
+ android:clickable="true"
+ android:focusable="true" />
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:elevation="24dp"
- android:orientation="horizontal">
+ </LinearLayout>
- <TextView
- android:id="@+id/transaction_last_update_label"
- android:layout_width="wrap_content"
+ <LinearLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
- android:text="@string/transactions_last_update_label"
- android:textColor="@android:color/tertiary_text_light" />
+ android:elevation="24dp"
+ android:orientation="horizontal">
- <TextView
- android:id="@+id/transactions_last_update"
- style="@android:style/Widget.DeviceDefault.Light.TextView"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="\?"
- android:textColor="@android:color/tertiary_text_light"
- tools:ignore="HardcodedText" />
- </LinearLayout>
+ <TextView
+ android:id="@+id/transaction_last_update_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:text="@string/transactions_last_update_label"
+ android:textColor="@android:color/tertiary_text_light" />
+
+ <TextView
+ android:id="@+id/transactions_last_update"
+ style="@android:style/Widget.DeviceDefault.Light.TextView"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="\?"
+ android:textColor="@android:color/tertiary_text_light"
+ tools:ignore="HardcodedText" />
+ </LinearLayout>
- <LinearLayout
- android:id="@+id/transaction_progress_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:orientation="horizontal"
- android:visibility="gone">
-
- <ProgressBar
- android:id="@+id/transaction_list_progress_bar"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="0dp"
+ <LinearLayout
+ android:id="@+id/transaction_progress_layout"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="-8dp"
- android:layout_marginBottom="-7dp"
- android:layout_weight="1"
- android:indeterminate="true"
- android:padding="0dp"
- android:progressTint="@color/colorPrimary"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent" />
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ android:visibility="gone">
+
+ <ProgressBar
+ android:id="@+id/transaction_list_progress_bar"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="-8dp"
+ android:layout_marginBottom="-7dp"
+ android:layout_weight="1"
+ android:indeterminate="true"
+ android:padding="0dp"
+ android:progressTint="@color/colorPrimary"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <TextView
+ android:id="@+id/transaction_list_cancel_download"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/ic_clear_black_24dp"
+ android:clickable="true"
+ android:focusable="true"
+ android:onClick="onStopTransactionRefreshClick" />
+ </LinearLayout>
- <TextView
- android:id="@+id/transaction_list_cancel_download"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@drawable/ic_clear_black_24dp"
- android:clickable="true"
- android:focusable="true"
- android:onClick="onStopTransactionRefreshClick" />
</LinearLayout>
- </LinearLayout>
+ <android.support.v4.view.ViewPager
+ android:id="@+id/root_frame"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/main_header">
- <android.support.v4.view.ViewPager
- android:id="@+id/root_frame"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- app:layout_behavior="@string/appbar_scrolling_view_behavior"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/main_header">
+ </android.support.v4.view.ViewPager>
- </android.support.v4.view.ViewPager>
+ <View
+ android:layout_width="0dp"
+ android:layout_height="4dp"
+ android:background="@drawable/drop_shadow"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/main_header" />
- <View
- android:layout_width="0dp"
- android:layout_height="4dp"
- android:background="@drawable/drop_shadow"
- app:layout_constraintTop_toBottomOf="@id/main_header" />
- </android.support.constraint.ConstraintLayout>
+ </android.support.constraint.ConstraintLayout>
+ <include layout="@layout/no_profiles" />
+ </android.support.constraint.ConstraintLayout>
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ 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
+ ~ the Free Software Foundation, either version 3 of the License, or
+ ~ (at your opinion), any later version.
+ ~
+ ~ Mobile-Ledger is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ~ GNU General Public License terms for details.
+ ~
+ ~ You should have received a copy of the GNU General Public License
+ ~ along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/no_profiles_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/colorPrimaryDark"
+ tools:showIn="@layout/activity_main">
+
+ <TextView
+ android:id="@+id/textView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="48dp"
+ android:text="@string/text_welcome"
+ android:textSize="52sp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <TextView
+ android:id="@+id/textView3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="8dp"
+ android:layout_marginTop="24dp"
+ android:layout_marginEnd="8dp"
+ android:text="@string/text_welcome_profile_needed"
+ android:textSize="20sp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/textView" />
+
+ <Button
+ android:id="@+id/btn_no_profiles_add"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="8dp"
+ android:layout_marginTop="24dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginBottom="8dp"
+ android:backgroundTint="@color/colorPrimary"
+ android:drawablePadding="16dp"
+ android:text="@string/create_profile_label"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/textView3" />
+</android.support.constraint.ConstraintLayout>
\ No newline at end of file
-->
<resources>
- <color name="colorPrimary">#935ff2</color>
+ <color name="colorPrimary">#935FF2</color>
<color name="colorPrimaryDark">#3e148c</color>
<color name="colorAccent">#724db6</color>
<color name="drawer_background">#ffffffff</color>
<string name="error_invalid_date">Invalid date</string>
<string name="profile_name_label">Profile name</string>
<string name="url_label">URL</string>
+ <string name="text_welcome">Welcome</string>
+ <string name="text_welcome_profile_needed">A profile needs to be created first</string>
+ <string name="create_profile_label">Create profile</string>
<string-array name="month_names">
<item>January</item>
<item>February</item>