From e6365b9d746ca51b693afacb747e1aca3f741976 Mon Sep 17 00:00:00 2001 From: M M Arif Date: Mon, 18 Mar 2024 05:12:24 +0000 Subject: [PATCH] Move settings data to db and other improvements (#1332) Closes #1331 Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1332 Co-authored-by: M M Arif Co-committed-by: M M Arif --- .woodpecker/locale.yml | 4 +- .../mian/gitnex/activities/BaseActivity.java | 58 +- .../gitnex/activities/CodeEditorActivity.java | 10 +- .../activities/CreateIssueActivity.java | 8 +- .../activities/CreateMilestoneActivity.java | 8 +- .../activities/CreatePullRequestActivity.java | 8 +- .../gitnex/activities/DeepLinksActivity.java | 30 +- .../gitnex/activities/EditIssueActivity.java | 8 +- .../activities/IssueDetailActivity.java | 65 +- .../mian/gitnex/activities/MainActivity.java | 43 +- .../OrganizationDetailActivity.java | 6 +- .../OrganizationTeamInfoActivity.java | 7 +- .../gitnex/activities/ProfileActivity.java | 6 +- .../gitnex/activities/RepoDetailActivity.java | 9 +- .../SettingsAppearanceActivity.java | 172 +- .../SettingsCodeEditorActivity.java | 38 +- .../activities/SettingsGeneralActivity.java | 139 +- .../SettingsNotificationsActivity.java | 24 +- .../activities/SettingsSecurityActivity.java | 80 +- .../gitnex/adapters/ExploreIssuesAdapter.java | 5 +- .../gitnex/adapters/IssueCommentsAdapter.java | 1602 +++++++++-------- .../mian/gitnex/adapters/IssuesAdapter.java | 5 +- .../gitnex/adapters/PullRequestsAdapter.java | 5 +- .../mian/gitnex/clients/RetrofitClient.java | 13 +- .../org/mian/gitnex/core/MainApplication.java | 15 +- .../gitnex/database/api/AppSettingsApi.java | 72 + .../gitnex/database/dao/AppSettingsDao.java | 42 + .../gitnex/database/db/GitnexDatabase.java | 27 +- .../gitnex/database/models/AppSettings.java | 52 + .../fragments/AccountSettingsFragment.java | 9 +- .../fragments/BottomSheetReplyFragment.java | 19 +- .../gitnex/fragments/ExploreFragment.java | 6 +- .../fragments/PullRequestChangesFragment.java | 13 +- .../gitnex/helpers/AppDatabaseSettings.java | 395 ++++ .../java/org/mian/gitnex/helpers/AppUtil.java | 30 +- .../org/mian/gitnex/helpers/Markdown.java | 14 +- .../org/mian/gitnex/helpers/PicassoCache.java | 9 +- .../java/org/mian/gitnex/helpers/TinyDB.java | 4 + .../helpers/codeeditor/theme/Theme.java | 8 +- .../gitnex/notifications/Notifications.java | 27 +- .../notifications/NotificationsWorker.java | 23 +- .../res/layout/activity_settings_security.xml | 4 +- .../{values-ar => values-ar-rSA}/strings.xml | 0 .../{values-cs => values-cs-rCZ}/strings.xml | 0 .../{values-de => values-de-rDE}/strings.xml | 0 .../{values-el => values-el-rGR}/strings.xml | 0 app/src/main/res/values-eo-rEO/strings.xml | 775 ++++++++ .../{values-es => values-es-rES}/strings.xml | 0 .../{values-fa => values-fa-rIR}/strings.xml | 0 .../{values-fi => values-fi-rFI}/strings.xml | 0 .../{values-fr => values-fr-rFR}/strings.xml | 0 .../{values-it => values-it-rIT}/strings.xml | 0 .../{values-ja => values-ja-rJP}/strings.xml | 0 .../{values-ko => values-ko-rKR}/strings.xml | 0 .../{values-lv => values-lv-rLV}/strings.xml | 0 .../{values-nl => values-nl-rNL}/strings.xml | 0 .../{values-pl => values-pl-rPL}/strings.xml | 0 .../{values-pt => values-pt-rBR}/strings.xml | 0 .../{values-ru => values-ru-rRU}/strings.xml | 0 .../{values-si => values-si-rLK}/strings.xml | 0 .../{values-sk => values-sk-rSK}/strings.xml | 0 .../{values-sr => values-sr-rRS}/strings.xml | 0 .../{values-tr => values-tr-rTR}/strings.xml | 0 .../{values-uk => values-uk-rUA}/strings.xml | 0 .../{values-zh => values-zh-rCN}/strings.xml | 0 app/src/main/res/values-zh-rTW/strings.xml | 773 ++++++++ app/src/main/res/values/settings.xml | 2 + app/src/main/res/values/strings.xml | 3 +- crowdin.example.yml | 2 +- 69 files changed, 3604 insertions(+), 1073 deletions(-) create mode 100644 app/src/main/java/org/mian/gitnex/database/api/AppSettingsApi.java create mode 100644 app/src/main/java/org/mian/gitnex/database/dao/AppSettingsDao.java create mode 100644 app/src/main/java/org/mian/gitnex/database/models/AppSettings.java create mode 100644 app/src/main/java/org/mian/gitnex/helpers/AppDatabaseSettings.java rename app/src/main/res/{values-ar => values-ar-rSA}/strings.xml (100%) rename app/src/main/res/{values-cs => values-cs-rCZ}/strings.xml (100%) rename app/src/main/res/{values-de => values-de-rDE}/strings.xml (100%) rename app/src/main/res/{values-el => values-el-rGR}/strings.xml (100%) create mode 100644 app/src/main/res/values-eo-rEO/strings.xml rename app/src/main/res/{values-es => values-es-rES}/strings.xml (100%) rename app/src/main/res/{values-fa => values-fa-rIR}/strings.xml (100%) rename app/src/main/res/{values-fi => values-fi-rFI}/strings.xml (100%) rename app/src/main/res/{values-fr => values-fr-rFR}/strings.xml (100%) rename app/src/main/res/{values-it => values-it-rIT}/strings.xml (100%) rename app/src/main/res/{values-ja => values-ja-rJP}/strings.xml (100%) rename app/src/main/res/{values-ko => values-ko-rKR}/strings.xml (100%) rename app/src/main/res/{values-lv => values-lv-rLV}/strings.xml (100%) rename app/src/main/res/{values-nl => values-nl-rNL}/strings.xml (100%) rename app/src/main/res/{values-pl => values-pl-rPL}/strings.xml (100%) rename app/src/main/res/{values-pt => values-pt-rBR}/strings.xml (100%) rename app/src/main/res/{values-ru => values-ru-rRU}/strings.xml (100%) rename app/src/main/res/{values-si => values-si-rLK}/strings.xml (100%) rename app/src/main/res/{values-sk => values-sk-rSK}/strings.xml (100%) rename app/src/main/res/{values-sr => values-sr-rRS}/strings.xml (100%) rename app/src/main/res/{values-tr => values-tr-rTR}/strings.xml (100%) rename app/src/main/res/{values-uk => values-uk-rUA}/strings.xml (100%) rename app/src/main/res/{values-zh => values-zh-rCN}/strings.xml (100%) create mode 100644 app/src/main/res/values-zh-rTW/strings.xml diff --git a/.woodpecker/locale.yml b/.woodpecker/locale.yml index 31a94fc0..e5f4656d 100644 --- a/.woodpecker/locale.yml +++ b/.woodpecker/locale.yml @@ -10,7 +10,7 @@ steps: branch: main push: - image: crowdin/cli:3.7.8 + image: crowdin/cli:3.16.0 commands: - crowdin push when: @@ -19,7 +19,7 @@ steps: path: [ app/src/main/res/values/strings.xml, fastlane/metadata/android/en-US/*.txt, fastlane/metadata/android/en-US/changelogs/*.txt ] pull: - image: crowdin/cli:3.7.8 + image: crowdin/cli:3.16.0 # we do not need to update the config file again since it persists commands: - crowdin pull diff --git a/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java b/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java index ce8ee3da..4728abce 100644 --- a/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java @@ -10,6 +10,7 @@ import java.util.Locale; import java.util.concurrent.Executor; import org.mian.gitnex.R; import org.mian.gitnex.core.MainApplication; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.TimeHelper; import org.mian.gitnex.helpers.TinyDB; @@ -34,7 +35,8 @@ public abstract class BaseActivity extends AppCompatActivity { this.appCtx = getApplicationContext(); this.tinyDB = TinyDB.getInstance(appCtx); - switch (tinyDB.getInt("themeId", 6)) { + switch (Integer.parseInt( + AppDatabaseSettings.getSettingsValue(ctx, AppDatabaseSettings.APP_THEME_KEY))) { case 0: setTheme(R.style.AppTheme); break; @@ -43,10 +45,18 @@ public abstract class BaseActivity extends AppCompatActivity { break; case 2: if (TimeHelper.timeBetweenHours( - tinyDB.getInt("darkThemeTimeHour", 18), - tinyDB.getInt("lightThemeTimeHour", 6), - tinyDB.getInt("darkThemeTimeMinute", 0), - tinyDB.getInt("lightThemeTimeMinute", 0))) { + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_DARK_HOUR_KEY)), + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_LIGHT_HOUR_KEY)), + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_DARK_MIN_KEY)), + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_LIGHT_MIN_KEY)))) { setTheme(R.style.AppTheme); } else { @@ -59,10 +69,18 @@ public abstract class BaseActivity extends AppCompatActivity { break; case 4: if (TimeHelper.timeBetweenHours( - tinyDB.getInt("darkThemeTimeHour", 18), - tinyDB.getInt("lightThemeTimeHour", 6), - tinyDB.getInt("darkThemeTimeMinute", 0), - tinyDB.getInt("lightThemeTimeMinute", 0))) { + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_DARK_HOUR_KEY)), + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_LIGHT_HOUR_KEY)), + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_DARK_MIN_KEY)), + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_LIGHT_MIN_KEY)))) { setTheme(R.style.AppTheme); } else { @@ -87,11 +105,14 @@ public abstract class BaseActivity extends AppCompatActivity { break; } - String locale = tinyDB.getString("locale"); - if (locale.isEmpty()) { + String[] locale = + AppDatabaseSettings.getSettingsValue(ctx, AppDatabaseSettings.APP_LOCALE_KEY) + .split("\\|"); + + if (locale[0].equals("0")) { AppUtil.setAppLocale(getResources(), Locale.getDefault().getLanguage()); } else { - AppUtil.setAppLocale(getResources(), locale); + AppUtil.setAppLocale(getResources(), locale[1]); } Notifications.startWorker(ctx); @@ -100,8 +121,12 @@ public abstract class BaseActivity extends AppCompatActivity { public void onResume() { super.onResume(); - if (tinyDB.getBoolean("biometricStatus", false) - && !tinyDB.getBoolean("biometricLifeCycle")) { + if (Boolean.parseBoolean( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_BIOMETRIC_KEY)) + && !Boolean.parseBoolean( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_BIOMETRIC_LIFE_CYCLE_KEY))) { Executor executor = ContextCompat.getMainExecutor(this); @@ -126,7 +151,10 @@ public abstract class BaseActivity extends AppCompatActivity { public void onAuthenticationSucceeded( @NonNull BiometricPrompt.AuthenticationResult result) { super.onAuthenticationSucceeded(result); - tinyDB.putBoolean("biometricLifeCycle", true); + AppDatabaseSettings.updateSettingsValue( + getApplicationContext(), + "true", + AppDatabaseSettings.APP_BIOMETRIC_LIFE_CYCLE_KEY); } // Authentication failed, close the app diff --git a/app/src/main/java/org/mian/gitnex/activities/CodeEditorActivity.java b/app/src/main/java/org/mian/gitnex/activities/CodeEditorActivity.java index 34060ad4..08b00d24 100644 --- a/app/src/main/java/org/mian/gitnex/activities/CodeEditorActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/CodeEditorActivity.java @@ -13,6 +13,7 @@ import java.util.Map; import org.mian.gitnex.R; import org.mian.gitnex.core.MainGrammarLocator; import org.mian.gitnex.databinding.ActivityCodeEditorBinding; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.codeeditor.CustomCodeViewAdapter; import org.mian.gitnex.helpers.codeeditor.SourcePositionListener; import org.mian.gitnex.helpers.codeeditor.languages.Language; @@ -73,9 +74,14 @@ public class CodeEditorActivity extends BaseActivity { binding.codeView.setLineNumberTextSize(32f); // Setup Auto indenting feature - if (tinyDB.getInt("ceIndentationId") == 0) { + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_CE_INDENTATION_KEY)) + == 0) { binding.codeView.setEnableAutoIndentation(true); - switch (tinyDB.getInt("ceIndentationTabsId")) { + switch (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_CE_TABS_WIDTH_KEY))) { case 0: binding.codeView.setTabLength(2); break; diff --git a/app/src/main/java/org/mian/gitnex/activities/CreateIssueActivity.java b/app/src/main/java/org/mian/gitnex/activities/CreateIssueActivity.java index 5fa8727f..556e4936 100644 --- a/app/src/main/java/org/mian/gitnex/activities/CreateIssueActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/CreateIssueActivity.java @@ -50,6 +50,7 @@ import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding; import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding; import org.mian.gitnex.fragments.IssuesFragment; import org.mian.gitnex.helpers.AlertDialogs; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.Constants; import org.mian.gitnex.helpers.Markdown; import org.mian.gitnex.helpers.SnackBar; @@ -315,6 +316,10 @@ public class CreateIssueActivity extends BaseActivity builder.setTitleText(R.string.newIssueDueDateTitle); MaterialDatePicker materialDatePicker = builder.build(); + String[] locale_ = + AppDatabaseSettings.getSettingsValue(ctx, AppDatabaseSettings.APP_LOCALE_KEY) + .split("\\|"); + viewBinding.newIssueDueDate.setOnClickListener( v -> materialDatePicker.show(getSupportFragmentManager(), "DATE_PICKER")); @@ -323,8 +328,7 @@ public class CreateIssueActivity extends BaseActivity Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); calendar.setTimeInMillis(selection); SimpleDateFormat format = - new SimpleDateFormat( - "yyyy-MM-dd", new Locale(tinyDB.getString("locale"))); + new SimpleDateFormat("yyyy-MM-dd", new Locale(locale_[1])); String formattedDate = format.format(calendar.getTime()); viewBinding.newIssueDueDate.setText(formattedDate); }); diff --git a/app/src/main/java/org/mian/gitnex/activities/CreateMilestoneActivity.java b/app/src/main/java/org/mian/gitnex/activities/CreateMilestoneActivity.java index ea220200..1d76c088 100644 --- a/app/src/main/java/org/mian/gitnex/activities/CreateMilestoneActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/CreateMilestoneActivity.java @@ -21,6 +21,7 @@ import org.mian.gitnex.R; import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.databinding.ActivityCreateMilestoneBinding; import org.mian.gitnex.helpers.AlertDialogs; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.Markdown; import org.mian.gitnex.helpers.SnackBar; import org.mian.gitnex.helpers.contexts.RepositoryContext; @@ -109,6 +110,10 @@ public class CreateMilestoneActivity extends BaseActivity { builder.setTitleText(R.string.newIssueDueDateTitle); MaterialDatePicker materialDatePicker = builder.build(); + String[] locale_ = + AppDatabaseSettings.getSettingsValue(ctx, AppDatabaseSettings.APP_LOCALE_KEY) + .split("\\|"); + binding.milestoneDueDate.setOnClickListener( v -> materialDatePicker.show(getSupportFragmentManager(), "DATE_PICKER")); @@ -117,8 +122,7 @@ public class CreateMilestoneActivity extends BaseActivity { Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); calendar.setTimeInMillis(selection); SimpleDateFormat format = - new SimpleDateFormat( - "yyyy-MM-dd", new Locale(tinyDB.getString("locale"))); + new SimpleDateFormat("yyyy-MM-dd", new Locale(locale_[1])); String formattedDate = format.format(calendar.getTime()); binding.milestoneDueDate.setText(formattedDate); }); diff --git a/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java b/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java index 70d6798a..1aefe7cc 100644 --- a/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java @@ -47,6 +47,7 @@ import org.mian.gitnex.databinding.BottomSheetAttachmentsBinding; import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding; import org.mian.gitnex.fragments.PullRequestsFragment; import org.mian.gitnex.helpers.AlertDialogs; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.Constants; import org.mian.gitnex.helpers.Markdown; import org.mian.gitnex.helpers.SnackBar; @@ -429,6 +430,10 @@ public class CreatePullRequestActivity extends BaseActivity builder.setTitleText(R.string.newIssueDueDateTitle); MaterialDatePicker materialDatePicker = builder.build(); + String[] locale_ = + AppDatabaseSettings.getSettingsValue(ctx, AppDatabaseSettings.APP_LOCALE_KEY) + .split("\\|"); + viewBinding.prDueDate.setOnClickListener( v -> materialDatePicker.show(getSupportFragmentManager(), "DATE_PICKER")); @@ -437,8 +442,7 @@ public class CreatePullRequestActivity extends BaseActivity Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); calendar.setTimeInMillis(selection); SimpleDateFormat format = - new SimpleDateFormat( - "yyyy-MM-dd", new Locale(tinyDB.getString("locale"))); + new SimpleDateFormat("yyyy-MM-dd", new Locale(locale_[1])); String formattedDate = format.format(calendar.getTime()); viewBinding.prDueDate.setText(formattedDate); }); diff --git a/app/src/main/java/org/mian/gitnex/activities/DeepLinksActivity.java b/app/src/main/java/org/mian/gitnex/activities/DeepLinksActivity.java index 07d2122a..5d0122ad 100644 --- a/app/src/main/java/org/mian/gitnex/activities/DeepLinksActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/DeepLinksActivity.java @@ -23,6 +23,7 @@ import org.mian.gitnex.database.api.BaseApi; import org.mian.gitnex.database.api.UserAccountsApi; import org.mian.gitnex.database.models.UserAccount; import org.mian.gitnex.databinding.ActivityDeeplinksBinding; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.contexts.IssueContext; import org.mian.gitnex.helpers.contexts.RepositoryContext; @@ -675,7 +676,9 @@ public class DeepLinksActivity extends BaseActivity { private void showNoActionButtons() { viewBinding.progressBar.setVisibility(View.GONE); - switch (tinyDB.getInt("defaultScreenId")) { + switch (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_LINK_HANDLER_KEY))) { case 1: // repos mainIntent.putExtra("launchFragmentByLinkHandler", "repos"); ctx.startActivity(mainIntent); @@ -708,7 +711,10 @@ public class DeepLinksActivity extends BaseActivity { viewBinding.repository.setOnClickListener( repository -> { - tinyDB.putInt("defaultScreenId", 1); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(1), + AppDatabaseSettings.APP_LINK_HANDLER_KEY); mainIntent.putExtra("launchFragmentByLinkHandler", "repos"); ctx.startActivity(mainIntent); finish(); @@ -716,7 +722,10 @@ public class DeepLinksActivity extends BaseActivity { viewBinding.organization.setOnClickListener( organization -> { - tinyDB.putInt("defaultScreenId", 2); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(2), + AppDatabaseSettings.APP_LINK_HANDLER_KEY); mainIntent.putExtra("launchFragmentByLinkHandler", "org"); ctx.startActivity(mainIntent); finish(); @@ -724,7 +733,10 @@ public class DeepLinksActivity extends BaseActivity { viewBinding.notification.setOnClickListener( notification -> { - tinyDB.putInt("defaultScreenId", 3); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(3), + AppDatabaseSettings.APP_LINK_HANDLER_KEY); mainIntent.putExtra("launchFragmentByLinkHandler", "notification"); ctx.startActivity(mainIntent); finish(); @@ -732,7 +744,10 @@ public class DeepLinksActivity extends BaseActivity { viewBinding.explore.setOnClickListener( explore -> { - tinyDB.putInt("defaultScreenId", 4); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(4), + AppDatabaseSettings.APP_LINK_HANDLER_KEY); mainIntent.putExtra("launchFragmentByLinkHandler", "explore"); ctx.startActivity(mainIntent); finish(); @@ -740,7 +755,10 @@ public class DeepLinksActivity extends BaseActivity { viewBinding.launchApp2.setOnClickListener( launchApp2 -> { - tinyDB.putInt("defaultScreenId", 0); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(0), + AppDatabaseSettings.APP_LINK_HANDLER_KEY); ctx.startActivity(mainIntent); finish(); }); diff --git a/app/src/main/java/org/mian/gitnex/activities/EditIssueActivity.java b/app/src/main/java/org/mian/gitnex/activities/EditIssueActivity.java index 75d841dc..7c451823 100644 --- a/app/src/main/java/org/mian/gitnex/activities/EditIssueActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/EditIssueActivity.java @@ -33,6 +33,7 @@ import org.mian.gitnex.databinding.ActivityEditIssueBinding; import org.mian.gitnex.fragments.IssuesFragment; import org.mian.gitnex.fragments.PullRequestsFragment; import org.mian.gitnex.helpers.AlertDialogs; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.Constants; import org.mian.gitnex.helpers.Markdown; import org.mian.gitnex.helpers.SnackBar; @@ -247,6 +248,10 @@ public class EditIssueActivity extends BaseActivity { builder.setTitleText(R.string.newIssueDueDateTitle); MaterialDatePicker materialDatePicker = builder.build(); + String[] locale_ = + AppDatabaseSettings.getSettingsValue(ctx, AppDatabaseSettings.APP_LOCALE_KEY) + .split("\\|"); + binding.editIssueDueDate.setOnClickListener( v -> materialDatePicker.show(getSupportFragmentManager(), "DATE_PICKER")); @@ -255,8 +260,7 @@ public class EditIssueActivity extends BaseActivity { Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); calendar.setTimeInMillis(selection); SimpleDateFormat format = - new SimpleDateFormat( - "yyyy-MM-dd", new Locale(tinyDB.getString("locale"))); + new SimpleDateFormat("yyyy-MM-dd", new Locale(locale_[1])); String formattedDate = format.format(calendar.getTime()); binding.editIssueDueDate.setText(formattedDate); }); diff --git a/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java index e9befe2b..7a20cd22 100644 --- a/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java @@ -73,6 +73,7 @@ import org.mian.gitnex.fragments.BottomSheetReplyFragment; import org.mian.gitnex.fragments.BottomSheetSingleIssueFragment; import org.mian.gitnex.fragments.IssuesFragment; import org.mian.gitnex.helpers.AlertDialogs; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.ClickListener; import org.mian.gitnex.helpers.ColorInverter; @@ -857,18 +858,34 @@ public class IssueDetailActivity extends BaseActivity } else { // open viewBinding.issuePrState.setImageResource(R.drawable.ic_pull_request); - if (tinyDB.getInt("themeId") == 3) { + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_KEY)) + == 3) { ImageViewCompat.setImageTintList( viewBinding.issuePrState, ColorStateList.valueOf( ctx.getResources() .getColor(R.color.retroThemeColorPrimary, null))); - } else if (tinyDB.getInt("themeId") == 4) { + } else if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_KEY)) + == 4) { if (TimeHelper.timeBetweenHours( - tinyDB.getInt("darkThemeTimeHour", 18), - tinyDB.getInt("lightThemeTimeHour", 6), - tinyDB.getInt("darkThemeTimeMinute", 0), - tinyDB.getInt("lightThemeTimeMinute", 0))) { + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_DARK_HOUR_KEY)), + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, + AppDatabaseSettings.APP_THEME_AUTO_LIGHT_HOUR_KEY)), + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_DARK_MIN_KEY)), + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, + AppDatabaseSettings.APP_THEME_AUTO_LIGHT_MIN_KEY)))) { ImageViewCompat.setImageTintList( viewBinding.issuePrState, ColorStateList.valueOf( @@ -880,7 +897,10 @@ public class IssueDetailActivity extends BaseActivity ctx.getResources() .getColor(R.color.retroThemeColorPrimary, null))); } - } else if (tinyDB.getInt("themeId") == 8) { + } else if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { ImageViewCompat.setImageTintList( viewBinding.issuePrState, @@ -908,17 +928,31 @@ public class IssueDetailActivity extends BaseActivity loadingFinishedPr = true; updateMenuState(); viewBinding.issuePrState.setImageResource(R.drawable.ic_issue); - if (tinyDB.getInt("themeId") == 3) { + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_KEY)) + == 3) { ImageViewCompat.setImageTintList( viewBinding.issuePrState, ColorStateList.valueOf( ctx.getResources().getColor(R.color.retroThemeColorPrimary, null))); - } else if (tinyDB.getInt("themeId") == 4) { + } else if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_KEY)) + == 4) { if (TimeHelper.timeBetweenHours( - tinyDB.getInt("darkThemeTimeHour", 18), - tinyDB.getInt("lightThemeTimeHour", 6), - tinyDB.getInt("darkThemeTimeMinute", 0), - tinyDB.getInt("lightThemeTimeMinute", 0))) { + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_DARK_HOUR_KEY)), + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_LIGHT_HOUR_KEY)), + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_DARK_MIN_KEY)), + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_LIGHT_MIN_KEY)))) { ImageViewCompat.setImageTintList( viewBinding.issuePrState, ColorStateList.valueOf( @@ -930,7 +964,10 @@ public class IssueDetailActivity extends BaseActivity ctx.getResources() .getColor(R.color.retroThemeColorPrimary, null))); } - } else if (tinyDB.getInt("themeId") == 8) { + } else if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { ImageViewCompat.setImageTintList( viewBinding.issuePrState, diff --git a/app/src/main/java/org/mian/gitnex/activities/MainActivity.java b/app/src/main/java/org/mian/gitnex/activities/MainActivity.java index f0dc01a3..1af81d1d 100644 --- a/app/src/main/java/org/mian/gitnex/activities/MainActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/MainActivity.java @@ -10,6 +10,7 @@ import android.view.MenuItem; import android.view.View; import android.widget.ImageView; import android.widget.TextView; +import androidx.activity.OnBackPressedCallback; import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AppCompatActivity; @@ -54,6 +55,7 @@ import org.mian.gitnex.fragments.SettingsFragment; import org.mian.gitnex.fragments.StarredRepositoriesFragment; import org.mian.gitnex.fragments.WatchedRepositoriesFragment; import org.mian.gitnex.helpers.AlertDialogs; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.ChangeLog; import org.mian.gitnex.helpers.RoundedTransformation; @@ -228,7 +230,7 @@ public class MainActivity extends BaseActivity .observe( (AppCompatActivity) ctx, userAccounts -> { - if (userAccounts.size() > 0) { + if (!userAccounts.isEmpty()) { userAccountsList.clear(); userAccountsList.addAll(userAccounts); navRecyclerViewUserAccounts.setAdapter( @@ -246,15 +248,15 @@ public class MainActivity extends BaseActivity String userFullNameNav = getAccount().getFullName(); String userAvatarNav = getAccount().getUserInfo().getAvatarUrl(); - if (!userEmailNav.equals("")) { + if (!userEmailNav.isEmpty()) { userEmail.setText(userEmailNav); } - if (!userFullNameNav.equals("")) { + if (!userFullNameNav.isEmpty()) { userFullName.setText(Html.fromHtml(userFullNameNav)); } - if (!userAvatarNav.equals("")) { + if (!userAvatarNav.isEmpty()) { int avatarRadius = AppUtil.getPixelsFromDensity(ctx, 60); @@ -400,13 +402,9 @@ public class MainActivity extends BaseActivity if (savedInstanceState == null) { - if (!getAccount().requiresVersion("1.12.3")) { - if (tinyDB.getInt("homeScreenId", 0) == 7) { - tinyDB.putInt("homeScreenId", 0); - } - } - - switch (tinyDB.getInt("homeScreenId", 0)) { + switch (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_HOME_SCREEN_KEY))) { case 1: toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos)); getSupportFragmentManager() @@ -566,6 +564,17 @@ public class MainActivity extends BaseActivity ChangeLog changelogDialog = new ChangeLog(this); changelogDialog.showDialog(); } + + OnBackPressedCallback onBackPressedCallback = + new OnBackPressedCallback(true) { + @Override + public void handleOnBackPressed() { + if (drawer.isDrawerOpen(GravityCompat.START)) { + drawer.closeDrawer(GravityCompat.START); + } + } + }; + getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback); } @Override @@ -639,18 +648,6 @@ public class MainActivity extends BaseActivity } } - @Override - public void onBackPressed() { - - if (drawer.isDrawerOpen(GravityCompat.START)) { - - drawer.closeDrawer(GravityCompat.START); - } else { - - super.onBackPressed(); - } - } - @Override public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) { diff --git a/app/src/main/java/org/mian/gitnex/activities/OrganizationDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/OrganizationDetailActivity.java index 3ccd3b67..41acaddf 100644 --- a/app/src/main/java/org/mian/gitnex/activities/OrganizationDetailActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/OrganizationDetailActivity.java @@ -28,6 +28,7 @@ import org.mian.gitnex.fragments.OrganizationLabelsFragment; import org.mian.gitnex.fragments.OrganizationMembersFragment; import org.mian.gitnex.fragments.OrganizationRepositoriesFragment; import org.mian.gitnex.fragments.OrganizationTeamsFragment; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.ViewPager2Transformers; import org.mian.gitnex.structs.BottomSheetListener; @@ -129,7 +130,10 @@ public class OrganizationDetailActivity extends BaseActivity implements BottomSh viewPager.setAdapter(new OrganizationDetailActivity.ViewPagerAdapter(this)); ViewPager2Transformers.returnSelectedTransformer( - viewPager, tinyDB.getInt("fragmentTabsAnimationId", 0)); + viewPager, + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_TABS_ANIMATION_KEY))); List tabsList = new ArrayList<>(); tabsList.add(getResources().getString(R.string.tabTextInfo)); diff --git a/app/src/main/java/org/mian/gitnex/activities/OrganizationTeamInfoActivity.java b/app/src/main/java/org/mian/gitnex/activities/OrganizationTeamInfoActivity.java index 5df687c5..5430003c 100644 --- a/app/src/main/java/org/mian/gitnex/activities/OrganizationTeamInfoActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/OrganizationTeamInfoActivity.java @@ -14,6 +14,7 @@ import org.mian.gitnex.databinding.ActivityOrgTeamInfoBinding; import org.mian.gitnex.fragments.OrganizationTeamInfoMembersFragment; import org.mian.gitnex.fragments.OrganizationTeamInfoPermissionsFragment; import org.mian.gitnex.fragments.OrganizationTeamInfoReposFragment; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.ViewPager2Transformers; /** @@ -37,6 +38,7 @@ public class OrganizationTeamInfoActivity extends BaseActivity { team = (Team) getIntent().getSerializableExtra("team"); + assert team != null; if (team.getName() != null && !team.getName().isEmpty()) { binding.toolbarTitle.setText(team.getName()); } else { @@ -68,7 +70,10 @@ public class OrganizationTeamInfoActivity extends BaseActivity { }); ViewPager2Transformers.returnSelectedTransformer( - binding.pager, tinyDB.getInt("fragmentTabsAnimationId", 0)); + binding.pager, + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_TABS_ANIMATION_KEY))); new TabLayoutMediator( binding.tabs, diff --git a/app/src/main/java/org/mian/gitnex/activities/ProfileActivity.java b/app/src/main/java/org/mian/gitnex/activities/ProfileActivity.java index a44d1652..8e69354c 100644 --- a/app/src/main/java/org/mian/gitnex/activities/ProfileActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/ProfileActivity.java @@ -26,6 +26,7 @@ import org.mian.gitnex.fragments.profile.FollowingFragment; import org.mian.gitnex.fragments.profile.OrganizationsFragment; import org.mian.gitnex.fragments.profile.RepositoriesFragment; import org.mian.gitnex.fragments.profile.StarredRepositoriesFragment; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.ViewPager2Transformers; @@ -76,7 +77,10 @@ public class ProfileActivity extends BaseActivity implements BottomSheetListener viewPager.setAdapter(new ViewPagerAdapter(this)); ViewPager2Transformers.returnSelectedTransformer( - viewPager, tinyDB.getInt("fragmentTabsAnimationId", 0)); + viewPager, + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_TABS_ANIMATION_KEY))); String[] tabTitles = { ctx.getResources().getString(R.string.tabTextInfo), diff --git a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java index b2ab63f1..501b9aa4 100644 --- a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java @@ -50,6 +50,7 @@ import org.mian.gitnex.fragments.PullRequestsFragment; import org.mian.gitnex.fragments.ReleasesFragment; import org.mian.gitnex.fragments.RepoInfoFragment; import org.mian.gitnex.fragments.WikiFragment; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.ViewPager2Transformers; @@ -539,7 +540,10 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe viewPager.setAdapter(new ViewPagerAdapter(this)); ViewPager2Transformers.returnSelectedTransformer( - viewPager, tinyDB.getInt("fragmentTabsAnimationId", 0)); + viewPager, + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_TABS_ANIMATION_KEY))); String[] tabTitles = { ctx.getResources().getString(R.string.tabTextInfo), @@ -578,7 +582,8 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe } } - if (tinyDB.getBoolean("enableCounterBadges", true)) { + if (Boolean.parseBoolean( + AppDatabaseSettings.getSettingsValue(ctx, AppDatabaseSettings.APP_COUNTER_KEY))) { @SuppressLint("InflateParams") View tabHeader2 = LayoutInflater.from(ctx).inflate(R.layout.badge_issue, null); if (textViewBadgeIssue == null) { diff --git a/app/src/main/java/org/mian/gitnex/activities/SettingsAppearanceActivity.java b/app/src/main/java/org/mian/gitnex/activities/SettingsAppearanceActivity.java index 0361e6d6..f8f9a619 100644 --- a/app/src/main/java/org/mian/gitnex/activities/SettingsAppearanceActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/SettingsAppearanceActivity.java @@ -2,6 +2,7 @@ package org.mian.gitnex.activities; import android.os.Build; import android.os.Bundle; +import android.os.Handler; import android.view.View; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.timepicker.MaterialTimePicker; @@ -10,10 +11,10 @@ import java.util.Locale; import org.mian.gitnex.R; import org.mian.gitnex.databinding.ActivitySettingsAppearanceBinding; import org.mian.gitnex.fragments.SettingsFragment; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.FontsOverride; import org.mian.gitnex.helpers.SnackBar; -import org.mian.gitnex.helpers.TinyDB; /** * @author M M Arif @@ -21,12 +22,12 @@ import org.mian.gitnex.helpers.TinyDB; public class SettingsAppearanceActivity extends BaseActivity { private static String[] customFontList; - private static int customFontSelectedChoice = 0; + private static int customFontSelectedChoice; private static String[] themeList; - private static int themeSelectedChoice = 0; - private static int langSelectedChoice = 0; + private static int themeSelectedChoice; + private static int langSelectedChoice; private static String[] fragmentTabsAnimationList; - private static int fragmentTabsAnimationSelectedChoice = 0; + private static int fragmentTabsAnimationSelectedChoice; @Override public void onCreate(Bundle savedInstanceState) { @@ -38,7 +39,7 @@ public class SettingsAppearanceActivity extends BaseActivity { setContentView(activitySettingsAppearanceBinding.getRoot()); LinkedHashMap lang = new LinkedHashMap<>(); - lang.put("", getString(R.string.settingsLanguageSystem)); + lang.put("sys", getString(R.string.settingsLanguageSystem)); for (String langCode : getResources().getStringArray(R.array.languages)) { lang.put(langCode, getLanguageDisplayName(langCode)); } @@ -55,8 +56,14 @@ public class SettingsAppearanceActivity extends BaseActivity { activitySettingsAppearanceBinding.topAppBar.setNavigationOnClickListener(v -> finish()); - String lightMinute = String.valueOf(tinyDB.getInt("lightThemeTimeMinute")); - String lightHour = String.valueOf(tinyDB.getInt("lightThemeTimeHour")); + String lightMinute = + String.valueOf( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_LIGHT_MIN_KEY)); + String lightHour = + String.valueOf( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_LIGHT_HOUR_KEY)); if (lightMinute.length() == 1) { lightMinute = "0" + lightMinute; } @@ -64,8 +71,14 @@ public class SettingsAppearanceActivity extends BaseActivity { lightHour = "0" + lightHour; } - String darkMinute = String.valueOf(tinyDB.getInt("darkThemeTimeMinute")); - String darkHour = String.valueOf(tinyDB.getInt("darkThemeTimeHour")); + String darkMinute = + String.valueOf( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_DARK_MIN_KEY)); + String darkHour = + String.valueOf( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_DARK_HOUR_KEY)); if (darkMinute.length() == 1) { darkMinute = "0" + darkMinute; } @@ -73,9 +86,18 @@ public class SettingsAppearanceActivity extends BaseActivity { darkHour = "0" + darkHour; } - fragmentTabsAnimationSelectedChoice = tinyDB.getInt("fragmentTabsAnimationId", 0); - customFontSelectedChoice = tinyDB.getInt("customFontId", 1); - themeSelectedChoice = tinyDB.getInt("themeId", 6); // use system theme as default + fragmentTabsAnimationSelectedChoice = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_TABS_ANIMATION_KEY)); + customFontSelectedChoice = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_FONT_KEY)); + themeSelectedChoice = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_KEY)); activitySettingsAppearanceBinding.lightThemeSelectedTime.setText( ctx.getResources() @@ -100,12 +122,15 @@ public class SettingsAppearanceActivity extends BaseActivity { } activitySettingsAppearanceBinding.switchCounterBadge.setChecked( - tinyDB.getBoolean("enableCounterBadges", true)); + Boolean.parseBoolean( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_COUNTER_KEY))); // counter badge switcher activitySettingsAppearanceBinding.switchCounterBadge.setOnCheckedChangeListener( (buttonView, isChecked) -> { - tinyDB.putBoolean("enableCounterBadges", isChecked); + AppDatabaseSettings.updateSettingsValue( + ctx, String.valueOf(isChecked), AppDatabaseSettings.APP_COUNTER_KEY); SnackBar.success( ctx, findViewById(android.R.id.content), @@ -118,11 +143,16 @@ public class SettingsAppearanceActivity extends BaseActivity { // show labels in lists(issues, pr) - default is color dots activitySettingsAppearanceBinding.switchLabelsInListBadge.setChecked( - tinyDB.getBoolean("showLabelsInList", false)); + Boolean.parseBoolean( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_LABELS_IN_LIST_KEY))); activitySettingsAppearanceBinding.switchLabelsInListBadge.setOnCheckedChangeListener( (buttonView, isChecked) -> { - tinyDB.putBoolean("showLabelsInList", isChecked); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(isChecked), + AppDatabaseSettings.APP_LABELS_IN_LIST_KEY); SnackBar.success( ctx, findViewById(android.R.id.content), @@ -147,7 +177,10 @@ public class SettingsAppearanceActivity extends BaseActivity { themeSelectedChoice = i; activitySettingsAppearanceBinding.themeSelected .setText(themeList[i]); - tinyDB.putInt("themeId", i); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(i), + AppDatabaseSettings.APP_THEME_KEY); SettingsFragment.refreshParent = true; this.recreate(); @@ -182,13 +215,26 @@ public class SettingsAppearanceActivity extends BaseActivity { customFontSelectedChoice = i; activitySettingsAppearanceBinding.customFontSelected .setText(customFontList[i]); - tinyDB.putInt("customFontId", i); - AppUtil.typeface = null; // reset typeface - FontsOverride.setDefaultFont(this); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(i), + AppDatabaseSettings.APP_FONT_KEY); + + new Handler() + .postDelayed( + () -> { + AppUtil.typeface = + null; // reset typeface + FontsOverride.setDefaultFont( + this); + SettingsFragment.refreshParent = + true; + this.recreate(); + this.overridePendingTransition( + 0, 0); + }, + 1000); - SettingsFragment.refreshParent = true; - this.recreate(); - this.overridePendingTransition(0, 0); dialogInterfaceCustomFont.dismiss(); SnackBar.success( ctx, @@ -209,19 +255,20 @@ public class SettingsAppearanceActivity extends BaseActivity { .setSingleChoiceItems( fragmentTabsAnimationList, fragmentTabsAnimationSelectedChoice, - (dialogInterfaceCustomFont, i) -> { + (dialogInterfaceTabsAnimation, i) -> { fragmentTabsAnimationSelectedChoice = i; activitySettingsAppearanceBinding .fragmentTabsAnimationFrameSelected.setText( fragmentTabsAnimationList[i]); - tinyDB.putInt("fragmentTabsAnimationId", i); - AppUtil.typeface = null; // reset typeface - FontsOverride.setDefaultFont(this); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(i), + AppDatabaseSettings.APP_TABS_ANIMATION_KEY); SettingsFragment.refreshParent = true; this.recreate(); this.overridePendingTransition(0, 0); - dialogInterfaceCustomFont.dismiss(); + dialogInterfaceTabsAnimation.dismiss(); SnackBar.success( ctx, findViewById(android.R.id.content), @@ -237,7 +284,10 @@ public class SettingsAppearanceActivity extends BaseActivity { AppUtil.openUrlInBrowser( this, getResources().getString(R.string.crowdInLink))); - langSelectedChoice = tinyDB.getInt("langId"); + String[] locale = + AppDatabaseSettings.getSettingsValue(ctx, AppDatabaseSettings.APP_LOCALE_KEY) + .split("\\|"); + langSelectedChoice = Integer.parseInt(locale[0]); activitySettingsAppearanceBinding.tvLanguageSelected.setText( lang.get(lang.keySet().toArray(new String[0])[langSelectedChoice])); @@ -255,8 +305,10 @@ public class SettingsAppearanceActivity extends BaseActivity { (dialogInterface, i) -> { String selectedLanguage = lang.keySet().toArray(new String[0])[i]; - tinyDB.putInt("langId", i); - tinyDB.putString("locale", selectedLanguage); + AppDatabaseSettings.updateSettingsValue( + ctx, + i + "|" + selectedLanguage, + AppDatabaseSettings.APP_LOCALE_KEY); SettingsFragment.refreshParent = true; this.overridePendingTransition(0, 0); @@ -274,18 +326,28 @@ public class SettingsAppearanceActivity extends BaseActivity { public void lightTimePicker() { - TinyDB db = TinyDB.getInstance(ctx); - - int hour = db.getInt("lightThemeTimeHour"); - int minute = db.getInt("lightThemeTimeMinute"); + int hour = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_LIGHT_HOUR_KEY)); + int minute = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_LIGHT_MIN_KEY)); MaterialTimePicker materialTimePicker = new MaterialTimePicker.Builder().setHour(hour).setMinute(minute).build(); materialTimePicker.addOnPositiveButtonClickListener( selection -> { - db.putInt("lightThemeTimeHour", materialTimePicker.getHour()); - db.putInt("lightThemeTimeMinute", materialTimePicker.getMinute()); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(materialTimePicker.getHour()), + AppDatabaseSettings.APP_THEME_AUTO_LIGHT_HOUR_KEY); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(materialTimePicker.getMinute()), + AppDatabaseSettings.APP_THEME_AUTO_LIGHT_MIN_KEY); SettingsFragment.refreshParent = true; overridePendingTransition(0, 0); SnackBar.success( @@ -300,18 +362,28 @@ public class SettingsAppearanceActivity extends BaseActivity { public void darkTimePicker() { - TinyDB db = TinyDB.getInstance(ctx); - - int hour = db.getInt("darkThemeTimeHour"); - int minute = db.getInt("darkThemeTimeMinute"); + int hour = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_DARK_HOUR_KEY)); + int minute = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_THEME_AUTO_DARK_MIN_KEY)); MaterialTimePicker materialTimePicker = new MaterialTimePicker.Builder().setHour(hour).setMinute(minute).build(); materialTimePicker.addOnPositiveButtonClickListener( selection -> { - db.putInt("darkThemeTimeHour", materialTimePicker.getHour()); - db.putInt("darkThemeTimeMinute", materialTimePicker.getMinute()); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(materialTimePicker.getHour()), + AppDatabaseSettings.APP_THEME_AUTO_DARK_HOUR_KEY); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(materialTimePicker.getMinute()), + AppDatabaseSettings.APP_THEME_AUTO_DARK_MIN_KEY); SettingsFragment.refreshParent = true; overridePendingTransition(0, 0); SnackBar.success( @@ -326,7 +398,17 @@ public class SettingsAppearanceActivity extends BaseActivity { private static String getLanguageDisplayName(String langCode) { Locale english = new Locale("en"); - Locale translated = new Locale(langCode); + + String[] multiCodeLang = langCode.split("-"); + String countryCode; + if (langCode.contains("-")) { + langCode = multiCodeLang[0]; + countryCode = multiCodeLang[1]; + } else { + countryCode = ""; + } + + Locale translated = new Locale(langCode, countryCode); return String.format( "%s (%s)", translated.getDisplayName(translated), translated.getDisplayName(english)); diff --git a/app/src/main/java/org/mian/gitnex/activities/SettingsCodeEditorActivity.java b/app/src/main/java/org/mian/gitnex/activities/SettingsCodeEditorActivity.java index 3cb93c29..861dc9b5 100644 --- a/app/src/main/java/org/mian/gitnex/activities/SettingsCodeEditorActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/SettingsCodeEditorActivity.java @@ -6,6 +6,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.mian.gitnex.R; import org.mian.gitnex.databinding.ActivitySettingsCodeEditorBinding; import org.mian.gitnex.fragments.SettingsFragment; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.SnackBar; /** @@ -14,11 +15,11 @@ import org.mian.gitnex.helpers.SnackBar; public class SettingsCodeEditorActivity extends BaseActivity { private static String[] colorList; - private static int colorSelectedChoice = 0; + private static int colorSelectedChoice; private static String[] indentationList; - private static int indentationSelectedChoice = 0; + private static int indentationSelectedChoice; private static String[] indentationTabsList; - private static int indentationTabsSelectedChoice = 0; + private static int indentationTabsSelectedChoice; @Override public void onCreate(Bundle savedInstanceState) { @@ -33,7 +34,10 @@ public class SettingsCodeEditorActivity extends BaseActivity { // color selector dialog colorList = getResources().getStringArray(R.array.ceColors); - colorSelectedChoice = tinyDB.getInt("ceColorId"); + colorSelectedChoice = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_CE_SYNTAX_HIGHLIGHT_KEY)); activitySettingsCodeEditorBinding.ceColorSelected.setText(colorList[colorSelectedChoice]); activitySettingsCodeEditorBinding.ceColorSelectionFrame.setOnClickListener( @@ -48,7 +52,11 @@ public class SettingsCodeEditorActivity extends BaseActivity { colorSelectedChoice = i; activitySettingsCodeEditorBinding.ceColorSelected .setText(colorList[i]); - tinyDB.putInt("ceColorId", i); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(i), + AppDatabaseSettings + .APP_CE_SYNTAX_HIGHLIGHT_KEY); SettingsFragment.refreshParent = true; this.recreate(); @@ -65,7 +73,10 @@ public class SettingsCodeEditorActivity extends BaseActivity { // indentation selector dialog indentationList = getResources().getStringArray(R.array.ceIndentation); - indentationSelectedChoice = tinyDB.getInt("ceIndentationId"); + indentationSelectedChoice = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_CE_INDENTATION_KEY)); activitySettingsCodeEditorBinding.indentationSelected.setText( indentationList[indentationSelectedChoice]); @@ -82,7 +93,10 @@ public class SettingsCodeEditorActivity extends BaseActivity { activitySettingsCodeEditorBinding .indentationSelected.setText( indentationList[i]); - tinyDB.putInt("ceIndentationId", i); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(i), + AppDatabaseSettings.APP_CE_INDENTATION_KEY); SettingsFragment.refreshParent = true; this.recreate(); @@ -107,7 +121,10 @@ public class SettingsCodeEditorActivity extends BaseActivity { } indentationTabsList = getResources().getStringArray(R.array.ceIndentationTabsWidth); - indentationTabsSelectedChoice = tinyDB.getInt("ceIndentationTabsId"); + indentationTabsSelectedChoice = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_CE_TABS_WIDTH_KEY)); activitySettingsCodeEditorBinding.indentationTabsSelected.setText( indentationTabsList[indentationTabsSelectedChoice]); @@ -124,7 +141,10 @@ public class SettingsCodeEditorActivity extends BaseActivity { activitySettingsCodeEditorBinding .indentationTabsSelected.setText( indentationTabsList[i]); - tinyDB.putInt("ceIndentationTabsId", i); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(i), + AppDatabaseSettings.APP_CE_TABS_WIDTH_KEY); SettingsFragment.refreshParent = true; this.recreate(); diff --git a/app/src/main/java/org/mian/gitnex/activities/SettingsGeneralActivity.java b/app/src/main/java/org/mian/gitnex/activities/SettingsGeneralActivity.java index 6f539315..8c548b2a 100644 --- a/app/src/main/java/org/mian/gitnex/activities/SettingsGeneralActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/SettingsGeneralActivity.java @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.List; import org.mian.gitnex.R; import org.mian.gitnex.databinding.ActivitySettingsGeneralBinding; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.SnackBar; /** @@ -14,11 +15,9 @@ import org.mian.gitnex.helpers.SnackBar; */ public class SettingsGeneralActivity extends BaseActivity { - private static int homeScreenSelectedChoice = 0; - private static int defaultLinkHandlerScreenSelectedChoice = 0; + private static int homeScreenSelectedChoice; + private static int defaultLinkHandlerScreenSelectedChoice; private ActivitySettingsGeneralBinding viewBinding; - private List homeScreenList; - private List linkHandlerDefaultScreen; @Override public void onCreate(Bundle savedInstanceState) { @@ -31,73 +30,15 @@ public class SettingsGeneralActivity extends BaseActivity { viewBinding.topAppBar.setNavigationOnClickListener(v -> finish()); // home screen - String[] appHomeDefaultScreen = getResources().getStringArray(R.array.appDefaultHomeScreen); - - String[] appHomeDefaultScreenNew = + String[] appHomeDefaultScreen = getResources().getStringArray(R.array.appDefaultHomeScreenNew); - if (getAccount().requiresVersion("1.12.3")) { + homeScreenSelectedChoice = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_HOME_SCREEN_KEY)); - appHomeDefaultScreen = appHomeDefaultScreenNew; - } - - homeScreenList = new ArrayList<>(Arrays.asList(appHomeDefaultScreen)); - - if (!getAccount().requiresVersion("1.14.0")) { - homeScreenList.remove(8); - } - - String[] homeScreenArray = new String[homeScreenList.size()]; - homeScreenList.toArray(homeScreenArray); - - if (homeScreenSelectedChoice == 0) { - - homeScreenSelectedChoice = tinyDB.getInt("homeScreenId", 0); - viewBinding.homeScreenSelected.setText(getResources().getString(R.string.navMyRepos)); - } - - if (homeScreenSelectedChoice == 1) { - - viewBinding.homeScreenSelected.setText( - getResources().getString(R.string.pageTitleStarredRepos)); - } else if (homeScreenSelectedChoice == 2) { - - viewBinding.homeScreenSelected.setText(getResources().getString(R.string.navOrg)); - } else if (homeScreenSelectedChoice == 3) { - - viewBinding.homeScreenSelected.setText(getResources().getString(R.string.navRepos)); - } else if (homeScreenSelectedChoice == 4) { - - viewBinding.homeScreenSelected.setText(getResources().getString(R.string.navAccount)); - } else if (homeScreenSelectedChoice == 5) { - - viewBinding.homeScreenSelected.setText( - getResources().getString(R.string.pageTitleExplore)); - } else if (homeScreenSelectedChoice == 6) { - - viewBinding.homeScreenSelected.setText(getResources().getString(R.string.titleDrafts)); - } else if (homeScreenSelectedChoice == 7) { - - viewBinding.homeScreenSelected.setText( - getResources().getString(R.string.pageTitleNotifications)); - } else if (homeScreenSelectedChoice == 8) { - - viewBinding.homeScreenSelected.setText(getResources().getString(R.string.navMyIssues)); - } else if (homeScreenSelectedChoice == 9) { - - viewBinding.homeScreenSelected.setText( - getResources().getString(R.string.navMostVisited)); - } else if (homeScreenSelectedChoice == 10) { - - viewBinding.homeScreenSelected.setText(getResources().getString(R.string.navNotes)); - } else if (homeScreenSelectedChoice == 11) { - - viewBinding.homeScreenSelected.setText(getResources().getString(R.string.dashboard)); - } else if (homeScreenSelectedChoice == 12) { - - viewBinding.homeScreenSelected.setText( - getResources().getString(R.string.navWatchedRepositories)); - } + viewBinding.homeScreenSelected.setText(appHomeDefaultScreen[homeScreenSelectedChoice]); viewBinding.homeScreenFrame.setOnClickListener( setDefaultHomeScreen -> { @@ -106,13 +47,17 @@ public class SettingsGeneralActivity extends BaseActivity { .setTitle(R.string.settingsHomeScreenSelectorDialogTitle) .setCancelable(homeScreenSelectedChoice != -1) .setSingleChoiceItems( - homeScreenArray, + appHomeDefaultScreen, homeScreenSelectedChoice, (dialogInterfaceHomeScreen, i) -> { homeScreenSelectedChoice = i; viewBinding.homeScreenSelected.setText( - homeScreenArray[i]); - tinyDB.putInt("homeScreenId", i); + appHomeDefaultScreen[i]); + + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(i), + AppDatabaseSettings.APP_HOME_SCREEN_KEY); dialogInterfaceHomeScreen.dismiss(); SnackBar.success( @@ -128,12 +73,16 @@ public class SettingsGeneralActivity extends BaseActivity { // link handler String[] linkHandlerDefaultScreenList = getResources().getStringArray(R.array.linkHandlerDefaultScreen); - linkHandlerDefaultScreen = new ArrayList<>(Arrays.asList(linkHandlerDefaultScreenList)); + List linkHandlerDefaultScreen = + new ArrayList<>(Arrays.asList(linkHandlerDefaultScreenList)); String[] linksArray = new String[linkHandlerDefaultScreen.size()]; linkHandlerDefaultScreen.toArray(linksArray); - defaultLinkHandlerScreenSelectedChoice = tinyDB.getInt("defaultScreenId"); + defaultLinkHandlerScreenSelectedChoice = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_LINK_HANDLER_KEY)); viewBinding.generalDeepLinkSelected.setText( linksArray[defaultLinkHandlerScreenSelectedChoice]); @@ -150,7 +99,11 @@ public class SettingsGeneralActivity extends BaseActivity { defaultLinkHandlerScreenSelectedChoice = i; viewBinding.generalDeepLinkSelected.setText( linksArray[i]); - tinyDB.putInt("defaultScreenId", i); + + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(i), + AppDatabaseSettings.APP_LINK_HANDLER_KEY); dialogInterfaceHomeScreen.dismiss(); SnackBar.success( @@ -163,11 +116,17 @@ public class SettingsGeneralActivity extends BaseActivity { }); // link handler - // custom tabs - viewBinding.switchTabs.setChecked(tinyDB.getBoolean("useCustomTabs")); + // custom tabs switcher + viewBinding.switchTabs.setChecked( + Boolean.parseBoolean( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_CUSTOM_BROWSER_KEY))); viewBinding.switchTabs.setOnCheckedChangeListener( (buttonView, isChecked) -> { - tinyDB.putBoolean("useCustomTabs", isChecked); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(isChecked), + AppDatabaseSettings.APP_CUSTOM_BROWSER_KEY); SnackBar.success( ctx, findViewById(android.R.id.content), @@ -175,16 +134,19 @@ public class SettingsGeneralActivity extends BaseActivity { }); viewBinding.customTabsFrame.setOnClickListener( v -> viewBinding.switchTabs.setChecked(!viewBinding.switchTabs.isChecked())); - // custom tabs + // custom tabs switcher - // enable drafts deletion + // drafts deletion switcher viewBinding.commentsDeletionSwitch.setChecked( - tinyDB.getBoolean("draftsCommentsDeletionEnabled", true)); - - // delete comments on submit switcher + Boolean.parseBoolean( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_DRAFTS_DELETION_KEY))); viewBinding.commentsDeletionSwitch.setOnCheckedChangeListener( (buttonView, isChecked) -> { - tinyDB.putBoolean("draftsCommentsDeletionEnabled", isChecked); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(isChecked), + AppDatabaseSettings.APP_DRAFTS_DELETION_KEY); SnackBar.success( ctx, findViewById(android.R.id.content), @@ -194,12 +156,19 @@ public class SettingsGeneralActivity extends BaseActivity { v -> viewBinding.commentsDeletionSwitch.setChecked( !viewBinding.commentsDeletionSwitch.isChecked())); - // enable drafts deletion + // drafts deletion switcher // crash reports switcher + viewBinding.crashReportsSwitch.setChecked( + Boolean.parseBoolean( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_CRASH_REPORTS_KEY))); viewBinding.crashReportsSwitch.setOnCheckedChangeListener( (buttonView, isChecked) -> { - tinyDB.putBoolean("crashReportingEnabled", isChecked); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(isChecked), + AppDatabaseSettings.APP_CRASH_REPORTS_KEY); SnackBar.success( ctx, findViewById(android.R.id.content), diff --git a/app/src/main/java/org/mian/gitnex/activities/SettingsNotificationsActivity.java b/app/src/main/java/org/mian/gitnex/activities/SettingsNotificationsActivity.java index a48b7343..02f3a589 100644 --- a/app/src/main/java/org/mian/gitnex/activities/SettingsNotificationsActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/SettingsNotificationsActivity.java @@ -6,6 +6,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.mian.gitnex.R; import org.mian.gitnex.databinding.ActivitySettingsNotificationsBinding; import org.mian.gitnex.fragments.SettingsFragment; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.SnackBar; import org.mian.gitnex.notifications.Notifications; @@ -18,7 +19,7 @@ public class SettingsNotificationsActivity extends BaseActivity { private ActivitySettingsNotificationsBinding viewBinding; private static String[] pollingDelayList; - private static int pollingDelayListSelectedChoice = 0; + private static int pollingDelayListSelectedChoice; @Override public void onCreate(Bundle savedInstanceState) { @@ -31,7 +32,9 @@ public class SettingsNotificationsActivity extends BaseActivity { viewBinding.topAppBar.setNavigationOnClickListener(v -> finish()); viewBinding.enableNotificationsMode.setChecked( - tinyDB.getBoolean("notificationsEnabled", true)); + Boolean.parseBoolean( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_NOTIFICATIONS_KEY))); if (!viewBinding.enableNotificationsMode.isChecked()) { AppUtil.setMultiVisibility(View.GONE, viewBinding.pollingDelayFrame); @@ -39,7 +42,10 @@ public class SettingsNotificationsActivity extends BaseActivity { viewBinding.enableNotificationsMode.setOnCheckedChangeListener( (buttonView, isChecked) -> { - tinyDB.putBoolean("notificationsEnabled", isChecked); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(isChecked), + AppDatabaseSettings.APP_NOTIFICATIONS_KEY); if (isChecked) { Notifications.startWorker(ctx); @@ -61,7 +67,10 @@ public class SettingsNotificationsActivity extends BaseActivity { // polling delay pollingDelayList = getResources().getStringArray(R.array.notificationsPollingDelay); - pollingDelayListSelectedChoice = tinyDB.getInt("notificationsPollingDelayId"); + pollingDelayListSelectedChoice = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY)); viewBinding.pollingDelaySelected.setText(pollingDelayList[pollingDelayListSelectedChoice]); viewBinding.pollingDelayFrame.setOnClickListener( @@ -77,7 +86,12 @@ public class SettingsNotificationsActivity extends BaseActivity { viewBinding.pollingDelaySelected.setText( pollingDelayList[ pollingDelayListSelectedChoice]); - tinyDB.putInt("notificationsPollingDelayId", i); + + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(i), + AppDatabaseSettings + .APP_NOTIFICATIONS_DELAY_KEY); Notifications.stopWorker(ctx); Notifications.startWorker(ctx); diff --git a/app/src/main/java/org/mian/gitnex/activities/SettingsSecurityActivity.java b/app/src/main/java/org/mian/gitnex/activities/SettingsSecurityActivity.java index 80d5159e..43bb7095 100644 --- a/app/src/main/java/org/mian/gitnex/activities/SettingsSecurityActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/SettingsSecurityActivity.java @@ -13,6 +13,7 @@ import java.io.IOException; import org.apache.commons.io.FileUtils; import org.mian.gitnex.R; import org.mian.gitnex.databinding.ActivitySettingsSecurityBinding; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.SnackBar; import org.mian.gitnex.helpers.ssl.MemorizingTrustManager; @@ -23,9 +24,9 @@ import org.mian.gitnex.helpers.ssl.MemorizingTrustManager; public class SettingsSecurityActivity extends BaseActivity { private static String[] cacheSizeDataList; - private static int cacheSizeDataSelectedChoice = 0; + private static int cacheSizeDataSelectedChoice; private static String[] cacheSizeImagesList; - private static int cacheSizeImagesSelectedChoice = 0; + private static int cacheSizeImagesSelectedChoice; @Override public void onCreate(Bundle savedInstanceState) { @@ -41,26 +42,24 @@ public class SettingsSecurityActivity extends BaseActivity { cacheSizeDataList = getResources().getStringArray(R.array.cacheSizeList); cacheSizeImagesList = getResources().getStringArray(R.array.cacheSizeList); + cacheSizeDataSelectedChoice = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_DATA_CACHE_KEY)); + cacheSizeImagesSelectedChoice = + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_IMAGES_CACHE_KEY)); + activitySettingsSecurityBinding.cacheSizeDataSelected.setText( - tinyDB.getString( - "cacheSizeStr", getString(R.string.cacheSizeDataSelectionSelectedText))); + cacheSizeDataList[cacheSizeDataSelectedChoice]); activitySettingsSecurityBinding.cacheSizeImagesSelected.setText( - tinyDB.getString( - "cacheSizeImagesStr", - getString(R.string.cacheSizeImagesSelectionSelectedText))); - - if (cacheSizeDataSelectedChoice == 0) { - - cacheSizeDataSelectedChoice = tinyDB.getInt("cacheSizeId"); - } - - if (cacheSizeImagesSelectedChoice == 0) { - - cacheSizeImagesSelectedChoice = tinyDB.getInt("cacheSizeImagesId"); - } + cacheSizeImagesList[cacheSizeImagesSelectedChoice]); activitySettingsSecurityBinding.switchBiometric.setChecked( - tinyDB.getBoolean("biometricStatus", false)); + Boolean.parseBoolean( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_BIOMETRIC_KEY))); // biometric switcher activitySettingsSecurityBinding.switchBiometric.setOnCheckedChangeListener( @@ -76,7 +75,8 @@ public class SettingsSecurityActivity extends BaseActivity { switch (biometricManager.canAuthenticate( BIOMETRIC_STRONG | DEVICE_CREDENTIAL)) { case BiometricManager.BIOMETRIC_SUCCESS: - tinyDB.putBoolean("biometricStatus", true); + AppDatabaseSettings.updateSettingsValue( + ctx, "true", AppDatabaseSettings.APP_BIOMETRIC_KEY); SnackBar.success( ctx, findViewById(android.R.id.content), @@ -86,7 +86,8 @@ public class SettingsSecurityActivity extends BaseActivity { case BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED: case BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED: case BiometricManager.BIOMETRIC_STATUS_UNKNOWN: - tinyDB.putBoolean("biometricStatus", false); + AppDatabaseSettings.updateSettingsValue( + ctx, "false", AppDatabaseSettings.APP_BIOMETRIC_KEY); activitySettingsSecurityBinding.switchBiometric.setChecked( false); SnackBar.error( @@ -95,7 +96,8 @@ public class SettingsSecurityActivity extends BaseActivity { getString(R.string.biometricNotSupported)); break; case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE: - tinyDB.putBoolean("biometricStatus", false); + AppDatabaseSettings.updateSettingsValue( + ctx, "false", AppDatabaseSettings.APP_BIOMETRIC_KEY); activitySettingsSecurityBinding.switchBiometric.setChecked( false); SnackBar.error( @@ -104,7 +106,8 @@ public class SettingsSecurityActivity extends BaseActivity { getString(R.string.biometricNotAvailable)); break; case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED: - tinyDB.putBoolean("biometricStatus", false); + AppDatabaseSettings.updateSettingsValue( + ctx, "false", AppDatabaseSettings.APP_BIOMETRIC_KEY); activitySettingsSecurityBinding.switchBiometric.setChecked( false); SnackBar.info( @@ -115,7 +118,8 @@ public class SettingsSecurityActivity extends BaseActivity { } } else { - tinyDB.putBoolean("biometricStatus", true); + AppDatabaseSettings.updateSettingsValue( + ctx, "true", AppDatabaseSettings.APP_BIOMETRIC_KEY); SnackBar.success( ctx, findViewById(android.R.id.content), @@ -123,7 +127,8 @@ public class SettingsSecurityActivity extends BaseActivity { } } else { - tinyDB.putBoolean("biometricStatus", false); + AppDatabaseSettings.updateSettingsValue( + ctx, "false", AppDatabaseSettings.APP_BIOMETRIC_KEY); SnackBar.success( ctx, findViewById(android.R.id.content), @@ -186,10 +191,16 @@ public class SettingsSecurityActivity extends BaseActivity { activitySettingsSecurityBinding .cacheSizeImagesSelected.setText( cacheSizeImagesList[i]); - tinyDB.putString( - "cacheSizeImagesStr", - cacheSizeImagesList[i]); - tinyDB.putInt("cacheSizeImagesId", i); + + AppDatabaseSettings.updateSettingsValue( + ctx, + cacheSizeImagesList[i], + AppDatabaseSettings + .APP_IMAGES_CACHE_SIZE_KEY); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(i), + AppDatabaseSettings.APP_IMAGES_CACHE_KEY); dialogInterfaceTheme.dismiss(); SnackBar.success( @@ -216,9 +227,16 @@ public class SettingsSecurityActivity extends BaseActivity { activitySettingsSecurityBinding .cacheSizeDataSelected.setText( cacheSizeDataList[i]); - tinyDB.putString( - "cacheSizeStr", cacheSizeDataList[i]); - tinyDB.putInt("cacheSizeId", i); + + AppDatabaseSettings.updateSettingsValue( + ctx, + cacheSizeDataList[i], + AppDatabaseSettings + .APP_DATA_CACHE_SIZE_KEY); + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(i), + AppDatabaseSettings.APP_DATA_CACHE_KEY); dialogInterfaceTheme.dismiss(); SnackBar.success( diff --git a/app/src/main/java/org/mian/gitnex/adapters/ExploreIssuesAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/ExploreIssuesAdapter.java index 0b5cb5a4..6b0ab2f1 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/ExploreIssuesAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/ExploreIssuesAdapter.java @@ -27,6 +27,7 @@ import org.mian.gitnex.R; import org.mian.gitnex.activities.IssueDetailActivity; import org.mian.gitnex.activities.ProfileActivity; import org.mian.gitnex.clients.PicassoService; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.ClickListener; import org.mian.gitnex.helpers.ColorInverter; @@ -239,7 +240,9 @@ public class ExploreIssuesAdapter extends RecyclerView.Adapter { - getAttachments(issueComment.getId(), view, token); - }, - 250); + if (issueComment != null) { + new Handler() + .postDelayed( + () -> { + getAttachments(issueComment.getId(), view, token); + }, + 250); + } menu.setOnClickListener( v -> { @@ -470,837 +473,934 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter { - spannableString.setSpan( - image, - text.indexOf('|'), - text.indexOf('|') + 1, - Spannable.SPAN_INCLUSIVE_EXCLUSIVE); - - if (tinyDB.getInt("themeId") == 8) { - if (!isNightModeThemeDynamic(context)) { - textView.setTextColor( - AppUtil.dynamicColorResource(context)); - } - } - textView.setText(spannableString); - timelineData.addView(textView); - }, - 250); - } - // pull/push/commit data view in timeline - else if (issueComment.getType().equalsIgnoreCase("pull_push")) { - - TextView start = new TextView(context); - - JSONObject commitsObj = null; - try { - commitsObj = new JSONObject(issueComment.getBody()); - } catch (JSONException ignored) { - } - - JSONArray commitsShaArray = null; - try { - commitsShaArray = Objects.requireNonNull(commitsObj).getJSONArray("commit_ids"); - } catch (JSONException ignored) { - } - - String commitText = context.getResources().getString(R.string.commitsText); - if (Objects.requireNonNull(commitsShaArray).length() == 1) { - commitText = context.getResources().getString(R.string.commitText); - } - - String commitString = - context.getString( - R.string.timelineAddedCommit, - issueComment.getUser().getLogin(), - commitText, - info); - if (tinyDB.getInt("themeId") == 8) { - if (!isNightModeThemeDynamic(context)) { - start.setTextColor(AppUtil.dynamicColorResource(context)); + if (!issueComment.getCreatedAt().equals(issueComment.getUpdatedAt())) { + infoBuilder + .append(context.getString(R.string.colorfulBulletSpan)) + .append(context.getString(R.string.modifiedText)); } } - start.setText(HtmlCompat.fromHtml(commitString, HtmlCompat.FROM_HTML_MODE_LEGACY)); - start.setTextSize(fontSize); + assert infoBuilder != null; + String info = infoBuilder.toString(); - timelineData.setOrientation(LinearLayout.VERTICAL); - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_commit)); - timelineData.addView(start); + // label view in timeline + if (issueComment.getType().equalsIgnoreCase("label")) { - for (int i = 0; i < Objects.requireNonNull(commitsShaArray).length(); i++) { + int color = Color.parseColor("#" + issueComment.getLabel().getColor()); + int height = AppUtil.getPixelsFromDensity(context, 20); + int textSize = AppUtil.getPixelsFromScaledDensity(context, 12); + TextDrawable drawable = + TextDrawable.builder() + .beginConfig() + .useFont(typeface) + .textColor(new ColorInverter().getContrastColor(color)) + .fontSize(textSize) + .width( + LabelWidthCalculator.calculateLabelWidth( + issueComment.getLabel().getName(), + typeface, + textSize, + AppUtil.getPixelsFromDensity(context, 10))) + .height(height) + .endConfig() + .buildRoundRect( + issueComment.getLabel().getName(), + color, + AppUtil.getPixelsFromDensity(context, 18)); + + TextView textView = new TextView(context); + String text; + + if (issueComment.getBody().isEmpty()) { + text = + context.getString( + R.string.timelineRemovedLabel, + issueComment.getUser().getLogin(), + info); + timelineIcon.setColorFilter( + context.getResources() + .getColor(R.color.iconIssuePrClosedColor, null)); + } else { + text = + context.getString( + R.string.timelineAddedLabel, + issueComment.getUser().getLogin(), + info); + } + + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_tag)); + + SpannableString spannableString = new SpannableString(text.replace('|', ' ')); + + drawable.setBounds( + 0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + ImageSpan image = new ImageSpan(drawable); + + new Handler() + .postDelayed( + () -> { + spannableString.setSpan( + image, + text.indexOf('|'), + text.indexOf('|') + 1, + Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, + AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + textView.setTextColor( + AppUtil.dynamicColorResource(context)); + } + } + textView.setText(spannableString); + timelineData.addView(textView); + }, + 250); + } + // pull/push/commit data view in timeline + else if (issueComment.getType().equalsIgnoreCase("pull_push")) { + + TextView start = new TextView(context); + + JSONObject commitsObj = null; try { - - String timelineCommits = - "" - + StringUtils.substring( - String.valueOf(commitsShaArray.get(i)), 0, 10) - + ""; - - TextView dynamicCommitTv = new TextView(context); - dynamicCommitTv.setId(View.generateViewId()); - - dynamicCommitTv.setText( - HtmlCompat.fromHtml( - timelineCommits, HtmlCompat.FROM_HTML_MODE_LEGACY)); - - JSONArray finalCommitsArray = commitsShaArray; - int finalI = i; - - dynamicCommitTv.setOnClickListener( - v14 -> { - intent = - IssueContext.fromIntent( - ((IssueDetailActivity) context) - .getIntent()) - .getRepository() - .getIntent(context, CommitDetailActivity.class); - try { - intent.putExtra( - "sha", (String) finalCommitsArray.get(finalI)); - } catch (JSONException ignored) { - } - context.startActivity(intent); - }); - - timelineData.setOrientation(LinearLayout.VERTICAL); - timelineData.addView(dynamicCommitTv); + commitsObj = new JSONObject(issueComment.getBody()); } catch (JSONException ignored) { } - } - } - // assignees data view in timeline - else if (issueComment.getType().equalsIgnoreCase("assignees")) { - TextView start = new TextView(context); + JSONArray commitsShaArray = null; + try { + commitsShaArray = + Objects.requireNonNull(commitsObj).getJSONArray("commit_ids"); + } catch (JSONException ignored) { + } - if (tinyDB.getInt("themeId") == 8) { - if (!isNightModeThemeDynamic(context)) { - start.setTextColor(AppUtil.dynamicColorResource(context)); + String commitText = context.getResources().getString(R.string.commitsText); + if (Objects.requireNonNull(commitsShaArray).length() == 1) { + commitText = context.getResources().getString(R.string.commitText); + } + + String commitString = + context.getString( + R.string.timelineAddedCommit, + issueComment.getUser().getLogin(), + commitText, + info); + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + start.setTextColor(AppUtil.dynamicColorResource(context)); + } + } + start.setText( + HtmlCompat.fromHtml(commitString, HtmlCompat.FROM_HTML_MODE_LEGACY)); + start.setTextSize(fontSize); + + timelineData.setOrientation(LinearLayout.VERTICAL); + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_commit)); + timelineData.addView(start); + + for (int i = 0; i < Objects.requireNonNull(commitsShaArray).length(); i++) { + + try { + + String timelineCommits = + "" + + StringUtils.substring( + String.valueOf(commitsShaArray.get(i)), 0, 10) + + ""; + + TextView dynamicCommitTv = new TextView(context); + dynamicCommitTv.setId(View.generateViewId()); + + dynamicCommitTv.setText( + HtmlCompat.fromHtml( + timelineCommits, HtmlCompat.FROM_HTML_MODE_LEGACY)); + + JSONArray finalCommitsArray = commitsShaArray; + int finalI = i; + + dynamicCommitTv.setOnClickListener( + v14 -> { + intent = + IssueContext.fromIntent( + ((IssueDetailActivity) context) + .getIntent()) + .getRepository() + .getIntent( + context, + CommitDetailActivity.class); + try { + intent.putExtra( + "sha", (String) finalCommitsArray.get(finalI)); + } catch (JSONException ignored) { + } + context.startActivity(intent); + }); + + timelineData.setOrientation(LinearLayout.VERTICAL); + timelineData.addView(dynamicCommitTv); + } catch (JSONException ignored) { + } } } + // assignees data view in timeline + else if (issueComment.getType().equalsIgnoreCase("assignees")) { - if (issueComment.isRemovedAssignee()) { + TextView start = new TextView(context); - if (issueComment - .getUser() - .getLogin() - .equalsIgnoreCase(issueComment.getAssignee().getLogin())) { + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + start.setTextColor(AppUtil.dynamicColorResource(context)); + } + } + + if (issueComment.isRemovedAssignee()) { + + if (issueComment + .getUser() + .getLogin() + .equalsIgnoreCase(issueComment.getAssignee().getLogin())) { + start.setText( + context.getString( + R.string.timelineAssigneesRemoved, + issueComment.getUser().getLogin(), + info)); + } else { + start.setText( + context.getString( + R.string.timelineAssigneesUnassigned, + issueComment.getAssignee().getLogin(), + issueComment.getUser().getLogin(), + info)); + } + timelineIcon.setColorFilter( + context.getResources() + .getColor(R.color.iconIssuePrClosedColor, null)); + } else { + if (issueComment + .getUser() + .getLogin() + .equalsIgnoreCase(issueComment.getAssignee().getLogin())) { + start.setText( + context.getString( + R.string.timelineAssigneesSelfAssigned, + issueComment.getUser().getLogin(), + info)); + } else { + start.setText( + context.getString( + R.string.timelineAssigneesAssigned, + issueComment.getAssignee().getLogin(), + issueComment.getUser().getLogin(), + info)); + } + } + start.setTextSize(fontSize); + + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_person)); + timelineData.addView(start); + } + // milestone data view in timeline + else if (issueComment.getType().equalsIgnoreCase("milestone")) { + + TextView start = new TextView(context); + + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + start.setTextColor(AppUtil.dynamicColorResource(context)); + } + } + + if (issueComment.getMilestone() != null) { start.setText( context.getString( - R.string.timelineAssigneesRemoved, + R.string.timelineMilestoneAdded, issueComment.getUser().getLogin(), + issueComment.getMilestone().getTitle(), info)); } else { - start.setText( - context.getString( - R.string.timelineAssigneesUnassigned, - issueComment.getAssignee().getLogin(), - issueComment.getUser().getLogin(), - info)); - } - timelineIcon.setColorFilter( - context.getResources().getColor(R.color.iconIssuePrClosedColor, null)); - } else { - if (issueComment - .getUser() - .getLogin() - .equalsIgnoreCase(issueComment.getAssignee().getLogin())) { - start.setText( - context.getString( - R.string.timelineAssigneesSelfAssigned, - issueComment.getUser().getLogin(), - info)); - } else { - start.setText( - context.getString( - R.string.timelineAssigneesAssigned, - issueComment.getAssignee().getLogin(), - issueComment.getUser().getLogin(), - info)); + if (issueComment.getOldMilestone() != null) { + start.setText( + context.getString( + R.string.timelineMilestoneRemoved, + issueComment.getUser().getLogin(), + issueComment.getOldMilestone().getTitle(), + info)); + } else { + start.setText( + context.getString( + R.string.timelineMilestoneDeleted, + issueComment.getUser().getLogin(), + info)); + } + timelineIcon.setColorFilter( + context.getResources() + .getColor(R.color.iconIssuePrClosedColor, null)); } + start.setTextSize(fontSize); + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_milestone)); + timelineData.addView(start); } - start.setTextSize(fontSize); + // status view in timeline + else if (issueComment.getType().equalsIgnoreCase("close") + || issueComment.getType().equalsIgnoreCase("reopen") + || issueComment.getType().equalsIgnoreCase("merge_pull") + || issueComment.getType().equalsIgnoreCase("commit_ref")) { - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_person)); - timelineData.addView(start); - } - // milestone data view in timeline - else if (issueComment.getType().equalsIgnoreCase("milestone")) { + TextView start = new TextView(context); - TextView start = new TextView(context); - - if (tinyDB.getInt("themeId") == 8) { - if (!isNightModeThemeDynamic(context)) { - start.setTextColor(AppUtil.dynamicColorResource(context)); + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + start.setTextColor(AppUtil.dynamicColorResource(context)); + } + } + + if (issue.getIssueType().equalsIgnoreCase("Issue")) { + if (issueComment.getType().equals("close")) { + start.setText( + context.getString( + R.string.timelineStatusClosedIssue, + issueComment.getUser().getLogin(), + info)); + timelineIcon.setColorFilter( + context.getResources() + .getColor(R.color.iconIssuePrClosedColor, null)); + } else if (issueComment.getType().equalsIgnoreCase("reopen")) { + start.setText( + context.getString( + R.string.timelineStatusReopenedIssue, + issueComment.getUser().getLogin(), + info)); + } else if (issueComment.getType().equalsIgnoreCase("commit_ref")) { + String commitString = + context.getString( + R.string.timelineStatusRefIssue, + issueComment.getUser().getLogin(), + ResourcesCompat.getColor( + context.getResources(), + R.color.lightBlue, + null), + context.getResources() + .getString(R.string.commitText) + .toLowerCase(), + info); + start.setText( + HtmlCompat.fromHtml( + commitString, HtmlCompat.FROM_HTML_MODE_LEGACY)); + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_bookmark)); + + start.setOnClickListener( + v14 -> { + intent = + IssueContext.fromIntent( + ((IssueDetailActivity) context) + .getIntent()) + .getRepository() + .getIntent( + context, + CommitDetailActivity.class); + intent.putExtra("sha", issueComment.getRefCommitSha()); + context.startActivity(intent); + }); + } + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_issue)); + } else if (issue.getIssueType().equalsIgnoreCase("Pull")) { + if (issueComment.getType().equalsIgnoreCase("close")) { + start.setText( + context.getString( + R.string.timelineStatusClosedPr, + issueComment.getUser().getLogin(), + info)); + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_pull_request)); + timelineIcon.setColorFilter( + context.getResources() + .getColor(R.color.iconIssuePrClosedColor, null)); + } else if (issueComment.getType().equalsIgnoreCase("merge_pull")) { + start.setText( + context.getString( + R.string.timelineStatusMergedPr, + issueComment.getUser().getLogin(), + info)); + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_pull_request)); + timelineIcon.setColorFilter( + context.getResources() + .getColor(R.color.iconPrMergedColor, null)); + } else if (issueComment.getType().equalsIgnoreCase("commit_ref")) { + String commitString = + context.getString( + R.string.timelineStatusRefPr, + issueComment.getUser().getLogin(), + ResourcesCompat.getColor( + context.getResources(), + R.color.lightBlue, + null), + context.getResources() + .getString(R.string.commitText) + .toLowerCase(), + info); + start.setText( + HtmlCompat.fromHtml( + commitString, HtmlCompat.FROM_HTML_MODE_LEGACY)); + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_bookmark)); + + start.setOnClickListener( + v14 -> { + intent = + IssueContext.fromIntent( + ((IssueDetailActivity) context) + .getIntent()) + .getRepository() + .getIntent( + context, + CommitDetailActivity.class); + intent.putExtra("sha", issueComment.getRefCommitSha()); + context.startActivity(intent); + }); + } else { + start.setText( + context.getString( + R.string.timelineStatusReopenedPr, + issueComment.getUser().getLogin(), + info)); + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_pull_request)); + } + } + start.setTextSize(fontSize); + + timelineData.addView(start); + } + // review data view in timeline + else if (issueComment.getType().equalsIgnoreCase("review_request") + || issueComment.getType().equalsIgnoreCase("review") + || issueComment.getType().equalsIgnoreCase("dismiss_review")) { + + TextView start = new TextView(context); + + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + start.setTextColor(AppUtil.dynamicColorResource(context)); + } + } + + if (issueComment.getType().equalsIgnoreCase("review")) { + if (!issueComment.getBody().equalsIgnoreCase("")) { + + start.setText( + context.getString( + R.string.timelineReviewLeftComment, + issueComment.getUser().getLogin(), + issueComment.getBody(), + info)); + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_comment)); + } else { + timelineView.setVisibility(View.GONE); + timelineDividerView.setVisibility(View.GONE); + } + } else if (issueComment.getType().equalsIgnoreCase("dismiss_review")) { + timelineView.setVisibility(View.GONE); + timelineDividerView.setVisibility(View.GONE); + } else if (issueComment.getType().equalsIgnoreCase("review_request")) { + String reviewer; + if (issueComment.getAssignee() != null) { + reviewer = issueComment.getAssignee().getLogin(); + } else { + if (issueComment.getAssigneeTeam() != null) { + reviewer = issueComment.getAssigneeTeam().getName(); + } else { + reviewer = ""; + } + } + start.setText( + context.getString( + R.string.timelineReviewRequest, + issueComment.getUser().getLogin(), + reviewer, + info)); + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_watchers)); + } + start.setTextSize(fontSize); + + timelineData.addView(start); + } + // change title data view in timeline + else if (issueComment.getType().equalsIgnoreCase("change_title")) { + + TextView start = new TextView(context); + + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + start.setTextColor(AppUtil.dynamicColorResource(context)); + } } - } - if (issueComment.getMilestone() != null) { start.setText( context.getString( - R.string.timelineMilestoneAdded, + R.string.timelineChangeTitle, issueComment.getUser().getLogin(), - issueComment.getMilestone().getTitle(), + issueComment.getOldTitle(), + issueComment.getNewTitle(), info)); - } else { - if (issueComment.getOldMilestone() != null) { - start.setText( - context.getString( - R.string.timelineMilestoneRemoved, - issueComment.getUser().getLogin(), - issueComment.getOldMilestone().getTitle(), - info)); - } else { - start.setText( - context.getString( - R.string.timelineMilestoneDeleted, - issueComment.getUser().getLogin(), - info)); - } - timelineIcon.setColorFilter( - context.getResources().getColor(R.color.iconIssuePrClosedColor, null)); - } - start.setTextSize(fontSize); - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_milestone)); - timelineData.addView(start); - } - // status view in timeline - else if (issueComment.getType().equalsIgnoreCase("close") - || issueComment.getType().equalsIgnoreCase("reopen") - || issueComment.getType().equalsIgnoreCase("merge_pull") - || issueComment.getType().equalsIgnoreCase("commit_ref")) { + start.setTextSize(fontSize); - TextView start = new TextView(context); - - if (tinyDB.getInt("themeId") == 8) { - if (!isNightModeThemeDynamic(context)) { - start.setTextColor(AppUtil.dynamicColorResource(context)); - } - } - - if (issue.getIssueType().equalsIgnoreCase("Issue")) { - if (issueComment.getType().equals("close")) { - start.setText( - context.getString( - R.string.timelineStatusClosedIssue, - issueComment.getUser().getLogin(), - info)); - timelineIcon.setColorFilter( - context.getResources() - .getColor(R.color.iconIssuePrClosedColor, null)); - } else if (issueComment.getType().equalsIgnoreCase("reopen")) { - start.setText( - context.getString( - R.string.timelineStatusReopenedIssue, - issueComment.getUser().getLogin(), - info)); - } else if (issueComment.getType().equalsIgnoreCase("commit_ref")) { - String commitString = - context.getString( - R.string.timelineStatusRefIssue, - issueComment.getUser().getLogin(), - ResourcesCompat.getColor( - context.getResources(), R.color.lightBlue, null), - context.getResources() - .getString(R.string.commitText) - .toLowerCase(), - info); - start.setText( - HtmlCompat.fromHtml( - commitString, HtmlCompat.FROM_HTML_MODE_LEGACY)); - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_bookmark)); - - start.setOnClickListener( - v14 -> { - intent = - IssueContext.fromIntent( - ((IssueDetailActivity) context) - .getIntent()) - .getRepository() - .getIntent(context, CommitDetailActivity.class); - intent.putExtra("sha", issueComment.getRefCommitSha()); - context.startActivity(intent); - }); - } timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_issue)); - } else if (issue.getIssueType().equalsIgnoreCase("Pull")) { - if (issueComment.getType().equalsIgnoreCase("close")) { - start.setText( - context.getString( - R.string.timelineStatusClosedPr, - issueComment.getUser().getLogin(), - info)); - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_pull_request)); - timelineIcon.setColorFilter( - context.getResources() - .getColor(R.color.iconIssuePrClosedColor, null)); - } else if (issueComment.getType().equalsIgnoreCase("merge_pull")) { - start.setText( - context.getString( - R.string.timelineStatusMergedPr, - issueComment.getUser().getLogin(), - info)); - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_pull_request)); - timelineIcon.setColorFilter( - context.getResources().getColor(R.color.iconPrMergedColor, null)); - } else if (issueComment.getType().equalsIgnoreCase("commit_ref")) { - String commitString = - context.getString( - R.string.timelineStatusRefPr, - issueComment.getUser().getLogin(), - ResourcesCompat.getColor( - context.getResources(), R.color.lightBlue, null), - context.getResources() - .getString(R.string.commitText) - .toLowerCase(), - info); - start.setText( - HtmlCompat.fromHtml( - commitString, HtmlCompat.FROM_HTML_MODE_LEGACY)); - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_bookmark)); - - start.setOnClickListener( - v14 -> { - intent = - IssueContext.fromIntent( - ((IssueDetailActivity) context) - .getIntent()) - .getRepository() - .getIntent(context, CommitDetailActivity.class); - intent.putExtra("sha", issueComment.getRefCommitSha()); - context.startActivity(intent); - }); - } else { - start.setText( - context.getString( - R.string.timelineStatusReopenedPr, - issueComment.getUser().getLogin(), - info)); - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_pull_request)); - } + ContextCompat.getDrawable(context, R.drawable.ic_edit)); + timelineData.addView(start); } - start.setTextSize(fontSize); + // lock/unlock data view in timeline + else if (issueComment.getType().equalsIgnoreCase("lock") + || issueComment.getType().equalsIgnoreCase("unlock")) { - timelineData.addView(start); - } - // review data view in timeline - else if (issueComment.getType().equalsIgnoreCase("review_request") - || issueComment.getType().equalsIgnoreCase("review") - || issueComment.getType().equalsIgnoreCase("dismiss_review")) { + TextView start = new TextView(context); - TextView start = new TextView(context); - - if (tinyDB.getInt("themeId") == 8) { - if (!isNightModeThemeDynamic(context)) { - start.setTextColor(AppUtil.dynamicColorResource(context)); + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + start.setTextColor(AppUtil.dynamicColorResource(context)); + } } - } - - if (issueComment.getType().equalsIgnoreCase("review")) { - if (!issueComment.getBody().equalsIgnoreCase("")) { + if (issueComment.getType().equalsIgnoreCase("lock")) { start.setText( context.getString( - R.string.timelineReviewLeftComment, + R.string.timelineLocked, issueComment.getUser().getLogin(), issueComment.getBody(), info)); timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_comment)); - } else { - timelineView.setVisibility(View.GONE); - timelineDividerView.setVisibility(View.GONE); + ContextCompat.getDrawable(context, R.drawable.ic_lock)); + } else if (issueComment.getType().equalsIgnoreCase("unlock")) { + start.setText( + context.getString( + R.string.timelineUnlocked, + issueComment.getUser().getLogin(), + info)); + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_key)); } - } else if (issueComment.getType().equalsIgnoreCase("dismiss_review")) { - timelineView.setVisibility(View.GONE); - timelineDividerView.setVisibility(View.GONE); - } else if (issueComment.getType().equalsIgnoreCase("review_request")) { - String reviewer; - if (issueComment.getAssignee() != null) { - reviewer = issueComment.getAssignee().getLogin(); - } else { - if (issueComment.getAssigneeTeam() != null) { - reviewer = issueComment.getAssigneeTeam().getName(); - } else { - reviewer = ""; + start.setTextSize(fontSize); + + timelineData.addView(start); + } + // dependency data view in timeline + else if (issueComment.getType().equalsIgnoreCase("add_dependency") + || issueComment.getType().equalsIgnoreCase("remove_dependency")) { + + TextView start = new TextView(context); + + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + start.setTextColor(AppUtil.dynamicColorResource(context)); } } - start.setText( - context.getString( - R.string.timelineReviewRequest, - issueComment.getUser().getLogin(), - reviewer, - info)); + + if (issueComment.getType().equalsIgnoreCase("add_dependency")) { + start.setText( + context.getString( + R.string.timelineDependencyAdded, + issueComment.getUser().getLogin(), + issueComment.getDependentIssue().getNumber(), + info)); + } else if (issueComment.getType().equalsIgnoreCase("remove_dependency")) { + start.setText( + context.getString( + R.string.timelineDependencyRemoved, + issueComment.getUser().getLogin(), + issueComment.getDependentIssue().getNumber(), + info)); + timelineIcon.setColorFilter( + context.getResources() + .getColor(R.color.iconIssuePrClosedColor, null)); + } + start.setTextSize(fontSize); + timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_watchers)); + ContextCompat.getDrawable(context, R.drawable.ic_dependency)); + timelineData.addView(start); } - start.setTextSize(fontSize); + // project data view in timeline + else if (issueComment.getType().equalsIgnoreCase("project") + || issueComment.getType().equalsIgnoreCase("project_board")) { - timelineData.addView(start); - } - // change title data view in timeline - else if (issueComment.getType().equalsIgnoreCase("change_title")) { + TextView start = new TextView(context); - TextView start = new TextView(context); - - if (tinyDB.getInt("themeId") == 8) { - if (!isNightModeThemeDynamic(context)) { - start.setTextColor(AppUtil.dynamicColorResource(context)); + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + start.setTextColor(AppUtil.dynamicColorResource(context)); + } } - } - start.setText( - context.getString( - R.string.timelineChangeTitle, - issueComment.getUser().getLogin(), - issueComment.getOldTitle(), - issueComment.getNewTitle(), - info)); - start.setTextSize(fontSize); - - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_edit)); - timelineData.addView(start); - } - // lock/unlock data view in timeline - else if (issueComment.getType().equalsIgnoreCase("lock") - || issueComment.getType().equalsIgnoreCase("unlock")) { - - TextView start = new TextView(context); - - if (tinyDB.getInt("themeId") == 8) { - if (!isNightModeThemeDynamic(context)) { - start.setTextColor(AppUtil.dynamicColorResource(context)); + if (issueComment.getProjectId() > 0) { + start.setText( + context.getString( + R.string.timelineProjectAdded, + issueComment.getUser().getLogin(), + info)); + } else { + start.setText( + context.getString( + R.string.timelineProjectRemoved, + issueComment.getUser().getLogin(), + info)); + timelineIcon.setColorFilter( + context.getResources() + .getColor(R.color.iconIssuePrClosedColor, null)); } - } + start.setTextSize(fontSize); - if (issueComment.getType().equalsIgnoreCase("lock")) { - start.setText( - context.getString( - R.string.timelineLocked, - issueComment.getUser().getLogin(), - issueComment.getBody(), - info)); timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_lock)); - } else if (issueComment.getType().equalsIgnoreCase("unlock")) { - start.setText( - context.getString( - R.string.timelineUnlocked, - issueComment.getUser().getLogin(), - info)); + ContextCompat.getDrawable(context, R.drawable.ic_kanban)); + timelineData.addView(start); + } + // due date/deadline data view in timeline + else if (issueComment.getType().equalsIgnoreCase("added_deadline") + || issueComment.getType().equalsIgnoreCase("modified_deadline") + || issueComment.getType().equalsIgnoreCase("removed_deadline")) { + + TextView start = new TextView(context); + + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + start.setTextColor(AppUtil.dynamicColorResource(context)); + } + } + + // TODO pretty-print + if (issueComment.getType().equalsIgnoreCase("added_deadline")) { + start.setText( + context.getString( + R.string.timelineDueDateAdded, + issueComment.getUser().getLogin(), + issueComment.getBody(), + info)); + } else if (issueComment.getType().equalsIgnoreCase("modified_deadline")) { + start.setText( + context.getString( + R.string.timelineDueDateModified, + issueComment.getUser().getLogin(), + issueComment.getBody().split("\\|")[0], + issueComment.getBody().split("\\|")[1], + info)); + } else if (issueComment.getType().equalsIgnoreCase("removed_deadline")) { + start.setText( + context.getString( + R.string.timelineDueDateRemoved, + issueComment.getUser().getLogin(), + issueComment.getBody(), + info)); + timelineIcon.setColorFilter( + context.getResources() + .getColor(R.color.iconIssuePrClosedColor, null)); + } + start.setTextSize(fontSize); + timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_key)); + ContextCompat.getDrawable(context, R.drawable.ic_clock)); + timelineData.addView(start); } - start.setTextSize(fontSize); + // branch data view in timeline + else if (issueComment.getType().equalsIgnoreCase("change_target_branch") + || issueComment.getType().equalsIgnoreCase("delete_branch")) { - timelineData.addView(start); - } - // dependency data view in timeline - else if (issueComment.getType().equalsIgnoreCase("add_dependency") - || issueComment.getType().equalsIgnoreCase("remove_dependency")) { + TextView start = new TextView(context); - TextView start = new TextView(context); - - if (tinyDB.getInt("themeId") == 8) { - if (!isNightModeThemeDynamic(context)) { - start.setTextColor(AppUtil.dynamicColorResource(context)); + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + start.setTextColor(AppUtil.dynamicColorResource(context)); + } } - } - if (issueComment.getType().equalsIgnoreCase("add_dependency")) { - start.setText( - context.getString( - R.string.timelineDependencyAdded, - issueComment.getUser().getLogin(), - issueComment.getDependentIssue().getNumber(), - info)); - } else if (issueComment.getType().equalsIgnoreCase("remove_dependency")) { - start.setText( - context.getString( - R.string.timelineDependencyRemoved, - issueComment.getUser().getLogin(), - issueComment.getDependentIssue().getNumber(), - info)); - timelineIcon.setColorFilter( - context.getResources().getColor(R.color.iconIssuePrClosedColor, null)); - } - start.setTextSize(fontSize); - - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_dependency)); - timelineData.addView(start); - } - // project data view in timeline - else if (issueComment.getType().equalsIgnoreCase("project") - || issueComment.getType().equalsIgnoreCase("project_board")) { - - TextView start = new TextView(context); - - if (tinyDB.getInt("themeId") == 8) { - if (!isNightModeThemeDynamic(context)) { - start.setTextColor(AppUtil.dynamicColorResource(context)); + if (issueComment.getType().equalsIgnoreCase("change_target_branch")) { + start.setText( + context.getString( + R.string.timelineBranchChanged, + issueComment.getUser().getLogin(), + issueComment.getOldRef(), + issueComment.getNewRef(), + info)); + } else if (issueComment.getType().equalsIgnoreCase("delete_branch")) { + start.setText( + context.getString( + R.string.timelineBranchDeleted, + issueComment.getUser().getLogin(), + issueComment.getOldRef(), + info)); + timelineIcon.setColorFilter( + context.getResources() + .getColor(R.color.iconIssuePrClosedColor, null)); } - } + start.setTextSize(fontSize); - if (issueComment.getProjectId() > 0) { - start.setText( - context.getString( - R.string.timelineProjectAdded, - issueComment.getUser().getLogin(), - info)); - } else { - start.setText( - context.getString( - R.string.timelineProjectRemoved, - issueComment.getUser().getLogin(), - info)); - timelineIcon.setColorFilter( - context.getResources().getColor(R.color.iconIssuePrClosedColor, null)); - } - start.setTextSize(fontSize); - - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_kanban)); - timelineData.addView(start); - } - // due date/deadline data view in timeline - else if (issueComment.getType().equalsIgnoreCase("added_deadline") - || issueComment.getType().equalsIgnoreCase("modified_deadline") - || issueComment.getType().equalsIgnoreCase("removed_deadline")) { - - TextView start = new TextView(context); - - if (tinyDB.getInt("themeId") == 8) { - if (!isNightModeThemeDynamic(context)) { - start.setTextColor(AppUtil.dynamicColorResource(context)); - } - } - - // TODO pretty-print - if (issueComment.getType().equalsIgnoreCase("added_deadline")) { - start.setText( - context.getString( - R.string.timelineDueDateAdded, - issueComment.getUser().getLogin(), - issueComment.getBody(), - info)); - } else if (issueComment.getType().equalsIgnoreCase("modified_deadline")) { - start.setText( - context.getString( - R.string.timelineDueDateModified, - issueComment.getUser().getLogin(), - issueComment.getBody().split("\\|")[0], - issueComment.getBody().split("\\|")[1], - info)); - } else if (issueComment.getType().equalsIgnoreCase("removed_deadline")) { - start.setText( - context.getString( - R.string.timelineDueDateRemoved, - issueComment.getUser().getLogin(), - issueComment.getBody(), - info)); - timelineIcon.setColorFilter( - context.getResources().getColor(R.color.iconIssuePrClosedColor, null)); - } - start.setTextSize(fontSize); - - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_clock)); - timelineData.addView(start); - } - // branch data view in timeline - else if (issueComment.getType().equalsIgnoreCase("change_target_branch") - || issueComment.getType().equalsIgnoreCase("delete_branch")) { - - TextView start = new TextView(context); - - if (tinyDB.getInt("themeId") == 8) { - if (!isNightModeThemeDynamic(context)) { - start.setTextColor(AppUtil.dynamicColorResource(context)); - } - } - - if (issueComment.getType().equalsIgnoreCase("change_target_branch")) { - start.setText( - context.getString( - R.string.timelineBranchChanged, - issueComment.getUser().getLogin(), - issueComment.getOldRef(), - issueComment.getNewRef(), - info)); - } else if (issueComment.getType().equalsIgnoreCase("delete_branch")) { - start.setText( - context.getString( - R.string.timelineBranchDeleted, - issueComment.getUser().getLogin(), - issueComment.getOldRef(), - info)); - timelineIcon.setColorFilter( - context.getResources().getColor(R.color.iconIssuePrClosedColor, null)); - } - start.setTextSize(fontSize); - - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_branch)); - timelineData.addView(start); - } - // time tracking data view in timeline - else if (issueComment.getType().equalsIgnoreCase("start_tracking") - || issueComment.getType().equalsIgnoreCase("stop_tracking") - || issueComment.getType().equalsIgnoreCase("cancel_tracking") - || issueComment.getType().equalsIgnoreCase("add_time_manual") - || issueComment.getType().equalsIgnoreCase("delete_time_manual")) { - - TextView start = new TextView(context); - - if (tinyDB.getInt("themeId") == 8) { - if (!isNightModeThemeDynamic(context)) { - start.setTextColor(AppUtil.dynamicColorResource(context)); - } - } - - if (issueComment.getType().equalsIgnoreCase("start_tracking")) { - start.setText( - context.getString( - R.string.timelineTimeTrackingStart, - issueComment.getUser().getLogin(), - info)); - } else if (issueComment.getType().equalsIgnoreCase("stop_tracking")) { - start.setText( - context.getString( - R.string.timelineTimeTrackingStop, - issueComment.getUser().getLogin(), - info)); - } else if (issueComment.getType().equalsIgnoreCase("cancel_tracking")) { - start.setText( - context.getString( - R.string.timelineTimeTrackingCancel, - issueComment.getUser().getLogin(), - info)); - timelineIcon.setColorFilter( - context.getResources().getColor(R.color.iconIssuePrClosedColor, null)); - } else if (issueComment.getType().equalsIgnoreCase("add_time_manual")) { - start.setText( - context.getString( - R.string.timelineTimeTrackingAddManualTime, - issueComment.getUser().getLogin(), - issueComment.getBody(), - info)); - } else if (issueComment.getType().equalsIgnoreCase("delete_time_manual")) { - start.setText( - context.getString( - R.string.timelineTimeTrackingDeleteManualTime, - issueComment.getUser().getLogin(), - issueComment.getBody(), - info)); - timelineIcon.setColorFilter( - context.getResources().getColor(R.color.iconIssuePrClosedColor, null)); - } - start.setTextSize(fontSize); - - timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_clock)); - timelineData.addView(start); - } - // issue/pr refs data view in timeline - else if (issueComment.getType().equalsIgnoreCase("change_issue_ref") - || issueComment.getType().equalsIgnoreCase("issue_ref") - || issueComment.getType().equalsIgnoreCase("comment_ref") - || issueComment.getType().equalsIgnoreCase("pull_ref")) { - - RecyclerView recyclerView = new RecyclerView(context); - - if (issueComment.getType().equalsIgnoreCase("change_issue_ref")) { - String text = - context.getString( - R.string.timelineChangeIssueRef, - issueComment.getUser().getLogin(), - issueComment.getNewRef(), - info); - Markdown.render(context, text, recyclerView, issue.getRepository()); timelineIcon.setImageDrawable( ContextCompat.getDrawable(context, R.drawable.ic_branch)); - } else if (issueComment.getType().equalsIgnoreCase("comment_ref") + timelineData.addView(start); + } + // time tracking data view in timeline + else if (issueComment.getType().equalsIgnoreCase("start_tracking") + || issueComment.getType().equalsIgnoreCase("stop_tracking") + || issueComment.getType().equalsIgnoreCase("cancel_tracking") + || issueComment.getType().equalsIgnoreCase("add_time_manual") + || issueComment.getType().equalsIgnoreCase("delete_time_manual")) { + + TextView start = new TextView(context); + + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + start.setTextColor(AppUtil.dynamicColorResource(context)); + } + } + + if (issueComment.getType().equalsIgnoreCase("start_tracking")) { + start.setText( + context.getString( + R.string.timelineTimeTrackingStart, + issueComment.getUser().getLogin(), + info)); + } else if (issueComment.getType().equalsIgnoreCase("stop_tracking")) { + start.setText( + context.getString( + R.string.timelineTimeTrackingStop, + issueComment.getUser().getLogin(), + info)); + } else if (issueComment.getType().equalsIgnoreCase("cancel_tracking")) { + start.setText( + context.getString( + R.string.timelineTimeTrackingCancel, + issueComment.getUser().getLogin(), + info)); + timelineIcon.setColorFilter( + context.getResources() + .getColor(R.color.iconIssuePrClosedColor, null)); + } else if (issueComment.getType().equalsIgnoreCase("add_time_manual")) { + start.setText( + context.getString( + R.string.timelineTimeTrackingAddManualTime, + issueComment.getUser().getLogin(), + issueComment.getBody(), + info)); + } else if (issueComment.getType().equalsIgnoreCase("delete_time_manual")) { + start.setText( + context.getString( + R.string.timelineTimeTrackingDeleteManualTime, + issueComment.getUser().getLogin(), + issueComment.getBody(), + info)); + timelineIcon.setColorFilter( + context.getResources() + .getColor(R.color.iconIssuePrClosedColor, null)); + } + start.setTextSize(fontSize); + + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_clock)); + timelineData.addView(start); + } + // issue/pr refs data view in timeline + else if (issueComment.getType().equalsIgnoreCase("change_issue_ref") || issueComment.getType().equalsIgnoreCase("issue_ref") + || issueComment.getType().equalsIgnoreCase("comment_ref") || issueComment.getType().equalsIgnoreCase("pull_ref")) { - if (issue.getIssueType().equalsIgnoreCase("Issue")) { + RecyclerView recyclerView = new RecyclerView(context); + + if (issueComment.getType().equalsIgnoreCase("change_issue_ref")) { String text = context.getString( - R.string.timelineRefIssue, + R.string.timelineChangeIssueRef, issueComment.getUser().getLogin(), - issueComment.getRefIssue().getNumber(), - info); - Markdown.render(context, text, recyclerView, issue.getRepository()); - } else if (issue.getIssueType().equalsIgnoreCase("Pull")) { - String text = - context.getString( - R.string.timelineRefPr, - issueComment.getUser().getLogin(), - issueComment.getRefIssue().getNumber(), + issueComment.getNewRef(), info); Markdown.render(context, text, recyclerView, issue.getRepository()); + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_branch)); + } else if (issueComment.getType().equalsIgnoreCase("comment_ref") + || issueComment.getType().equalsIgnoreCase("issue_ref") + || issueComment.getType().equalsIgnoreCase("pull_ref")) { + + if (issue.getIssueType().equalsIgnoreCase("Issue")) { + String text = + context.getString( + R.string.timelineRefIssue, + issueComment.getUser().getLogin(), + issueComment.getRefIssue().getNumber(), + info); + Markdown.render(context, text, recyclerView, issue.getRepository()); + } else if (issue.getIssueType().equalsIgnoreCase("Pull")) { + String text = + context.getString( + R.string.timelineRefPr, + issueComment.getUser().getLogin(), + issueComment.getRefIssue().getNumber(), + info); + Markdown.render(context, text, recyclerView, issue.getRepository()); + } + timelineIcon.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_bookmark)); } + + timelineData.addView(recyclerView); + } + // code data view in timeline + else if (issueComment.getType().equalsIgnoreCase("code")) { + timelineView.setVisibility(View.GONE); + timelineDividerView.setVisibility(View.GONE); + } + // schedule pr view in timeline + else if (issueComment.getType().equalsIgnoreCase("pull_scheduled_merge") + || issueComment.getType().equalsIgnoreCase("pull_cancel_scheduled_merge")) { + timelineView.setVisibility(View.GONE); + timelineDividerView.setVisibility(View.GONE); + } + // issue/pr pinned + else if (issueComment.getType().equalsIgnoreCase("pin")) { + TextView start = new TextView(context); + + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_THEME_KEY)) + == 8) { + if (!isNightModeThemeDynamic(context)) { + start.setTextColor(AppUtil.dynamicColorResource(context)); + } + } + + start.setText( + context.getString( + R.string.timelinePinned, + issueComment.getUser().getLogin(), + info)); + + start.setTextSize(fontSize); + timelineIcon.setImageDrawable( - ContextCompat.getDrawable(context, R.drawable.ic_bookmark)); + ContextCompat.getDrawable(context, R.drawable.ic_pin)); + timelineData.addView(start); + } else { + timelineView.setVisibility(View.GONE); } - timelineData.addView(recyclerView); - } - // code data view in timeline - else if (issueComment.getType().equalsIgnoreCase("code")) { - timelineView.setVisibility(View.GONE); - timelineDividerView.setVisibility(View.GONE); - } - // schedule pr view in timeline - else if (issueComment.getType().equalsIgnoreCase("pull_scheduled_merge") - || issueComment.getType().equalsIgnoreCase("pull_cancel_scheduled_merge")) { - timelineView.setVisibility(View.GONE); - timelineDividerView.setVisibility(View.GONE); + // comment data view in timeline + if (issueComment.getType().equalsIgnoreCase("comment")) { + + author.setText(issueComment.getUser().getLogin()); + + PicassoService.getInstance(context) + .get() + .load(issueComment.getUser().getAvatarUrl()) + .placeholder(R.drawable.loader_animated) + .transform(new RoundedTransformation(imgRadius, 0)) + .resize( + AppUtil.getPixelsFromDensity(context, 35), + AppUtil.getPixelsFromDensity(context, 35)) + .centerCrop() + .into(avatar); + + Markdown.render( + context, issueComment.getBody(), comment, issue.getRepository()); + + information.setText(info); + + Bundle bundle1 = new Bundle(); + bundle1.putAll(bundle); + bundle1.putInt("commentId", Math.toIntExact(issueComment.getId())); + + ReactionList reactionList = new ReactionList(context, bundle1); + + commentReactionBadges.addView(reactionList); + reactionList.setOnReactionAddedListener( + () -> { + if (commentReactionBadges.getVisibility() != View.VISIBLE) { + commentReactionBadges.post( + () -> + commentReactionBadges.setVisibility( + View.VISIBLE)); + } + }); + } else { + commentView.setVisibility(View.GONE); + } } else { + timelineDividerView.setVisibility(View.GONE); timelineView.setVisibility(View.GONE); - } - - // comment data view in timeline - if (issueComment.getType().equalsIgnoreCase("comment")) { - - author.setText(issueComment.getUser().getLogin()); - - PicassoService.getInstance(context) - .get() - .load(issueComment.getUser().getAvatarUrl()) - .placeholder(R.drawable.loader_animated) - .transform(new RoundedTransformation(imgRadius, 0)) - .resize( - AppUtil.getPixelsFromDensity(context, 35), - AppUtil.getPixelsFromDensity(context, 35)) - .centerCrop() - .into(avatar); - - Markdown.render(context, issueComment.getBody(), comment, issue.getRepository()); - - information.setText(info); - - Bundle bundle1 = new Bundle(); - bundle1.putAll(bundle); - bundle1.putInt("commentId", Math.toIntExact(issueComment.getId())); - - ReactionList reactionList = new ReactionList(context, bundle1); - - commentReactionBadges.addView(reactionList); - reactionList.setOnReactionAddedListener( - () -> { - if (commentReactionBadges.getVisibility() != View.VISIBLE) { - commentReactionBadges.post( - () -> commentReactionBadges.setVisibility(View.VISIBLE)); - } - }); - } else { commentView.setVisibility(View.GONE); } } diff --git a/app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java index f4ff33bb..40011f22 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java @@ -29,6 +29,7 @@ import org.mian.gitnex.activities.IssueDetailActivity; import org.mian.gitnex.activities.ProfileActivity; import org.mian.gitnex.activities.RepoDetailActivity; import org.mian.gitnex.clients.PicassoService; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.ClickListener; import org.mian.gitnex.helpers.ColorInverter; @@ -212,7 +213,9 @@ public class IssuesAdapter extends RecyclerView.Adapter if (issue.getLabels() != null) { - if (!tinyDb.getBoolean("showLabelsInList", false)) { // default + if (!Boolean.parseBoolean( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_LABELS_IN_LIST_KEY))) { labelsScrollViewWithText.setVisibility(View.GONE); labelsScrollViewDots.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/org/mian/gitnex/adapters/PullRequestsAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/PullRequestsAdapter.java index b29390de..b9519781 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/PullRequestsAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/PullRequestsAdapter.java @@ -31,6 +31,7 @@ import org.mian.gitnex.activities.IssueDetailActivity; import org.mian.gitnex.activities.ProfileActivity; import org.mian.gitnex.activities.RepoDetailActivity; import org.mian.gitnex.clients.PicassoService; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.ClickListener; import org.mian.gitnex.helpers.ColorInverter; @@ -206,7 +207,9 @@ public class PullRequestsAdapter extends RecyclerView.Adapter> fetchAllSettings() { + return appSettingsDao.fetchAllSettings(); + } + + public AppSettings fetchSettingById(int settingId) { + return appSettingsDao.fetchSettingById(settingId); + } + + public AppSettings fetchSettingByKey(String settingKey) { + return appSettingsDao.fetchSettingByKey(settingKey); + } + + public Integer fetchTotalSettingsCount() { + return appSettingsDao.fetchTotalSettingsCount(); + } + + public Integer fetchSettingCountByKey(String settingKey) { + return appSettingsDao.fetchSettingCountByKey(settingKey); + } + + public void updateSettingValueByKey(String settingValue, String settingKey) { + executorService.execute( + () -> appSettingsDao.updateSettingValueByKey(settingValue, settingKey)); + } + + public void updateSettingDefaultByKey(String settingDefault, String settingKey) { + executorService.execute( + () -> appSettingsDao.updateSettingDefaultByKey(settingDefault, settingKey)); + } + + public void deleteBySettingKey(final String settingKey) { + final AppSettings appSettings = appSettingsDao.fetchSettingByKey(settingKey); + + if (appSettings != null) { + executorService.execute(() -> appSettingsDao.deleteBySettingKey(settingKey)); + } + } +} diff --git a/app/src/main/java/org/mian/gitnex/database/dao/AppSettingsDao.java b/app/src/main/java/org/mian/gitnex/database/dao/AppSettingsDao.java new file mode 100644 index 00000000..d34be2b7 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/database/dao/AppSettingsDao.java @@ -0,0 +1,42 @@ +package org.mian.gitnex.database.dao; + +import androidx.lifecycle.LiveData; +import androidx.room.Dao; +import androidx.room.Insert; +import androidx.room.Query; +import java.util.List; +import org.mian.gitnex.database.models.AppSettings; + +/** + * @author M M Arif + */ +@Dao +public interface AppSettingsDao { + + @Insert + long insertNewSetting(AppSettings appSettings); + + @Query("SELECT * FROM AppSettings") + LiveData> fetchAllSettings(); + + @Query("SELECT * FROM AppSettings WHERE settingId = :settingId") + AppSettings fetchSettingById(int settingId); + + @Query("SELECT * FROM AppSettings WHERE settingKey = :settingKey") + AppSettings fetchSettingByKey(String settingKey); + + @Query("SELECT count(settingId) FROM AppSettings") + Integer fetchTotalSettingsCount(); + + @Query("SELECT count(settingId) FROM AppSettings WHERE settingKey = :settingKey") + Integer fetchSettingCountByKey(String settingKey); + + @Query("UPDATE AppSettings SET settingValue = :settingValue WHERE settingKey = :settingKey") + void updateSettingValueByKey(String settingValue, String settingKey); + + @Query("UPDATE AppSettings SET settingDefault = :settingDefault WHERE settingKey = :settingKey") + void updateSettingDefaultByKey(String settingDefault, String settingKey); + + @Query("DELETE FROM AppSettings WHERE settingKey = :settingKey") + void deleteBySettingKey(String settingKey); +} diff --git a/app/src/main/java/org/mian/gitnex/database/db/GitnexDatabase.java b/app/src/main/java/org/mian/gitnex/database/db/GitnexDatabase.java index cac62fd3..2f320601 100644 --- a/app/src/main/java/org/mian/gitnex/database/db/GitnexDatabase.java +++ b/app/src/main/java/org/mian/gitnex/database/db/GitnexDatabase.java @@ -7,10 +7,12 @@ import androidx.room.Room; import androidx.room.RoomDatabase; import androidx.room.migration.Migration; import androidx.sqlite.db.SupportSQLiteDatabase; +import org.mian.gitnex.database.dao.AppSettingsDao; import org.mian.gitnex.database.dao.DraftsDao; import org.mian.gitnex.database.dao.NotesDao; import org.mian.gitnex.database.dao.RepositoriesDao; import org.mian.gitnex.database.dao.UserAccountsDao; +import org.mian.gitnex.database.models.AppSettings; import org.mian.gitnex.database.models.Draft; import org.mian.gitnex.database.models.Notes; import org.mian.gitnex.database.models.Repository; @@ -20,8 +22,14 @@ import org.mian.gitnex.database.models.UserAccount; * @author M M Arif */ @Database( - entities = {Draft.class, Repository.class, UserAccount.class, Notes.class}, - version = 7, + entities = { + Draft.class, + Repository.class, + UserAccount.class, + Notes.class, + AppSettings.class + }, + version = 8, exportSchema = false) public abstract class GitnexDatabase extends RoomDatabase { @@ -79,6 +87,16 @@ public abstract class GitnexDatabase extends RoomDatabase { "CREATE TABLE IF NOT EXISTS 'Notes' ('noteId' INTEGER NOT NULL, 'content' TEXT, 'datetime' INTEGER, 'modified' INTEGER, PRIMARY KEY('noteid'))"); } }; + + private static final Migration MIGRATION_7_8 = + new Migration(7, 8) { + + @Override + public void migrate(@NonNull SupportSQLiteDatabase database) { + database.execSQL( + "CREATE TABLE IF NOT EXISTS 'appSettings' ('settingId' INTEGER NOT NULL, 'settingKey' TEXT, 'settingValue' TEXT, 'settingDefault' TEXT, PRIMARY KEY('settingId'))"); + } + }; private static volatile GitnexDatabase gitnexDatabase; public static GitnexDatabase getDatabaseInstance(Context context) { @@ -97,7 +115,8 @@ public abstract class GitnexDatabase extends RoomDatabase { MIGRATION_3_4, MIGRATION_4_5, MIGRATION_5_6, - MIGRATION_6_7) + MIGRATION_6_7, + MIGRATION_7_8) .build(); } } @@ -113,4 +132,6 @@ public abstract class GitnexDatabase extends RoomDatabase { public abstract UserAccountsDao userAccountsDao(); public abstract NotesDao notesDao(); + + public abstract AppSettingsDao appSettingsDao(); } diff --git a/app/src/main/java/org/mian/gitnex/database/models/AppSettings.java b/app/src/main/java/org/mian/gitnex/database/models/AppSettings.java new file mode 100644 index 00000000..e0afb6ab --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/database/models/AppSettings.java @@ -0,0 +1,52 @@ +package org.mian.gitnex.database.models; + +import androidx.annotation.Nullable; +import androidx.room.Entity; +import androidx.room.PrimaryKey; +import java.io.Serializable; + +/** + * @author M M Arif + */ +@Entity(tableName = "appSettings") +public class AppSettings implements Serializable { + + @PrimaryKey(autoGenerate = true) + private int settingId; + + private String settingKey; + private String settingValue; + @Nullable private String settingDefault; + + public int getSettingId() { + return settingId; + } + + public void setSettingId(int settingId) { + this.settingId = settingId; + } + + @Nullable public String getSettingKey() { + return settingKey; + } + + public void setSettingKey(@Nullable String settingKey) { + this.settingKey = settingKey; + } + + public String getSettingValue() { + return settingValue; + } + + public void setSettingValue(String settingValue) { + this.settingValue = settingValue; + } + + public String getSettingDefault() { + return settingDefault; + } + + public void setSettingDefault(String settingDefault) { + this.settingDefault = settingDefault; + } +} diff --git a/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsFragment.java b/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsFragment.java index 5fa523be..4a3cc015 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/AccountSettingsFragment.java @@ -17,8 +17,8 @@ import com.google.android.material.tabs.TabLayoutMediator; import org.mian.gitnex.R; import org.mian.gitnex.activities.BaseActivity; import org.mian.gitnex.activities.MainActivity; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; -import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.ViewPager2Transformers; import org.mian.gitnex.helpers.contexts.AccountContext; @@ -31,7 +31,6 @@ public class AccountSettingsFragment extends Fragment { private Context ctx; private View view; private Typeface myTypeface; - private TinyDB tinyDB; @Nullable @Override public View onCreateView( @@ -40,7 +39,6 @@ public class AccountSettingsFragment extends Fragment { @Nullable Bundle savedInstanceState) { ctx = getContext(); - tinyDB = TinyDB.getInstance(ctx); view = inflater.inflate(R.layout.fragment_account_settings, container, false); setHasOptionsMenu(false); @@ -76,7 +74,10 @@ public class AccountSettingsFragment extends Fragment { viewPager.setAdapter(new ViewPagerAdapter(this)); ViewPager2Transformers.returnSelectedTransformer( - viewPager, tinyDB.getInt("fragmentTabsAnimationId", 0)); + viewPager, + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_TABS_ANIMATION_KEY))); String[] tabTitles = { ctx.getResources().getString(R.string.accountEmails), diff --git a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetReplyFragment.java b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetReplyFragment.java index 9b0eef65..a2e702a8 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetReplyFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetReplyFragment.java @@ -31,6 +31,7 @@ import org.mian.gitnex.activities.MainActivity; import org.mian.gitnex.database.api.BaseApi; import org.mian.gitnex.database.api.DraftsApi; import org.mian.gitnex.databinding.BottomSheetReplyLayoutBinding; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.Constants; import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.Toasty; @@ -202,9 +203,12 @@ public class BottomSheetReplyFragment extends BottomSheetDialogFragment { getString(R.string.commentSuccess)); if (draftId != 0 - && tinyDB.getBoolean( - "draftsCommentsDeletionEnabled", - true)) { + && Boolean.parseBoolean( + AppDatabaseSettings + .getSettingsValue( + getContext(), + AppDatabaseSettings + .APP_DRAFTS_DELETION_KEY))) { draftsApi.deleteSingleDraft((int) draftId); } @@ -238,9 +242,12 @@ public class BottomSheetReplyFragment extends BottomSheetDialogFragment { if (status == ActionResult.Status.SUCCESS) { if (draftId != 0 - && tinyDB.getBoolean( - "draftsCommentsDeletionEnabled", - true)) { + && Boolean.parseBoolean( + AppDatabaseSettings + .getSettingsValue( + getContext(), + AppDatabaseSettings + .APP_DRAFTS_DELETION_KEY))) { draftsApi.deleteSingleDraft((int) draftId); } diff --git a/app/src/main/java/org/mian/gitnex/fragments/ExploreFragment.java b/app/src/main/java/org/mian/gitnex/fragments/ExploreFragment.java index 6c0520b0..fee96786 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/ExploreFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/ExploreFragment.java @@ -16,6 +16,7 @@ import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayoutMediator; import org.mian.gitnex.R; import org.mian.gitnex.activities.MainActivity; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.ViewPager2Transformers; @@ -49,7 +50,10 @@ public class ExploreFragment extends Fragment { viewPager.setAdapter(new ViewPagerAdapter(this)); ViewPager2Transformers.returnSelectedTransformer( - viewPager, tinyDB.getInt("fragmentTabsAnimationId", 0)); + viewPager, + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_TABS_ANIMATION_KEY))); String[] tabTitles = { getResources().getString(R.string.navRepos), diff --git a/app/src/main/java/org/mian/gitnex/fragments/PullRequestChangesFragment.java b/app/src/main/java/org/mian/gitnex/fragments/PullRequestChangesFragment.java index 21c34218..e088ec89 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/PullRequestChangesFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/PullRequestChangesFragment.java @@ -10,7 +10,7 @@ import androidx.viewpager2.adapter.FragmentStateAdapter; import com.google.android.material.tabs.TabLayoutMediator; import org.mian.gitnex.R; import org.mian.gitnex.databinding.FragmentPrChangesBinding; -import org.mian.gitnex.helpers.TinyDB; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.ViewPager2Transformers; /** @@ -21,7 +21,6 @@ public class PullRequestChangesFragment extends Fragment { private final DiffFilesFragment diffFilesFragment = DiffFilesFragment.newInstance(); private final PullRequestCommitsFragment pullRequestCommitsFragment = PullRequestCommitsFragment.newInstance(); - private FragmentPrChangesBinding binding; public PullRequestChangesFragment() {} @@ -33,9 +32,8 @@ public class PullRequestChangesFragment extends Fragment { public View onCreateView( @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentPrChangesBinding.inflate(inflater, container, false); - - TinyDB tinyDB = TinyDB.getInstance(getContext()); + FragmentPrChangesBinding binding = + FragmentPrChangesBinding.inflate(inflater, container, false); binding.close.setOnClickListener(v -> requireActivity().finish()); @@ -62,7 +60,10 @@ public class PullRequestChangesFragment extends Fragment { new String[] {getString(R.string.tabTextFiles), getString(R.string.commits)}; ViewPager2Transformers.returnSelectedTransformer( - binding.container, tinyDB.getInt("fragmentTabsAnimationId", 0)); + binding.container, + Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + getContext(), AppDatabaseSettings.APP_TABS_ANIMATION_KEY))); new TabLayoutMediator( binding.tabs, diff --git a/app/src/main/java/org/mian/gitnex/helpers/AppDatabaseSettings.java b/app/src/main/java/org/mian/gitnex/helpers/AppDatabaseSettings.java new file mode 100644 index 00000000..59a315d3 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/helpers/AppDatabaseSettings.java @@ -0,0 +1,395 @@ +package org.mian.gitnex.helpers; + +import android.content.Context; +import android.util.Log; +import org.mian.gitnex.database.api.AppSettingsApi; +import org.mian.gitnex.database.api.BaseApi; +import org.mian.gitnex.database.models.AppSettings; + +/** + * @author M M Arif + */ +public class AppDatabaseSettings { + + public static String APP_THEME_KEY = "app_theme"; + public static String APP_THEME_DEFAULT = "6"; + public static String APP_THEME_AUTO_LIGHT_HOUR_KEY = "app_theme_auto_light_hour"; + public static String APP_THEME_AUTO_LIGHT_HOUR_DEFAULT = "6"; + public static String APP_THEME_AUTO_LIGHT_MIN_KEY = "app_theme_auto_light_min"; + public static String APP_THEME_AUTO_LIGHT_MIN_DEFAULT = "0"; + public static String APP_THEME_AUTO_DARK_HOUR_KEY = "app_theme_auto_dark_hour"; + public static String APP_THEME_AUTO_DARK_HOUR_DEFAULT = "18"; + public static String APP_THEME_AUTO_DARK_MIN_KEY = "app_theme_auto_dark_min"; + public static String APP_THEME_AUTO_DARK_MIN_DEFAULT = "0"; + public static String APP_FONT_KEY = "app_font"; + public static String APP_FONT_DEFAULT = "3"; + public static String APP_TABS_ANIMATION_KEY = "app_tabs_animation"; + public static String APP_TABS_ANIMATION_DEFAULT = "0"; + public static String APP_LOCALE_KEY = "app_locale"; + public static String APP_LOCALE_KEY_DEFAULT = "0|sys"; + public static String APP_COUNTER_KEY = "app_counter_badges"; + public static String APP_COUNTER_DEFAULT = "true"; + public static String APP_LABELS_IN_LIST_KEY = "app_labels_in_list"; + public static String APP_LABELS_IN_LIST_DEFAULT = "false"; + public static String APP_LINK_HANDLER_KEY = "app_link_handler"; + public static String APP_LINK_HANDLER_DEFAULT = "0"; + public static String APP_HOME_SCREEN_KEY = "app_home_screen"; + public static String APP_HOME_SCREEN_DEFAULT = "3"; + public static String APP_CUSTOM_BROWSER_KEY = "app_custom_browser_tab"; + public static String APP_CUSTOM_BROWSER_DEFAULT = "true"; + public static String APP_DRAFTS_DELETION_KEY = "app_drafts_deletion"; + public static String APP_DRAFTS_DELETION_DEFAULT = "true"; + public static String APP_CRASH_REPORTS_KEY = "app_crash_reports"; + public static String APP_CRASH_REPORTS_DEFAULT = "false"; + public static String APP_CE_SYNTAX_HIGHLIGHT_KEY = "app_ce_syntax_highlight"; + public static String APP_CE_SYNTAX_HIGHLIGHT_DEFAULT = "0"; + public static String APP_CE_INDENTATION_KEY = "app_ce_indentation"; + public static String APP_CE_INDENTATION_DEFAULT = "0"; + public static String APP_CE_TABS_WIDTH_KEY = "app_ce_tabs_width"; + public static String APP_CE_TABS_WIDTH_DEFAULT = "1"; + public static String APP_NOTIFICATIONS_KEY = "app_notifications"; + public static String APP_NOTIFICATIONS_DEFAULT = "true"; + public static String APP_NOTIFICATIONS_DELAY_KEY = "app_notifications_delay"; + public static String APP_NOTIFICATIONS_DELAY_DEFAULT = "0"; + public static String APP_BIOMETRIC_KEY = "app_biometric"; + public static String APP_BIOMETRIC_DEFAULT = "false"; + public static String APP_BIOMETRIC_LIFE_CYCLE_KEY = "app_biometric_life_cycle"; + public static String APP_BIOMETRIC_LIFE_CYCLE_DEFAULT = "false"; + public static String APP_DATA_CACHE_KEY = "app_data_cache"; + public static String APP_DATA_CACHE_DEFAULT = "1"; + public static String APP_DATA_CACHE_SIZE_KEY = "app_data_cache_size"; + public static String APP_DATA_CACHE_SIZE_DEFAULT = "100 MB"; + public static String APP_IMAGES_CACHE_KEY = "app_images_cache"; + public static String APP_IMAGES_CACHE_DEFAULT = "1"; + public static String APP_IMAGES_CACHE_SIZE_KEY = "app_images_cache_size"; + public static String APP_IMAGES_CACHE_SIZE_DEFAULT = "100 MB"; + + public static void initDefaultSettings(Context ctx) { + + AppSettingsApi appSettingsApi = BaseApi.getInstance(ctx, AppSettingsApi.class); + assert appSettingsApi != null; + + if (appSettingsApi.fetchSettingCountByKey(APP_THEME_KEY) == 0) { + appSettingsApi.insertNewSetting(APP_THEME_KEY, APP_THEME_DEFAULT, APP_THEME_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_THEME_AUTO_LIGHT_HOUR_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_THEME_AUTO_LIGHT_HOUR_KEY, + APP_THEME_AUTO_LIGHT_HOUR_DEFAULT, + APP_THEME_AUTO_LIGHT_HOUR_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_THEME_AUTO_LIGHT_MIN_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_THEME_AUTO_LIGHT_MIN_KEY, + APP_THEME_AUTO_LIGHT_MIN_DEFAULT, + APP_THEME_AUTO_LIGHT_MIN_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_THEME_AUTO_DARK_HOUR_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_THEME_AUTO_DARK_HOUR_KEY, + APP_THEME_AUTO_DARK_HOUR_DEFAULT, + APP_THEME_AUTO_DARK_HOUR_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_THEME_AUTO_DARK_MIN_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_THEME_AUTO_DARK_MIN_KEY, + APP_THEME_AUTO_DARK_MIN_DEFAULT, + APP_THEME_AUTO_DARK_MIN_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_FONT_KEY) == 0) { + appSettingsApi.insertNewSetting(APP_FONT_KEY, APP_FONT_DEFAULT, APP_FONT_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_TABS_ANIMATION_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_TABS_ANIMATION_KEY, APP_TABS_ANIMATION_DEFAULT, APP_TABS_ANIMATION_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_LOCALE_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_LOCALE_KEY, APP_LOCALE_KEY_DEFAULT, APP_LOCALE_KEY_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_COUNTER_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_COUNTER_KEY, APP_COUNTER_DEFAULT, APP_COUNTER_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_LABELS_IN_LIST_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_LABELS_IN_LIST_KEY, APP_LABELS_IN_LIST_DEFAULT, APP_LABELS_IN_LIST_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_LINK_HANDLER_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_LINK_HANDLER_KEY, APP_LINK_HANDLER_DEFAULT, APP_LINK_HANDLER_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_HOME_SCREEN_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_HOME_SCREEN_KEY, APP_HOME_SCREEN_DEFAULT, APP_HOME_SCREEN_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_CUSTOM_BROWSER_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_CUSTOM_BROWSER_KEY, APP_CUSTOM_BROWSER_DEFAULT, APP_CUSTOM_BROWSER_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_DRAFTS_DELETION_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_DRAFTS_DELETION_KEY, + APP_DRAFTS_DELETION_DEFAULT, + APP_DRAFTS_DELETION_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_CRASH_REPORTS_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_CRASH_REPORTS_KEY, APP_CRASH_REPORTS_DEFAULT, APP_CRASH_REPORTS_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_CE_SYNTAX_HIGHLIGHT_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_CE_SYNTAX_HIGHLIGHT_KEY, + APP_CE_SYNTAX_HIGHLIGHT_DEFAULT, + APP_CE_SYNTAX_HIGHLIGHT_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_CE_INDENTATION_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_CE_INDENTATION_KEY, APP_CE_INDENTATION_DEFAULT, APP_CE_INDENTATION_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_CE_TABS_WIDTH_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_CE_TABS_WIDTH_KEY, APP_CE_TABS_WIDTH_DEFAULT, APP_CE_TABS_WIDTH_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_NOTIFICATIONS_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_NOTIFICATIONS_KEY, APP_NOTIFICATIONS_DEFAULT, APP_NOTIFICATIONS_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_NOTIFICATIONS_DELAY_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_NOTIFICATIONS_DELAY_KEY, + APP_NOTIFICATIONS_DELAY_DEFAULT, + APP_NOTIFICATIONS_DELAY_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_BIOMETRIC_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_BIOMETRIC_KEY, APP_BIOMETRIC_DEFAULT, APP_BIOMETRIC_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_BIOMETRIC_LIFE_CYCLE_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_BIOMETRIC_LIFE_CYCLE_KEY, + APP_BIOMETRIC_LIFE_CYCLE_DEFAULT, + APP_BIOMETRIC_LIFE_CYCLE_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_DATA_CACHE_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_DATA_CACHE_KEY, APP_DATA_CACHE_DEFAULT, APP_DATA_CACHE_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_DATA_CACHE_SIZE_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_DATA_CACHE_SIZE_KEY, + APP_DATA_CACHE_SIZE_DEFAULT, + APP_DATA_CACHE_SIZE_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_IMAGES_CACHE_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_IMAGES_CACHE_KEY, APP_IMAGES_CACHE_DEFAULT, APP_IMAGES_CACHE_DEFAULT); + } + if (appSettingsApi.fetchSettingCountByKey(APP_IMAGES_CACHE_SIZE_KEY) == 0) { + appSettingsApi.insertNewSetting( + APP_IMAGES_CACHE_SIZE_KEY, + APP_IMAGES_CACHE_SIZE_DEFAULT, + APP_IMAGES_CACHE_SIZE_DEFAULT); + } + + if (appSettingsApi.fetchSettingCountByKey("prefsMigration") == 0) { + appSettingsApi.insertNewSetting("prefsMigration", "true", "true"); + } + } + + public static String getSettingsValue(Context ctx, String key) { + + AppSettingsApi appSettingsApi = BaseApi.getInstance(ctx, AppSettingsApi.class); + assert appSettingsApi != null; + AppSettings appSettings = appSettingsApi.fetchSettingByKey(key); + return appSettings.getSettingValue(); + } + + public static void updateSettingsValue(Context ctx, String val, String key) { + + AppSettingsApi appSettingsApi = BaseApi.getInstance(ctx, AppSettingsApi.class); + assert appSettingsApi != null; + appSettingsApi.updateSettingValueByKey(val, key); + } + + // remove this in the upcoming releases (5.5 or up) + public static void prefsMigration(Context ctx) { + + TinyDB tinyDB = TinyDB.getInstance(ctx); + + Log.e("TestVal", "prefsMigration-ran"); + + if (tinyDB.checkForExistingPref("themeId")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getInt("themeId")), + AppDatabaseSettings.APP_THEME_KEY); + tinyDB.remove("themeId"); + } + + if (tinyDB.checkForExistingPref("lightThemeTimeHour")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getInt("lightThemeTimeHour")), + AppDatabaseSettings.APP_THEME_AUTO_LIGHT_HOUR_KEY); + tinyDB.remove("lightThemeTimeHour"); + } + if (tinyDB.checkForExistingPref("lightThemeTimeMinute")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getInt("lightThemeTimeMinute")), + AppDatabaseSettings.APP_THEME_AUTO_LIGHT_MIN_KEY); + tinyDB.remove("lightThemeTimeMinute"); + } + + if (tinyDB.checkForExistingPref("darkThemeTimeHour")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getInt("darkThemeTimeHour")), + AppDatabaseSettings.APP_THEME_AUTO_DARK_HOUR_KEY); + tinyDB.remove("darkThemeTimeHour"); + } + if (tinyDB.checkForExistingPref("darkThemeTimeMinute")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getInt("darkThemeTimeMinute")), + AppDatabaseSettings.APP_THEME_AUTO_DARK_MIN_KEY); + tinyDB.remove("darkThemeTimeMinute"); + } + + if (tinyDB.checkForExistingPref("customFontId")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getInt("customFontId")), + AppDatabaseSettings.APP_FONT_KEY); + tinyDB.remove("customFontId"); + } + + if (tinyDB.checkForExistingPref("fragmentTabsAnimationId")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getInt("fragmentTabsAnimationId")), + AppDatabaseSettings.APP_TABS_ANIMATION_KEY); + tinyDB.remove("fragmentTabsAnimationId"); + } + + if (tinyDB.checkForExistingPref("locale")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + tinyDB.getInt("langId") + "|" + tinyDB.getString("locale"), + AppDatabaseSettings.APP_LOCALE_KEY); + tinyDB.remove("locale"); + tinyDB.remove("langId"); + } + + if (tinyDB.checkForExistingPref("ceColorId")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getInt("ceColorId")), + AppDatabaseSettings.APP_CE_SYNTAX_HIGHLIGHT_KEY); + tinyDB.remove("ceColorId"); + } + if (tinyDB.checkForExistingPref("ceIndentationId")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getInt("ceIndentationId")), + AppDatabaseSettings.APP_CE_INDENTATION_KEY); + tinyDB.remove("ceIndentationId"); + } + if (tinyDB.checkForExistingPref("ceIndentationTabsId")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getInt("ceIndentationTabsId")), + AppDatabaseSettings.APP_CE_TABS_WIDTH_KEY); + tinyDB.remove("ceIndentationTabsId"); + } + + if (tinyDB.checkForExistingPref("homeScreenId")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getInt("homeScreenId")), + AppDatabaseSettings.APP_HOME_SCREEN_KEY); + tinyDB.remove("homeScreenId"); + } + + if (tinyDB.checkForExistingPref("defaultScreenId")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getInt("defaultScreenId")), + AppDatabaseSettings.APP_LINK_HANDLER_KEY); + tinyDB.remove("defaultScreenId"); + } + + if (tinyDB.checkForExistingPref("enableCounterBadges")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getBoolean("enableCounterBadges")), + AppDatabaseSettings.APP_COUNTER_KEY); + tinyDB.remove("enableCounterBadges"); + } + + if (tinyDB.checkForExistingPref("showLabelsInList")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getBoolean("showLabelsInList")), + AppDatabaseSettings.APP_LABELS_IN_LIST_KEY); + tinyDB.remove("showLabelsInList"); + } + + if (tinyDB.checkForExistingPref("notificationsEnabled")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getBoolean("notificationsEnabled")), + AppDatabaseSettings.APP_NOTIFICATIONS_KEY); + tinyDB.remove("notificationsEnabled"); + } + if (tinyDB.checkForExistingPref("notificationsPollingDelayId")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getInt("notificationsPollingDelayId")), + AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY); + tinyDB.remove("notificationsPollingDelayId"); + } + + if (tinyDB.checkForExistingPref("biometricStatus")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getBoolean("biometricStatus")), + AppDatabaseSettings.APP_BIOMETRIC_KEY); + tinyDB.remove("biometricStatus"); + } + if (tinyDB.checkForExistingPref("biometricLifeCycle")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getBoolean("biometricLifeCycle")), + AppDatabaseSettings.APP_BIOMETRIC_LIFE_CYCLE_KEY); + tinyDB.remove("biometricLifeCycle"); + } + + if (tinyDB.checkForExistingPref("useCustomTabs")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getBoolean("useCustomTabs")), + AppDatabaseSettings.APP_CUSTOM_BROWSER_KEY); + tinyDB.remove("useCustomTabs"); + } + + if (tinyDB.checkForExistingPref("crashReportingEnabled")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getBoolean("crashReportingEnabled")), + AppDatabaseSettings.APP_CRASH_REPORTS_KEY); + tinyDB.remove("crashReportingEnabled"); + } + + if (tinyDB.checkForExistingPref("draftsCommentsDeletionEnabled")) { + AppDatabaseSettings.updateSettingsValue( + ctx, + String.valueOf(tinyDB.getBoolean("draftsCommentsDeletionEnabled")), + AppDatabaseSettings.APP_DRAFTS_DELETION_KEY); + tinyDB.remove("draftsCommentsDeletionEnabled"); + } + + AppDatabaseSettings.updateSettingsValue(ctx, "false", "prefsMigration"); + } +} diff --git a/app/src/main/java/org/mian/gitnex/helpers/AppUtil.java b/app/src/main/java/org/mian/gitnex/helpers/AppUtil.java index 947b9861..d228727d 100644 --- a/app/src/main/java/org/mian/gitnex/helpers/AppUtil.java +++ b/app/src/main/java/org/mian/gitnex/helpers/AppUtil.java @@ -316,16 +316,27 @@ public class AppUtil { public static void setAppLocale(Resources resource, String locCode) { + String[] multiCodeLang = locCode.split("-"); + String countryCode; + if (locCode.contains("-")) { + locCode = multiCodeLang[0]; + countryCode = multiCodeLang[1]; + } else { + countryCode = ""; + } + DisplayMetrics dm = resource.getDisplayMetrics(); Configuration config = resource.getConfiguration(); - config.setLocale(new Locale(locCode.toLowerCase())); + config.setLocale(new Locale(locCode.toLowerCase(), countryCode)); resource.updateConfiguration(config, dm); } public static String getTimestampFromDate(Context context, Date date) { - TinyDB tinyDB = TinyDB.getInstance(context); - Locale locale = new Locale(tinyDB.getString("locale")); + String[] locale_ = + AppDatabaseSettings.getSettingsValue(context, AppDatabaseSettings.APP_LOCALE_KEY) + .split("\\|"); + Locale locale = new Locale(locale_[1]); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", locale).format(date); @@ -394,7 +405,7 @@ public class AppUtil { public static String encodeBase64(String str) { String base64Str = str; - if (!str.equals("")) { + if (!str.isEmpty()) { byte[] data = str.getBytes(StandardCharsets.UTF_8); base64Str = Base64.encodeToString(data, Base64.DEFAULT); } @@ -529,10 +540,10 @@ public class AppUtil { public static void openUrlInBrowser(Context context, String url) { - TinyDB tinyDB = TinyDB.getInstance(context); - Intent i; - if (tinyDB.getBoolean("useCustomTabs")) { + if (Boolean.parseBoolean( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_CUSTOM_BROWSER_KEY))) { i = new CustomTabsIntent.Builder() .setDefaultColorSchemeParams( @@ -593,8 +604,11 @@ public class AppUtil { } public static Typeface getTypeface(Context context) { + if (typeface == null) { - switch (TinyDB.getInstance(context).getInt("customFontId", -1)) { + switch (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_FONT_KEY))) { case 0: typeface = Typeface.createFromAsset(context.getAssets(), "fonts/roboto.ttf"); break; diff --git a/app/src/main/java/org/mian/gitnex/helpers/Markdown.java b/app/src/main/java/org/mian/gitnex/helpers/Markdown.java index 9ffa7d5a..2b57233e 100644 --- a/app/src/main/java/org/mian/gitnex/helpers/Markdown.java +++ b/app/src/main/java/org/mian/gitnex/helpers/Markdown.java @@ -211,7 +211,12 @@ public class Markdown { if (tf == null) { tf = AppUtil.getTypeface(textView.getContext()); } - if (tinyDB.getInt("themeId") == 8) { + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, + AppDatabaseSettings + .APP_THEME_KEY)) + == 8) { if (!isNightModeThemeDynamic(context)) { textView.setTextColor( AppUtil.dynamicColorResource(context)); @@ -375,7 +380,12 @@ public class Markdown { if (tf == null) { tf = AppUtil.getTypeface(context); } - if (tinyDB.getInt("themeId") == 8) { + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, + AppDatabaseSettings + .APP_THEME_KEY)) + == 8) { if (!isNightModeThemeDynamic(context)) { textView.setTextColor( AppUtil.dynamicColorResource(context)); diff --git a/app/src/main/java/org/mian/gitnex/helpers/PicassoCache.java b/app/src/main/java/org/mian/gitnex/helpers/PicassoCache.java index 81346add..2412cb2a 100644 --- a/app/src/main/java/org/mian/gitnex/helpers/PicassoCache.java +++ b/app/src/main/java/org/mian/gitnex/helpers/PicassoCache.java @@ -15,7 +15,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.UUID; -import org.mian.gitnex.R; /** * @author opyale @@ -34,14 +33,10 @@ public class PicassoCache implements Cache { public PicassoCache(File cachePath, Context ctx) throws IOException, ClassNotFoundException { - TinyDB tinyDb = TinyDB.getInstance(ctx); - CACHE_SIZE = FilesData.returnOnlyNumberFileSize( - tinyDb.getString( - "cacheSizeImagesStr", - ctx.getString( - R.string.cacheSizeImagesSelectionSelectedText))) + AppDatabaseSettings.getSettingsValue( + ctx, AppDatabaseSettings.APP_IMAGES_CACHE_SIZE_KEY)) * 1024 * 1024; this.cachePath = cachePath; diff --git a/app/src/main/java/org/mian/gitnex/helpers/TinyDB.java b/app/src/main/java/org/mian/gitnex/helpers/TinyDB.java index 751604f5..50f6ad5f 100644 --- a/app/src/main/java/org/mian/gitnex/helpers/TinyDB.java +++ b/app/src/main/java/org/mian/gitnex/helpers/TinyDB.java @@ -327,4 +327,8 @@ public class TinyDB { throw new NullPointerException(); } } + + public boolean checkForExistingPref(String key) { + return preferences.contains(key); + } } diff --git a/app/src/main/java/org/mian/gitnex/helpers/codeeditor/theme/Theme.java b/app/src/main/java/org/mian/gitnex/helpers/codeeditor/theme/Theme.java index b61701eb..d434cd7c 100644 --- a/app/src/main/java/org/mian/gitnex/helpers/codeeditor/theme/Theme.java +++ b/app/src/main/java/org/mian/gitnex/helpers/codeeditor/theme/Theme.java @@ -3,8 +3,8 @@ package org.mian.gitnex.helpers.codeeditor.theme; import android.content.Context; import androidx.annotation.ColorRes; import org.mian.gitnex.R; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.AppUtil; -import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.codeeditor.languages.LanguageElement; /** @@ -19,8 +19,10 @@ public interface Theme { BlueMoonDarkTheme BLUE_MOON_DARK_THEME = new BlueMoonDarkTheme(); static Theme getDefaultTheme(Context context) { - TinyDB tinyDB = TinyDB.getInstance(context); - if (tinyDB.getInt("ceColorId") == 0) { + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_CE_SYNTAX_HIGHLIGHT_KEY)) + == 0) { return AppUtil.getColorFromAttribute(context, R.attr.isDark) == 1 ? FIVE_COLORS_DARK : FIVE_COLORS; diff --git a/app/src/main/java/org/mian/gitnex/notifications/Notifications.java b/app/src/main/java/org/mian/gitnex/notifications/Notifications.java index 2d165ddc..2a7169e0 100644 --- a/app/src/main/java/org/mian/gitnex/notifications/Notifications.java +++ b/app/src/main/java/org/mian/gitnex/notifications/Notifications.java @@ -16,6 +16,7 @@ import androidx.work.WorkManager; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import java.util.concurrent.TimeUnit; import org.mian.gitnex.R; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.Constants; import org.mian.gitnex.helpers.TinyDB; @@ -72,22 +73,34 @@ public class Notifications { public static void startWorker(Context context) { - TinyDB tinyDB = TinyDB.getInstance(context); - int delay; - if (tinyDB.getInt("notificationsPollingDelayId") == 0) { + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY)) + == 0) { delay = 15; - } else if (tinyDB.getInt("notificationsPollingDelayId") == 1) { + } else if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY)) + == 1) { delay = 30; - } else if (tinyDB.getInt("notificationsPollingDelayId") == 2) { + } else if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY)) + == 2) { delay = 45; - } else if (tinyDB.getInt("notificationsPollingDelayId") == 3) { + } else if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY)) + == 3) { delay = 60; } else { delay = Constants.defaultPollingDelay; } - if (tinyDB.getBoolean("notificationsEnabled", true)) { + if (Boolean.parseBoolean( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_NOTIFICATIONS_KEY))) { if (!NotificationManagerCompat.from(context).areNotificationsEnabled()) { MaterialAlertDialogBuilder materialAlertDialogBuilder = diff --git a/app/src/main/java/org/mian/gitnex/notifications/NotificationsWorker.java b/app/src/main/java/org/mian/gitnex/notifications/NotificationsWorker.java index 3f92ed87..0f1aec63 100644 --- a/app/src/main/java/org/mian/gitnex/notifications/NotificationsWorker.java +++ b/app/src/main/java/org/mian/gitnex/notifications/NotificationsWorker.java @@ -28,8 +28,8 @@ import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.database.api.BaseApi; import org.mian.gitnex.database.api.UserAccountsApi; import org.mian.gitnex.database.models.UserAccount; +import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.Constants; -import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.Version; import retrofit2.Call; import retrofit2.Response; @@ -49,18 +49,29 @@ public class NotificationsWorker extends Worker { UserAccountsApi userAccountsApi = BaseApi.getInstance(context, UserAccountsApi.class); this.context = context; - TinyDB tinyDB = TinyDB.getInstance(context); assert userAccountsApi != null; this.userAccounts = new HashMap<>(userAccountsApi.getCount()); int delay; - if (tinyDB.getInt("notificationsPollingDelayId") == 0) { + if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY)) + == 0) { delay = 15; - } else if (tinyDB.getInt("notificationsPollingDelayId") == 1) { + } else if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY)) + == 1) { delay = 30; - } else if (tinyDB.getInt("notificationsPollingDelayId") == 2) { + } else if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY)) + == 2) { delay = 45; - } else if (tinyDB.getInt("notificationsPollingDelayId") == 3) { + } else if (Integer.parseInt( + AppDatabaseSettings.getSettingsValue( + context, AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY)) + == 3) { delay = 60; } else { delay = Constants.defaultPollingDelay; diff --git a/app/src/main/res/layout/activity_settings_security.xml b/app/src/main/res/layout/activity_settings_security.xml index 4fcc211f..fa58d60b 100644 --- a/app/src/main/res/layout/activity_settings_security.xml +++ b/app/src/main/res/layout/activity_settings_security.xml @@ -106,7 +106,7 @@ android:id="@+id/cacheSizeDataSelected" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/cacheSizeDataSelectionSelectedText" + android:text="@string/cacheSizeDataDialogHeader" android:textColor="?attr/selectedTextColor" android:textSize="@dimen/dimen16sp" /> @@ -131,7 +131,7 @@ android:id="@+id/cacheSizeImagesSelected" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/cacheSizeImagesSelectionSelectedText" + android:text="@string/cacheSizeImagesDialogHeader" android:textColor="?attr/selectedTextColor" android:textSize="@dimen/dimen16sp" /> diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar-rSA/strings.xml similarity index 100% rename from app/src/main/res/values-ar/strings.xml rename to app/src/main/res/values-ar-rSA/strings.xml diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml similarity index 100% rename from app/src/main/res/values-cs/strings.xml rename to app/src/main/res/values-cs-rCZ/strings.xml diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de-rDE/strings.xml similarity index 100% rename from app/src/main/res/values-de/strings.xml rename to app/src/main/res/values-de-rDE/strings.xml diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el-rGR/strings.xml similarity index 100% rename from app/src/main/res/values-el/strings.xml rename to app/src/main/res/values-el-rGR/strings.xml diff --git a/app/src/main/res/values-eo-rEO/strings.xml b/app/src/main/res/values-eo-rEO/strings.xml new file mode 100644 index 00000000..08af8f33 --- /dev/null +++ b/app/src/main/res/values-eo-rEO/strings.xml @@ -0,0 +1,775 @@ + + + + Miaj Deponejoj + Steligitaj Deponejoj + Deponejoj + Profilo + Agordoj + Organizoj + Pri + Rangi GitNex + Elsaluti + Administrado de Instanco + Miaj Problemoj + Plej Vizititaj Deponejoj + Notoj + Agordoj de Konto + Rigarditajn Deponejojn + + + Nova Deponejo + Problemoj + Nova Organizo + Nova Mejloŝtono + Nova Problemo + Nova Etikedo + Agnoskoj + Elekti Branĉon + Ĝisdatigi Etikedon + Steligitaj Deponejoj + Nova Teamo + Aldoni Retpoŝtadreson + Nova Dosiero + Esplori + Administrado + Nova Tiro-Peto + Uzantoj + Aldoni Deponejon + + Demonstra deponejo + Demonstra priskribo + Demonstra organizo + Krei + Ĝisdatigi + Nomo de la Deponejo + Priskribo de la Deponejo + Privata + Proprulo + Issue Labels + Make repository a template + Nomo de la Organizo + Priskribo de la Organizo + %1$s - %2$s + Uzantnomo + Pasvorto + ENSALUTI + URL de la Instanco + Malfermi Navigan Tirkeston + Fermi Navigan Tirkeston + Protocol + 1- Choose the correct protocol(https or http). \n2- Enter instance url e.g: try.gitea.io. \n3- If you have enabled 2FA for your account, enter the code in the OTP Code field. \n4- For HTTP basic auth use USERNAME@DOMAIN.COM in the URL field. + Couldn\'t connect to host. Please check your URL or port for any errors + It is not recommended to use HTTP protocol unless you are testing on local network + Malformed JSON was received. Server response was not successful + Instance URL is required + Username is required + Password is required + Protocol is required + Enter URL without http or https. Example: codeberg.org + Cannot access network, please check your Internet connection + Repository name is empty + Repository name is not valid. [a–z A–Z 0–9 – _] + Repository name is reserved + Repository name contains reserved keywords + Repository description exceeds the max 255 characters limit + Repository created successfully + Repository of this name already exists under selected Owner + Select owner for the repository + The default branch must not be empty + Organization name is empty + Organization name is not valid, [a–z A–Z 0–9 – _] + Organization description exceeds the max 255 characters limit + Organization created successfully + Organization already exists + %1$s addition(s) and %2$s deletion(s) + Processing + Search + Close + Add + Org + Repo + Pri + Remove + Instance has returned an error. Code %d + Details + Files + Milestones + Releases + Branches + Collaborators + Pull Requests + Pull Request + Size + Default Branch + SSH URL + Clone URL + Repo URL + Forks + Created + Last Updated + Pliaj Informoj + ĉe + Mejloŝtono %1$s + Pagenda %1$s + Asignita al: %1$s + Asignita al Mi + Komento + Bonvolu skribi vian komenton + Komento afiŝita + Ĉi tiu funkcio estos forigita estonte + Bildo + Aŭtoro de la Enmeto: %1$s + Elŝutaĵoj + Eldonita de @%1$s + Eldonaj notoj ne estas provizitaj de la eldonisto. + Titolo + Priskribo + Limdato + Milestone title is empty + Milestone description exceeds the max 255 characters limit + Milestone created successfully + Please choose due date + No due date + No description + %1$d Open + %1$d Closed + Select Milestone + Select Assignees + Select Labels + Title + Assignees + Description + Due Date + Milestone + Labels + Issue title is empty + Issue description is empty + New issue created successfully + No milestone + No assignees found + + Translation + System + Security + Delete Trusted Certificates + Delete Trusted Certificates? + Are you sure to delete any manually trusted certificate or hostname? \n\nYou will also be logged out. + Settings saved + Language + English + Appearance + Choose Language + Light Theme Switch Time + Dark Theme Switch Time + Choose Time Format + Translate GitNex via Crowdin + Code Block Color + Code Block Color Selector + Home Screen + My Repositories + Select Home Screen + Font + Choose Font + Select App Theme + Theme + Counter Badges + Source Code Theme + Data Cache Size + Data Cache Size + Images Cache Size + Images Cache Size + Clear Cache + Clear Cache? + This will delete all the cache data including files and images.\n\nProceed with deletion? + Drafts + Comments draft + Enable Drafts Deletion + Delete comment draft when comment is posted + General + Home screen, drafts, crash reports + Default Link Handler + Choose what screen should be loaded if the app cannot handle external links. It will redirect you automatically. + Select Default Link Handler Screen + Biometric Support + Labels With Text Support + Enabling this will show labels with text in issues and pr lists, default are color dots + Syntax Highlighting Color + Indentation + Tabs Width + System Default Font + Tabs Animation + Fade Out + Zoom Out + + No more data available + New Label + Repo Menu + Label Name + Label Color + Label name is empty + Label name is not valid + Label created + Label updated + Desc + Label deleted + Select a branch for release + Authorization Error + It seems that the Access Token is revoked OR your are not allowed to see these contents.\n\nIn case of revoked Token, please logout and login again + Do you really want to delete this label? + + Teams + Members + Team name + Team desc + Permissions + • Members of this team do not have any permissions. + • Members of this team can view team repositories. + • Members of this team can view and push to team repositories. + • Members of this team can push to and from team repositories and add collaborators. + • Members of this team have owner permissions. + show all + Org members + Organization team members + Remove %s + Add %s + Do you want to add this user to the team? + Do you want to remove this user from the team? + Member added to the team successfully + Member removed from the team successfully + Repository added to the team successfully + Repository removed from the team successfully + Add repository %1$s to organization %2$s team %3$s + Remove repository %1$s from team %2$s + Add / Remove Member + + + Team Name + Description + Permission + Access Controls + Members can view and clone team repositories + Members can read and push to team repositories + Members can pull and push to team repositories and add collaborators to them + Please enter team name + Team name should contain only alphanumeric, dash (-), underscore (_) and dot (.) characters + Please select permission + Team description have illegal characters + Team description have more than 100 characters + Team created successfully + + + Edit Comment + Comment updated + Share Comment + Comment deleted successfully + Copy Comment + + + Search users + Username + Remove %s? + Do you want to remove this user from the repository? + User removed from the repository. + User added to the repository. + + + Followers + Following + + + Emails + Email Address + New email added successfully + Email address is empty + Email address is not valid + Email address is already in use + Primary + SSH Keys + + + Add / Remove Labels + Labels updated + Close Issue + Edit Issue + Reopen Issue + Issue closed + Issue reopened + Add / Remove Assignees + Assignees updated + Subscribe + Unsubscribe + + Repository Meta + + New User + System Users + Admin + Cron Tasks + Schedule + Next Run + Last Run + Executions + Task %1$s is initiated successfully + + + Full Name + Email + Username + Password + Invalid Full Name + Invalid Username + Invalid Email + New user added successfully + User already exists + + + Edit Issue #%1$s + Issue updated + + + New Release + Tag Name + Title + Content + Mark as Pre-Release + Select Branch + Draft + Tag name is empty + Title is empty + New release created + Do you really want to delete this release? + Release deleted + + OTP code should be numbers + OTP Code (Optional) + Enter otp code if 2FA is enabled + Open in Browser + Stargazers + Watchers + No website found + No description found + No location found + Star + Watcher + Source code (ZIP) + Source code (TAR.GZ) + + File Name + New Branch Name + File Content + Create New File + with folder: app/test.md + Commit Message + Invalid branch name, may only contain –, a–z, 0–9 + Commit message is too long + New file created + Select or create a branch + Fields like filename, content and commit message are required + Leave blank to push to the default branch + New branch name cannot be empty if current branch is not selected + Filter + Branches + Markdown + Copy Issue URL + URL copied to clipboard + Comment copied to clipboard + SHA copied to clipboard + %1$d\uFF05 completed + + Sorry this file cannot be viewed as API returned an error + Files of this type cannot be edited + Not supported + + OK + Done + Cancel + Something went wrong, please try again + This request needs higher version than the one installed. Please upgrade your instance to the latest version. + 🌟 Nothing in here 🌟 + Add + Remove + You are not authorized to perform this action. + Menu + Edit + Delete + Copy + Quote Reply + edited + Save + Website + Location + Max 255 characters + All fields are required + Continue + Token + View in Browser + Open + Closed + We cannot reach the server at the moment, please check your server status and try again + Copy URL + Hold on ☕ + File + Issue + Label + Release + Pull Request + Collaborator + Unstar + Watch + Unwatch + Share + Repository + Team + Organization + Add / Remove + Download + Reopen + Open in Browser + Delete %s + Reset + BETA + None + main + License + + Explore users + Explore issues + Explore repositories + Repository added to starred list + Repository removed from starred list + Repository added to watch list + Repository removed from watch list + Drafts + Unsupported old version(%1$s) of Gitea detected. Please update to latest stable version. If you continue, some features may not work. + New Gitea version detected! Please UPDATE GitNex! + No Gitea detected! + Unsupported Version of Gitea + Basic Auth + Instance has returned an error - Unauthorized. Check your credentials and try again + Token is required + Deleted Fork + Edit Pull Request #%1$s + Pull Request updated + %1$s Files Changed + %1$s File Changed + Update Pull Request + Show Changed Files + Merge Pull Request + Branch deleted successfully + Could not delete branch + Branch does not exist + Merge + Delete branch after merge + Merge may fail if you are not authorized to merge this Pull Request. + Disabled Merge button means that there are conflicts OR other things to fix before Merge + This branch belong to a forked repository + Merge comment + Pull Request was merged successfully + Pull Request is not available for merge + Merge Pull Request + Rebase and Merge + Rebase and Merge (--no-ff) + Squash and Merge + Merge Strategy + Select merge strategy + Not allowed to merge [Reason: Does not have enough approvals] + Delete Branch + Please wait for the file to load to memory + File saved successfully + This file type/size is not supported in file viewer. You can download it from the menu. + Delete This File + Edit This File + File is set for deletion by branch %1$s + Edit %1$s + File is modified by branch %1$s + Size + Share Issue + Share Repository + Create Repository + Commits + %1$s authored and %2$s committed %3$s]]> + %1$s committed %2$s]]> + View Commits + + Certificate Verification + Accept Unknown Certificate? + The server certificate is not signed by a known Certificate Authority + The server certificate is expired. + Accept Mismatching Server Name? + Server could not authenticate as \"%s\". The certificate is only valid for: + Do you want to connect anyway? + Certificate details: + Trust + Abort + Subscribed successfully + You have already subscribed + Subscription failed + Unsubscribed successfully + You have already Unsubscribed + Un-Subscription failed + Close Milestone + Open Milestone + Milestone status updated successfully + Crash Reports + Enable Crash Reports + GitNex has stopped :( + Crash reports + It is encouraged to open an issue at the project repository with how to reproduce this bug. It is easier to debug and fix the problem that way.\n\nTap the OK button to send the crash report by email instead. Additional content could be added in the email.\nThank you! + Please sign in again + Due to some major changes regarding the internal functioning of the app, we require you to login again. These changes allow us to make the app more flexible in the future.\n\nThank you for your patience and sorry for the inconvenience. + Delete All Drafts + No drafts found + Drafts deleted successfully + Draft deleted successfully + This will delete all the drafts for this account. \n\nProceed with deletion? + Draft was saved automatically. + Counter is reset successfully + Do you want to reset counter for repository %s? + This will reset all the counters for this account repositories. + Themes, fonts, badges, translation + Biometric authentication, SSL certificates, cache + Languages + Crash reports + If you like GitNex you can give it a thumbs up + App version, build, user instance version + Syntax color, indentation + Archived + This repo is archived. You can view files, but cannot push or open issues/pull-requests. + Account deleted successfully + Remove Account + Are you sure you want to remove this account from the app?\n\nThis will remove all the data related to this account on the app only. + New Account + Add Account + Account already exists in the app + Account added successfully + Switched to account : %1$s@%2$s + + Notifications + All caught up 🚀 + Notifications Polling Delay + 15 Minutes + 30 Minutes + 45 Minutes + 1 Hour + Select Polling Delay + Choose a minutely delay in which GitNex tries to poll new notifications + Mark Read + Mark Unread + Pin + Successfully marked all notifications as read + Polling delay + Enable Notifications + Enable Light + Enable Vibration + Choose Color + New messages for %s + You\'ve got %d new notifications. + Notifications + This is the main notification channel of GitNex. + + You have %s new notification + You have %s new notifications + + To receive notifications, you must enable notifications for GitNex. Tap Open to access your phone settings and enable notifications. + Read + Unread + Repository Settings + Edit Properties + Delete Repository + Be careful, this operation CANNOT be undone! + Set as Template + Enable Issues + External Issue Tracker Url + Enable Wiki + External Wiki Url + Enable Pull Requests + Enable Time Tracker + Enable Merge Commits + Enable Rebase + Enable Squash and Merge + Enable Rebase with Merge Commits (——no-ff) + Repository properties updated successfully + Things to know before deletion:\n\n- This operation CANNOT be undone.\n- This operation will permanently delete the repository including code, issues, comments, wiki data and collaborator settings.\n\nEnter the repository name as confirmation + Repository name does not match + Repository deleted successfully + Transfer Ownership + Transfer this repository to a user or to an organization for which you have administrator rights + Things to know before transfer:\n\n- You will lose access to the repository if you transfer it to an individual user.\n- You will keep access to the repository if you transfer it to an organization that you (co-)own.\n\nEnter the repository name as confirmation + Perform Transfer + New Owner + Repository transferred successfully + New owner is required + There is a problem with the owner name. Make sure that the new owner exists + Filter Repositories + Search ONLY in Topic + Search in Description + Only Archived Repositories + Only Private Repositories + Search in Template Repositories + Merge Into + Pull From + These branches are equal. There is no need to create a pull request + Merge into branch is required + Pull from branch is required + Title is required + Pull Request created successfully + A pull request between these branches already exists + Pull Request closed + Pull Request reopened + Pull Request Info + It seems that the account for URI %1$s does not exist in the app. You can add one by tapping on the Add New Account button. + Go to App + GitNex cannot handle the requested resource. You can open an issue at the project repository as an improvement, providing details of the work. Just launch a default screen for now from the buttons below; it can be changed from settings. + Biometric Authentication + Unlock using your biometric credentials + No biometric features available on this device + Biometric features are currently unavailable + Enroll biometric from phone settings + Login ID \'%s\' copied to clipboard + + Download in progress + Downloading %s + Download successful + Downloaded %s + Download failed + Couldn\'t download %s + Download manager + Indicates the progress of ongoing downloads + Updated %s + Joined + Follow + Unfollow + Unfollowed @%s + You now follow @%s + Couldn\'t unfollow user + Couldn\'t follow user + The pull request conflicts with the base branch. Please resolve the conflicts and try again. + Pull Request updated successfully + Merge + Rebase + Select Update Strategy + Avatar + Tags + Releases/Tags + Create Tag Only + Tag created + Use as reference + Do you really want to delete this tag? + Tag deleted + A tag attached to a release cannot be deleted directly + Use Custom Tabs + No application found to open this link. SSH URLs and URLs with another prefix the http:// or https:// are not supported by most browser + Log in again + %s \u25CF not logged in + Follow system (Light/Dark) + Follow system (Light/Pitch Black) + Dynamic colors - Follow system (Light/Dark) + Codeberg (Dark) + Fork of: %s + Adopt + Adopted repository %s + Unadopted Repositories + - Adopt will add repository %1$s to organization/user %2$s.\n- Delete will remove it from the system. + Commits + + Wiki + %1$s updated %2$s]]> + Do you really want to delete %s? + Wiki page deleted successfully + Page name and page content can\'t be empty + Create Wiki Page + Wiki page updated successfully + Wiki page created successfully + + Open in Code Editor + + New Note + Edit Note + Start taking your notes here + Created %s + Updated %s + Do you really want to delete this note? + + Note deleted successfully + Notes deleted successfully + + This will delete all of your notes. This action cannot be undone. + + commit + commit + %1$s added %2$s %3$s + + %1$s added the | label %2$s + + %1$s removed the | label %2$s + %1$s removed their assignment %2$s + %1$s was unassigned by %2$s %3$s + %1$s self-assigned this %2$s + %1$s was assigned by %2$s %3$s + %1$s added this to the %2$s milestone %3$s + %1$s removed this from the %2$s milestone %3$s + %1$s added this to a deleted milestone %2$s + %1$s closed this issue %2$s + %1$s reopened this issue %2$s + %1$s reopened this pull request %2$s + %1$s closed this pull request %2$s + %1$s merged this pull request %2$s + %3$s %4$s]]> + %1$s requested review from %2$s %3$s + %1$s changed title from %2$s to %3$s %4$s + %1$s locked as %2$s and limited conversation to collaborators %3$s + %1$s unlocked this conversation %2$s + %1$s added a new dependency #%2$d %3$s + %1$s removed a dependency #%2$d %3$s + %1$s added this to a project %2$s + %1$s removed this from a project %2$s + %1$s added the due date %2$s %3$s + %1$s modified the due date to %2$s from %3$s %4$s + %1$s removed the due date %2$s %3$s + %1$s changed target branch from %2$s to %3$s %4$s + %1$s deleted branch %2$s %3$s + %1$s started working %2$s + %1$s stopped time tracking %2$s + %1$s cancelled time tracking %2$s + %1$s added spent time %2$s %3$s + %1$s deleted spent time %2$s %3$s + %1$s added reference %2$s %3$s + %1$s referenced this issue in #%2$d %3$s + %1$s referenced this pull request in #%2$d %3$s + %3$s %4$s]]> + %1$s left a comment: %2$s %3$s + Statuses + This status has no linked target URL. + Starred Repos + Language Statistics + Dashboard + created repository + renamed repository from %1$s to + starred + transferred repository %1$s to + created branch %1$s in + pushed to %1$s at + opened issue + commented on issue + closed issue + reopened issue + created pull request + closed pull request + reopened pull request + merged pull request + approved + suggested changes for + commented on pull request + automatically merged pull request + deleted branch %1$s at + pushed tag %1$s to + deleted tag %1$s from + released %1$s at + synced commits to %1$s at + synced new reference %1$s to + synced and deleted reference %1$s at + Attachment + Attachments + An issue was created but cannot process attachments at this time. Check the server logs for more details. + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es-rES/strings.xml similarity index 100% rename from app/src/main/res/values-es/strings.xml rename to app/src/main/res/values-es-rES/strings.xml diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa-rIR/strings.xml similarity index 100% rename from app/src/main/res/values-fa/strings.xml rename to app/src/main/res/values-fa-rIR/strings.xml diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi-rFI/strings.xml similarity index 100% rename from app/src/main/res/values-fi/strings.xml rename to app/src/main/res/values-fi-rFI/strings.xml diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr-rFR/strings.xml similarity index 100% rename from app/src/main/res/values-fr/strings.xml rename to app/src/main/res/values-fr-rFR/strings.xml diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it-rIT/strings.xml similarity index 100% rename from app/src/main/res/values-it/strings.xml rename to app/src/main/res/values-it-rIT/strings.xml diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml similarity index 100% rename from app/src/main/res/values-ja/strings.xml rename to app/src/main/res/values-ja-rJP/strings.xml diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml similarity index 100% rename from app/src/main/res/values-ko/strings.xml rename to app/src/main/res/values-ko-rKR/strings.xml diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv-rLV/strings.xml similarity index 100% rename from app/src/main/res/values-lv/strings.xml rename to app/src/main/res/values-lv-rLV/strings.xml diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl-rNL/strings.xml similarity index 100% rename from app/src/main/res/values-nl/strings.xml rename to app/src/main/res/values-nl-rNL/strings.xml diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl-rPL/strings.xml similarity index 100% rename from app/src/main/res/values-pl/strings.xml rename to app/src/main/res/values-pl-rPL/strings.xml diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml similarity index 100% rename from app/src/main/res/values-pt/strings.xml rename to app/src/main/res/values-pt-rBR/strings.xml diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru-rRU/strings.xml similarity index 100% rename from app/src/main/res/values-ru/strings.xml rename to app/src/main/res/values-ru-rRU/strings.xml diff --git a/app/src/main/res/values-si/strings.xml b/app/src/main/res/values-si-rLK/strings.xml similarity index 100% rename from app/src/main/res/values-si/strings.xml rename to app/src/main/res/values-si-rLK/strings.xml diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml similarity index 100% rename from app/src/main/res/values-sk/strings.xml rename to app/src/main/res/values-sk-rSK/strings.xml diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr-rRS/strings.xml similarity index 100% rename from app/src/main/res/values-sr/strings.xml rename to app/src/main/res/values-sr-rRS/strings.xml diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr-rTR/strings.xml similarity index 100% rename from app/src/main/res/values-tr/strings.xml rename to app/src/main/res/values-tr-rTR/strings.xml diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk-rUA/strings.xml similarity index 100% rename from app/src/main/res/values-uk/strings.xml rename to app/src/main/res/values-uk-rUA/strings.xml diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml similarity index 100% rename from app/src/main/res/values-zh/strings.xml rename to app/src/main/res/values-zh-rCN/strings.xml diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 00000000..7086484e --- /dev/null +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,773 @@ + + + + 我的倉儲 + 已按讚 + 倉儲列表 + 個人檔案 + 設定 + 組織 + 關於 + 五星好評! + 登出 + Instance Administration + 我的議題 + 最常瀏覽的倉儲 + Notes + 帳號設定 + Watched Repositories + + + 新增倉儲 + 議題 + 新增組織 + 新增里程碑 + 新增議題 + 新增標籤 + 鳴謝 + 選擇分支 + 更新標籤 + 已按讚 + 新增團隊 + 新增電子郵件地址 + 新增檔案 + 探索 + Administration + 新增合併請求 + Users + 新增倉儲 + + Demo repo + Demo description + Demo organization + Create + 更新 + 倉儲名稱 + 倉儲描述 + Private + Owner + 議題標籤 + Make repository a template + 組織名稱 + Organization Description + %1$s - %2$s + 使用者名稱 + 密碼 + 登入 + 執行個體網址 + Open Navigation Drawer + Close Navigation Drawer + Protocol + 1- Choose the correct protocol(https or http). \n2- Enter instance url e.g: try.gitea.io. \n3- If you have enabled 2FA for your account, enter the code in the OTP Code field. \n4- For HTTP basic auth use USERNAME@DOMAIN.COM in the URL field. + Couldn\'t connect to host. Please check your URL or port for any errors + It is not recommended to use HTTP protocol unless you are testing on local network + Malformed JSON was received. Server response was not successful + Instance URL is required + Username is required + Password is required + Protocol is required + Enter URL without http or https. Example: codeberg.org + Cannot access network, please check your Internet connection + Repository name is empty + Repository name is not valid. [a–z A–Z 0–9 – _] + Repository name is reserved + Repository name contains reserved keywords + Repository description exceeds the max 255 characters limit + Repository created successfully + Repository of this name already exists under selected Owner + Select owner for the repository + The default branch must not be empty + Organization name is empty + Organization name is not valid, [a–z A–Z 0–9 – _] + Organization description exceeds the max 255 characters limit + Organization created successfully + Organization already exists + %1$s addition(s) and %2$s deletion(s) + Processing + Search + Close + Add + Org + Repo + Pri + Remove + Instance has returned an error. Code %d + Details + Files + Milestones + Releases + Branches + Collaborators + Pull Requests + Pull Request + Size + Default Branch + SSH URL + Clone URL + Repo URL + Forks + Created + Last Updated + More Information + at + Milestone %1$s + Due on %1$s + Assigned to: %1$s + Assigned to Me + Comment + Please write your comment + Comment posted + This function will be removed in the future + Image + Commit author: %1$s + Downloads + Published by @%1$s + Release notes are not provided by the publisher. + Title + Description + Due Date + Milestone title is empty + Milestone description exceeds the max 255 characters limit + Milestone created successfully + Please choose due date + No due date + No description + %1$d Open + %1$d Closed + Select Milestone + Select Assignees + Select Labels + Title + Assignees + Description + Due Date + Milestone + Labels + Issue title is empty + Issue description is empty + New issue created successfully + No milestone + No assignees found + + Translation + System + Security + Delete Trusted Certificates + Delete Trusted Certificates? + Are you sure to delete any manually trusted certificate or hostname? \n\nYou will also be logged out. + Settings saved + Language + English + Appearance + Choose Language + Light Theme Switch Time + Dark Theme Switch Time + Choose Time Format + Translate GitNex via Crowdin + Code Block Color + Code Block Color Selector + Home Screen + My Repositories + Select Home Screen + Font + Choose Font + Select App Theme + Theme + Counter Badges + Source Code Theme + Data Cache Size + Data Cache Size + Images Cache Size + Images Cache Size + Clear Cache + Clear Cache? + This will delete all the cache data including files and images.\n\nProceed with deletion? + Drafts + Comments draft + Enable Drafts Deletion + Delete comment draft when comment is posted + General + Home screen, drafts, crash reports + Default Link Handler + Choose what screen should be loaded if the app cannot handle external links. It will redirect you automatically. + Select Default Link Handler Screen + Biometric Support + Labels With Text Support + Enabling this will show labels with text in issues and pr lists, default are color dots + Syntax Highlighting Color + Indentation + Tabs Width + System Default Font + Tabs Animation + Fade Out + Zoom Out + + No more data available + New Label + Repo Menu + Label Name + Label Color + Label name is empty + Label name is not valid + Label created + Label updated + Desc + Label deleted + Select a branch for release + Authorization Error + It seems that the Access Token is revoked OR your are not allowed to see these contents.\n\nIn case of revoked Token, please logout and login again + Do you really want to delete this label? + + Teams + Members + Team name + Team desc + Permissions + • Members of this team do not have any permissions. + • Members of this team can view team repositories. + • Members of this team can view and push to team repositories. + • Members of this team can push to and from team repositories and add collaborators. + • Members of this team have owner permissions. + show all + Org members + Organization team members + Remove %s + Add %s + Do you want to add this user to the team? + Do you want to remove this user from the team? + Member added to the team successfully + Member removed from the team successfully + Repository added to the team successfully + Repository removed from the team successfully + Add repository %1$s to organization %2$s team %3$s + Remove repository %1$s from team %2$s + Add / Remove Member + + + Team Name + Description + Permission + Access Controls + Members can view and clone team repositories + Members can read and push to team repositories + Members can pull and push to team repositories and add collaborators to them + Please enter team name + Team name should contain only alphanumeric, dash (-), underscore (_) and dot (.) characters + Please select permission + Team description have illegal characters + Team description have more than 100 characters + Team created successfully + + + Edit Comment + Comment updated + Share Comment + Comment deleted successfully + Copy Comment + + + Search users + Username + Remove %s? + Do you want to remove this user from the repository? + User removed from the repository. + User added to the repository. + + + Followers + Following + + + Emails + Email Address + New email added successfully + Email address is empty + Email address is not valid + Email address is already in use + Primary + SSH Keys + + + Add / Remove Labels + Labels updated + Close Issue + Edit Issue + Reopen Issue + Issue closed + Issue reopened + Add / Remove Assignees + Assignees updated + Subscribe + Unsubscribe + + Repository Meta + + New User + System Users + Admin + Cron Tasks + Schedule + Next Run + Last Run + Executions + Task %1$s is initiated successfully + + + Full Name + Email + Username + Password + Invalid Full Name + Invalid Username + Invalid Email + New user added successfully + User already exists + + + Edit Issue #%1$s + Issue updated + + + New Release + Tag Name + Title + Content + Mark as Pre-Release + Select Branch + Draft + Tag name is empty + Title is empty + New release created + Do you really want to delete this release? + Release deleted + + OTP code should be numbers + OTP Code (Optional) + Enter otp code if 2FA is enabled + Open in Browser + Stargazers + Watchers + No website found + No description found + No location found + Star + Watcher + Source code (ZIP) + Source code (TAR.GZ) + + File Name + New Branch Name + File Content + Create New File + with folder: app/test.md + Commit Message + Invalid branch name, may only contain –, a–z, 0–9 + Commit message is too long + New file created + Select or create a branch + Fields like filename, content and commit message are required + Leave blank to push to the default branch + New branch name cannot be empty if current branch is not selected + Filter + Branches + Markdown + Copy Issue URL + URL copied to clipboard + Comment copied to clipboard + SHA copied to clipboard + %1$d\uFF05 completed + + Sorry this file cannot be viewed as API returned an error + Files of this type cannot be edited + Not supported + + OK + Done + Cancel + Something went wrong, please try again + This request needs higher version than the one installed. Please upgrade your instance to the latest version. + 🌟 Nothing in here 🌟 + Add + Remove + You are not authorized to perform this action. + Menu + Edit + Delete + Copy + Quote Reply + edited + Save + Website + Location + Max 255 characters + All fields are required + Continue + Token + View in Browser + Open + Closed + We cannot reach the server at the moment, please check your server status and try again + Copy URL + Hold on ☕ + File + Issue + Label + Release + Pull Request + Collaborator + Unstar + Watch + Unwatch + Share + Repository + Team + Organization + Add / Remove + Download + Reopen + Open in Browser + Delete %s + Reset + BETA + None + main + License + + Explore users + Explore issues + Explore repositories + Repository added to starred list + Repository removed from starred list + Repository added to watch list + Repository removed from watch list + Drafts + Unsupported old version(%1$s) of Gitea detected. Please update to latest stable version. If you continue, some features may not work. + New Gitea version detected! Please UPDATE GitNex! + No Gitea detected! + Unsupported Version of Gitea + Basic Auth + Instance has returned an error - Unauthorized. Check your credentials and try again + Token is required + Deleted Fork + Edit Pull Request #%1$s + Pull Request updated + %1$s Files Changed + %1$s File Changed + Update Pull Request + Show Changed Files + Merge Pull Request + Branch deleted successfully + Could not delete branch + Branch does not exist + Merge + Delete branch after merge + Merge may fail if you are not authorized to merge this Pull Request. + Disabled Merge button means that there are conflicts OR other things to fix before Merge + This branch belong to a forked repository + Merge comment + Pull Request was merged successfully + Pull Request is not available for merge + Merge Pull Request + Rebase and Merge + Rebase and Merge (--no-ff) + Squash and Merge + Merge Strategy + Select merge strategy + Not allowed to merge [Reason: Does not have enough approvals] + Delete Branch + Please wait for the file to load to memory + File saved successfully + This file type/size is not supported in file viewer. You can download it from the menu. + Delete This File + Edit This File + File is set for deletion by branch %1$s + Edit %1$s + File is modified by branch %1$s + Size + Share Issue + Share Repository + Create Repository + Commits + %1$s authored and %2$s committed %3$s]]> + %1$s committed %2$s]]> + View Commits + + Certificate Verification + Accept Unknown Certificate? + The server certificate is not signed by a known Certificate Authority + The server certificate is expired. + Accept Mismatching Server Name? + Server could not authenticate as \"%s\". The certificate is only valid for: + Do you want to connect anyway? + Certificate details: + Trust + Abort + Subscribed successfully + You have already subscribed + Subscription failed + Unsubscribed successfully + You have already Unsubscribed + Un-Subscription failed + Close Milestone + Open Milestone + Milestone status updated successfully + Crash Reports + Enable Crash Reports + GitNex has stopped :( + Crash reports + It is encouraged to open an issue at the project repository with how to reproduce this bug. It is easier to debug and fix the problem that way.\n\nTap the OK button to send the crash report by email instead. Additional content could be added in the email.\nThank you! + Please sign in again + Due to some major changes regarding the internal functioning of the app, we require you to login again. These changes allow us to make the app more flexible in the future.\n\nThank you for your patience and sorry for the inconvenience. + Delete All Drafts + No drafts found + Drafts deleted successfully + Draft deleted successfully + This will delete all the drafts for this account. \n\nProceed with deletion? + Draft was saved automatically. + Counter is reset successfully + Do you want to reset counter for repository %s? + This will reset all the counters for this account repositories. + Themes, fonts, badges, translation + Biometric authentication, SSL certificates, cache + Languages + Crash reports + 如果你也喜歡 GitNext,歡迎五星好評! + App version, build, user instance version + Syntax color, indentation + Archived + This repo is archived. You can view files, but cannot push or open issues/pull-requests. + Account deleted successfully + Remove Account + Are you sure you want to remove this account from the app?\n\nThis will remove all the data related to this account on the app only. + New Account + Add Account + Account already exists in the app + Account added successfully + Switched to account : %1$s@%2$s + + Notifications + All caught up 🚀 + Notifications Polling Delay + 15 Minutes + 30 Minutes + 45 Minutes + 1 Hour + Select Polling Delay + Choose a minutely delay in which GitNex tries to poll new notifications + Mark Read + Mark Unread + Pin + Successfully marked all notifications as read + Polling delay + Enable Notifications + Enable Light + Enable Vibration + Choose Color + New messages for %s + 您有 %d 則新通知 + Notifications + This is the main notification channel of GitNex. + + You have %s new notifications + + To receive notifications, you must enable notifications for GitNex. Tap Open to access your phone settings and enable notifications. + Read + Unread + Repository Settings + Edit Properties + Delete Repository + Be careful, this operation CANNOT be undone! + Set as Template + Enable Issues + External Issue Tracker Url + Enable Wiki + External Wiki Url + Enable Pull Requests + Enable Time Tracker + Enable Merge Commits + Enable Rebase + Enable Squash and Merge + Enable Rebase with Merge Commits (——no-ff) + Repository properties updated successfully + Things to know before deletion:\n\n- This operation CANNOT be undone.\n- This operation will permanently delete the repository including code, issues, comments, wiki data and collaborator settings.\n\nEnter the repository name as confirmation + Repository name does not match + Repository deleted successfully + Transfer Ownership + Transfer this repository to a user or to an organization for which you have administrator rights + Things to know before transfer:\n\n- You will lose access to the repository if you transfer it to an individual user.\n- You will keep access to the repository if you transfer it to an organization that you (co-)own.\n\nEnter the repository name as confirmation + Perform Transfer + New Owner + Repository transferred successfully + New owner is required + There is a problem with the owner name. Make sure that the new owner exists + Filter Repositories + Search ONLY in Topic + Search in Description + Only Archived Repositories + Only Private Repositories + Search in Template Repositories + Merge Into + Pull From + These branches are equal. There is no need to create a pull request + Merge into branch is required + Pull from branch is required + Title is required + Pull Request created successfully + A pull request between these branches already exists + Pull Request closed + Pull Request reopened + Pull Request Info + It seems that the account for URI %1$s does not exist in the app. You can add one by tapping on the Add New Account button. + Go to App + GitNex cannot handle the requested resource. You can open an issue at the project repository as an improvement, providing details of the work. Just launch a default screen for now from the buttons below; it can be changed from settings. + Biometric Authentication + Unlock using your biometric credentials + No biometric features available on this device + Biometric features are currently unavailable + Enroll biometric from phone settings + Login ID \'%s\' copied to clipboard + + Download in progress + Downloading %s + Download successful + Downloaded %s + Download failed + Couldn\'t download %s + Download manager + Indicates the progress of ongoing downloads + Updated %s + Joined + Follow + Unfollow + Unfollowed @%s + You now follow @%s + Couldn\'t unfollow user + Couldn\'t follow user + The pull request conflicts with the base branch. Please resolve the conflicts and try again. + Pull Request updated successfully + Merge + Rebase + Select Update Strategy + Avatar + Tags + Releases/Tags + Create Tag Only + Tag created + Use as reference + Do you really want to delete this tag? + Tag deleted + A tag attached to a release cannot be deleted directly + Use Custom Tabs + No application found to open this link. SSH URLs and URLs with another prefix the http:// or https:// are not supported by most browser + Log in again + %s \u25CF not logged in + Follow system (Light/Dark) + Follow system (Light/Pitch Black) + Dynamic colors - Follow system (Light/Dark) + Codeberg (Dark) + Fork of: %s + Adopt + Adopted repository %s + Unadopted Repositories + - Adopt will add repository %1$s to organization/user %2$s.\n- Delete will remove it from the system. + Commits + + Wiki + %1$s updated %2$s]]> + Do you really want to delete %s? + Wiki page deleted successfully + Page name and page content can\'t be empty + Create Wiki Page + Wiki page updated successfully + Wiki page created successfully + + Open in Code Editor + + New Note + Edit Note + Start taking your notes here + Created %s + Updated %s + Do you really want to delete this note? + + Notes deleted successfully + + This will delete all of your notes. This action cannot be undone. + + commit + commit + %1$s added %2$s %3$s + + %1$s added the | label %2$s + + %1$s removed the | label %2$s + %1$s removed their assignment %2$s + %1$s was unassigned by %2$s %3$s + %1$s self-assigned this %2$s + %1$s was assigned by %2$s %3$s + %1$s added this to the %2$s milestone %3$s + %1$s removed this from the %2$s milestone %3$s + %1$s added this to a deleted milestone %2$s + %1$s closed this issue %2$s + %1$s reopened this issue %2$s + %1$s reopened this pull request %2$s + %1$s closed this pull request %2$s + %1$s merged this pull request %2$s + %3$s %4$s]]> + %1$s requested review from %2$s %3$s + %1$s changed title from %2$s to %3$s %4$s + %1$s locked as %2$s and limited conversation to collaborators %3$s + %1$s unlocked this conversation %2$s + %1$s added a new dependency #%2$d %3$s + %1$s removed a dependency #%2$d %3$s + %1$s added this to a project %2$s + %1$s removed this from a project %2$s + %1$s added the due date %2$s %3$s + %1$s modified the due date to %2$s from %3$s %4$s + %1$s removed the due date %2$s %3$s + %1$s changed target branch from %2$s to %3$s %4$s + %1$s deleted branch %2$s %3$s + %1$s started working %2$s + %1$s stopped time tracking %2$s + %1$s cancelled time tracking %2$s + %1$s added spent time %2$s %3$s + %1$s deleted spent time %2$s %3$s + %1$s added reference %2$s %3$s + %1$s referenced this issue in #%2$d %3$s + %1$s referenced this pull request in #%2$d %3$s + %3$s %4$s]]> + %1$s left a comment: %2$s %3$s + Statuses + This status has no linked target URL. + Starred Repos + Language Statistics + Dashboard + created repository + renamed repository from %1$s to + starred + transferred repository %1$s to + created branch %1$s in + pushed to %1$s at + opened issue + commented on issue + closed issue + reopened issue + created pull request + closed pull request + reopened pull request + merged pull request + approved + suggested changes for + commented on pull request + automatically merged pull request + deleted branch %1$s at + pushed tag %1$s to + deleted tag %1$s from + released %1$s at + synced commits to %1$s at + synced new reference %1$s to + synced and deleted reference %1$s at + Attachment + Attachments + An issue was created but cannot process attachments at this time. Check the server logs for more details. + diff --git a/app/src/main/res/values/settings.xml b/app/src/main/res/values/settings.xml index b0e188c8..a302c2ee 100644 --- a/app/src/main/res/values/settings.xml +++ b/app/src/main/res/values/settings.xml @@ -20,6 +20,8 @@ tr uk el + eo + zh-TW diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e7d59dd9..f02fe5cb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -237,10 +237,8 @@ Sublime Data Cache Size Data Cache Size - 50 MB Images Cache Size Images Cache Size - 50 MB Clear Cache 0 B Clear Cache? @@ -876,6 +874,7 @@ %1$s referenced this pull request in #%2$d %3$s %3$s %4$s]]> %1$s left a comment: %2$s %3$s + %1$s pinned this %2$s Statuses This status has no linked target URL. diff --git a/crowdin.example.yml b/crowdin.example.yml index 344f2fc1..fc588f19 100644 --- a/crowdin.example.yml +++ b/crowdin.example.yml @@ -5,7 +5,7 @@ preserve_hierarchy: false files: [ { "source": "app/src/main/res/values/strings.xml", - "translation": "app/src/main/res/values-%two_letters_code%/strings.xml", + "translation": "app/src/main/res/values-%android_code%/strings.xml", }, { "source": "fastlane/metadata/android/en-US/short_description.txt",