Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/stefan-niedermann/nextcloud-notes.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Niedermann <info@niedermann.it>2022-08-15 11:22:07 +0300
committerStefan Niedermann <info@niedermann.it>2022-08-15 11:22:07 +0300
commitcfe2a8ccf6129ec12cade2c5e27ed13198a01f15 (patch)
tree0f7e418cfd57e4826924a73a63c415363ef66196
parent0f4c3a0baf772645729607bcd5fe74de8e258ad2 (diff)
⚙️ Support custom file extensions (Notes ≥ 4.5.0)
Signed-off-by: Stefan Niedermann <info@niedermann.it>
-rw-r--r--app/build.gradle2
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/IManageAccountsCallback.java16
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountAdapter.java23
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountViewHolder.java43
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountsActivity.java181
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/shared/model/ApiVersion.java25
-rw-r--r--app/src/test/java/it/niedermann/owncloud/notes/shared/model/ApiVersionTest.java45
-rw-r--r--build.gradle2
-rw-r--r--fastlane/metadata/android/en-US/changelogs/3005001.txt1
9 files changed, 166 insertions, 172 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 68fb851d..b795ef11 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -76,7 +76,7 @@ android {
}
dependencies {
- coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.0'
+ coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.6'
// Nextcloud SSO
implementation 'com.github.nextcloud:Android-SingleSignOn:0.6.1'
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/IManageAccountsCallback.java b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/IManageAccountsCallback.java
new file mode 100644
index 00000000..93b04811
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/IManageAccountsCallback.java
@@ -0,0 +1,16 @@
+package it.niedermann.owncloud.notes.manageaccounts;
+
+import androidx.annotation.NonNull;
+
+import it.niedermann.owncloud.notes.persistence.entity.Account;
+
+public interface IManageAccountsCallback {
+
+ void onSelect(@NonNull Account account);
+
+ void onDelete(@NonNull Account account);
+
+ void onChangeNotesPath(@NonNull Account account);
+
+ void onChangeFileSuffix(@NonNull Account account);
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountAdapter.java
index 19adee12..1c665857 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountAdapter.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountAdapter.java
@@ -21,22 +21,10 @@ public class ManageAccountAdapter extends RecyclerView.Adapter<ManageAccountView
@NonNull
private final List<Account> localAccounts = new ArrayList<>();
@NonNull
- private final Consumer<Account> onAccountClick;
- @NonNull
- private final Consumer<Account> onAccountDelete;
- @NonNull
- Consumer<Account> onChangeNotesPath;
- @NonNull
- Consumer<Account> onChangeFileSuffix;
+ private final IManageAccountsCallback callback;
- public ManageAccountAdapter(@NonNull Consumer<Account> onAccountClick,
- @NonNull Consumer<Account> onAccountDelete,
- @NonNull Consumer<Account> onChangeNotesPath,
- @NonNull Consumer<Account> onChangeFileSuffix) {
- this.onAccountClick = onAccountClick;
- this.onAccountDelete = onAccountDelete;
- this.onChangeNotesPath = onChangeNotesPath;
- this.onChangeFileSuffix = onChangeFileSuffix;
+ public ManageAccountAdapter(@NonNull IManageAccountsCallback callback) {
+ this.callback = callback;
setHasStableIds(true);
}
@@ -54,10 +42,7 @@ public class ManageAccountAdapter extends RecyclerView.Adapter<ManageAccountView
@Override
public void onBindViewHolder(@NonNull ManageAccountViewHolder holder, int position) {
final var localAccount = localAccounts.get(position);
- holder.bind(localAccount, (localAccountClicked) -> {
- setCurrentLocalAccount(localAccountClicked);
- onAccountClick.accept(localAccountClicked);
- }, onAccountDelete, onChangeNotesPath, onChangeFileSuffix, currentLocalAccount != null && currentLocalAccount.getId() == localAccount.getId());
+ holder.bind(localAccount, callback, currentLocalAccount != null && currentLocalAccount.getId() == localAccount.getId());
}
@Override
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountViewHolder.java b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountViewHolder.java
index 3b61851a..26b1e785 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountViewHolder.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountViewHolder.java
@@ -1,30 +1,25 @@
package it.niedermann.owncloud.notes.manageaccounts;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+import static it.niedermann.owncloud.notes.branding.BrandingUtil.applyBrandToLayerDrawable;
+import static it.niedermann.owncloud.notes.shared.util.ApiVersionUtil.getPreferredApiVersion;
+
import android.graphics.drawable.LayerDrawable;
import android.net.Uri;
-import android.view.Menu;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.PopupMenu;
-import androidx.core.util.Consumer;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
-import java.util.stream.Stream;
-
import it.niedermann.nextcloud.sso.glide.SingleSignOnUrl;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.databinding.ItemAccountChooseBinding;
import it.niedermann.owncloud.notes.persistence.entity.Account;
-import it.niedermann.owncloud.notes.shared.model.ApiVersion;
-
-import static android.view.View.GONE;
-import static android.view.View.VISIBLE;
-import static it.niedermann.owncloud.notes.branding.BrandingUtil.applyBrandToLayerDrawable;
-import static it.niedermann.owncloud.notes.shared.util.ApiVersionUtil.getPreferredApiVersion;
public class ManageAccountViewHolder extends RecyclerView.ViewHolder {
@@ -37,10 +32,7 @@ public class ManageAccountViewHolder extends RecyclerView.ViewHolder {
public void bind(
@NonNull Account localAccount,
- @NonNull Consumer<Account> onAccountClick,
- @NonNull Consumer<Account> onAccountDelete,
- @NonNull Consumer<Account> onChangeNotesPath,
- @NonNull Consumer<Account> onChangeFileSuffix,
+ @NonNull IManageAccountsCallback callback,
boolean isCurrentAccount
) {
binding.accountName.setText(localAccount.getUserName());
@@ -50,28 +42,31 @@ public class ManageAccountViewHolder extends RecyclerView.ViewHolder {
.error(R.drawable.ic_account_circle_grey_24dp)
.apply(RequestOptions.circleCropTransform())
.into(binding.accountItemAvatar);
- itemView.setOnClickListener((v) -> onAccountClick.accept(localAccount));
+ itemView.setOnClickListener((v) -> callback.onSelect(localAccount));
binding.accountContextMenu.setVisibility(VISIBLE);
binding.accountContextMenu.setOnClickListener((v) -> {
final var popup = new PopupMenu(itemView.getContext(), v);
popup.inflate(R.menu.menu_account);
+
final var preferredApiVersion = getPreferredApiVersion(localAccount.getApiVersion());
- if (preferredApiVersion != null && !preferredApiVersion.supportsSettings()) {
- final var menu = popup.getMenu();
- Stream.of(
- R.id.notes_path,
- R.id.file_suffix
- ).forEach((i) -> menu.removeItem(menu.findItem(i).getItemId()));
+
+ if (preferredApiVersion == null || !preferredApiVersion.supportsFileSuffixChange()) {
+ popup.getMenu().removeItem(popup.getMenu().findItem(R.id.file_suffix).getItemId());
+ }
+
+ if (preferredApiVersion == null || !preferredApiVersion.supportsNotesPathChange()) {
+ popup.getMenu().removeItem(popup.getMenu().findItem(R.id.notes_path).getItemId());
}
+
popup.setOnMenuItemClickListener(item -> {
if (item.getItemId() == R.id.notes_path) {
- onChangeNotesPath.accept(localAccount);
+ callback.onChangeNotesPath(localAccount);
return true;
} else if (item.getItemId() == R.id.file_suffix) {
- onChangeFileSuffix.accept(localAccount);
+ callback.onChangeFileSuffix(localAccount);
return true;
} else if (item.getItemId() == R.id.delete) {
- onAccountDelete.accept(localAccount);
+ callback.onDelete(localAccount);
return true;
}
return false;
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountsActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountsActivity.java
index b6341f61..8d0c253f 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountsActivity.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountsActivity.java
@@ -1,26 +1,28 @@
package it.niedermann.owncloud.notes.manageaccounts;
+import static it.niedermann.owncloud.notes.shared.util.ApiVersionUtil.getPreferredApiVersion;
+
import android.accounts.NetworkErrorException;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
-import android.widget.Spinner;
import android.widget.Toast;
import androidx.annotation.AttrRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
-import androidx.appcompat.app.AlertDialog;
+import androidx.annotation.StringRes;
import androidx.lifecycle.ViewModelProvider;
import com.nextcloud.android.sso.AccountImporter;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
+import java.util.function.Function;
+
import it.niedermann.owncloud.notes.LockedActivity;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.branding.BrandedAlertDialogBuilder;
@@ -35,11 +37,7 @@ import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
-import static android.os.Build.VERSION.SDK_INT;
-import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
-import static it.niedermann.owncloud.notes.shared.util.ApiVersionUtil.getPreferredApiVersion;
-
-public class ManageAccountsActivity extends LockedActivity {
+public class ManageAccountsActivity extends LockedActivity implements IManageAccountsCallback {
private ActivityManageAccountsBinding binding;
private ManageAccountsViewModel viewModel;
@@ -55,12 +53,7 @@ public class ManageAccountsActivity extends LockedActivity {
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
- adapter = new ManageAccountAdapter(
- this::selectAccount,
- this::deleteAccount,
- this::onChangeNotesPath,
- this::onChangeFileSuffix
- );
+ adapter = new ManageAccountAdapter(this);
binding.accounts.setAdapter(adapter);
viewModel.getAccounts$().observe(this, (accounts) -> {
@@ -69,7 +62,7 @@ public class ManageAccountsActivity extends LockedActivity {
return;
}
this.adapter.setLocalAccounts(accounts);
- viewModel.getCurrentAccount(this, new IResponseCallback<Account>() {
+ viewModel.getCurrentAccount(this, new IResponseCallback<>() {
@Override
public void onSuccess(Account result) {
runOnUiThread(() -> adapter.setCurrentLocalAccount(result));
@@ -84,12 +77,13 @@ public class ManageAccountsActivity extends LockedActivity {
});
}
- private void selectAccount(@NonNull Account accountToSelect) {
+ public void onSelect(@NonNull Account accountToSelect) {
+ adapter.setCurrentLocalAccount(accountToSelect);
viewModel.selectAccount(accountToSelect, this);
}
- private void deleteAccount(@NonNull Account accountToDelete) {
- viewModel.countUnsynchronizedNotes(accountToDelete.getId(), new IResponseCallback<Long>() {
+ public void onDelete(@NonNull Account accountToDelete) {
+ viewModel.countUnsynchronizedNotes(accountToDelete.getId(), new IResponseCallback<>() {
@Override
public void onSuccess(Long unsynchronizedChangesCount) {
runOnUiThread(() -> {
@@ -113,127 +107,76 @@ public class ManageAccountsActivity extends LockedActivity {
});
}
- private void onChangeNotesPath(@NonNull Account localAccount) {
+ public void onChangeNotesPath(@NonNull Account localAccount) {
+ changeAccountSetting(localAccount,
+ R.string.settings_notes_path,
+ R.string.settings_notes_path_description,
+ R.string.settings_notes_path_success,
+ NotesSettings::getNotesPath,
+ property -> new NotesSettings(property, null)
+ );
+ }
+
+ public void onChangeFileSuffix(@NonNull Account localAccount) {
+ changeAccountSetting(localAccount,
+ R.string.settings_file_suffix,
+ R.string.settings_file_suffix_description,
+ R.string.settings_file_suffix_success,
+ NotesSettings::getFileSuffix,
+ property -> new NotesSettings(null, property)
+ );
+ }
+
+ private void changeAccountSetting(@NonNull Account localAccount, @StringRes int title, @StringRes int message, @StringRes int successMessage, @NonNull Function<NotesSettings, String> propertyExtractor, @NonNull Function<String, NotesSettings> settingsFactory) {
final var repository = NotesRepository.getInstance(getApplicationContext());
final var editText = new EditText(this);
final var wrapper = createDialogViewWrapper();
final var dialog = new BrandedAlertDialogBuilder(this)
- .setTitle(R.string.settings_notes_path)
- .setMessage(R.string.settings_notes_path_description)
+ .setTitle(title)
+ .setMessage(message)
.setView(wrapper)
.setNeutralButton(android.R.string.cancel, null)
- .setPositiveButton(R.string.action_edit_save, (v, d) -> new Thread(() -> {
- try {
- final var putSettingsCall = repository.putServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), new NotesSettings(editText.getText().toString(), null), getPreferredApiVersion(localAccount.getApiVersion()));
- putSettingsCall.enqueue(new Callback<>() {
- @Override
- public void onResponse(@NonNull Call<NotesSettings> call, @NonNull Response<NotesSettings> response) {
- final var body = response.body();
- if (response.isSuccessful() && body != null) {
- runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, getString(R.string.settings_notes_path_success, body.getNotesPath()), Toast.LENGTH_LONG).show());
- } else {
- runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, getString(R.string.http_status_code, response.code()), Toast.LENGTH_LONG).show());
+ .setPositiveButton(R.string.action_edit_save, (v, d) -> {
+ final var property = editText.getText().toString();
+ new Thread(() -> {
+ try {
+ final var putSettingsCall = repository.putServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), settingsFactory.apply(property), getPreferredApiVersion(localAccount.getApiVersion()));
+ putSettingsCall.enqueue(new Callback<>() {
+ @Override
+ public void onResponse(@NonNull Call<NotesSettings> call, @NonNull Response<NotesSettings> response) {
+ final var body = response.body();
+ if (response.isSuccessful() && body != null) {
+ runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, getString(successMessage, propertyExtractor.apply(body)), Toast.LENGTH_LONG).show());
+ } else {
+ runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, getString(R.string.http_status_code, response.code()), Toast.LENGTH_LONG).show());
+ }
}
- }
- @Override
- public void onFailure(@NonNull Call<NotesSettings> call, @NonNull Throwable t) {
- runOnUiThread(() -> ExceptionDialogFragment.newInstance(t).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()));
- }
- });
- } catch (NextcloudFilesAppAccountNotFoundException e) {
- ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
- }
- }).start())
- .show();
- try {
- repository.getServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), getPreferredApiVersion(localAccount.getApiVersion()))
- .enqueue(new Callback<>() {
- @Override
- public void onResponse(@NonNull Call<NotesSettings> call, @NonNull Response<NotesSettings> response) {
- runOnUiThread(() -> {
- final var body = response.body();
- if (response.isSuccessful() && body != null) {
- wrapper.removeAllViews();
- final var editText = new EditText(ManageAccountsActivity.this);
- editText.setText(body.getNotesPath());
- wrapper.addView(editText);
- } else {
- dialog.dismiss();
- ExceptionDialogFragment.newInstance(new NetworkErrorException(getString(R.string.http_status_code, response.code()))).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
+ @Override
+ public void onFailure(@NonNull Call<NotesSettings> call, @NonNull Throwable t) {
+ runOnUiThread(() -> ExceptionDialogFragment.newInstance(t).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()));
}
});
+ } catch (NextcloudFilesAppAccountNotFoundException e) {
+ ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
}
-
- @Override
- public void onFailure(@NonNull Call<NotesSettings> call, @NonNull Throwable t) {
- runOnUiThread(() -> {
- dialog.dismiss();
- ExceptionDialogFragment.newInstance(t).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
- });
- }
- });
- } catch (NextcloudFilesAppAccountNotFoundException e) {
- dialog.dismiss();
- ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
- }
- }
-
- private void onChangeFileSuffix(@NonNull Account localAccount) {
- final var repository = NotesRepository.getInstance(getApplicationContext());
- final var spinner = new Spinner(this);
- final var wrapper = createDialogViewWrapper();
- final var adapter = ArrayAdapter.createFromResource(this, R.array.settings_file_suffixes, android.R.layout.simple_spinner_item);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- spinner.setAdapter(adapter);
- final var dialog = new BrandedAlertDialogBuilder(this)
- .setTitle(R.string.settings_file_suffix)
- .setMessage(R.string.settings_file_suffix_description)
- .setView(wrapper)
- .setNeutralButton(android.R.string.cancel, null)
- .setPositiveButton(R.string.action_edit_save, (v, d) -> new Thread(() -> {
- try {
- final Call<NotesSettings> putSettingsCall = repository.putServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), new NotesSettings(null, spinner.getSelectedItem().toString()), getPreferredApiVersion(localAccount.getApiVersion()));
- putSettingsCall.enqueue(new Callback<>() {
- @Override
- public void onResponse(@NonNull Call<NotesSettings> call, @NonNull Response<NotesSettings> response) {
- final var body = response.body();
- if (response.isSuccessful() && body != null) {
- runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, getString(R.string.settings_file_suffix_success, body.getNotesPath()), Toast.LENGTH_LONG).show());
- } else {
- runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, getString(R.string.http_status_code, response.code()), Toast.LENGTH_LONG).show());
- }
- }
-
- @Override
- public void onFailure(@NonNull Call<NotesSettings> call, @NonNull Throwable t) {
- runOnUiThread(() -> ExceptionDialogFragment.newInstance(t).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()));
- }
- });
- } catch (NextcloudFilesAppAccountNotFoundException e) {
- runOnUiThread(() -> ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()));
- }
- }).start())
+ }).start();
+ })
.show();
try {
repository.getServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), getPreferredApiVersion(localAccount.getApiVersion()))
.enqueue(new Callback<>() {
@Override
public void onResponse(@NonNull Call<NotesSettings> call, @NonNull Response<NotesSettings> response) {
- final NotesSettings body = response.body();
runOnUiThread(() -> {
+ final var body = response.body();
if (response.isSuccessful() && body != null) {
- for (int i = 0; i < adapter.getCount(); i++) {
- if (adapter.getItem(i).equals(body.getFileSuffix())) {
- spinner.setSelection(i);
- break;
- }
- }
wrapper.removeAllViews();
- wrapper.addView(spinner);
+ editText.setText(propertyExtractor.apply(body));
+ wrapper.addView(editText);
} else {
dialog.dismiss();
- ExceptionDialogFragment.newInstance(new Exception(getString(R.string.http_status_code, response.code()))).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
+ ExceptionDialogFragment.newInstance(new NetworkErrorException(getString(R.string.http_status_code, response.code()))).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
}
});
}
@@ -258,9 +201,7 @@ public class ManageAccountsActivity extends LockedActivity {
progressBar.setIndeterminate(true);
final var wrapper = new FrameLayout(this);
final int paddingVertical = getResources().getDimensionPixelSize(R.dimen.spacer_1x);
- final int paddingHorizontal = SDK_INT >= LOLLIPOP_MR1
- ? getDimensionFromAttribute(android.R.attr.dialogPreferredPadding)
- : getResources().getDimensionPixelSize(R.dimen.spacer_2x);
+ final int paddingHorizontal = getDimensionFromAttribute(android.R.attr.dialogPreferredPadding);
wrapper.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical);
wrapper.addView(progressBar);
return wrapper;
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ApiVersion.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ApiVersion.java
index 7ac09d66..f0dcf0ad 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ApiVersion.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ApiVersion.java
@@ -4,16 +4,16 @@ package it.niedermann.owncloud.notes.shared.model;
import androidx.annotation.NonNull;
import java.util.Objects;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
@SuppressWarnings("WeakerAccess")
public class ApiVersion implements Comparable<ApiVersion> {
private static final Pattern NUMBER_EXTRACTION_PATTERN = Pattern.compile("[0-9]+");
- private static final ApiVersion VERSION_1_2 = new ApiVersion("1.2", 1, 2);
- public static final ApiVersion API_VERSION_0_2 = new ApiVersion(0, 2);
- public static final ApiVersion API_VERSION_1_0 = new ApiVersion(1, 0);
+ public static final ApiVersion API_VERSION_0_2 = new ApiVersion("0.2", 0, 2);
+ public static final ApiVersion API_VERSION_1_0 = new ApiVersion("1.0", 1, 0);
+ public static final ApiVersion API_VERSION_1_2 = new ApiVersion("1.2", 1, 2);
+ public static final ApiVersion API_VERSION_1_3 = new ApiVersion("1.3", 1, 3);
public static final ApiVersion[] SUPPORTED_API_VERSIONS = new ApiVersion[]{
API_VERSION_1_0,
@@ -45,7 +45,7 @@ public class ApiVersion implements Comparable<ApiVersion> {
public static ApiVersion of(String versionString) {
int major = 0, minor = 0;
if (versionString != null) {
- String[] split = versionString.split("\\.");
+ final String[] split = versionString.split("\\.");
if (split.length > 0) {
major = extractNumber(split[0]);
if (split.length > 1) {
@@ -80,8 +80,19 @@ public class ApiVersion implements Comparable<ApiVersion> {
return 0;
}
- public boolean supportsSettings() {
- return getMajor() >= 1 && getMinor() >= 2;
+ /**
+ * While setting the file suffix to <code>.txt</code> or <code>.md</code> was possible starting
+ * with {@link #API_VERSION_1_2}, we will only support this feature with {@link #API_VERSION_1_3}
+ * because it allows us to set any value and skip client side validations.
+ *
+ * @see <a href="https://github.com/nextcloud/notes/blob/master/docs/api/v1.md#settings">Settings API</a>
+ */
+ public boolean supportsFileSuffixChange() {
+ return getMajor() >= API_VERSION_1_3.getMajor() && getMinor() >= API_VERSION_1_3.getMinor();
+ }
+
+ public boolean supportsNotesPathChange() {
+ return getMajor() >= API_VERSION_1_2.getMajor() && getMinor() >= API_VERSION_1_2.getMinor();
}
/**
diff --git a/app/src/test/java/it/niedermann/owncloud/notes/shared/model/ApiVersionTest.java b/app/src/test/java/it/niedermann/owncloud/notes/shared/model/ApiVersionTest.java
new file mode 100644
index 00000000..5b3b6f5b
--- /dev/null
+++ b/app/src/test/java/it/niedermann/owncloud/notes/shared/model/ApiVersionTest.java
@@ -0,0 +1,45 @@
+package it.niedermann.owncloud.notes.shared.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class ApiVersionTest {
+
+ @Test
+ public void shouldOnlyCompareMajorApiVersions() {
+ final var apiVersion = new ApiVersion("1.0", 1, 0);
+
+ assertEquals(1, apiVersion.compareTo(ApiVersion.API_VERSION_0_2));
+ assertEquals(0, apiVersion.compareTo(ApiVersion.API_VERSION_1_0));
+ assertEquals(0, apiVersion.compareTo(ApiVersion.API_VERSION_1_2));
+ }
+
+ @Test
+ public void shouldOnlyEqualMajorApiVersions() {
+ final var apiVersion = new ApiVersion("1.0", 1, 0);
+
+ assertNotEquals(apiVersion, ApiVersion.API_VERSION_0_2);
+ assertEquals(apiVersion, ApiVersion.API_VERSION_1_0);
+ assertEquals(apiVersion, ApiVersion.API_VERSION_1_2);
+ }
+
+ @Test
+ public void shouldSupportFileSuffixChangesWithApi1_3andAbove() {
+ assertFalse(ApiVersion.API_VERSION_0_2.supportsFileSuffixChange());
+ assertFalse(ApiVersion.API_VERSION_1_0.supportsFileSuffixChange());
+ assertFalse(ApiVersion.API_VERSION_1_2.supportsFileSuffixChange());
+ assertTrue(ApiVersion.API_VERSION_1_3.supportsFileSuffixChange());
+ }
+
+ @Test
+ public void shouldSupportNotesPathChangesWithApi1_2andAbove() {
+ assertFalse(ApiVersion.API_VERSION_0_2.supportsNotesPathChange());
+ assertFalse(ApiVersion.API_VERSION_1_0.supportsNotesPathChange());
+ assertTrue(ApiVersion.API_VERSION_1_2.supportsNotesPathChange());
+ assertTrue(ApiVersion.API_VERSION_1_3.supportsNotesPathChange());
+ }
+} \ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 6a4a994a..04e3f46c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.3.0-beta05'
+ classpath 'com.android.tools.build:gradle:7.2.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/fastlane/metadata/android/en-US/changelogs/3005001.txt b/fastlane/metadata/android/en-US/changelogs/3005001.txt
index d92d4a72..d11ac7ff 100644
--- a/fastlane/metadata/android/en-US/changelogs/3005001.txt
+++ b/fastlane/metadata/android/en-US/changelogs/3005001.txt
@@ -1,6 +1,7 @@
- 📱️ Add option to not keep screen on (#1531)
- 🐞 Favorite star in menu not clickable (#1541)
- 🐞 Fix back button behavior in widgets (#1412) - by @newhinton
+- ⚙️ Support custom file extensions (Notes ≥ 4.5.0)
- ⚙️ Add monochrome icon (#1544) - by @salixor
- ⚙️ Use the new Android 12 SplashScreen API (#1546) - by @salixor
- 🌎 Updated translations