diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..7a118b49 --- /dev/null +++ b/Gemfile @@ -0,0 +1,3 @@ +source "https://rubygems.org" + +gem "fastlane" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 00000000..97d10ae7 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,214 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.4) + rexml + addressable (2.8.0) + public_suffix (>= 2.0.2, < 5.0) + artifactory (3.0.15) + atomos (0.1.3) + aws-eventstream (1.2.0) + aws-partitions (1.505.0) + aws-sdk-core (3.121.0) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.239.0) + aws-sigv4 (~> 1.1) + jmespath (~> 1.0) + aws-sdk-kms (1.48.0) + aws-sdk-core (~> 3, >= 3.120.0) + aws-sigv4 (~> 1.1) + aws-sdk-s3 (1.103.0) + aws-sdk-core (~> 3, >= 3.120.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.4) + aws-sigv4 (1.4.0) + aws-eventstream (~> 1, >= 1.0.2) + babosa (1.0.4) + claide (1.0.3) + colored (1.2) + colored2 (3.1.2) + commander (4.6.0) + highline (~> 2.0.0) + declarative (0.0.20) + digest-crc (0.6.4) + rake (>= 12.0.0, < 14.0.0) + domain_name (0.5.20190701) + unf (>= 0.0.5, < 1.0.0) + dotenv (2.7.6) + emoji_regex (3.2.2) + excon (0.85.0) + faraday (1.8.0) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0.1) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.1) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) + multipart-post (>= 1.2, < 3) + ruby2_keywords (>= 0.0.4) + faraday-cookie_jar (0.0.7) + faraday (>= 0.8.0) + http-cookie (~> 1.0.0) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.0) + faraday-excon (1.1.0) + faraday-httpclient (1.0.1) + faraday-net_http (1.0.1) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + faraday_middleware (1.1.0) + faraday (~> 1.0) + fastimage (2.2.5) + fastlane (2.194.0) + CFPropertyList (>= 2.3, < 4.0.0) + addressable (>= 2.8, < 3.0.0) + artifactory (~> 3.0) + aws-sdk-s3 (~> 1.0) + babosa (>= 1.0.3, < 2.0.0) + bundler (>= 1.12.0, < 3.0.0) + colored + commander (~> 4.6) + dotenv (>= 2.1.1, < 3.0.0) + emoji_regex (>= 0.1, < 4.0) + excon (>= 0.71.0, < 1.0.0) + faraday (~> 1.0) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 1.0) + fastimage (>= 2.1.0, < 3.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) + google-apis-androidpublisher_v3 (~> 0.3) + google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-storage (~> 1.31) + highline (~> 2.0) + json (< 3.0.0) + jwt (>= 2.1.0, < 3) + mini_magick (>= 4.9.4, < 5.0.0) + multipart-post (~> 2.0.0) + naturally (~> 2.2) + optparse (~> 0.1.1) + plist (>= 3.1.0, < 4.0.0) + rubyzip (>= 2.0.0, < 3.0.0) + security (= 0.1.3) + simctl (~> 1.6.3) + terminal-notifier (>= 2.0.0, < 3.0.0) + terminal-table (>= 1.4.5, < 2.0.0) + tty-screen (>= 0.6.3, < 1.0.0) + tty-spinner (>= 0.8.0, < 1.0.0) + word_wrap (~> 1.0.0) + xcodeproj (>= 1.13.0, < 2.0.0) + xcpretty (~> 0.3.0) + xcpretty-travis-formatter (>= 0.0.3) + gh_inspector (1.1.3) + google-apis-androidpublisher_v3 (0.11.0) + google-apis-core (>= 0.4, < 2.a) + google-apis-core (0.4.1) + addressable (~> 2.5, >= 2.5.1) + googleauth (>= 0.16.2, < 2.a) + httpclient (>= 2.8.1, < 3.a) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.a) + rexml + webrick + google-apis-iamcredentials_v1 (0.7.0) + google-apis-core (>= 0.4, < 2.a) + google-apis-playcustomapp_v1 (0.5.0) + google-apis-core (>= 0.4, < 2.a) + google-apis-storage_v1 (0.7.0) + google-apis-core (>= 0.4, < 2.a) + google-cloud-core (1.6.0) + google-cloud-env (~> 1.0) + google-cloud-errors (~> 1.0) + google-cloud-env (1.5.0) + faraday (>= 0.17.3, < 2.0) + google-cloud-errors (1.2.0) + google-cloud-storage (1.34.1) + addressable (~> 2.5) + digest-crc (~> 0.4) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.1) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) + mini_mime (~> 1.0) + googleauth (0.17.1) + faraday (>= 0.17.3, < 2.0) + jwt (>= 1.4, < 3.0) + memoist (~> 0.16) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (~> 0.15) + highline (2.0.3) + http-cookie (1.0.4) + domain_name (~> 0.5) + httpclient (2.8.3) + jmespath (1.4.0) + json (2.5.1) + jwt (2.2.3) + memoist (0.16.2) + mini_magick (4.11.0) + mini_mime (1.1.1) + multi_json (1.15.0) + multipart-post (2.0.0) + nanaimo (0.3.0) + naturally (2.2.1) + optparse (0.1.1) + os (1.1.1) + plist (3.6.0) + public_suffix (4.0.6) + rake (13.0.6) + representable (3.1.1) + declarative (< 0.1.0) + trailblazer-option (>= 0.1.1, < 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + rexml (3.2.5) + rouge (2.0.7) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) + security (0.1.3) + signet (0.16.0) + addressable (~> 2.8) + faraday (>= 0.17.3, < 2.0) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + simctl (1.6.8) + CFPropertyList + naturally + terminal-notifier (2.0.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + trailblazer-option (0.1.1) + tty-cursor (0.7.1) + tty-screen (0.8.1) + tty-spinner (0.9.3) + tty-cursor (~> 0.7) + uber (0.1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.8) + unicode-display_width (1.8.0) + webrick (1.7.0) + word_wrap (1.0.0) + xcodeproj (1.21.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.3.0) + rexml (~> 3.2.4) + xcpretty (0.3.0) + rouge (~> 2.0.7) + xcpretty-travis-formatter (1.0.1) + xcpretty (~> 0.2, >= 0.0.7) + +PLATFORMS + universal-darwin-20 + +DEPENDENCIES + fastlane + +BUNDLED WITH + 2.2.26 diff --git a/app/build.gradle b/app/build.gradle index 51f70095..049633c8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -48,8 +48,8 @@ android { applicationId "com.handydev.financier" minSdkVersion 21 targetSdkVersion 29 - versionCode 222 - versionName "2.0.22" + versionCode 223 + versionName "2.0.23" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled true javaCompileOptions { @@ -144,10 +144,11 @@ dependencies { implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" implementation "androidx.viewpager2:viewpager2:1.0.0" implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" + implementation "androidx.preference:preference-ktx:1.1.1" //googledrive googleplayImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' - googleplayImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + googleplayImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0' googleplayImplementation 'com.google.android.gms:play-services-auth:19.2.0' googleplayImplementation 'com.google.http-client:google-http-client-gson:1.26.0' googleplayImplementation 'com.google.api-client:google-api-client-android:1.26.0' @@ -163,7 +164,7 @@ dependencies { //untied - SAME AS ABOVE untiedImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' - untiedImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + untiedImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0' untiedImplementation 'com.google.android.gms:play-services-auth:19.2.0' untiedImplementation 'com.google.http-client:google-http-client-gson:1.26.0' untiedImplementation 'com.google.api-client:google-api-client-android:1.26.0' diff --git a/app/src/fdroid/java/com/handydev/financier/MainActivity.kt b/app/src/fdroid/java/com/handydev/financier/MainActivity.kt index d23adba5..5b21a4c2 100644 --- a/app/src/fdroid/java/com/handydev/financier/MainActivity.kt +++ b/app/src/fdroid/java/com/handydev/financier/MainActivity.kt @@ -1,14 +1,3 @@ -/******************************************************************************* - * Copyright (c) 2010 Denis Solonenko. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v2.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * - * - * Contributors: - * Denis Solonenko - initial API and implementation - */ package com.handydev.financier import android.content.Context @@ -22,6 +11,7 @@ import androidx.databinding.DataBindingUtil import androidx.fragment.app.FragmentActivity import androidx.lifecycle.ViewModelProvider import androidx.viewpager2.widget.ViewPager2 +import com.handydev.financier.activity.RefreshSupportedActivity import com.handydev.financier.bus.RefreshData import com.handydev.financier.databinding.MainBinding import com.handydev.financier.db.DatabaseAdapter @@ -133,7 +123,8 @@ class MainActivity : FragmentActivity() { fun refreshCurrentTab() { for(fragment in supportFragmentManager.fragments) { - if(fragment.isVisible && fragment is RefreshSupportedActivity) { + if(fragment.isVisible && fragment is RefreshSupportedActivity + ) { fragment.recreateCursor() fragment.integrityCheck() } diff --git a/app/src/fdroid/java/com/handydev/financier/activity/PreferencesActivity.java b/app/src/fdroid/java/com/handydev/financier/activity/PreferencesActivity.java index 9262e5b0..02793638 100644 --- a/app/src/fdroid/java/com/handydev/financier/activity/PreferencesActivity.java +++ b/app/src/fdroid/java/com/handydev/financier/activity/PreferencesActivity.java @@ -1,13 +1,3 @@ -/******************************************************************************* - * Copyright (c) 2010 Denis Solonenko. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v2.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * - * Contributors: - * Denis Solonenko - initial API and implementation - ******************************************************************************/ package com.handydev.financier.activity; import android.Manifest; diff --git a/app/src/fdroid/java/com/handydev/financier/app/FinancierApp.java b/app/src/fdroid/java/com/handydev/financier/app/FinancierApp.java index 3edcb83c..a453cd91 100644 --- a/app/src/fdroid/java/com/handydev/financier/app/FinancierApp.java +++ b/app/src/fdroid/java/com/handydev/financier/app/FinancierApp.java @@ -3,8 +3,7 @@ import android.content.Context; import android.content.res.Configuration; -import androidx.multidex.MultiDexApplication; - +import com.handydev.financier.FinancierApplication; import com.handydev.financier.utils.MyPreferences; import org.androidannotations.annotations.AfterInject; diff --git a/app/src/googleplay/AndroidManifext.xml b/app/src/googleplay/AndroidManifest.xml similarity index 100% rename from app/src/googleplay/AndroidManifext.xml rename to app/src/googleplay/AndroidManifest.xml diff --git a/app/src/googleplay/java/com/handydev/financier/MainActivity.kt b/app/src/googleplay/java/com/handydev/financier/MainActivity.kt index fdcbb054..882195fa 100644 --- a/app/src/googleplay/java/com/handydev/financier/MainActivity.kt +++ b/app/src/googleplay/java/com/handydev/financier/MainActivity.kt @@ -28,7 +28,7 @@ import com.google.android.gms.auth.api.signin.GoogleSignInAccount import com.google.android.gms.auth.api.signin.GoogleSignInOptions import com.google.android.gms.common.api.Scope import com.google.api.services.drive.DriveScopes -import com.handydev.financier.activity.PreferencesActivity.CHOOSE_ACCOUNT +import com.handydev.financier.activity.PreferencesActivity.Companion.CHOOSE_ACCOUNT import com.handydev.financier.activity.RefreshSupportedActivity import com.handydev.financier.app.FinancierApp import com.handydev.financier.base.AbstractListFragment @@ -42,7 +42,7 @@ import com.handydev.financier.protocol.IOnBackPressed import com.handydev.financier.utils.CurrencyCache import com.handydev.financier.utils.MyPreferences import com.handydev.financier.utils.PinProtection -import com.handydev.main.fragments.MenuListFragment +import com.handydev.financier.fragments.MenuListFragment import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode diff --git a/app/src/googleplay/java/com/handydev/financier/activity/PreferencesActivity.java b/app/src/googleplay/java/com/handydev/financier/activity/PreferencesActivity.java deleted file mode 100644 index 43309467..00000000 --- a/app/src/googleplay/java/com/handydev/financier/activity/PreferencesActivity.java +++ /dev/null @@ -1,280 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010 Denis Solonenko. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v2.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * - * Contributors: - * Denis Solonenko - initial API and implementation - ******************************************************************************/ -package com.handydev.financier.activity; - -import android.Manifest; -import android.accounts.Account; -import android.accounts.AccountManager; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.Intent.ShortcutIconResource; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.preference.Preference; -import android.preference.Preference.OnPreferenceChangeListener; -import android.preference.PreferenceActivity; -import android.preference.PreferenceManager; -import android.preference.PreferenceScreen; - -import com.google.android.gms.auth.api.signin.GoogleSignIn; -import com.google.android.gms.auth.api.signin.GoogleSignInClient; -import com.google.android.gms.auth.api.signin.GoogleSignInOptions; -import com.google.android.gms.common.api.Scope; -import com.google.api.services.drive.DriveScopes; -import com.handydev.financier.R; -import com.handydev.financier.app.FinancierApp; -import com.handydev.financier.dialog.FolderBrowser; -import com.handydev.financier.export.Export; -import com.handydev.financier.export.drive.DriveBackupError; -import com.handydev.financier.export.dropbox.Dropbox; -import com.handydev.financier.rates.ExchangeRateProviderFactory; -import com.handydev.financier.utils.MyPreferences; -import com.handydev.financier.utils.PinProtection; - -import org.greenrobot.eventbus.EventBus; - -import static com.handydev.financier.activity.RequestPermission.isRequestingPermission; -import static com.handydev.financier.utils.FingerprintUtils.fingerprintUnavailable; -import static com.handydev.financier.utils.FingerprintUtils.reasonWhyFingerprintUnavailable; - -public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener { - - private static final int SELECT_DATABASE_FOLDER = 100; - public static final int CHOOSE_ACCOUNT = 101; - - Preference pOpenExchangeRatesAppId; - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - setGDriveBackupFolder(); - } - - - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(MyPreferences.switchLocale(base)); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - addPreferencesFromResource(R.xml.preferences); - PreferenceScreen preferenceScreen = getPreferenceScreen(); - setGDriveBackupFolder(); - Preference pLocale = preferenceScreen.findPreference("ui_language"); - pLocale.setOnPreferenceChangeListener((preference, newValue) -> { - String locale = (String) newValue; - MyPreferences.switchLocale(PreferencesActivity.this, locale); - return true; - }); - Preference pNewTransactionShortcut = preferenceScreen.findPreference("shortcut_new_transaction"); - pNewTransactionShortcut.setOnPreferenceClickListener(arg0 -> { - addShortcut(".activity.TransactionActivity", R.string.transaction, R.drawable.icon_transaction); - return true; - }); - Preference pNewTransferShortcut = preferenceScreen.findPreference("shortcut_new_transfer"); - pNewTransferShortcut.setOnPreferenceClickListener(arg0 -> { - addShortcut(".activity.TransferActivity", R.string.transfer, R.drawable.icon_transfer); - return true; - }); - Preference pDatabaseBackupFolder = preferenceScreen.findPreference("database_backup_folder"); - pDatabaseBackupFolder.setOnPreferenceClickListener(arg0 -> { - if (isRequestingPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - return false; - } - selectDatabaseBackupFolder(); - return true; - }); - - Preference pGDriveBackupFolder = preferenceScreen.findPreference("backup_folder"); - pGDriveBackupFolder.setOnPreferenceChangeListener((preference, o) -> { - setGDriveBackupFolder(); - return true; - }); - - Preference pAuthDropbox = preferenceScreen.findPreference("dropbox_authorize"); - pAuthDropbox.setOnPreferenceClickListener(arg0 -> { - authDropbox(); - return true; - }); - Preference pDeauthDropbox = preferenceScreen.findPreference("dropbox_unlink"); - pDeauthDropbox.setOnPreferenceClickListener(arg0 -> { - deAuthDropbox(); - return true; - }); - Preference pExchangeProvider = preferenceScreen.findPreference("exchange_rate_provider"); - pOpenExchangeRatesAppId = preferenceScreen.findPreference("openexchangerates_app_id"); - pExchangeProvider.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - pOpenExchangeRatesAppId.setEnabled(isOpenExchangeRatesProvider((String) newValue)); - return true; - } - - private boolean isOpenExchangeRatesProvider(String provider) { - return ExchangeRateProviderFactory.openexchangerates.name().equals(provider); - } - }); - Preference pDriveAccount = preferenceScreen.findPreference("google_drive_backup_account"); - pDriveAccount.setOnPreferenceClickListener(arg0 -> { - chooseAccount(); - return true; - }); - Preference useFingerprint = preferenceScreen.findPreference("pin_protection_use_fingerprint"); - if (fingerprintUnavailable(this)) { - useFingerprint.setSummary(getString(R.string.fingerprint_unavailable, reasonWhyFingerprintUnavailable(this))); - useFingerprint.setEnabled(false); - } - linkToDropbox(); - setCurrentDatabaseBackupFolder(); - enableOpenExchangeApp(); - selectAccount(); - } - - private void chooseAccount() { - GoogleSignInOptions signInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) - .requestEmail() - .requestScopes(new Scope(DriveScopes.DRIVE_FILE), new Scope(DriveScopes.DRIVE_APPDATA)) - .build(); - GoogleSignInClient client = GoogleSignIn.getClient(this, signInOptions); - client.signOut().addOnSuccessListener(aVoid -> { - MyPreferences.setGoogleDriveAccount(PreferencesActivity.this, ""); - startActivityForResult(client.getSignInIntent(), CHOOSE_ACCOUNT); - }); - } - - private Account getSelectedAccount() { - String accountName = MyPreferences.getGoogleDriveAccount(this); - if (accountName != null) { - AccountManager accountManager = AccountManager.get(this); - Account[] accounts = accountManager.getAccountsByType("com.google"); - for (Account account : accounts) { - if (accountName.equals(account.name)) { - return account; - } - } - } - return null; - } - - private void linkToDropbox() { - boolean dropboxAuthorized = MyPreferences.isDropboxAuthorized(this); - PreferenceScreen preferenceScreen = getPreferenceScreen(); - preferenceScreen.findPreference("dropbox_unlink").setEnabled(dropboxAuthorized); - preferenceScreen.findPreference("dropbox_upload_backup").setEnabled(dropboxAuthorized); - preferenceScreen.findPreference("dropbox_upload_autobackup").setEnabled(dropboxAuthorized); - } - - private void selectDatabaseBackupFolder() { - Intent intent = new Intent(this, FolderBrowser.class); - intent.putExtra(FolderBrowser.PATH, getDatabaseBackupFolder()); - startActivityForResult(intent, SELECT_DATABASE_FOLDER); - } - - private void enableOpenExchangeApp() { - pOpenExchangeRatesAppId.setEnabled(MyPreferences.isOpenExchangeRatesProviderSelected(this)); - } - - private String getDatabaseBackupFolder() { - return Export.getBackupFolder(this).getAbsolutePath(); - } - - private void setCurrentDatabaseBackupFolder() { - Preference pDatabaseBackupFolder = getPreferenceScreen().findPreference("database_backup_folder"); - String summary = getString(R.string.database_backup_folder_summary, getDatabaseBackupFolder()); - pDatabaseBackupFolder.setSummary(summary); - } - - private void setGDriveBackupFolder() { - Preference pGDriveBackupFolder = getPreferenceScreen().findPreference("backup_folder"); - pGDriveBackupFolder.setSummary(MyPreferences.getBackupFolder(this)); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_OK) { - switch (requestCode) { - case SELECT_DATABASE_FOLDER: - String databaseBackupFolder = data.getStringExtra(FolderBrowser.PATH); - MyPreferences.setDatabaseBackupFolder(this, databaseBackupFolder); - setCurrentDatabaseBackupFolder(); - break; - case CHOOSE_ACCOUNT: - handleSignInResult(data); - break; - } - } - } - - private void handleSignInResult(Intent intent) { - GoogleSignIn.getSignedInAccountFromIntent(intent).addOnSuccessListener(googleSignInAccount -> { - MyPreferences.setGoogleDriveAccount(this, googleSignInAccount.getEmail()); - FinancierApp.driveClient.setAccount(googleSignInAccount.getAccount()); - selectAccount(); - }).addOnFailureListener(e -> EventBus.getDefault().post(new DriveBackupError(e.getMessage()))); - } - - private void selectAccount() { - Preference pDriveAccount = getPreferenceScreen().findPreference("google_drive_backup_account"); - Account account = getSelectedAccount(); - if (account != null) { - pDriveAccount.setSummary(account.name); - } - } - - private void addShortcut(String activity, int nameId, int iconId) { - Intent intent = createShortcutIntent(activity, getString(nameId), Intent.ShortcutIconResource.fromContext(this, iconId), - "com.android.launcher.action.INSTALL_SHORTCUT"); - sendBroadcast(intent); - } - - private Intent createShortcutIntent(String activity, String shortcutName, ShortcutIconResource shortcutIcon, String action) { - Intent shortcutIntent = new Intent(); - shortcutIntent.setComponent(new ComponentName(this.getPackageName(), activity)); - shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - Intent intent = new Intent(); - intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); - intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, shortcutName); - intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIcon); - intent.setAction(action); - return intent; - } - - Dropbox dropbox = new Dropbox(this); - - private void authDropbox() { - dropbox.startAuth(); - } - - private void deAuthDropbox() { - dropbox.deAuth(); - linkToDropbox(); - } - - @Override - protected void onPause() { - super.onPause(); - PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this); - PinProtection.lock(this); - } - - @Override - protected void onResume() { - super.onResume(); - PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); - PinProtection.unlock(this); - dropbox.completeAuth(); - linkToDropbox(); - } -} diff --git a/app/src/googleplay/java/com/handydev/financier/activity/PreferencesActivity.kt b/app/src/googleplay/java/com/handydev/financier/activity/PreferencesActivity.kt new file mode 100644 index 00000000..c4c59acf --- /dev/null +++ b/app/src/googleplay/java/com/handydev/financier/activity/PreferencesActivity.kt @@ -0,0 +1,332 @@ +package com.handydev.financier.activity + +import android.Manifest +import android.accounts.Account +import android.accounts.AccountManager +import android.app.Activity.RESULT_CANCELED +import android.app.Activity.RESULT_OK +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.SharedPreferences +import android.os.Bundle +import android.provider.Contacts.SettingsColumns.KEY +import androidx.appcompat.app.AppCompatActivity +import androidx.preference.Preference +import androidx.preference.PreferenceFragmentCompat +import androidx.preference.PreferenceManager +import androidx.preference.PreferenceScreen +import com.google.android.gms.auth.api.signin.GoogleSignIn +import com.google.android.gms.auth.api.signin.GoogleSignInClient +import com.google.android.gms.auth.api.signin.GoogleSignInOptions +import com.google.android.gms.common.api.Scope +import com.google.api.services.drive.DriveScopes +import com.handydev.financier.R +import com.handydev.financier.activity.PreferencesActivity.Companion.CHOOSE_ACCOUNT +import com.handydev.financier.activity.PreferencesActivity.Companion.SELECT_DATABASE_FOLDER +import com.handydev.financier.activity.RequestPermission.isRequestingPermission +import com.handydev.financier.app.FinancierApp +import com.handydev.financier.dialog.FolderBrowser +import com.handydev.financier.dialog.PinDialogPreference +import com.handydev.financier.export.Export +import com.handydev.financier.export.drive.DriveBackupError +import com.handydev.financier.export.dropbox.Dropbox +import com.handydev.financier.fragments.FinancierPreferenceDialogFragment +import com.handydev.financier.rates.ExchangeRateProviderFactory +import com.handydev.financier.utils.FingerprintUtils.fingerprintUnavailable +import com.handydev.financier.utils.FingerprintUtils.reasonWhyFingerprintUnavailable +import com.handydev.financier.utils.MyPreferences +import com.handydev.financier.utils.PinProtection +import org.greenrobot.eventbus.EventBus + +class PreferencesFragment: PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener { + var pOpenExchangeRatesAppId: Preference? = null + var dropbox: Dropbox? = null + private var rootKey: String? = null + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + setGDriveBackupFolder() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + val unmaskedRequestCode = requestCode and 0x0000ffff + if (resultCode == RESULT_OK || resultCode == RESULT_CANCELED) { + when (unmaskedRequestCode) { + SELECT_DATABASE_FOLDER -> { + val databaseBackupFolder = data?.getStringExtra(FolderBrowser.PATH) + MyPreferences.setDatabaseBackupFolder(context, databaseBackupFolder) + setCurrentDatabaseBackupFolder() + } + CHOOSE_ACCOUNT -> if(data != null) { handleSignInResult(data) } + } + } + } + + private fun handleSignInResult(intent: Intent) { + GoogleSignIn.getSignedInAccountFromIntent(intent) + .addOnSuccessListener { googleSignInAccount -> + MyPreferences.setGoogleDriveAccount(context, googleSignInAccount.email) + FinancierApp.driveClient.account = googleSignInAccount.account + selectAccount() + }.addOnFailureListener { e -> + EventBus.getDefault().post(DriveBackupError(e.message)) + } + } + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + this.rootKey = rootKey + dropbox = Dropbox(context) + setPreferencesFromResource(R.xml.preferences, rootKey) + if(rootKey != null) { + return + } + setGDriveBackupFolder() + val pLocale: Preference? = preferenceScreen?.findPreference("ui_language") + pLocale?.setOnPreferenceChangeListener { _, newValue -> + val locale = newValue as String + MyPreferences.switchLocale(this@PreferencesFragment.context, locale) + true + } + val pNewTransactionShortcut: Preference? = + preferenceScreen?.findPreference("shortcut_new_transaction") + pNewTransactionShortcut?.setOnPreferenceClickListener { + addShortcut( + ".activity.TransactionActivity", + R.string.transaction, + R.drawable.icon_transaction + ) + true + } + val pNewTransferShortcut: Preference? = + preferenceScreen.findPreference("shortcut_new_transfer") + pNewTransferShortcut?.setOnPreferenceClickListener { + addShortcut(".activity.TransferActivity", R.string.transfer, R.drawable.icon_transfer) + true + } + val pDatabaseBackupFolder: Preference? = + preferenceScreen.findPreference("database_backup_folder") + pDatabaseBackupFolder?.setOnPreferenceClickListener { + if (isRequestingPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + return@setOnPreferenceClickListener false + } + selectDatabaseBackupFolder() + true + } + val pGDriveBackupFolder: Preference? = preferenceScreen?.findPreference("backup_folder") + pGDriveBackupFolder?.setOnPreferenceChangeListener { _, _ -> + setGDriveBackupFolder() + true + } + val pAuthDropbox: Preference? = preferenceScreen.findPreference("dropbox_authorize") + pAuthDropbox?.setOnPreferenceClickListener { + authDropbox() + true + } + val pDeauthDropbox: Preference? = preferenceScreen.findPreference("dropbox_unlink") + pDeauthDropbox?.setOnPreferenceClickListener { + deAuthDropbox() + true + } + val pExchangeProvider: Preference? = + preferenceScreen.findPreference("exchange_rate_provider") + pOpenExchangeRatesAppId = preferenceScreen.findPreference("openexchangerates_app_id") + pExchangeProvider?.onPreferenceChangeListener = Preference.OnPreferenceChangeListener() { preference, newValue -> + pOpenExchangeRatesAppId?.isEnabled = isOpenExchangeRatesProvider(newValue as String?) + true + } + val pDriveAccount: Preference? = + preferenceScreen.findPreference("google_drive_backup_account") + pDriveAccount?.setOnPreferenceClickListener { arg0 -> + chooseAccount() + true + } + val useFingerprint: Preference? = + preferenceScreen.findPreference("pin_protection_use_fingerprint") + if (fingerprintUnavailable(context)) { + useFingerprint?.summary = getString( + R.string.fingerprint_unavailable, + reasonWhyFingerprintUnavailable(context) + ) + useFingerprint?.isEnabled = false + } + linkToDropbox() + setCurrentDatabaseBackupFolder() + enableOpenExchangeApp() + selectAccount() + } + + override fun onDisplayPreferenceDialog(preference: Preference?) { + if (preference is PinDialogPreference) { + val fragment = FinancierPreferenceDialogFragment.newInstance(preference.key) + fragment?.setTargetFragment(this, 0) + val manager = requireFragmentManager() + fragment?.show(manager, null) + } else { + super.onDisplayPreferenceDialog(preference) + } + } + + private fun setGDriveBackupFolder() { + val pGDriveBackupFolder: Preference? = preferenceScreen?.findPreference("backup_folder") + pGDriveBackupFolder?.summary = MyPreferences.getBackupFolder(context) + } + + private fun chooseAccount() { + val signInOptions: GoogleSignInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestEmail() + .requestScopes(Scope(DriveScopes.DRIVE_FILE), Scope(DriveScopes.DRIVE_APPDATA)) + .build() + val client: GoogleSignInClient = GoogleSignIn.getClient(requireContext(), signInOptions) + client.signOut().addOnSuccessListener { + MyPreferences.setGoogleDriveAccount(this@PreferencesFragment.context, "") + startActivityForResult(client.signInIntent, PreferencesActivity.CHOOSE_ACCOUNT) + } + } + + private fun selectAccount() { + val pDriveAccount: Preference? = + preferenceScreen.findPreference("google_drive_backup_account") + val account: Account? = selectedAccount + if (account != null) { + pDriveAccount?.summary = account.name + } + } + + private val selectedAccount: Account? + get() { + val accountName = MyPreferences.getGoogleDriveAccount(context) + if (accountName != null) { + val accountManager: AccountManager = AccountManager.get(context) + val accounts: Array = accountManager.getAccountsByType("com.google") + for (account in accounts) { + if (accountName.equals(account.name)) { + return account + } + } + } + return null + } + + private fun linkToDropbox() { + val dropboxAuthorized: Boolean = MyPreferences.isDropboxAuthorized(context) + preferenceScreen.findPreference("dropbox_unlink")?.isEnabled = dropboxAuthorized + preferenceScreen.findPreference("dropbox_upload_backup")?.isEnabled = dropboxAuthorized + preferenceScreen.findPreference("dropbox_upload_autobackup")?.isEnabled = dropboxAuthorized + } + + private fun selectDatabaseBackupFolder() { + val intent = Intent(context, FolderBrowser::class.java) + intent.putExtra(FolderBrowser.PATH, databaseBackupFolder) + startActivityForResult(intent, PreferencesActivity.SELECT_DATABASE_FOLDER) + } + + private fun enableOpenExchangeApp() { + pOpenExchangeRatesAppId?.isEnabled = MyPreferences.isOpenExchangeRatesProviderSelected(context) + } + + private val databaseBackupFolder: String + get() = Export.getBackupFolder(context).absolutePath + + private fun setCurrentDatabaseBackupFolder() { + val pDatabaseBackupFolder: Preference? = + preferenceScreen.findPreference("database_backup_folder") + val summary: String = + getString(R.string.database_backup_folder_summary, databaseBackupFolder) + pDatabaseBackupFolder?.summary = summary + } + + private fun isOpenExchangeRatesProvider(provider: String?): Boolean { + return ExchangeRateProviderFactory.openexchangerates.name == provider + } + + private fun addShortcut(activity: String, nameId: Int, iconId: Int) { + val intent: Intent = createShortcutIntent( + activity, getString(nameId), Intent.ShortcutIconResource.fromContext(context, iconId), + "com.android.launcher.action.INSTALL_SHORTCUT" + ) + requireActivity().sendBroadcast(intent) + } + + private fun createShortcutIntent( + activity: String, + shortcutName: String, + shortcutIcon: Intent.ShortcutIconResource, + action: String + ): Intent { + val shortcutIntent = Intent() + shortcutIntent.component = ComponentName(requireContext().packageName, activity) + shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + val intent = Intent() + intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent) + intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, shortcutName) + intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIcon) + intent.action = action + return intent + } + + private fun authDropbox() { + dropbox?.startAuth() + } + + private fun deAuthDropbox() { + dropbox?.deAuth() + linkToDropbox() + } + + override fun onPause() { + super.onPause() + if(rootKey == null) { + PreferenceManager.getDefaultSharedPreferences(context) + .unregisterOnSharedPreferenceChangeListener(this) + PinProtection.lock(context) + } + } + + override fun onResume() { + super.onResume() + if(rootKey == null) { + PreferenceManager.getDefaultSharedPreferences(context) + .registerOnSharedPreferenceChangeListener(this) + PinProtection.unlock(context) + dropbox?.completeAuth() + linkToDropbox() + } + } +} + +class PreferencesActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartScreenCallback { //PreferenceActivity(), SharedPreferences.OnSharedPreferenceChangeListener { + override fun attachBaseContext(base: Context?) { + super.attachBaseContext(MyPreferences.switchLocale(base)) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + supportActionBar?.hide() + val key = intent.getStringExtra(STARTING_KEY) + val args = Bundle() + val fragment = PreferencesFragment() + if(key != null) { + args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, key) + fragment.arguments = args + } + supportFragmentManager.beginTransaction().replace(android.R.id.content, fragment).commit() + } + + companion object { + const val SELECT_DATABASE_FOLDER = 100 + const val CHOOSE_ACCOUNT = 101 + const val STARTING_KEY = "Key" + } + + override fun onPreferenceStartScreen( + caller: PreferenceFragmentCompat?, + pref: PreferenceScreen? + ): Boolean { + val intent = Intent(this@PreferencesActivity, PreferencesActivity::class.java) + intent.putExtra(STARTING_KEY, pref?.key) + startActivity(intent) + return true + } +} \ No newline at end of file diff --git a/app/src/googleplay/java/com/handydev/financier/fragments/MenuListFragment.kt b/app/src/googleplay/java/com/handydev/financier/fragments/MenuListFragment.kt index 4fd435f0..79c4f9e3 100644 --- a/app/src/googleplay/java/com/handydev/financier/fragments/MenuListFragment.kt +++ b/app/src/googleplay/java/com/handydev/financier/fragments/MenuListFragment.kt @@ -1,4 +1,4 @@ -package com.handydev.main.fragments +package com.handydev.financier.fragments import android.app.Activity import androidx.appcompat.app.AlertDialog diff --git a/app/src/googleplay/res/xml/preferences.xml b/app/src/googleplay/res/xml/preferences.xml index dff98979..ecda1dec 100644 --- a/app/src/googleplay/res/xml/preferences.xml +++ b/app/src/googleplay/res/xml/preferences.xml @@ -1,13 +1,3 @@ - @@ -304,11 +297,7 @@ android:key="auto_backup_enabled" android:summary="@string/auto_backup_enabled_summary" android:title="@string/auto_backup_enabled" /> - + +

2.0.23, 27 Sep 2021

+

+[*]All transaction lists now look the same (and correct). +[*]Transaction list is now updated after a transaction is entered/edited. +[*]Preferences completely refactored (nothing should change for the user). +

+

2.0.22, 24 Sep 2021

- [*]Fix date selection in filters not completely visible sometimes. - [*]Fixed time selector in filters always showing AM/PM even when not needed. +[*]Fix date selection in filters not completely visible sometimes. +[*]Fixed time selector in filters always showing AM/PM even when not needed.

2.0.21, 10 Sep 2021

diff --git a/app/src/main/java/com/handydev/financier/MainViewModel.kt b/app/src/main/java/com/handydev/financier/MainViewModel.kt index 423eb3fd..b2f2ef1d 100644 --- a/app/src/main/java/com/handydev/financier/MainViewModel.kt +++ b/app/src/main/java/com/handydev/financier/MainViewModel.kt @@ -13,8 +13,6 @@ import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.adapter.FragmentStateAdapter import com.handydev.financier.utils.MyPreferences import com.handydev.financier.fragments.* -import com.handydev.main.fragments.MenuListFragment - class MainViewModelFactory(val activity: FragmentActivity, val context: Context) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { diff --git a/app/src/main/java/com/handydev/financier/activity/BlotterActivity.java b/app/src/main/java/com/handydev/financier/activity/BlotterActivity.java index 243ac082..322b4dff 100644 --- a/app/src/main/java/com/handydev/financier/activity/BlotterActivity.java +++ b/app/src/main/java/com/handydev/financier/activity/BlotterActivity.java @@ -26,7 +26,6 @@ import greendroid.widget.QuickActionWidget; import com.handydev.financier.R; import com.handydev.financier.adapter.BlotterListAdapter; -import com.handydev.financier.adapter.TransactionsListAdapter; import com.handydev.financier.blotter.AccountTotalCalculationTask; import com.handydev.financier.blotter.BlotterFilter; import com.handydev.financier.blotter.BlotterTotalCalculationTask; @@ -456,11 +455,7 @@ protected Cursor createCursor() { @Override protected ListAdapter createAdapter(Cursor cursor) { - if (isAccountBlotter) { - return new TransactionsListAdapter(this, db, cursor); - } else { - return new BlotterListAdapter(this, db, cursor); - } + return new BlotterListAdapter(this, db, cursor); } @Override diff --git a/app/src/main/java/com/handydev/financier/activity/BudgetBlotterActivity.java b/app/src/main/java/com/handydev/financier/activity/BudgetBlotterActivity.java index 56eaa9a0..b4f8ed06 100644 --- a/app/src/main/java/com/handydev/financier/activity/BudgetBlotterActivity.java +++ b/app/src/main/java/com/handydev/financier/activity/BudgetBlotterActivity.java @@ -18,7 +18,7 @@ import java.util.Map; -import com.handydev.financier.adapter.TransactionsListAdapter; +import com.handydev.financier.adapter.BlotterListAdapter; import com.handydev.financier.blotter.TotalCalculationTask; import com.handydev.financier.model.Budget; import com.handydev.financier.model.Category; @@ -51,7 +51,7 @@ protected Cursor createCursor() { @Override protected ListAdapter createAdapter(Cursor cursor) { - return new TransactionsListAdapter(this, db, cursor); + return new BlotterListAdapter(this, db, cursor); } private Cursor getBlotterForBudget(long budgetId) { diff --git a/app/src/main/java/com/handydev/financier/activity/MenuListItem.java b/app/src/main/java/com/handydev/financier/activity/MenuListItem.java index 080eb09b..9f673b98 100644 --- a/app/src/main/java/com/handydev/financier/activity/MenuListItem.java +++ b/app/src/main/java/com/handydev/financier/activity/MenuListItem.java @@ -26,13 +26,13 @@ import com.handydev.financier.export.qif.QifExportTask; import com.handydev.financier.export.qif.QifImportOptions; import com.handydev.financier.export.qif.QifImportTask; +import com.handydev.financier.fragments.MenuListFragment; import com.handydev.financier.utils.EntityEnum; import com.handydev.financier.utils.EnumUtils; import com.handydev.financier.utils.ExecutableEntityEnum; import com.handydev.financier.utils.IntegrityFix; import com.handydev.financier.utils.SummaryEntityEnum; import com.handydev.financier.MainActivity; -import com.handydev.main.fragments.MenuListFragment; import org.greenrobot.eventbus.EventBus; diff --git a/app/src/main/java/com/handydev/financier/activity/SplitsBlotterActivity.java b/app/src/main/java/com/handydev/financier/activity/SplitsBlotterActivity.java index 7d3f7e37..3c17e8bf 100644 --- a/app/src/main/java/com/handydev/financier/activity/SplitsBlotterActivity.java +++ b/app/src/main/java/com/handydev/financier/activity/SplitsBlotterActivity.java @@ -14,7 +14,8 @@ import android.os.Bundle; import android.view.View; import android.widget.ListAdapter; -import com.handydev.financier.adapter.TransactionsListAdapter; + +import com.handydev.financier.adapter.BlotterListAdapter; import com.handydev.financier.blotter.BlotterTotalCalculationTask; import com.handydev.financier.blotter.TotalCalculationTask; @@ -33,7 +34,7 @@ protected Cursor createCursor() { @Override protected ListAdapter createAdapter(Cursor cursor) { - return new TransactionsListAdapter(this, db, cursor); + return new BlotterListAdapter(this, db, cursor); } @Override diff --git a/app/src/main/java/com/handydev/financier/activity/TransactionActivity.java b/app/src/main/java/com/handydev/financier/activity/TransactionActivity.java index f4dbd94a..5d59261e 100644 --- a/app/src/main/java/com/handydev/financier/activity/TransactionActivity.java +++ b/app/src/main/java/com/handydev/financier/activity/TransactionActivity.java @@ -13,7 +13,6 @@ import android.content.Intent; import android.os.Bundle; import android.util.Log; -import android.view.KeyEvent; import android.view.View; import android.widget.LinearLayout; import android.widget.ListAdapter; @@ -542,7 +541,7 @@ protected void onRestoreInstanceState(Bundle savedInstanceState) { private void addOrEditSplit(Transaction split) { View v = findView(split); if (v == null) { - v = activityLayout.addSplitNodeMinus(splitsLayout, R.id.edit_aplit, R.id.delete_split, R.string.split, ""); + v = activityLayout.addSplitNodeMinus(splitsLayout, R.id.edit_split, R.id.delete_split, R.string.split, ""); } setSplitData(v, split); viewToSplitMap.put(v, split); diff --git a/app/src/main/java/com/handydev/financier/adapter/BlotterListAdapter.kt b/app/src/main/java/com/handydev/financier/adapter/BlotterListAdapter.kt index 3c6cde39..b552c327 100644 --- a/app/src/main/java/com/handydev/financier/adapter/BlotterListAdapter.kt +++ b/app/src/main/java/com/handydev/financier/adapter/BlotterListAdapter.kt @@ -34,7 +34,7 @@ open class BlotterListAdapter @JvmOverloads constructor( protected val icBlotterIncome: Drawable? = ContextCompat.getDrawable(context, R.drawable.ic_action_arrow_left_bottom) protected val icBlotterExpense: Drawable? = ContextCompat.getDrawable(context, R.drawable.ic_action_arrow_right_top) private val icBlotterTransfer: Drawable? = ContextCompat.getDrawable(context, R.drawable.ic_action_arrow_top_down) - private val icBlotterSplit: Drawable? = ContextCompat.getDrawable(context, R.drawable.ic_action_share) + val icBlotterSplit: Drawable? = ContextCompat.getDrawable(context, R.drawable.ic_action_share) protected val u: Utils = Utils(context) protected val db: DatabaseAdapter? private val colors: IntArray diff --git a/app/src/main/java/com/handydev/financier/adapter/TransactionsListAdapter.kt b/app/src/main/java/com/handydev/financier/adapter/TransactionsListAdapter.kt deleted file mode 100644 index 9a9d7c15..00000000 --- a/app/src/main/java/com/handydev/financier/adapter/TransactionsListAdapter.kt +++ /dev/null @@ -1,91 +0,0 @@ -package com.handydev.financier.adapter - -import android.content.Context -import android.database.Cursor -import android.graphics.Color -import android.text.format.DateUtils -import com.handydev.financier.R -import com.handydev.financier.db.DatabaseAdapter -import com.handydev.financier.db.DatabaseHelper.BlotterColumns -import com.handydev.financier.utils.CurrencyCache -import com.handydev.financier.utils.StringUtil -import com.handydev.financier.utils.TransactionTitleUtils.generateTransactionTitle -import com.handydev.financier.utils.Utils - -class TransactionsListAdapter(context: Context, db: DatabaseAdapter?, c: Cursor?) : - BlotterListAdapter(context, db, c) { - override fun bindView(v: BlotterViewHolder, context: Context, cursor: Cursor) { - val toAccountId = cursor.getLong(BlotterColumns.to_account_id.ordinal) - val payee = cursor.getString(BlotterColumns.payee.ordinal) - var note = cursor.getString(BlotterColumns.note.ordinal) - val locationId = cursor.getLong(BlotterColumns.location_id.ordinal) - var location: String? = "" - if (locationId > 0) { - location = cursor.getString(BlotterColumns.location.ordinal) - } - val toAccount = cursor.getString(BlotterColumns.to_account_title.ordinal) - val fromAmount = cursor.getLong(BlotterColumns.from_amount.ordinal) - if (toAccountId > 0) { - v.topView.setText(R.string.transfer) - note = if (fromAmount > 0) { - "$toAccount \u00BB" - } else { - "\u00AB $toAccount" - } - } else { - val title = cursor.getString(BlotterColumns.from_account_title.ordinal) - v.topView.text = title - } - val categoryId = cursor.getLong(BlotterColumns.category_id.ordinal) - var category: String? = "" - if (categoryId != 0L) { - category = cursor.getString(BlotterColumns.category_title.ordinal) - } - val text = generateTransactionTitle(sb, payee, note, location, categoryId, category!!) - v.centerView.text = text - sb.setLength(0) - val currencyId = cursor.getLong(BlotterColumns.from_account_currency_id.ordinal) - val c = CurrencyCache.getCurrency(db, currencyId) - val originalCurrencyId = cursor.getLong(BlotterColumns.original_currency_id.ordinal) - if (originalCurrencyId > 0) { - val originalCurrency = CurrencyCache.getCurrency(db, originalCurrencyId) - val originalAmount = cursor.getLong(BlotterColumns.original_from_amount.ordinal) - u.setAmountText( - sb, - v.rightCenterView, - originalCurrency, - originalAmount, - c, - fromAmount, - true - ) - } else { - u.setAmountText(v.rightCenterView, c, fromAmount, true) - } - /*if (fromAmount > 0) { - v.iconView.setImageDrawable(icBlotterIncome) - v.iconView.setColorFilter(u.positiveColor) - } else if (fromAmount < 0) { - v.iconView.setImageDrawable(icBlotterExpense) - v.iconView.setColorFilter(u.negativeColor) - }*/ - val date = cursor.getLong(BlotterColumns.datetime.ordinal) - v.bottomView.text = StringUtil.capitalize( - DateUtils.formatDateTime( - context, date, - DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_SHOW_TIME or DateUtils.FORMAT_ABBREV_MONTH or DateUtils.FORMAT_SHOW_WEEKDAY or DateUtils.FORMAT_ABBREV_WEEKDAY - ) - ) - /*if (date > System.currentTimeMillis()) { - u.setFutureTextColor(v.bottomView) - } else { - v.bottomView.setTextColor(v.topView.textColors.defaultColor) - } - */ - val balance = cursor.getLong(BlotterColumns.from_account_balance.ordinal) - v.rightView?.text = Utils.amountToString(c, balance, false) - removeRightViewIfNeeded(v) - setIndicatorColor(v, cursor) - alternateColorIfNeeded(v, context, cursor) - } -} diff --git a/app/src/main/java/com/handydev/financier/dialog/PinDialogPreference.java b/app/src/main/java/com/handydev/financier/dialog/PinDialogPreference.java index 9a6d69ac..41645cb8 100644 --- a/app/src/main/java/com/handydev/financier/dialog/PinDialogPreference.java +++ b/app/src/main/java/com/handydev/financier/dialog/PinDialogPreference.java @@ -1,13 +1,3 @@ -/******************************************************************************* - * Copyright (c) 2010 Denis Solonenko. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v2.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * - * Contributors: - * Denis Solonenko - initial API and implementation - ******************************************************************************/ package com.handydev.financier.dialog; import com.handydev.financier.R; @@ -16,7 +6,7 @@ import android.app.Dialog; import android.content.Context; import android.os.Bundle; -import android.preference.DialogPreference; +import androidx.preference.DialogPreference; import android.util.AttributeSet; public class PinDialogPreference extends DialogPreference implements PinView.PinListener { @@ -38,7 +28,7 @@ protected void showDialog(Bundle state) { .setTitle(R.string.set_pin) .setView(pinView.getView()) .create(); - dialog.setOnDismissListener(this); + //dialog.setOnDismissListener(this); dialog.show(); } diff --git a/app/src/main/java/com/handydev/financier/dialog/TimePreference.java b/app/src/main/java/com/handydev/financier/dialog/TimePreference.java index 8947b5fe..e68abd1d 100644 --- a/app/src/main/java/com/handydev/financier/dialog/TimePreference.java +++ b/app/src/main/java/com/handydev/financier/dialog/TimePreference.java @@ -9,7 +9,7 @@ package com.handydev.financier.dialog; import android.content.Context; -import android.preference.DialogPreference; +import androidx.preference.DialogPreference; import android.util.AttributeSet; import android.view.View; import android.widget.TimePicker; @@ -34,7 +34,7 @@ public TimePreference(Context context, AttributeSet attrs, int defStyle) { setPersistent(true); } - public TimePreference(Context context, AttributeSet attrs) { + /*public TimePreference(Context context, AttributeSet attrs) { super(context, attrs); setPersistent(true); } @@ -72,14 +72,13 @@ private int getMinute() { return hm-100*h; } - @Override - public void onTimeChanged(TimePicker timePicker, int hh, int mm) { - this.hh = hh; - this.mm = mm; - } - @Override public CharSequence getSummary() { return getContext().getString(R.string.auto_backup_time_summary, getHour(), getMinute()); + }*/ + @Override + public void onTimeChanged(TimePicker timePicker, int hh, int mm) { + this.hh = hh; + this.mm = mm; } } diff --git a/app/src/main/java/com/handydev/financier/fragments/BlotterFragment.kt b/app/src/main/java/com/handydev/financier/fragments/BlotterFragment.kt index f716bc87..ef098ed5 100644 --- a/app/src/main/java/com/handydev/financier/fragments/BlotterFragment.kt +++ b/app/src/main/java/com/handydev/financier/fragments/BlotterFragment.kt @@ -8,6 +8,7 @@ import android.database.Cursor import android.os.Bundle import android.text.Editable import android.text.TextWatcher +import android.util.Log import android.view.MenuInflater import android.view.MenuItem import android.view.View @@ -18,7 +19,6 @@ import androidx.appcompat.app.AlertDialog import com.handydev.financier.R import com.handydev.financier.activity.* import com.handydev.financier.adapter.BlotterListAdapter -import com.handydev.financier.adapter.TransactionsListAdapter import com.handydev.financier.base.AbstractListFragment import com.handydev.financier.blotter.AccountTotalCalculationTask import com.handydev.financier.blotter.BlotterFilter @@ -69,6 +69,7 @@ open class BlotterFragment: AbstractListFragment(R.layout.blotter), IOTransactio private var isAccountBlotter = false private var showAllBlotterButtons = true + private var shouldUpdateTransactionsOnResume = true protected fun calculateTotals() { if (calculationTask != null) { @@ -93,9 +94,19 @@ open class BlotterFragment: AbstractListFragment(R.layout.blotter), IOTransactio override fun recreateCursor() { super.recreateCursor() + Log.d("recreateCursor", "recreateCursor") calculateTotals() } + override fun onResume() { + super.onResume() + if(shouldUpdateTransactionsOnResume) { + recreateCursor() + } else { + shouldUpdateTransactionsOnResume = true + } + } + override fun internalOnCreate(savedInstanceState: Bundle?) { super.internalOnCreate(savedInstanceState) integrityCheck() @@ -421,11 +432,7 @@ open class BlotterFragment: AbstractListFragment(R.layout.blotter), IOTransactio if(activity == null) { return null } - return if (isAccountBlotter) { - TransactionsListAdapter(requireActivity(), db, cursor) - } else { - BlotterListAdapter(requireActivity(), db, cursor) - } + return BlotterListAdapter(requireActivity(), db, cursor) } override fun deleteItem(v: View?, position: Int, id: Long) { @@ -475,8 +482,8 @@ open class BlotterFragment: AbstractListFragment(R.layout.blotter), IOTransactio createTransactionFromTemplate(data) } if (resultCode == Activity.RESULT_OK || resultCode == Activity.RESULT_FIRST_USER) { + shouldUpdateTransactionsOnResume = false recreateCursor() - calculateTotals() } } diff --git a/app/src/main/java/com/handydev/financier/fragments/FinancierPreferenceDialogFragment.kt b/app/src/main/java/com/handydev/financier/fragments/FinancierPreferenceDialogFragment.kt new file mode 100644 index 00000000..37a3a02f --- /dev/null +++ b/app/src/main/java/com/handydev/financier/fragments/FinancierPreferenceDialogFragment.kt @@ -0,0 +1,19 @@ +package com.handydev.financier.fragments + +import androidx.preference.PreferenceDialogFragmentCompat +import android.os.Bundle + +class FinancierPreferenceDialogFragment: PreferenceDialogFragmentCompat() { + override fun onDialogClosed(positiveResult: Boolean) { + } + + companion object { + fun newInstance(key: String?): FinancierPreferenceDialogFragment? { + val fragment = FinancierPreferenceDialogFragment() + val bundle = Bundle(1) + bundle.putString(ARG_KEY, key) + fragment.arguments = bundle + return fragment + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/handydev/financier/model/Currency.java b/app/src/main/java/com/handydev/financier/model/Currency.java index a23ed7c9..4a2b34f6 100644 --- a/app/src/main/java/com/handydev/financier/model/Currency.java +++ b/app/src/main/java/com/handydev/financier/model/Currency.java @@ -14,7 +14,6 @@ import com.handydev.financier.db.DatabaseAdapter; import com.handydev.financier.utils.CurrencyCache; -import javax.annotation.Nullable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @@ -26,6 +25,8 @@ import static com.handydev.financier.db.DatabaseHelper.CURRENCY_TABLE; import static com.handydev.orb.EntityManager.DEF_SORT_COL; +import androidx.annotation.Nullable; + @Entity @Table(name = CURRENCY_TABLE) public class Currency extends MyEntity implements SortableEntity { @@ -94,7 +95,8 @@ public static Currency defaultCurrency() { return c; } - public static @Nullable Currency getDefaultCurrency(DatabaseAdapter db) { + public static @Nullable + Currency getDefaultCurrency(DatabaseAdapter db) { List currencies = db.getAllCurrenciesList("name"); for (Currency currency : currencies) { if (currency.isDefault) { diff --git a/app/src/main/res/layout/account_list_item.xml b/app/src/main/res/layout/account_list_item.xml index 76f67868..5193130a 100644 --- a/app/src/main/res/layout/account_list_item.xml +++ b/app/src/main/res/layout/account_list_item.xml @@ -59,7 +59,7 @@ android:id="@+id/account_name_type_container" android:layout_width="0dp" android:layout_height="wrap_content" - app:layout_constraintWidth_percent="0.5" + app:layout_constraintWidth_percent="0.6" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" @@ -89,7 +89,7 @@ - + diff --git a/fastlane/README.md b/fastlane/README.md new file mode 100644 index 00000000..7a4888dd --- /dev/null +++ b/fastlane/README.md @@ -0,0 +1,39 @@ +fastlane documentation +================ +# Installation + +Make sure you have the latest version of the Xcode command line tools installed: + +``` +xcode-select --install +``` + +Install _fastlane_ using +``` +[sudo] gem install fastlane -NV +``` +or alternatively using `brew install fastlane` + +# Available Actions +## Android +### android test +``` +fastlane android test +``` +Runs all the tests +### android github +``` +fastlane android github +``` +Submit a new version to GitHub +### android googleplay +``` +fastlane android googleplay +``` +Deploy a new version to the Google Play + +---- + +This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. +More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). +The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). diff --git a/fastlane/metadata/android/en-US/changelogs/213.txt b/fastlane/metadata/android/en-US/changelogs/213.txt new file mode 100644 index 00000000..6b974580 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/213.txt @@ -0,0 +1 @@ +Categories filter in transaction now shows nested categories correctly. \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt new file mode 100644 index 00000000..485ec53e --- /dev/null +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -0,0 +1,40 @@ +Financier is based on the great Financisto app. + +Features include: +- Multiple accounts, multiple currencies. +- Home currency and exchange rates. +- Transfers with downloadable rates. +- Scheduled & recurring transactions. +- Split transactions. +- Hierarchical categories with custom attributes. +- Recurring budgets. +- Projects and payees. +- Filtering and reporting. +- Cloud backup (Dropbox, Google Docs). +- Automatic daily backups. +- QIF/CSV import/export. + +*WARNING* + +Please DO BACKUP before upgrade! + +Please DO NOT move Financier to SD card if you're using the widget and/or scheduled transactions. + +*PERMISSIONS* + +GET_ACCOUNTS/USE_CREDENTIALS - For backup on Google Drive + +INTERNET - for downloading currency rates in multi-currency transfer; to do online backup to Dropbox and Google Docs; + +CAMERA - to attach pictures to transactions. + +*FAQ* + +Q: Why currency XYZ is missing? +A: You can add any currency manually. Go to Menu -> Entities -> Currencies -> [+] + +Q: How to delete account/transaction/balance etc? +A: Long tap on an item in the list to bring up the popup menu. + +Q: Shortcuts do not work on Home screen. +A: Try to restart your phone, it helps with most of the launchers out there. \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/images/featureGraphic.png b/fastlane/metadata/android/en-US/images/featureGraphic.png new file mode 100644 index 00000000..87ff08d6 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/featureGraphic.png differ diff --git a/fastlane/metadata/android/en-US/images/icon.png b/fastlane/metadata/android/en-US/images/icon.png new file mode 100644 index 00000000..7783a950 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/icon.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/1_en-US.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/1_en-US.png new file mode 100644 index 00000000..b7a139db Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/1_en-US.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/2_en-US.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/2_en-US.png new file mode 100644 index 00000000..cde736f9 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/2_en-US.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/3_en-US.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/3_en-US.png new file mode 100644 index 00000000..c4d5bce8 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/3_en-US.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/4_en-US.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/4_en-US.png new file mode 100644 index 00000000..1167ccb9 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/4_en-US.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/5_en-US.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/5_en-US.png new file mode 100644 index 00000000..856c6002 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/5_en-US.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/6_en-US.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/6_en-US.png new file mode 100644 index 00000000..a3f842bc Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/6_en-US.png differ diff --git a/fastlane/metadata/android/en-US/short_description.txt b/fastlane/metadata/android/en-US/short_description.txt new file mode 100644 index 00000000..0d65de1b --- /dev/null +++ b/fastlane/metadata/android/en-US/short_description.txt @@ -0,0 +1 @@ +Open-source personal finance tracker. \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/title.txt b/fastlane/metadata/android/en-US/title.txt new file mode 100644 index 00000000..84ed3453 --- /dev/null +++ b/fastlane/metadata/android/en-US/title.txt @@ -0,0 +1 @@ +Financier \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/video.txt b/fastlane/metadata/android/en-US/video.txt new file mode 100644 index 00000000..e69de29b