Loading app/build.gradle +1 −1 Original line number Diff line number Diff line Loading @@ -56,7 +56,7 @@ dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.6' // Nextcloud SSO implementation 'foundation.e.lib:Android-SingleSignOn:1.0.5-alpha' implementation 'foundation.e.lib:Android-SingleSignOn:1.0.7-alpha' implementation ('com.github.stefan-niedermann:android-commons:0.2.7') { exclude group: 'com.github.nextcloud', module: 'Android-SingleSignOn' } Loading app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportAccountActivity.java +79 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotSupportedExcepti import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException; import com.nextcloud.android.sso.exceptions.UnknownErrorException; import com.nextcloud.android.sso.helper.SingleAccountHelper; import com.nextcloud.android.sso.model.SingleSignOnAccount; import com.nextcloud.android.sso.ui.UiExceptionManager; import java.net.HttpURLConnection; Loading Loading @@ -68,6 +69,8 @@ public class ImportAccountActivity extends AppCompatActivity { binding.addButton.setOnClickListener((v) -> { binding.addButton.setEnabled(false); binding.addButton.setVisibility(View.INVISIBLE); binding.addLocalButton.setEnabled(false); binding.addLocalButton.setVisibility(View.INVISIBLE); binding.status.setVisibility(View.GONE); try { AccountImporter.pickNewAccount(this); Loading @@ -79,10 +82,14 @@ public class ImportAccountActivity extends AppCompatActivity { } catch (AndroidGetAccountsPermissionNotGranted e) { binding.addButton.setEnabled(true); binding.addButton.setVisibility(View.VISIBLE); binding.addLocalButton.setEnabled(true); binding.addLocalButton.setVisibility(View.VISIBLE); AccountImporter.requestAndroidAccountPermissionsAndPickAccount(this); } }); handleLocalAccount(); handleAutoMurenaAccountSetup(); } Loading Loading @@ -186,6 +193,8 @@ public class ImportAccountActivity extends AppCompatActivity { runOnUiThread(() -> { binding.addButton.setEnabled(true); binding.addButton.setVisibility(View.VISIBLE); binding.addLocalButton.setEnabled(true); binding.addLocalButton.setVisibility(View.VISIBLE); binding.progressCircular.setVisibility(View.GONE); binding.progressText.setVisibility(View.GONE); }); Loading @@ -195,6 +204,8 @@ public class ImportAccountActivity extends AppCompatActivity { if (importMurenaAccountViewModel.isMurenaAccountPresent()) { binding.addButton.setEnabled(false); binding.addButton.setVisibility(View.INVISIBLE); binding.addLocalButton.setEnabled(false); binding.addLocalButton.setVisibility(View.INVISIBLE); binding.status.setVisibility(View.GONE); pickMurenaAccount(); Loading @@ -214,7 +225,75 @@ public class ImportAccountActivity extends AppCompatActivity { NextcloudFilesAppAccountPermissionNotGrantedException e) { binding.addButton.setEnabled(true); binding.addButton.setVisibility(View.VISIBLE); binding.addLocalButton.setEnabled(true); binding.addLocalButton.setVisibility(View.VISIBLE); AccountImporter.requestAndroidAccountPermissionsAndPickAccount(this); } } private void handleLocalAccount() { binding.addLocalButton.setOnClickListener(v -> { SingleSignOnAccount singleSignOnAccount = AccountImporter.pickLocalAccount(this); SingleAccountHelper.setCurrentAccount(getApplicationContext(), singleSignOnAccount.name); executor.submit(() -> { Log.i(TAG, "Added local account: " + "name:" + singleSignOnAccount.name); try { Log.i(TAG, "Loading capabilities for " + singleSignOnAccount.name); final var capabilities = CapabilitiesClient.getCapabilities(getApplicationContext(), singleSignOnAccount, null, ApiProvider.getInstance()); final String displayName = CapabilitiesClient.getDisplayName(getApplicationContext(), singleSignOnAccount, ApiProvider.getInstance()); importAccountViewModel.addAccount(singleSignOnAccount.url, singleSignOnAccount.userId, singleSignOnAccount.name, capabilities, displayName, new IResponseCallback<>() { /** * Update syncing when adding account * https://github.com/stefan-niedermann/nextcloud-deck/issues/531 * @param account the account to add */ @Override public void onSuccess(Account account) { runOnUiThread(() -> { Log.i(TAG, capabilities.toString()); BrandingUtil.saveBrandColors(ImportAccountActivity.this, capabilities.getColor(), capabilities.getTextColor()); setResult(RESULT_OK); Intent intent = new Intent(ImportAccountActivity.this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); finish(); }); SyncWorker.update(ImportAccountActivity.this, PreferenceManager.getDefaultSharedPreferences(ImportAccountActivity.this) .getBoolean(getString(R.string.pref_key_background_sync), true)); } @Override public void onError(@NonNull Throwable t) { runOnUiThread(() -> { restoreCleanState(); ExceptionDialogFragment.newInstance(t).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); }); } }); } catch (Throwable t) { t.printStackTrace(); ApiProvider.getInstance().invalidateAPICache(singleSignOnAccount); SingleAccountHelper.setCurrentAccount(this, null); runOnUiThread(() -> { restoreCleanState(); if (t instanceof NextcloudHttpRequestFailedException && ((NextcloudHttpRequestFailedException) t).getStatusCode() == HttpURLConnection.HTTP_UNAVAILABLE) { binding.status.setText(R.string.error_maintenance_mode); binding.status.setVisibility(View.VISIBLE); } else if (t instanceof NetworkErrorException) { binding.status.setText(getString(R.string.error_sync, getString(R.string.error_no_network))); binding.status.setVisibility(View.VISIBLE); } else if (t instanceof UnknownErrorException && t.getMessage() != null && t.getMessage().contains("No address associated with hostname")) { // https://github.com/stefan-niedermann/nextcloud-notes/issues/1014 binding.status.setText(R.string.you_have_to_be_connected_to_the_internet_in_order_to_add_an_account); binding.status.setVisibility(View.VISIBLE); } else { ExceptionDialogFragment.newInstance(t).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); } }); } }); }); } } No newline at end of file app/src/main/java/it/niedermann/owncloud/notes/main/menu/MenuAdapter.java +15 −6 Original line number Diff line number Diff line Loading @@ -15,12 +15,16 @@ import com.nextcloud.android.sso.Constants; import com.nextcloud.android.sso.helper.VersionCheckHelper; import com.nextcloud.android.sso.model.FilesAppType; import java.util.ArrayList; import java.util.stream.Collectors; import it.niedermann.owncloud.notes.FormattingHelpActivity; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.about.AboutActivity; import it.niedermann.owncloud.notes.databinding.ItemNavigationBinding; import it.niedermann.owncloud.notes.persistence.entity.Account; import it.niedermann.owncloud.notes.preferences.PreferencesActivity; import it.niedermann.owncloud.notes.shared.util.AccountSyncUtil; public class MenuAdapter extends RecyclerView.Adapter<MenuViewHolder> { Loading @@ -30,12 +34,17 @@ public class MenuAdapter extends RecyclerView.Adapter<MenuViewHolder> { private final Consumer<MenuItem> onClick; public MenuAdapter(@NonNull Context context, @NonNull Account account, int settingsRequestCode, @NonNull Consumer<MenuItem> onClick) { this.menuItems = new MenuItem[]{ new MenuItem(new Intent(context, FormattingHelpActivity.class), R.string.action_formatting_help, R.drawable.ic_baseline_help_outline_24), new MenuItem(generateTrashbinIntent(context, account), R.string.action_trashbin, R.drawable.ic_delete_grey600_24dp), new MenuItem(new Intent(context, PreferencesActivity.class), settingsRequestCode, R.string.action_settings, R.drawable.ic_settings_grey600_24dp), new MenuItem(new Intent(context, AboutActivity.class), R.string.simple_about, R.drawable.ic_info_outline_grey600_24dp) }; var menuList = new ArrayList<MenuItem>(); menuList.add(new MenuItem(new Intent(context, FormattingHelpActivity.class), R.string.action_formatting_help, R.drawable.ic_baseline_help_outline_24)); if (!AccountSyncUtil.isLocalAccount(context, account)) { menuList.add(new MenuItem(generateTrashbinIntent(context, account), R.string.action_trashbin, R.drawable.ic_delete_grey600_24dp)); } menuList.add(new MenuItem(new Intent(context, PreferencesActivity.class), settingsRequestCode, R.string.action_settings, R.drawable.ic_settings_grey600_24dp)); menuList.add(new MenuItem(new Intent(context, AboutActivity.class), R.string.simple_about, R.drawable.ic_info_outline_grey600_24dp)); this.menuItems = menuList.toArray(new MenuItem[0]); this.onClick = onClick; setHasStableIds(true); } Loading app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountViewHolder.java +4 −2 Original line number Diff line number Diff line Loading @@ -51,11 +51,13 @@ public class ManageAccountViewHolder extends RecyclerView.ViewHolder { final var preferredApiVersion = getPreferredApiVersion(localAccount.getApiVersion()); if (preferredApiVersion == null || !preferredApiVersion.supportsFileSuffixChange()) { boolean isLocalAccount = AccountSyncUtil.isLocalAccount(itemView.getContext(), localAccount); if (preferredApiVersion == null || !preferredApiVersion.supportsFileSuffixChange() || isLocalAccount) { popup.getMenu().removeItem(popup.getMenu().findItem(R.id.file_suffix).getItemId()); } if (preferredApiVersion == null || !preferredApiVersion.supportsNotesPathChange()) { if (preferredApiVersion == null || !preferredApiVersion.supportsNotesPathChange() || isLocalAccount) { popup.getMenu().removeItem(popup.getMenu().findItem(R.id.notes_path).getItemId()); } Loading app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesClient.java +9 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ import androidx.annotation.WorkerThread; import com.nextcloud.android.sso.model.SingleSignOnAccount; import it.niedermann.owncloud.notes.shared.model.Capabilities; import it.niedermann.owncloud.notes.shared.util.AccountSyncUtil; import it.niedermann.owncloud.notes.shared.util.SSOUtil; import trikita.log.Log; Loading @@ -21,6 +22,10 @@ public class CapabilitiesClient { @WorkerThread public static Capabilities getCapabilities(@NonNull Context context, @NonNull SingleSignOnAccount ssoAccount, @Nullable String lastETag, @NonNull ApiProvider apiProvider) throws Throwable { if (AccountSyncUtil.isLocalAccount(ssoAccount)) { return new Capabilities(); } final var ocsAPI = apiProvider.getOcsAPI(context, ssoAccount); try { final var response = ocsAPI.getCapabilities(lastETag).blockingSingle(); Loading @@ -45,6 +50,10 @@ public class CapabilitiesClient { @WorkerThread @Nullable public static String getDisplayName(@NonNull Context context, @NonNull SingleSignOnAccount ssoAccount, @NonNull ApiProvider apiProvider) { if (AccountSyncUtil.isLocalAccount(ssoAccount)) { return ssoAccount.name; } final var ocsAPI = apiProvider.getOcsAPI(context, ssoAccount); try { final var userResponse = ocsAPI.getUser(SSOUtil.sanitizeUserId(ssoAccount.userId)).execute(); Loading Loading
app/build.gradle +1 −1 Original line number Diff line number Diff line Loading @@ -56,7 +56,7 @@ dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.6' // Nextcloud SSO implementation 'foundation.e.lib:Android-SingleSignOn:1.0.5-alpha' implementation 'foundation.e.lib:Android-SingleSignOn:1.0.7-alpha' implementation ('com.github.stefan-niedermann:android-commons:0.2.7') { exclude group: 'com.github.nextcloud', module: 'Android-SingleSignOn' } Loading
app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportAccountActivity.java +79 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotSupportedExcepti import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException; import com.nextcloud.android.sso.exceptions.UnknownErrorException; import com.nextcloud.android.sso.helper.SingleAccountHelper; import com.nextcloud.android.sso.model.SingleSignOnAccount; import com.nextcloud.android.sso.ui.UiExceptionManager; import java.net.HttpURLConnection; Loading Loading @@ -68,6 +69,8 @@ public class ImportAccountActivity extends AppCompatActivity { binding.addButton.setOnClickListener((v) -> { binding.addButton.setEnabled(false); binding.addButton.setVisibility(View.INVISIBLE); binding.addLocalButton.setEnabled(false); binding.addLocalButton.setVisibility(View.INVISIBLE); binding.status.setVisibility(View.GONE); try { AccountImporter.pickNewAccount(this); Loading @@ -79,10 +82,14 @@ public class ImportAccountActivity extends AppCompatActivity { } catch (AndroidGetAccountsPermissionNotGranted e) { binding.addButton.setEnabled(true); binding.addButton.setVisibility(View.VISIBLE); binding.addLocalButton.setEnabled(true); binding.addLocalButton.setVisibility(View.VISIBLE); AccountImporter.requestAndroidAccountPermissionsAndPickAccount(this); } }); handleLocalAccount(); handleAutoMurenaAccountSetup(); } Loading Loading @@ -186,6 +193,8 @@ public class ImportAccountActivity extends AppCompatActivity { runOnUiThread(() -> { binding.addButton.setEnabled(true); binding.addButton.setVisibility(View.VISIBLE); binding.addLocalButton.setEnabled(true); binding.addLocalButton.setVisibility(View.VISIBLE); binding.progressCircular.setVisibility(View.GONE); binding.progressText.setVisibility(View.GONE); }); Loading @@ -195,6 +204,8 @@ public class ImportAccountActivity extends AppCompatActivity { if (importMurenaAccountViewModel.isMurenaAccountPresent()) { binding.addButton.setEnabled(false); binding.addButton.setVisibility(View.INVISIBLE); binding.addLocalButton.setEnabled(false); binding.addLocalButton.setVisibility(View.INVISIBLE); binding.status.setVisibility(View.GONE); pickMurenaAccount(); Loading @@ -214,7 +225,75 @@ public class ImportAccountActivity extends AppCompatActivity { NextcloudFilesAppAccountPermissionNotGrantedException e) { binding.addButton.setEnabled(true); binding.addButton.setVisibility(View.VISIBLE); binding.addLocalButton.setEnabled(true); binding.addLocalButton.setVisibility(View.VISIBLE); AccountImporter.requestAndroidAccountPermissionsAndPickAccount(this); } } private void handleLocalAccount() { binding.addLocalButton.setOnClickListener(v -> { SingleSignOnAccount singleSignOnAccount = AccountImporter.pickLocalAccount(this); SingleAccountHelper.setCurrentAccount(getApplicationContext(), singleSignOnAccount.name); executor.submit(() -> { Log.i(TAG, "Added local account: " + "name:" + singleSignOnAccount.name); try { Log.i(TAG, "Loading capabilities for " + singleSignOnAccount.name); final var capabilities = CapabilitiesClient.getCapabilities(getApplicationContext(), singleSignOnAccount, null, ApiProvider.getInstance()); final String displayName = CapabilitiesClient.getDisplayName(getApplicationContext(), singleSignOnAccount, ApiProvider.getInstance()); importAccountViewModel.addAccount(singleSignOnAccount.url, singleSignOnAccount.userId, singleSignOnAccount.name, capabilities, displayName, new IResponseCallback<>() { /** * Update syncing when adding account * https://github.com/stefan-niedermann/nextcloud-deck/issues/531 * @param account the account to add */ @Override public void onSuccess(Account account) { runOnUiThread(() -> { Log.i(TAG, capabilities.toString()); BrandingUtil.saveBrandColors(ImportAccountActivity.this, capabilities.getColor(), capabilities.getTextColor()); setResult(RESULT_OK); Intent intent = new Intent(ImportAccountActivity.this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); finish(); }); SyncWorker.update(ImportAccountActivity.this, PreferenceManager.getDefaultSharedPreferences(ImportAccountActivity.this) .getBoolean(getString(R.string.pref_key_background_sync), true)); } @Override public void onError(@NonNull Throwable t) { runOnUiThread(() -> { restoreCleanState(); ExceptionDialogFragment.newInstance(t).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); }); } }); } catch (Throwable t) { t.printStackTrace(); ApiProvider.getInstance().invalidateAPICache(singleSignOnAccount); SingleAccountHelper.setCurrentAccount(this, null); runOnUiThread(() -> { restoreCleanState(); if (t instanceof NextcloudHttpRequestFailedException && ((NextcloudHttpRequestFailedException) t).getStatusCode() == HttpURLConnection.HTTP_UNAVAILABLE) { binding.status.setText(R.string.error_maintenance_mode); binding.status.setVisibility(View.VISIBLE); } else if (t instanceof NetworkErrorException) { binding.status.setText(getString(R.string.error_sync, getString(R.string.error_no_network))); binding.status.setVisibility(View.VISIBLE); } else if (t instanceof UnknownErrorException && t.getMessage() != null && t.getMessage().contains("No address associated with hostname")) { // https://github.com/stefan-niedermann/nextcloud-notes/issues/1014 binding.status.setText(R.string.you_have_to_be_connected_to_the_internet_in_order_to_add_an_account); binding.status.setVisibility(View.VISIBLE); } else { ExceptionDialogFragment.newInstance(t).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()); } }); } }); }); } } No newline at end of file
app/src/main/java/it/niedermann/owncloud/notes/main/menu/MenuAdapter.java +15 −6 Original line number Diff line number Diff line Loading @@ -15,12 +15,16 @@ import com.nextcloud.android.sso.Constants; import com.nextcloud.android.sso.helper.VersionCheckHelper; import com.nextcloud.android.sso.model.FilesAppType; import java.util.ArrayList; import java.util.stream.Collectors; import it.niedermann.owncloud.notes.FormattingHelpActivity; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.about.AboutActivity; import it.niedermann.owncloud.notes.databinding.ItemNavigationBinding; import it.niedermann.owncloud.notes.persistence.entity.Account; import it.niedermann.owncloud.notes.preferences.PreferencesActivity; import it.niedermann.owncloud.notes.shared.util.AccountSyncUtil; public class MenuAdapter extends RecyclerView.Adapter<MenuViewHolder> { Loading @@ -30,12 +34,17 @@ public class MenuAdapter extends RecyclerView.Adapter<MenuViewHolder> { private final Consumer<MenuItem> onClick; public MenuAdapter(@NonNull Context context, @NonNull Account account, int settingsRequestCode, @NonNull Consumer<MenuItem> onClick) { this.menuItems = new MenuItem[]{ new MenuItem(new Intent(context, FormattingHelpActivity.class), R.string.action_formatting_help, R.drawable.ic_baseline_help_outline_24), new MenuItem(generateTrashbinIntent(context, account), R.string.action_trashbin, R.drawable.ic_delete_grey600_24dp), new MenuItem(new Intent(context, PreferencesActivity.class), settingsRequestCode, R.string.action_settings, R.drawable.ic_settings_grey600_24dp), new MenuItem(new Intent(context, AboutActivity.class), R.string.simple_about, R.drawable.ic_info_outline_grey600_24dp) }; var menuList = new ArrayList<MenuItem>(); menuList.add(new MenuItem(new Intent(context, FormattingHelpActivity.class), R.string.action_formatting_help, R.drawable.ic_baseline_help_outline_24)); if (!AccountSyncUtil.isLocalAccount(context, account)) { menuList.add(new MenuItem(generateTrashbinIntent(context, account), R.string.action_trashbin, R.drawable.ic_delete_grey600_24dp)); } menuList.add(new MenuItem(new Intent(context, PreferencesActivity.class), settingsRequestCode, R.string.action_settings, R.drawable.ic_settings_grey600_24dp)); menuList.add(new MenuItem(new Intent(context, AboutActivity.class), R.string.simple_about, R.drawable.ic_info_outline_grey600_24dp)); this.menuItems = menuList.toArray(new MenuItem[0]); this.onClick = onClick; setHasStableIds(true); } Loading
app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountViewHolder.java +4 −2 Original line number Diff line number Diff line Loading @@ -51,11 +51,13 @@ public class ManageAccountViewHolder extends RecyclerView.ViewHolder { final var preferredApiVersion = getPreferredApiVersion(localAccount.getApiVersion()); if (preferredApiVersion == null || !preferredApiVersion.supportsFileSuffixChange()) { boolean isLocalAccount = AccountSyncUtil.isLocalAccount(itemView.getContext(), localAccount); if (preferredApiVersion == null || !preferredApiVersion.supportsFileSuffixChange() || isLocalAccount) { popup.getMenu().removeItem(popup.getMenu().findItem(R.id.file_suffix).getItemId()); } if (preferredApiVersion == null || !preferredApiVersion.supportsNotesPathChange()) { if (preferredApiVersion == null || !preferredApiVersion.supportsNotesPathChange() || isLocalAccount) { popup.getMenu().removeItem(popup.getMenu().findItem(R.id.notes_path).getItemId()); } Loading
app/src/main/java/it/niedermann/owncloud/notes/persistence/CapabilitiesClient.java +9 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ import androidx.annotation.WorkerThread; import com.nextcloud.android.sso.model.SingleSignOnAccount; import it.niedermann.owncloud.notes.shared.model.Capabilities; import it.niedermann.owncloud.notes.shared.util.AccountSyncUtil; import it.niedermann.owncloud.notes.shared.util.SSOUtil; import trikita.log.Log; Loading @@ -21,6 +22,10 @@ public class CapabilitiesClient { @WorkerThread public static Capabilities getCapabilities(@NonNull Context context, @NonNull SingleSignOnAccount ssoAccount, @Nullable String lastETag, @NonNull ApiProvider apiProvider) throws Throwable { if (AccountSyncUtil.isLocalAccount(ssoAccount)) { return new Capabilities(); } final var ocsAPI = apiProvider.getOcsAPI(context, ssoAccount); try { final var response = ocsAPI.getCapabilities(lastETag).blockingSingle(); Loading @@ -45,6 +50,10 @@ public class CapabilitiesClient { @WorkerThread @Nullable public static String getDisplayName(@NonNull Context context, @NonNull SingleSignOnAccount ssoAccount, @NonNull ApiProvider apiProvider) { if (AccountSyncUtil.isLocalAccount(ssoAccount)) { return ssoAccount.name; } final var ocsAPI = apiProvider.getOcsAPI(context, ssoAccount); try { final var userResponse = ocsAPI.getUser(SSOUtil.sanitizeUserId(ssoAccount.userId)).execute(); Loading