/*
- * Copyright © 2020 Damyan Ivanov.
+ * Copyright © 2021 Damyan Ivanov.
* This file is part of MoLe.
* MoLe is free software: you can distribute it and/or modify it
* under the term of the GNU General Public License as published by
}
dependencies {
+ implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
def nav_version = '2.3.1'
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright © 2020 Damyan Ivanov.
+ ~ Copyright © 2021 Damyan Ivanov.
~ This file is part of MoLe.
~ MoLe is free software: you can distribute it and/or modify it
~ under the term of the GNU General Public License as published by
android:roundIcon="@drawable/app_icon_round"
android:supportsRtl="true"
tools:ignore="GoogleAppIndexingWarning">
+ <activity
+ android:name=".ui.activity.PatternsActivity"
+ android:label="@string/title_activity_patterns"
+ android:theme="@style/AppTheme.default" />
<activity
android:name=".ui.activity.SplashActivity"
android:label="@string/app_name"
--- /dev/null
+/*
+ * Copyright © 2021 Damyan Ivanov.
+ * This file is part of MoLe.
+ * MoLe 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.
+ *
+ * MoLe 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 MoLe. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package net.ktnx.mobileledger.model;
+
+public class PatternEntry {
+ private final int id;
+ private String name;
+ public PatternEntry(int id) {
+ this.id = id;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public int getId() { return id; }
+}
/*
- * Copyright © 2020 Damyan Ivanov.
+ * Copyright © 2021 Damyan Ivanov.
* This file is part of MoLe.
* MoLe is free software: you can distribute it and/or modify it
* under the term of the GNU General Public License as published by
Data.backgroundTasksRunning.observe(this, this::onRetrieveRunningChanged);
if (barDrawerToggle == null) {
- barDrawerToggle = new ActionBarDrawerToggle(this, b.drawerLayout, b.toolbar,
- R.string.navigation_drawer_open, R.string.navigation_drawer_close);
+ barDrawerToggle = new ActionBarDrawerToggle(this, b.drawerLayout, b.toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
b.drawerLayout.addDrawerListener(barDrawerToggle);
}
barDrawerToggle.syncState();
PackageInfo pi = getApplicationContext().getPackageManager()
.getPackageInfo(getPackageName(), 0);
((TextView) b.navUpper.findViewById(R.id.drawer_version_text)).setText(pi.versionName);
- ((TextView) b.noProfilesLayout.findViewById(R.id.drawer_version_text)).setText(
- pi.versionName);
+ ((TextView) b.noProfilesLayout.findViewById(R.id.drawer_version_text)).setText(pi.versionName);
}
catch (Exception e) {
e.printStackTrace();
.setValue(savedInstanceState.getString(STATE_ACC_FILTER, null));
}
- b.btnNoProfilesAdd.setOnClickListener(
- v -> MobileLedgerProfile.startEditProfileActivity(this, null));
+ b.btnNoProfilesAdd.setOnClickListener(v -> MobileLedgerProfile.startEditProfileActivity(this, null));
b.btnAddTransaction.setOnClickListener(this::fabNewTransactionClicked);
- b.navNewProfileButton.setOnClickListener(
- v -> MobileLedgerProfile.startEditProfileActivity(this, null));
+ b.navNewProfileButton.setOnClickListener(v -> MobileLedgerProfile.startEditProfileActivity(this, null));
b.transactionListCancelDownload.setOnClickListener(this::onStopTransactionRefreshClick);
b.navProfileList.setLayoutManager(llm);
b.navProfilesStartEdit.setOnClickListener((v) -> mProfileListAdapter.flipEditingProfiles());
- b.navProfilesCancelEdit.setOnClickListener(
- (v) -> mProfileListAdapter.flipEditingProfiles());
- b.navProfileListHeadButtons.setOnClickListener(
- (v) -> mProfileListAdapter.flipEditingProfiles());
+ b.navProfilesCancelEdit.setOnClickListener((v) -> mProfileListAdapter.flipEditingProfiles());
+ b.navProfileListHeadButtons.setOnClickListener((v) -> mProfileListAdapter.flipEditingProfiles());
if (drawerListener == null) {
drawerListener = new DrawerLayout.SimpleDrawerListener() {
@Override
Data.lastUpdateAccountCount.observe(this, date -> refreshLastUpdateInfo());
b.navAccountSummary.setOnClickListener(this::onAccountSummaryClicked);
b.navLatestTransactions.setOnClickListener(this::onLatestTransactionsClicked);
+ b.navPatterns.setOnClickListener(this::onPatternsClick);
+ }
+ private void onPatternsClick(View view) {
+ Intent intent = new Intent(this, PatternsActivity.class);
+ startActivity(intent);
}
private void scheduleDataRetrievalIfStale(long lastUpdate) {
long now = new Date().getTime();
/*
- * Copyright © 2020 Damyan Ivanov.
+ * Copyright © 2021 Damyan Ivanov.
* This file is part of MoLe.
* MoLe is free software: you can distribute it and/or modify it
* under the term of the GNU General Public License as published by
package net.ktnx.mobileledger.ui.activity;
+import android.app.Activity;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.renderscript.RSInvalidStateException;
import android.view.ViewGroup;
import android.widget.ProgressBar;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContract;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import org.jetbrains.annotations.NotNull;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
public class NewTransactionFragment extends Fragment {
private NewTransactionItemsAdapter listAdapter;
private NewTransactionModel viewModel;
+ final ActivityResultLauncher<Void> scanQrLauncher =
+ registerForActivityResult(new ActivityResultContract<Void, String>() {
+ @NonNull
+ @Override
+ public Intent createIntent(@NonNull Context context, Void input) {
+ final Intent intent = new Intent("com.google.zxing.client.android.SCAN");
+ intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
+ return intent;
+ }
+ @Override
+ public String parseResult(int resultCode, @Nullable Intent intent) {
+ if (resultCode == Activity.RESULT_CANCELED)
+ return null;
+ return intent.getStringExtra("SCAN_RESULT");
+ }
+ }, this::onQrScanned);
private FloatingActionButton fab;
private OnNewTransactionFragmentInteractionListener mListener;
private MobileLedgerProfile mProfile;
// Required empty public constructor
setHasOptionsMenu(true);
}
+ private void onQrScanned(String text) {
+ Logger.debug("qr", String.format("Got QR scan result [%s]", text));
+ Pattern p =
+ Pattern.compile("^(\\d+)\\*(\\d+)\\*(\\d+)-(\\d+)-(\\d+)\\*([:\\d]+)\\*([\\d.]+)$");
+ Matcher m = p.matcher(text);
+ if (m.matches()) {
+ float amount = Float.parseFloat(m.group(7));
+ viewModel.setDate(
+ new SimpleDate(Integer.parseInt(m.group(3)), Integer.parseInt(m.group(4)),
+ Integer.parseInt(m.group(5))));
+
+ if (viewModel.accountsInInitialState()) {
+ {
+ NewTransactionModel.Item firstItem = viewModel.getItem(1);
+ if (firstItem == null) {
+ viewModel.addAccount(new LedgerTransactionAccount("разход:пазар"));
+ listAdapter.notifyItemInserted(viewModel.items.size() - 1);
+ }
+ else {
+ firstItem.setAccountName("разход:пазар");
+ firstItem.getAccount()
+ .resetAmount();
+ listAdapter.notifyItemChanged(1);
+ }
+ }
+ {
+ NewTransactionModel.Item secondItem = viewModel.getItem(2);
+ if (secondItem == null) {
+ viewModel.addAccount(
+ new LedgerTransactionAccount("актив:кеш:дам", -amount, null, null));
+ listAdapter.notifyItemInserted(viewModel.items.size() - 1);
+ }
+ else {
+ secondItem.setAccountName("актив:кеш:дам");
+ secondItem.getAccount()
+ .setAmount(-amount);
+ listAdapter.notifyItemChanged(2);
+ }
+ }
+ }
+ else {
+ viewModel.addAccount(new LedgerTransactionAccount("разход:пазар"));
+ viewModel.addAccount(
+ new LedgerTransactionAccount("актив:кеш:дам", -amount, null, null));
+ listAdapter.notifyItemRangeInserted(viewModel.items.size() - 1, 2);
+ }
+
+ listAdapter.checkTransactionSubmittable();
+ }
+ }
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
final FragmentActivity activity = getActivity();
inflater.inflate(R.menu.new_transaction_fragment, menu);
+
+ menu.findItem(R.id.scan_qr)
+ .setOnMenuItemClickListener(this::onScanQrAction);
+
menu.findItem(R.id.action_reset_new_transaction_activity)
.setOnMenuItemClickListener(item -> {
listAdapter.reset();
if (activity != null)
viewModel.showComments.observe(activity, toggleCommentsItem::setChecked);
}
+ private boolean onScanQrAction(MenuItem item) {
+ try {
+ scanQrLauncher.launch(null);
+ }
+ catch (Exception e) {
+ Logger.debug("qr", "Error launching QR scanner", e);
+ }
+
+ return true;
+ }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
--- /dev/null
+/*
+ * Copyright © 2021 Damyan Ivanov.
+ * This file is part of MoLe.
+ * MoLe 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.
+ *
+ * MoLe 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 MoLe. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package net.ktnx.mobileledger.ui.activity;
+
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.View;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.google.android.material.snackbar.Snackbar;
+
+import net.ktnx.mobileledger.R;
+import net.ktnx.mobileledger.databinding.ActivityPatternsBinding;
+import net.ktnx.mobileledger.ui.patterns.PatternsModel;
+import net.ktnx.mobileledger.ui.patterns.PatternsRecyclerViewAdapter;
+
+public class PatternsActivity extends CrashReportingActivity {
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.pattern_list_menu, menu);
+
+ return true;
+ }
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ActivityPatternsBinding b = ActivityPatternsBinding.inflate(getLayoutInflater());
+ setContentView(b.getRoot());
+ setSupportActionBar(b.toolbar);
+ b.toolbarLayout.setTitle(getTitle());
+
+ b.fab.setOnClickListener(this::fabClicked);
+
+ PatternsRecyclerViewAdapter modelAdapter = new PatternsRecyclerViewAdapter();
+
+ b.patternList.setAdapter(modelAdapter);
+ PatternsModel.retrievePatterns(modelAdapter);
+ LinearLayoutManager llm = new LinearLayoutManager(this);
+ llm.setOrientation(RecyclerView.VERTICAL);
+ b.patternList.setLayoutManager(llm);
+ }
+ private void fabClicked(View view) {
+ Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_INDEFINITE)
+ .setAction("Action", null)
+ .show();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright © 2021 Damyan Ivanov.
+ * This file is part of MoLe.
+ * MoLe 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.
+ *
+ * MoLe 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 MoLe. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package net.ktnx.mobileledger.ui.patterns;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import net.ktnx.mobileledger.databinding.PatternLayoutBinding;
+import net.ktnx.mobileledger.model.PatternEntry;
+
+class PatternViewHolder extends RecyclerView.ViewHolder {
+ final PatternLayoutBinding b;
+ public PatternViewHolder(@NonNull PatternLayoutBinding binding) {
+ super(binding.getRoot());
+ b = binding;
+ }
+ public void bindToItem(PatternEntry item) {
+ b.patternName.setText(item.getName());
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2021 Damyan Ivanov.
+ * This file is part of MoLe.
+ * MoLe 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.
+ *
+ * MoLe 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 MoLe. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package net.ktnx.mobileledger.ui.patterns;
+
+import android.database.Cursor;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.MutableLiveData;
+
+import net.ktnx.mobileledger.model.PatternEntry;
+import net.ktnx.mobileledger.utils.Logger;
+import net.ktnx.mobileledger.utils.MLDB;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+public class PatternsModel {
+ private static final MutableLiveData<Integer> patternCount = new MutableLiveData<>(0);
+ private static final Map<Integer, WeakReference<PatternEntry>> cachedEntries =
+ new HashMap<Integer, WeakReference<PatternEntry>>() {};
+ public synchronized static void retrievePatterns(PatternsRecyclerViewAdapter modelAdapter) {
+ final ArrayList<PatternEntry> idList = new ArrayList<>();
+ MLDB.queryInBackground("select id, name from patterns", null, new MLDB.CallbackHelper() {
+ @Override
+ public void onDone() {
+ modelAdapter.setPatterns(idList);
+ Logger.debug("patterns",
+ String.format(Locale.US, "Pattern list loaded from db with %d entries",
+ idList.size()));
+ }
+ @Override
+ public boolean onRow(@NonNull Cursor cursor) {
+ final PatternEntry entry = new PatternEntry(cursor.getInt(0));
+ entry.setName(cursor.getString(1));
+ idList.add(entry);
+ return true;
+ }
+ });
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2021 Damyan Ivanov.
+ * This file is part of MoLe.
+ * MoLe 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.
+ *
+ * MoLe 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 MoLe. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package net.ktnx.mobileledger.ui.patterns;
+
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.AsyncListDiffer;
+import androidx.recyclerview.widget.DiffUtil;
+import androidx.recyclerview.widget.RecyclerView;
+
+import net.ktnx.mobileledger.databinding.PatternLayoutBinding;
+import net.ktnx.mobileledger.model.PatternEntry;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.Objects;
+
+public class PatternsRecyclerViewAdapter extends RecyclerView.Adapter<PatternViewHolder> {
+ private final AsyncListDiffer<PatternEntry> listDiffer;
+ public PatternsRecyclerViewAdapter() {
+ listDiffer = new AsyncListDiffer<>(this, new DiffUtil.ItemCallback<PatternEntry>() {
+ @Override
+ public boolean areItemsTheSame(@NotNull PatternEntry oldItem,
+ @NotNull PatternEntry newItem) {
+ return oldItem.getId() == newItem.getId();
+ }
+ @Override
+ public boolean areContentsTheSame(@NotNull PatternEntry oldItem,
+ @NotNull PatternEntry newItem) {
+ return Objects.equals(oldItem.getName(), newItem.getName());
+ }
+ });
+ }
+ @NonNull
+ @Override
+ public PatternViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ PatternLayoutBinding b =
+ PatternLayoutBinding.inflate(LayoutInflater.from(parent.getContext()), parent,
+ false);
+
+ return new PatternViewHolder(b);
+ }
+ @Override
+ public void onBindViewHolder(@NonNull PatternViewHolder holder, int position) {
+ holder.bindToItem(listDiffer.getCurrentList()
+ .get(position));
+ }
+ @Override
+ public int getItemCount() {
+ return listDiffer.getCurrentList()
+ .size();
+ }
+ public void setPatterns(List<PatternEntry> newList) {
+ listDiffer.submitList(newList);
+ }
+}
/*
- * Copyright © 2019 Damyan Ivanov.
+ * Copyright © 2021 Damyan Ivanov.
* This file is part of MoLe.
* MoLe is free software: you can distribute it and/or modify it
* under the term of the GNU General Public License as published by
(parent, itemView, position, id) -> callback.descriptionSelected(
String.valueOf(view.getText())));
}
- public static void queryInBackground(@NonNull String statement, @NonNull String[] params,
- @NonNull CallbackHelper callbackHelper) {
+ public static void queryInBackground(@NonNull String statement, String[] params,
+ @NonNull final CallbackHelper callbackHelper) {
/* All callbacks are called in the new (asynchronous) thread! */
Thread t = new Thread(() -> {
callbackHelper.onStart();
--- /dev/null
+<!--
+ ~ Copyright © 2021 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe 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.
+ ~
+ ~ MoLe 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 MoLe. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:autoMirrored="true"
+ android:tint="?colorPrimary"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M14.06,9.94L12,9l2.06,-0.94L15,6l0.94,2.06L18,9l-2.06,0.94L15,12L14.06,9.94zM4,14l0.94,-2.06L7,11l-2.06,-0.94L4,8l-0.94,2.06L1,11l2.06,0.94L4,14zM8.5,9l1.09,-2.41L12,5.5L9.59,4.41L8.5,2L7.41,4.41L5,5.5l2.41,1.09L8.5,9zM4.5,20.5l6,-6.01l4,4L23,8.93l-1.41,-1.41l-7.09,7.97l-4,-4L3,19L4.5,20.5z"
+ />
+</vector>
--- /dev/null
+<!--
+ ~ Copyright © 2021 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe 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.
+ ~
+ ~ MoLe 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 MoLe. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:autoMirrored="true"
+ android:tint="?colorPrimary"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,19h-2v-2h2v2zM15.07,11.25l-0.9,0.92C13.45,12.9 13,13.5 13,15h-2v-0.5c0,-1.1 0.45,-2.1 1.17,-2.83l1.24,-1.26c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2L8,9c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,0.88 -0.36,1.68 -0.93,2.25z"
+ />
+</vector>
--- /dev/null
+<!--
+ ~ Copyright © 2021 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe 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.
+ ~
+ ~ MoLe 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 MoLe. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:autoMirrored="true"
+ android:tint="?colorOnPrimary"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,19h-2v-2h2v2zM15.07,11.25l-0.9,0.92C13.45,12.9 13,13.5 13,15h-2v-0.5c0,-1.1 0.45,-2.1 1.17,-2.83l1.24,-1.26c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2L8,9c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,0.88 -0.36,1.68 -0.93,2.25z"
+ />
+</vector>
--- /dev/null
+<!--
+ ~ Copyright © 2021 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe 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.
+ ~
+ ~ MoLe 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 MoLe. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:autoMirrored="true"
+ android:tint="#EEEEEE"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9.5,6.5v3h-3v-3H9.5M11,5H5v6h6V5L11,5zM9.5,14.5v3h-3v-3H9.5M11,13H5v6h6V13L11,13zM17.5,6.5v3h-3v-3H17.5M19,5h-6v6h6V5L19,5zM13,13h1.5v1.5H13V13zM14.5,14.5H16V16h-1.5V14.5zM16,13h1.5v1.5H16V13zM13,16h1.5v1.5H13V16zM14.5,17.5H16V19h-1.5V17.5zM16,16h1.5v1.5H16V16zM17.5,14.5H19V16h-1.5V14.5zM17.5,17.5H19V19h-1.5V17.5zM22,7h-2V4h-3V2h5V7zM22,22v-5h-2v3h-3v2H22zM2,22h5v-2H4v-3H2V22zM2,2v5h2V4h3V2H2z"
+ />
+</vector>
<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright © 2020 Damyan Ivanov.
+ ~ Copyright © 2021 Damyan Ivanov.
~ This file is part of MoLe.
~ MoLe is free software: you can distribute it and/or modify it
~ under the term of the GNU General Public License as published by
android:layout_height="match_parent"
android:background="?android:attr/colorBackground"
android:orientation="vertical"
- android:visibility="gone"
+ android:visibility="visible"
>
<com.google.android.material.floatingactionbutton.FloatingActionButton
</LinearLayout>
</LinearLayout>
+ <TextView
+ android:id="@+id/nav_patterns"
+ style="@style/nav_button"
+ android:text="@string/nav_patterns"
+ app:drawableStartCompat="@drawable/ic_baseline_auto_graph_24"
+ />
</LinearLayout>
</ScrollView>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright © 2021 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe 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.
+ ~
+ ~ MoLe 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 MoLe. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
+
+ tools:context=".ui.activity.PatternsActivity"
+ >
+
+ <com.google.android.material.appbar.AppBarLayout
+ android:id="@+id/app_bar"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/app_bar_height"
+ android:fitsSystemWindows="true"
+ >
+
+ <com.google.android.material.appbar.CollapsingToolbarLayout
+ android:id="@+id/toolbar_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
+ app:contentScrim="?attr/colorPrimary"
+ app:layout_scrollFlags="scroll|exitUntilCollapsed"
+ app:toolbarId="@+id/toolbar"
+ >
+
+ <androidx.appcompat.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ app:layout_collapseMode="pin"
+ app:popupTheme="@style/AppTheme.PopupOverlay"
+ />
+
+ </com.google.android.material.appbar.CollapsingToolbarLayout>
+ </com.google.android.material.appbar.AppBarLayout>
+
+ <androidx.core.widget.NestedScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior"
+ tools:context=".ui.activity.PatternsActivity"
+ tools:showIn="@layout/activity_patterns"
+ >
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/pattern_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ />
+
+ </androidx.core.widget.NestedScrollView>
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
+ android:id="@+id/fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="@dimen/fab_margin"
+ app:layout_anchor="@id/pattern_list"
+ app:layout_anchorGravity="top|end"
+ app:layout_behavior="com.google.android.material.floatingactionbutton.FloatingActionButton$Behavior"
+ app:srcCompat="@drawable/ic_add_white_24dp"
+ />
+
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright © 2021 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe 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.
+ ~
+ ~ MoLe 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 MoLe. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ >
+ <TextView
+ android:id="@+id/pattern_name"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/text_margin"
+ android:layout_marginEnd="@dimen/text_margin"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/edit_buton"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ />
+ <ImageButton
+ android:id="@+id/edit_buton"
+ android:layout_width="@dimen/toolbar_height"
+ android:layout_height="@dimen/toolbar_height"
+ android:contentDescription="@string/edit_button_description"
+ android:src="@drawable/ic_mode_edit_black_24dp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ />
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright © 2020 Damyan Ivanov.
+ ~ Copyright © 2021 Damyan Ivanov.
~ This file is part of MoLe.
~ MoLe is free software: you can distribute it and/or modify it
~ under the term of the GNU General Public License as published by
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ >
+ <item
+ android:id="@+id/scan_qr"
+ android:icon="@drawable/ic_baseline_qr_code_scanner_24"
+ android:title="@string/scan_qr"
+ app:showAsAction="ifRoom"
+ />
<item
android:id="@+id/toggle_currency"
android:title="@string/show_currency_input"
android:checkable="true"
android:checked="false"
app:actionLayout="@layout/switch_item"
- app:showAsAction="never" />
+ app:showAsAction="never"
+ />
<item
android:id="@+id/toggle_comments"
android:checkable="true"
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright © 2021 Damyan Ivanov.
+ ~ This file is part of MoLe.
+ ~ MoLe 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.
+ ~
+ ~ MoLe 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 MoLe. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ >
+
+ <item
+ android:icon="@drawable/ic_baseline_help_24_white"
+ android:title="@string/help_menu_item_title"
+ app:showAsAction="ifRoom"
+ />
+</menu>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright © 2020 Damyan Ivanov.
+ ~ Copyright © 2021 Damyan Ivanov.
~ This file is part of MoLe.
~ MoLe is free software: you can distribute it and/or modify it
~ under the term of the GNU General Public License as published by
<string name="btn_profile_options">Настройка на профила</string>
<string name="err_json_send_error_head">Грешка при изпращане на движението към сървъра</string>
<string name="err_json_send_error_tail">Вероятно настроената версия на протокола не се поддържа.</string>
+ <string name="err_json_send_error_unsupported">Възможно е програмния интерфейс на сървъра да не се поддържа от MoLe</string>
+ <string name="scan_qr">Сканиране на QR код</string>
+ <string name="nav_patterns">Шаблони</string>
+ <string name="title_activity_patterns">Шаблони</string>
</resources>
<!--
- ~ Copyright © 2020 Damyan Ivanov.
+ ~ Copyright © 2021 Damyan Ivanov.
~ This file is part of MoLe.
~ MoLe is free software: you can distribute it and/or modify it
~ under the term of the GNU General Public License as published by
<string name="err_json_send_error_head">Error storing transaction on backend server</string>
<string name="err_json_send_error_tail">A mismatch in the configured API version could be causing this</string>
<string name="err_json_send_error_unsupported">Perhaps the API of the backend server is not supported by MoLe</string>
+ <string name="scan_qr">Scan QR code</string>
+ <string name="nav_patterns">Patterns</string>
+ <string name="title_activity_patterns">Patterns</string>
+ <string name="pattern_regex_hint">Pattern (regular expression)</string>
+ <string name="help_menu_item_title">Help</string>
+ <string name="edit_button_description">Edit button</string>
</resources>