From b788c07f36ed742869d7b419e03aca62ad9ba831 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 15 Mar 2021 10:59:46 +0100 Subject: [PATCH 01/12] #916 Change remote account settings - UI --- .../AccountSwitcherViewHolder.java | 2 +- .../manageaccounts/ManageAccountAdapter.java | 31 +++++--- .../ManageAccountViewHolder.java | 40 ++++++++-- .../ManageAccountsActivity.java | 77 ++++++++++++++----- .../main/res/layout/item_account_choose.xml | 4 +- app/src/main/res/menu/menu_account.xml | 23 ++++++ app/src/main/res/values/strings.xml | 3 + 7 files changed, 140 insertions(+), 40 deletions(-) create mode 100644 app/src/main/res/menu/menu_account.xml diff --git a/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherViewHolder.java b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherViewHolder.java index db0379dfe..ae57b8926 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherViewHolder.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherViewHolder.java @@ -34,6 +34,6 @@ public void bind(@NonNull LocalAccount localAccount, @NonNull Consumer onAccountClick.accept(localAccount)); - binding.delete.setVisibility(View.GONE); + binding.accountContextMenu.setVisibility(View.GONE); } } 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 33156fb60..8d04e34ea 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 @@ -1,6 +1,7 @@ package it.niedermann.owncloud.notes.manageaccounts; import android.view.LayoutInflater; +import android.view.MenuInflater; import android.view.ViewGroup; import androidx.annotation.NonNull; @@ -12,6 +13,7 @@ import java.util.List; import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.persistence.NotesDatabase; import it.niedermann.owncloud.notes.shared.model.LocalAccount; public class ManageAccountAdapter extends RecyclerView.Adapter { @@ -22,12 +24,21 @@ public class ManageAccountAdapter extends RecyclerView.Adapter localAccounts = new ArrayList<>(); @NonNull private final Consumer onAccountClick; - @Nullable + @NonNull private final Consumer onAccountDelete; + @NonNull + Consumer onChangeNotesPath; + @NonNull + Consumer onChangeFileSuffix; - public ManageAccountAdapter(@NonNull Consumer onAccountClick, @Nullable Consumer onAccountDelete) { + public ManageAccountAdapter(@NonNull Consumer onAccountClick, + @NonNull Consumer onAccountDelete, + @NonNull Consumer onChangeNotesPath, + @NonNull Consumer onChangeFileSuffix) { this.onAccountClick = onAccountClick; this.onAccountDelete = onAccountDelete; + this.onChangeNotesPath = onChangeNotesPath; + this.onChangeFileSuffix = onChangeFileSuffix; setHasStableIds(true); } @@ -49,17 +60,15 @@ public void onBindViewHolder(@NonNull ManageAccountViewHolder holder, int positi setCurrentLocalAccount(localAccountClicked); onAccountClick.accept(localAccountClicked); }, (localAccountToDelete -> { - if (onAccountDelete != null) { - for (int i = 0; i < localAccounts.size(); i++) { - if (localAccounts.get(i).getId() == localAccountToDelete.getId()) { - localAccounts.remove(i); - notifyItemRemoved(i); - break; - } + for (int i = 0; i < localAccounts.size(); i++) { + if (localAccounts.get(i).getId() == localAccountToDelete.getId()) { + localAccounts.remove(i); + notifyItemRemoved(i); + break; } - onAccountDelete.accept(localAccountToDelete); } - }), currentLocalAccount != null && currentLocalAccount.getId() == localAccount.getId()); + onAccountDelete.accept(localAccountToDelete); + }), onChangeNotesPath, onChangeFileSuffix, 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 f077f75be..96a8f381e 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 @@ -2,10 +2,14 @@ import android.graphics.drawable.LayerDrawable; import android.net.Uri; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.widget.PopupMenu; import androidx.core.util.Consumer; import androidx.recyclerview.widget.RecyclerView; @@ -23,14 +27,21 @@ public class ManageAccountViewHolder extends RecyclerView.ViewHolder { - private ItemAccountChooseBinding binding; + private final ItemAccountChooseBinding binding; public ManageAccountViewHolder(@NonNull View itemView) { super(itemView); binding = ItemAccountChooseBinding.bind(itemView); } - public void bind(@NonNull LocalAccount localAccount, @NonNull Consumer onAccountClick, @Nullable Consumer onAccountDelete, boolean isCurrentAccount) { + public void bind( + @NonNull LocalAccount localAccount, + @NonNull Consumer onAccountClick, + @NonNull Consumer onAccountDelete, + @NonNull Consumer onChangeNotesPath, + @NonNull Consumer onChangeFileSuffix, + boolean isCurrentAccount + ) { binding.accountName.setText(localAccount.getUserName()); binding.accountHost.setText(Uri.parse(localAccount.getUrl()).getHost()); Glide.with(itemView.getContext()) @@ -39,12 +50,25 @@ public void bind(@NonNull LocalAccount localAccount, @NonNull Consumer onAccountClick.accept(localAccount)); - if (onAccountDelete == null) { - binding.delete.setVisibility(GONE); - } else { - binding.delete.setVisibility(VISIBLE); - binding.delete.setOnClickListener((v) -> onAccountDelete.accept(localAccount)); - } + binding.accountContextMenu.setVisibility(VISIBLE); + binding.accountContextMenu.setOnClickListener((v) -> { + final PopupMenu popup = new PopupMenu(itemView.getContext(), v); + popup.inflate(R.menu.menu_account); + popup.setOnMenuItemClickListener(item -> { + if (item.getItemId() == R.id.notes_path) { + onChangeNotesPath.accept(localAccount); + return true; + } else if (item.getItemId() == R.id.file_suffix) { + onChangeFileSuffix.accept(localAccount); + return true; + } else if (item.getItemId() == R.id.delete) { + onAccountDelete.accept(localAccount); + return true; + } + return false; + }); + popup.show(); + }); if (isCurrentAccount) { binding.currentAccountIndicator.setVisibility(VISIBLE); applyBrandToLayerDrawable((LayerDrawable) binding.currentAccountIndicator.getDrawable(), R.id.area, localAccount.getColor()); 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 7cf64230d..3874ca11b 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,7 +1,10 @@ package it.niedermann.owncloud.notes.manageaccounts; import android.os.Bundle; +import android.widget.EditText; +import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; @@ -10,9 +13,12 @@ import com.nextcloud.android.sso.helper.SingleAccountHelper; import com.nextcloud.android.sso.model.SingleSignOnAccount; +import java.util.ArrayList; import java.util.List; import it.niedermann.owncloud.notes.LockedActivity; +import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.branding.BrandedAlertDialogBuilder; import it.niedermann.owncloud.notes.databinding.ActivityManageAccountsBinding; import it.niedermann.owncloud.notes.shared.model.LocalAccount; import it.niedermann.owncloud.notes.persistence.NotesDatabase; @@ -22,6 +28,7 @@ public class ManageAccountsActivity extends LockedActivity { private ActivityManageAccountsBinding binding; private ManageAccountAdapter adapter; private NotesDatabase db = null; + private List localAccounts = new ArrayList<>(); @Override public void onCreate(@Nullable Bundle savedInstanceState) { @@ -34,27 +41,18 @@ public void onCreate(@Nullable Bundle savedInstanceState) { db = NotesDatabase.getInstance(this); - List localAccounts = db.getAccounts(); + localAccounts.clear(); + localAccounts.addAll(db.getAccounts()); - adapter = new ManageAccountAdapter((localAccount) -> SingleAccountHelper.setCurrentAccount(getApplicationContext(), localAccount.getAccountName()), (localAccount) -> { - db.deleteAccount(localAccount); - for (LocalAccount temp : localAccounts) { - if (temp.getId() == localAccount.getId()) { - localAccounts.remove(temp); - break; - } - } - if (localAccounts.size() > 0) { - SingleAccountHelper.setCurrentAccount(getApplicationContext(), localAccounts.get(0).getAccountName()); - adapter.setCurrentLocalAccount(localAccounts.get(0)); - } else { - setResult(AppCompatActivity.RESULT_FIRST_USER); - finish(); - } - }); + adapter = new ManageAccountAdapter( + (localAccount) -> SingleAccountHelper.setCurrentAccount(getApplicationContext(), localAccount.getAccountName()), + this::onAccountDelete, + this::onChangeNotesPath, + this::onChangeFileSuffix + ); adapter.setLocalAccounts(localAccounts); try { - SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(this); + final SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(this); if (ssoAccount != null) { adapter.setCurrentLocalAccount(db.getLocalAccountByAccountName(ssoAccount.name)); } @@ -64,6 +62,49 @@ public void onCreate(@Nullable Bundle savedInstanceState) { binding.accounts.setAdapter(adapter); } + private void onAccountDelete(@NonNull LocalAccount localAccount) { + db.deleteAccount(localAccount); + for (LocalAccount temp : localAccounts) { + if (temp.getId() == localAccount.getId()) { + localAccounts.remove(temp); + break; + } + } + if (localAccounts.size() > 0) { + SingleAccountHelper.setCurrentAccount(getApplicationContext(), localAccounts.get(0).getAccountName()); + adapter.setCurrentLocalAccount(localAccounts.get(0)); + } else { + setResult(AppCompatActivity.RESULT_FIRST_USER); + finish(); + } + } + + private void onChangeNotesPath(@NonNull LocalAccount localAccount) { + final EditText editText = new EditText(this); + new BrandedAlertDialogBuilder(this) + .setTitle(R.string.settings_notes_path) + .setMessage("Folder to store your notes in your Nextcloud") + .setView(editText) + .setNeutralButton(android.R.string.cancel, null) + .setPositiveButton(R.string.action_edit_save, (v, d) -> { + Toast.makeText(this, "Submitted " + editText.getText(), Toast.LENGTH_LONG).show(); + }) + .show(); + } + + private void onChangeFileSuffix(@NonNull LocalAccount localAccount) { + final EditText editText = new EditText(this); + new BrandedAlertDialogBuilder(this) + .setTitle(R.string.settings_file_suffix) + .setMessage("File extension for new notes in your Nextcloud") + .setView(editText) + .setNeutralButton(android.R.string.cancel, null) + .setPositiveButton("Save", (v, d) -> { + Toast.makeText(this, "Submitted " + editText.getText(), Toast.LENGTH_LONG).show(); + }) + .show(); + } + @Override public void applyBrand(int mainColor, int textColor) { applyBrandToPrimaryToolbar(binding.appBar, binding.toolbar); diff --git a/app/src/main/res/layout/item_account_choose.xml b/app/src/main/res/layout/item_account_choose.xml index 8f321800c..8cfbd4beb 100644 --- a/app/src/main/res/layout/item_account_choose.xml +++ b/app/src/main/res/layout/item_account_choose.xml @@ -64,7 +64,7 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 45ba55a18..841ec5a38 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -295,4 +295,7 @@ No account configured yet You don\'t have configured any other accounts yet. Context based formatting popover + Set folder + File extension + Remove account From a447542fc16f602fa0e7db7533b2ca78b72d18fc Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 15 Mar 2021 15:29:47 +0100 Subject: [PATCH 02/12] #916 Change remote account settings - UI --- .../ManageAccountViewHolder.java | 10 ++++ .../ManageAccountsActivity.java | 47 +++++++++++++++++-- .../notes/shared/model/ApiVersion.java | 10 +++- app/src/main/res/values/strings.xml | 7 +++ 4 files changed, 67 insertions(+), 7 deletions(-) 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 96a8f381e..910dccc0e 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 @@ -16,6 +16,9 @@ import com.bumptech.glide.Glide; import com.bumptech.glide.request.RequestOptions; +import java.util.Arrays; +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; @@ -54,6 +57,13 @@ public void bind( binding.accountContextMenu.setOnClickListener((v) -> { final PopupMenu popup = new PopupMenu(itemView.getContext(), v); popup.inflate(R.menu.menu_account); + if (!localAccount.getPreferredApiVersion().supportsSettings()) { + final Menu menu = popup.getMenu(); + Stream.of( + R.id.notes_path, + R.id.file_suffix + ).forEach((i) -> menu.removeItem(menu.findItem(i).getItemId())); + } popup.setOnMenuItemClickListener(item -> { if (item.getItemId() == R.id.notes_path) { onChangeNotesPath.accept(localAccount); 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 3874ca11b..1e51c20ea 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,11 +1,18 @@ package it.niedermann.owncloud.notes.manageaccounts; import android.os.Bundle; +import android.util.TypedValue; +import android.view.View; +import android.widget.ArrayAdapter; import android.widget.EditText; +import android.widget.FrameLayout; +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.AppCompatActivity; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException; @@ -23,6 +30,9 @@ import it.niedermann.owncloud.notes.shared.model.LocalAccount; import it.niedermann.owncloud.notes.persistence.NotesDatabase; +import static android.os.Build.VERSION.SDK_INT; +import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; + public class ManageAccountsActivity extends LockedActivity { private ActivityManageAccountsBinding binding; @@ -81,10 +91,11 @@ private void onAccountDelete(@NonNull LocalAccount localAccount) { private void onChangeNotesPath(@NonNull LocalAccount localAccount) { final EditText editText = new EditText(this); + final View wrapper = createDialogViewWrapper(editText); new BrandedAlertDialogBuilder(this) .setTitle(R.string.settings_notes_path) - .setMessage("Folder to store your notes in your Nextcloud") - .setView(editText) + .setMessage("Folder to store your notes in your Nextcloud") + .setView(wrapper) .setNeutralButton(android.R.string.cancel, null) .setPositiveButton(R.string.action_edit_save, (v, d) -> { Toast.makeText(this, "Submitted " + editText.getText(), Toast.LENGTH_LONG).show(); @@ -93,18 +104,44 @@ private void onChangeNotesPath(@NonNull LocalAccount localAccount) { } private void onChangeFileSuffix(@NonNull LocalAccount localAccount) { - final EditText editText = new EditText(this); + final Spinner spinner = new Spinner(this); + final View wrapper = createDialogViewWrapper(spinner); + final ArrayAdapter 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); new BrandedAlertDialogBuilder(this) .setTitle(R.string.settings_file_suffix) .setMessage("File extension for new notes in your Nextcloud") - .setView(editText) + .setView(wrapper) .setNeutralButton(android.R.string.cancel, null) .setPositiveButton("Save", (v, d) -> { - Toast.makeText(this, "Submitted " + editText.getText(), Toast.LENGTH_LONG).show(); + Toast.makeText(this, "Submitted " + spinner.getSelectedItem(), Toast.LENGTH_LONG).show(); }) .show(); } + @NonNull + private View createDialogViewWrapper(@NonNull View view) { + final FrameLayout 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); + wrapper.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical); + wrapper.addView(view); + return wrapper; + } + + @Px + private int getDimensionFromAttribute(@SuppressWarnings("SameParameterValue") @AttrRes int attr) { + final TypedValue typedValue = new TypedValue(); + if (getTheme().resolveAttribute(attr, typedValue, true)) + return TypedValue.complexToDimensionPixelSize(typedValue.data, getResources().getDisplayMetrics()); + else { + return 0; + } + } + @Override public void applyBrand(int mainColor, int textColor) { applyBrandToPrimaryToolbar(binding.appBar, binding.toolbar); 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 b27afd7a2..b4c62f5b6 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 @@ -9,10 +9,11 @@ @SuppressWarnings("WeakerAccess") public class ApiVersion implements Comparable { private static final Pattern NUMBER_EXTRACTION_PATTERN = Pattern.compile("[0-9]+"); + private static final ApiVersion VERSION_1_2 = new ApiVersion("1.2", 1, 2); private String originalVersion = "?"; - private int major; - private int minor; + private final int major; + private final int minor; public ApiVersion(String originalVersion, int major, int minor) { this(major, minor); @@ -74,6 +75,11 @@ public int compareTo(ApiVersion compare) { return 0; } + public boolean supportsSettings() { + // TODO + return true;//getMajor() >= VERSION_1_2.getMajor() && getMinor() >= VERSION_1_2.getMinor(); + } + @NonNull @Override public String toString() { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 841ec5a38..9dde766ab 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -298,4 +298,11 @@ Set folder File extension Remove account + + + + .txt + .md + + From 669d457f5c2eaf062dec08a133f3516ee4038c4d Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 15 Mar 2021 23:37:29 +0100 Subject: [PATCH 03/12] #916 Change remote account settings - Server connection --- .../ManageAccountsActivity.java | 56 ++++++++++++++++--- .../notes/persistence/NotesClient.java | 11 ++++ .../notes/persistence/NotesClientV1.java | 16 +++++- .../notes/shared/model/ServerSettings.java | 47 ++++++++++++++++ 4 files changed, 122 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/it/niedermann/owncloud/notes/shared/model/ServerSettings.java 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 1e51c20ea..7f973528f 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 @@ -13,8 +13,10 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.Px; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; +import com.nextcloud.android.sso.AccountImporter; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException; import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException; import com.nextcloud.android.sso.helper.SingleAccountHelper; @@ -27,8 +29,11 @@ import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.branding.BrandedAlertDialogBuilder; import it.niedermann.owncloud.notes.databinding.ActivityManageAccountsBinding; -import it.niedermann.owncloud.notes.shared.model.LocalAccount; +import it.niedermann.owncloud.notes.exception.ExceptionDialogFragment; +import it.niedermann.owncloud.notes.persistence.NotesClient; import it.niedermann.owncloud.notes.persistence.NotesDatabase; +import it.niedermann.owncloud.notes.shared.model.LocalAccount; +import it.niedermann.owncloud.notes.shared.model.ServerSettings; import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; @@ -90,34 +95,71 @@ private void onAccountDelete(@NonNull LocalAccount localAccount) { } private void onChangeNotesPath(@NonNull LocalAccount localAccount) { + final NotesClient client = NotesClient.newInstance(localAccount.getPreferredApiVersion(), getApplicationContext()); final EditText editText = new EditText(this); + editText.setEnabled(false); final View wrapper = createDialogViewWrapper(editText); - new BrandedAlertDialogBuilder(this) + final AlertDialog dialog = new BrandedAlertDialogBuilder(this) .setTitle(R.string.settings_notes_path) .setMessage("Folder to store your notes in your Nextcloud") .setView(wrapper) .setNeutralButton(android.R.string.cancel, null) - .setPositiveButton(R.string.action_edit_save, (v, d) -> { - Toast.makeText(this, "Submitted " + editText.getText(), Toast.LENGTH_LONG).show(); - }) + .setPositiveButton(R.string.action_edit_save, (v, d) -> new Thread(() -> { + try { + final ServerSettings newSettings = client.putServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), new ServerSettings(editText.getText().toString(), null)); + Toast.makeText(this, "New notes path: " + newSettings.getNotesPath(), Toast.LENGTH_LONG).show(); + } catch (Exception e) { + ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); + } + }).start()) .show(); + new Thread(() -> { + try { + final ServerSettings oldSettings = client.getServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName())); + editText.setText(oldSettings.getNotesPath()); + editText.setEnabled(true); + } catch (Exception e) { + dialog.dismiss(); + ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); + } + }).start(); } private void onChangeFileSuffix(@NonNull LocalAccount localAccount) { + final NotesClient client = NotesClient.newInstance(localAccount.getPreferredApiVersion(), getApplicationContext()); final Spinner spinner = new Spinner(this); + spinner.setEnabled(false); final View wrapper = createDialogViewWrapper(spinner); final ArrayAdapter 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); - new BrandedAlertDialogBuilder(this) + final AlertDialog dialog = new BrandedAlertDialogBuilder(this) .setTitle(R.string.settings_file_suffix) .setMessage("File extension for new notes in your Nextcloud") .setView(wrapper) .setNeutralButton(android.R.string.cancel, null) .setPositiveButton("Save", (v, d) -> { - Toast.makeText(this, "Submitted " + spinner.getSelectedItem(), Toast.LENGTH_LONG).show(); + new Thread(() -> { + try { + final ServerSettings newSettings = client.putServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), new ServerSettings(null, spinner.getSelectedItem().toString())); + Toast.makeText(this, "New file suffix: " + newSettings.getNotesPath(), Toast.LENGTH_LONG).show(); + } catch (Exception e) { + ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); + } + }).start(); }) .show(); + new Thread(() -> { + try { + final ServerSettings oldSettings = client.getServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName())); + // TODO +// spinner.setSelection(adapteroldSettings.getNotesPath()); + spinner.setEnabled(true); + } catch (Exception e) { + dialog.dismiss(); + ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); + } + }).start(); } @NonNull diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClient.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClient.java index c9ab9b39c..cffce6c91 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClient.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClient.java @@ -29,6 +29,7 @@ import it.niedermann.owncloud.notes.shared.model.CloudNote; import it.niedermann.owncloud.notes.shared.model.ServerResponse.NoteResponse; import it.niedermann.owncloud.notes.shared.model.ServerResponse.NotesResponse; +import it.niedermann.owncloud.notes.shared.model.ServerSettings; @SuppressWarnings("WeakerAccess") @WorkerThread @@ -61,6 +62,8 @@ public abstract class NotesClient { public static final String JSON_CATEGORY = "category"; public static final String JSON_ETAG = "etag"; public static final String JSON_MODIFIED = "modified"; + public static final String JSON_SETTINGS_NOTES_PATH = "notesPath"; + public static final String JSON_SETTINGS_FILE_SUFFIX = "fileSuffix"; public static final ApiVersion[] SUPPORTED_API_VERSIONS = new ApiVersion[]{ new ApiVersion(1, 0), @@ -96,6 +99,14 @@ public NotesClient(@NonNull Context appContext) { abstract void deleteNote(SingleSignOnAccount ssoAccount, long noteId) throws Exception; + public ServerSettings getServerSettings(SingleSignOnAccount ssoAccount) throws Exception { + throw new UnsupportedOperationException("Not available in this API version"); + } + + public ServerSettings putServerSettings(SingleSignOnAccount ssoAccount, @NonNull ServerSettings settings) throws Exception { + throw new UnsupportedOperationException("Not available in this API version"); + } + /** * This entity class is used to return relevant data of the HTTP reponse. */ diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClientV1.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClientV1.java index 220d4f8f7..c9150f6c2 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClientV1.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesClientV1.java @@ -15,6 +15,7 @@ import it.niedermann.owncloud.notes.shared.model.CloudNote; import it.niedermann.owncloud.notes.shared.model.ServerResponse.NoteResponse; import it.niedermann.owncloud.notes.shared.model.ServerResponse.NotesResponse; +import it.niedermann.owncloud.notes.shared.model.ServerSettings; @WorkerThread public class NotesClientV1 extends NotesClient { @@ -32,7 +33,7 @@ NotesResponse getNotes(SingleSignOnAccount ssoAccount, long lastModified, String } private NoteResponse putNote(SingleSignOnAccount ssoAccount, CloudNote note, String path, String method) throws Exception { - JSONObject paramObject = new JSONObject(); + final JSONObject paramObject = new JSONObject(); paramObject.accumulate(JSON_TITLE, note.getTitle()); paramObject.accumulate(JSON_CONTENT, note.getContent()); paramObject.accumulate(JSON_MODIFIED, note.getModified().getTimeInMillis() / 1000); @@ -57,4 +58,17 @@ void deleteNote(SingleSignOnAccount ssoAccount, long noteId) throws Exception { protected String getApiPath() { return API_PATH; } + + @Override + public ServerSettings getServerSettings(SingleSignOnAccount ssoAccount) throws Exception { + return ServerSettings.from(new JSONObject(this.requestServer(ssoAccount, "settings", METHOD_GET, null, null, null).getContent())); + } + + @Override + public ServerSettings putServerSettings(SingleSignOnAccount ssoAccount, @NonNull ServerSettings settings) throws Exception { + final JSONObject paramObject = new JSONObject(); + paramObject.accumulate(JSON_SETTINGS_NOTES_PATH, settings.getNotesPath()); + paramObject.accumulate(JSON_SETTINGS_FILE_SUFFIX, settings.getFileSuffix()); + return ServerSettings.from(new JSONObject(this.requestServer(ssoAccount, "settings", METHOD_PUT, null, paramObject, null).getContent())); + } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ServerSettings.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ServerSettings.java new file mode 100644 index 000000000..e977b6972 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/ServerSettings.java @@ -0,0 +1,47 @@ +package it.niedermann.owncloud.notes.shared.model; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.Serializable; + +import static it.niedermann.owncloud.notes.persistence.NotesClient.JSON_SETTINGS_FILE_SUFFIX; +import static it.niedermann.owncloud.notes.persistence.NotesClient.JSON_SETTINGS_NOTES_PATH; + +public class ServerSettings implements Serializable { + private String notesPath = ""; + private String fileSuffix = ""; + + public ServerSettings(String notesPath, String fileSuffix) { + setNotesPath(notesPath); + setFileSuffix(fileSuffix); + } + + public static ServerSettings from(JSONObject settings) throws JSONException { + String notesPath = ""; + if (settings.has(JSON_SETTINGS_NOTES_PATH)) { + notesPath = settings.getString(JSON_SETTINGS_NOTES_PATH); + } + String fileSuffix = ""; + if (settings.has(JSON_SETTINGS_FILE_SUFFIX)) { + fileSuffix = settings.getString(JSON_SETTINGS_FILE_SUFFIX); + } + return new ServerSettings(notesPath, fileSuffix); + } + + public String getNotesPath() { + return notesPath; + } + + public void setNotesPath(String notesPath) { + this.notesPath = notesPath; + } + + public String getFileSuffix() { + return fileSuffix; + } + + public void setFileSuffix(String fileSuffix) { + this.fileSuffix = fileSuffix; + } +} \ No newline at end of file From 63de9d8131bef879848c15d53a8d36e660f2eae2 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 15 Mar 2021 23:42:08 +0100 Subject: [PATCH 04/12] #916 Change remote account settings - Server connection --- .../ManageAccountsActivity.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) 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 7f973528f..8e5bfcd48 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 @@ -43,7 +43,7 @@ public class ManageAccountsActivity extends LockedActivity { private ActivityManageAccountsBinding binding; private ManageAccountAdapter adapter; private NotesDatabase db = null; - private List localAccounts = new ArrayList<>(); + private final List localAccounts = new ArrayList<>(); @Override public void onCreate(@Nullable Bundle savedInstanceState) { @@ -138,16 +138,14 @@ private void onChangeFileSuffix(@NonNull LocalAccount localAccount) { .setMessage("File extension for new notes in your Nextcloud") .setView(wrapper) .setNeutralButton(android.R.string.cancel, null) - .setPositiveButton("Save", (v, d) -> { - new Thread(() -> { - try { - final ServerSettings newSettings = client.putServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), new ServerSettings(null, spinner.getSelectedItem().toString())); - Toast.makeText(this, "New file suffix: " + newSettings.getNotesPath(), Toast.LENGTH_LONG).show(); - } catch (Exception e) { - ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); - } - }).start(); - }) + .setPositiveButton("Save", (v, d) -> new Thread(() -> { + try { + final ServerSettings newSettings = client.putServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), new ServerSettings(null, spinner.getSelectedItem().toString())); + Toast.makeText(this, "New file suffix: " + newSettings.getNotesPath(), Toast.LENGTH_LONG).show(); + } catch (Exception e) { + ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); + } + }).start()) .show(); new Thread(() -> { try { From a5a84360bea5a9d4d7c755200ce87a8888cfbb2d Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 16 Mar 2021 11:40:49 +0100 Subject: [PATCH 05/12] Preselect file suffix spinner when loaded --- .../notes/manageaccounts/ManageAccountsActivity.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 8e5bfcd48..b6950c85a 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 @@ -150,8 +150,12 @@ private void onChangeFileSuffix(@NonNull LocalAccount localAccount) { new Thread(() -> { try { final ServerSettings oldSettings = client.getServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName())); - // TODO -// spinner.setSelection(adapteroldSettings.getNotesPath()); + for (int i = 0; i < adapter.getCount(); i++) { + if (adapter.getItem(i).equals(oldSettings.getFileSuffix())) { + spinner.setSelection(i); + break; + } + } spinner.setEnabled(true); } catch (Exception e) { dialog.dismiss(); From 5ede3bd0e0651d3e1ee6936df9e78108fc48b428 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 3 May 2021 19:05:48 +0200 Subject: [PATCH 06/12] #916 Improve handling --- .../ManageAccountsActivity.java | 97 ++++++++++--------- 1 file changed, 53 insertions(+), 44 deletions(-) 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 01eafd623..dcdd35339 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 @@ -127,8 +127,9 @@ private void onChangeNotesPath(@NonNull Account localAccount) { putSettingsCall.enqueue(new Callback() { @Override public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - Toast.makeText(ManageAccountsActivity.this, "New notes path: " + response.body().getNotesPath(), Toast.LENGTH_LONG).show(); + final NotesSettings body = response.body(); + if (response.isSuccessful() && body != null) { + Toast.makeText(ManageAccountsActivity.this, "New notes path: " + body.getNotesPath(), Toast.LENGTH_LONG).show(); } else { Toast.makeText(ManageAccountsActivity.this, "HTTP status code: " + response.code(), Toast.LENGTH_LONG).show(); } @@ -145,25 +146,29 @@ public void onFailure(@NonNull Call call, @NonNull Throwable t) { }).start()) .show(); try { - final Call oldSettingsCall = repository.getServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), localAccount.getPreferredApiVersion()); - oldSettingsCall.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - runOnUiThread(() -> { - if (response.isSuccessful()) { - editText.setText(response.body().getNotesPath()); - editText.setEnabled(true); - } else { - ExceptionDialogFragment.newInstance(new NetworkErrorException("HTTP status code: " + response.code())).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); + repository.getServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), localAccount.getPreferredApiVersion()) + .enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + runOnUiThread(() -> { + final NotesSettings body = response.body(); + if (response.isSuccessful() && body != null) { + editText.setText(body.getNotesPath()); + editText.setEnabled(true); + } else { + ExceptionDialogFragment.newInstance(new NetworkErrorException("HTTP status code: " + response.code())).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); + } + }); } - }); - } - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - ExceptionDialogFragment.newInstance(t).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); - } - }); + @Override + public void onFailure(@NonNull Call 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()); @@ -189,8 +194,9 @@ private void onChangeFileSuffix(@NonNull Account localAccount) { putSettingsCall.enqueue(new Callback() { @Override public void onResponse(@NonNull Call call, @NonNull Response response) { - if (response.isSuccessful()) { - Toast.makeText(ManageAccountsActivity.this, "New file suffix: " + response.body().getNotesPath(), Toast.LENGTH_LONG).show(); + final NotesSettings body = response.body(); + if (response.isSuccessful() && body != null) { + Toast.makeText(ManageAccountsActivity.this, "New file suffix: " + body.getNotesPath(), Toast.LENGTH_LONG).show(); } else { Toast.makeText(ManageAccountsActivity.this, "HTTP status code: " + response.code(), Toast.LENGTH_LONG).show(); } @@ -202,36 +208,39 @@ public void onFailure(@NonNull Call call, @NonNull Throwable t) { } }); } catch (NextcloudFilesAppAccountNotFoundException e) { - ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); + runOnUiThread(() -> ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName())); } }).start()) .show(); try { - final Call oldSettingsCall = repository.getServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), localAccount.getPreferredApiVersion()); - oldSettingsCall.enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - runOnUiThread(() -> { - if (response.isSuccessful()) { - for (int i = 0; i < adapter.getCount(); i++) { - if (adapter.getItem(i).equals(response.body().getFileSuffix())) { - spinner.setSelection(i); - break; + repository.getServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), localAccount.getPreferredApiVersion()) + .enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + final NotesSettings body = response.body(); + runOnUiThread(() -> { + if (response.isSuccessful() && body != null) { + for (int i = 0; i < adapter.getCount(); i++) { + if (adapter.getItem(i).equals(body.getFileSuffix())) { + spinner.setSelection(i); + break; + } + } + spinner.setEnabled(true); + } else { + ExceptionDialogFragment.newInstance(new Exception("HTTP status code: " + response.code())).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); } - } - spinner.setEnabled(true); - } else { - ExceptionDialogFragment.newInstance(new Exception("HTTP status code: " + response.code())).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); + }); } - }); - } - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - dialog.dismiss(); - ExceptionDialogFragment.newInstance(t).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); - } - }); + @Override + public void onFailure(@NonNull Call 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()); From 0d1136aad3cae384e7a9c636f79e4d121b28dd89 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 3 May 2021 19:07:29 +0200 Subject: [PATCH 07/12] #916 Use generic "Remove" as menu item --- app/src/main/res/menu/menu_account.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/menu/menu_account.xml b/app/src/main/res/menu/menu_account.xml index 95cb00d7b..507d3f05b 100644 --- a/app/src/main/res/menu/menu_account.xml +++ b/app/src/main/res/menu/menu_account.xml @@ -17,7 +17,7 @@ \ No newline at end of file From ef993ca0d80a38d424658d337dc24c43d294aa78 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 28 Jun 2021 10:08:50 +0200 Subject: [PATCH 08/12] #916 Server settings Signed-off-by: Stefan Niedermann --- .../it/niedermann/owncloud/notes/shared/model/ApiVersion.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 589f2571e..b35daaca3 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 @@ -81,9 +81,7 @@ public int compareTo(@NonNull ApiVersion compare) { } public boolean supportsSettings() { - // TODO - return true; -// return getMajor() >= 1 && getMinor() >= 2; + return getMajor() >= 1 && getMinor() >= 2; } /** From 491ccd57dabd56c8a0b34fdc4e81a19e82d1b9a6 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 28 Jun 2021 10:10:51 +0200 Subject: [PATCH 09/12] Fix build Signed-off-by: Stefan Niedermann --- .../notes/manageaccounts/ManageAccountViewHolder.java | 11 +++++------ .../notes/manageaccounts/ManageAccountsActivity.java | 9 +++++---- .../owncloud/notes/persistence/NotesRepository.java | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) 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 1d01387a1..ac56593df 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,15 +1,11 @@ package it.niedermann.owncloud.notes.manageaccounts; -import android.graphics.Color; import android.graphics.drawable.LayerDrawable; import android.net.Uri; -import android.view.LayoutInflater; import android.view.Menu; -import android.view.MenuInflater; import android.view.View; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.appcompat.widget.PopupMenu; import androidx.core.util.Consumer; import androidx.recyclerview.widget.RecyclerView; @@ -17,17 +13,19 @@ import com.bumptech.glide.Glide; import com.bumptech.glide.request.RequestOptions; -import java.util.Arrays; 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 it.niedermann.owncloud.notes.shared.util.ApiVersionUtil; 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 { @@ -58,7 +56,8 @@ public void bind( binding.accountContextMenu.setOnClickListener((v) -> { final PopupMenu popup = new PopupMenu(itemView.getContext(), v); popup.inflate(R.menu.menu_account); - if (!localAccount.getPreferredApiVersion().supportsSettings()) { + final ApiVersion preferredApiVersion = getPreferredApiVersion(localAccount.getApiVersion()); + if (preferredApiVersion != null && !preferredApiVersion.supportsSettings()) { final Menu menu = popup.getMenu(); Stream.of( R.id.notes_path, 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 dcdd35339..fc9f18ebd 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 @@ -36,6 +36,7 @@ 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 { @@ -123,7 +124,7 @@ private void onChangeNotesPath(@NonNull Account localAccount) { .setNeutralButton(android.R.string.cancel, null) .setPositiveButton(R.string.action_edit_save, (v, d) -> new Thread(() -> { try { - final Call putSettingsCall = repository.putServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), new NotesSettings(editText.getText().toString(), null), localAccount.getPreferredApiVersion()); + final Call 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 call, @NonNull Response response) { @@ -146,7 +147,7 @@ public void onFailure(@NonNull Call call, @NonNull Throwable t) { }).start()) .show(); try { - repository.getServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), localAccount.getPreferredApiVersion()) + repository.getServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), getPreferredApiVersion(localAccount.getApiVersion())) .enqueue(new Callback() { @Override public void onResponse(@NonNull Call call, @NonNull Response response) { @@ -190,7 +191,7 @@ private void onChangeFileSuffix(@NonNull Account localAccount) { .setNeutralButton(android.R.string.cancel, null) .setPositiveButton("Save", (v, d) -> new Thread(() -> { try { - final Call putSettingsCall = repository.putServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), new NotesSettings(null, spinner.getSelectedItem().toString()), localAccount.getPreferredApiVersion()); + final Call 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 call, @NonNull Response response) { @@ -213,7 +214,7 @@ public void onFailure(@NonNull Call call, @NonNull Throwable t) { }).start()) .show(); try { - repository.getServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), localAccount.getPreferredApiVersion()) + repository.getServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), getPreferredApiVersion(localAccount.getApiVersion())) .enqueue(new Callback() { @Override public void onResponse(@NonNull Call call, @NonNull Response response) { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesRepository.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesRepository.java index f36fd72a6..24a286195 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesRepository.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesRepository.java @@ -911,11 +911,11 @@ public LiveData> getSyncErrors() { } public Call getServerSettings(@NonNull SingleSignOnAccount ssoAccount, @Nullable ApiVersion preferredApiVersion) { - return ApiProvider.getNotesAPI(context, ssoAccount, preferredApiVersion).getSettings(); + return ApiProvider.getInstance().getNotesAPI(context, ssoAccount, preferredApiVersion).getSettings(); } public Call putServerSettings(@NonNull SingleSignOnAccount ssoAccount, @NonNull NotesSettings settings, @Nullable ApiVersion preferredApiVersion) { - return ApiProvider.getNotesAPI(context, ssoAccount, preferredApiVersion).putSettings(settings); + return ApiProvider.getInstance().getNotesAPI(context, ssoAccount, preferredApiVersion).putSettings(settings); } public void updateDisplayName(long id, @Nullable String displayName) { From d07e368d0000259371abc2491b543bf40f47ec2c Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 28 Jun 2021 13:19:45 +0200 Subject: [PATCH 10/12] Expose settings attributes Signed-off-by: Stefan Niedermann --- .../notes/manageaccounts/ManageAccountViewHolder.java | 1 - .../notes/manageaccounts/ManageAccountsActivity.java | 8 ++++---- .../owncloud/notes/shared/model/NotesSettings.java | 4 ++++ 3 files changed, 8 insertions(+), 5 deletions(-) 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 ac56593df..2c29ce99f 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 @@ -20,7 +20,6 @@ import it.niedermann.owncloud.notes.databinding.ItemAccountChooseBinding; import it.niedermann.owncloud.notes.persistence.entity.Account; import it.niedermann.owncloud.notes.shared.model.ApiVersion; -import it.niedermann.owncloud.notes.shared.util.ApiVersionUtil; import static android.view.View.GONE; import static android.view.View.VISIBLE; 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 fc9f18ebd..a433d4fca 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 @@ -130,9 +130,9 @@ private void onChangeNotesPath(@NonNull Account localAccount) { public void onResponse(@NonNull Call call, @NonNull Response response) { final NotesSettings body = response.body(); if (response.isSuccessful() && body != null) { - Toast.makeText(ManageAccountsActivity.this, "New notes path: " + body.getNotesPath(), Toast.LENGTH_LONG).show(); + runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, "New notes path: " + body.getNotesPath(), Toast.LENGTH_LONG).show()); } else { - Toast.makeText(ManageAccountsActivity.this, "HTTP status code: " + response.code(), Toast.LENGTH_LONG).show(); + runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, "HTTP status code: " + response.code(), Toast.LENGTH_LONG).show()); } } @@ -197,9 +197,9 @@ private void onChangeFileSuffix(@NonNull Account localAccount) { public void onResponse(@NonNull Call call, @NonNull Response response) { final NotesSettings body = response.body(); if (response.isSuccessful() && body != null) { - Toast.makeText(ManageAccountsActivity.this, "New file suffix: " + body.getNotesPath(), Toast.LENGTH_LONG).show(); + runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, "New file suffix: " + body.getNotesPath(), Toast.LENGTH_LONG).show()); } else { - Toast.makeText(ManageAccountsActivity.this, "HTTP status code: " + response.code(), Toast.LENGTH_LONG).show(); + runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, "HTTP status code: " + response.code(), Toast.LENGTH_LONG).show()); } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/NotesSettings.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/NotesSettings.java index ff11434f5..bffb23441 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/NotesSettings.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/NotesSettings.java @@ -2,10 +2,14 @@ import androidx.annotation.Nullable; +import com.google.gson.annotations.Expose; + public class NotesSettings { + @Expose @Nullable private String notesPath; + @Expose @Nullable private String fileSuffix; From ee2a340b68862749cd634339ac9fc57b4b338d6b Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 28 Jun 2021 13:39:55 +0200 Subject: [PATCH 11/12] Settings: i18n Signed-off-by: Stefan Niedermann --- .../ManageAccountsActivity.java | 40 ++++++++++--------- app/src/main/res/values/strings.xml | 16 +++++--- 2 files changed, 32 insertions(+), 24 deletions(-) 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 a433d4fca..74d50159f 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 @@ -3,10 +3,11 @@ import android.accounts.NetworkErrorException; import android.os.Bundle; import android.util.TypedValue; -import android.view.View; +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; @@ -115,11 +116,10 @@ public void onError(@NonNull Throwable t) { private void onChangeNotesPath(@NonNull Account localAccount) { final NotesRepository repository = NotesRepository.getInstance(getApplicationContext()); final EditText editText = new EditText(this); - editText.setEnabled(false); - final View wrapper = createDialogViewWrapper(editText); + final ViewGroup wrapper = createDialogViewWrapper(); final AlertDialog dialog = new BrandedAlertDialogBuilder(this) .setTitle(R.string.settings_notes_path) - .setMessage("Folder to store your notes in your Nextcloud") + .setMessage(R.string.settings_notes_path_description) .setView(wrapper) .setNeutralButton(android.R.string.cancel, null) .setPositiveButton(R.string.action_edit_save, (v, d) -> new Thread(() -> { @@ -130,9 +130,9 @@ private void onChangeNotesPath(@NonNull Account localAccount) { public void onResponse(@NonNull Call call, @NonNull Response response) { final NotesSettings body = response.body(); if (response.isSuccessful() && body != null) { - runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, "New notes path: " + body.getNotesPath(), Toast.LENGTH_LONG).show()); + runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, getString(R.string.settings_notes_path_success, body.getNotesPath()), Toast.LENGTH_LONG).show()); } else { - runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, "HTTP status code: " + response.code(), Toast.LENGTH_LONG).show()); + runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, getString(R.string.http_status_code, response.code()), Toast.LENGTH_LONG).show()); } } @@ -154,10 +154,12 @@ public void onResponse(@NonNull Call call, @NonNull Response { final NotesSettings body = response.body(); if (response.isSuccessful() && body != null) { + wrapper.removeAllViews(); + final EditText editText = new EditText(ManageAccountsActivity.this); editText.setText(body.getNotesPath()); - editText.setEnabled(true); + wrapper.addView(editText); } else { - ExceptionDialogFragment.newInstance(new NetworkErrorException("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()); } }); } @@ -179,17 +181,16 @@ public void onFailure(@NonNull Call call, @NonNull Throwable t) { private void onChangeFileSuffix(@NonNull Account localAccount) { final NotesRepository repository = NotesRepository.getInstance(getApplicationContext()); final Spinner spinner = new Spinner(this); - spinner.setEnabled(false); - final View wrapper = createDialogViewWrapper(spinner); + final ViewGroup wrapper = createDialogViewWrapper(); final ArrayAdapter 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 AlertDialog dialog = new BrandedAlertDialogBuilder(this) .setTitle(R.string.settings_file_suffix) - .setMessage("File extension for new notes in your Nextcloud") + .setMessage(R.string.settings_file_suffix_description) .setView(wrapper) .setNeutralButton(android.R.string.cancel, null) - .setPositiveButton("Save", (v, d) -> new Thread(() -> { + .setPositiveButton(R.string.action_edit_save, (v, d) -> new Thread(() -> { try { final Call putSettingsCall = repository.putServerSettings(AccountImporter.getSingleSignOnAccount(this, localAccount.getAccountName()), new NotesSettings(null, spinner.getSelectedItem().toString()), getPreferredApiVersion(localAccount.getApiVersion())); putSettingsCall.enqueue(new Callback() { @@ -197,9 +198,9 @@ private void onChangeFileSuffix(@NonNull Account localAccount) { public void onResponse(@NonNull Call call, @NonNull Response response) { final NotesSettings body = response.body(); if (response.isSuccessful() && body != null) { - runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, "New file suffix: " + body.getNotesPath(), Toast.LENGTH_LONG).show()); + runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, getString(R.string.settings_file_suffix_success, body.getNotesPath()), Toast.LENGTH_LONG).show()); } else { - runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, "HTTP status code: " + response.code(), Toast.LENGTH_LONG).show()); + runOnUiThread(() -> Toast.makeText(ManageAccountsActivity.this, getString(R.string.http_status_code, response.code()), Toast.LENGTH_LONG).show()); } } @@ -227,9 +228,10 @@ public void onResponse(@NonNull Call call, @NonNull Response call, @NonNull Throwable t) { } @NonNull - private View createDialogViewWrapper(@NonNull View view) { + private ViewGroup createDialogViewWrapper() { + final ProgressBar progressBar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal); + progressBar.setIndeterminate(true); final FrameLayout 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); wrapper.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical); - wrapper.addView(view); + wrapper.addView(progressBar); return wrapper; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ee2d67f15..ace142d74 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -294,16 +294,20 @@ You have to be connected to the internet in order to add an account. Set folder - File extension - - - .txt - .md - Next Previous Backup Repair We detected an irrecoverably state of the app. Please backup your unsynchronized changes and clear the storage of the Notes app. + Folder to store your notes in your Nextcloud + + .txt + .md + + New notes folder: %1$s + File extension + File extension for new notes in your Nextcloud + New file suffix: %1$s + HTTP status code: %1$d From f9ccd7b95bb80f70b386a33e920969931ab75902 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 28 Jun 2021 13:41:39 +0200 Subject: [PATCH 12/12] Dismiss dialog when fetching existing settings was not successful Signed-off-by: Stefan Niedermann --- .../owncloud/notes/manageaccounts/ManageAccountsActivity.java | 2 ++ 1 file changed, 2 insertions(+) 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 74d50159f..d1b0e603d 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 @@ -159,6 +159,7 @@ public void onResponse(@NonNull Call call, @NonNull Response call, @NonNull Response