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>2020-03-14 01:04:38 +0300
committerstefan-niedermann <info@niedermann.it>2020-03-14 01:04:38 +0300
commite97eaa95c5484cf88cd91d71f71c614de9415d73 (patch)
treec2ba6791f43189b9eda50cc3212ddad5313c846f
parent87a9dbf3be27564555703a1bd29a19ab3ccf124e (diff)
Move contents of nextcloud-commons-lib back to project
Signed-off-by: stefan-niedermann <info@niedermann.it>
-rw-r--r--app/build.gradle7
-rw-r--r--app/src/main/AndroidManifest.xml28
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/ExceptionHandler.java48
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/ExceptionUtil.java72
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/ExceptionActivity.java32
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java2
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java2
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/SelectSingleNoteActivity.java2
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/SplashscreenActivity.java2
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/glide/SingleSignOnLibraryGlideModule.java33
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/glide/SingleSignOnStreamFetcher.java81
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/glide/SingleSignOnUrlLoader.java88
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java2
-rw-r--r--app/src/main/res/layout/activity_exception.xml76
-rw-r--r--fastlane/metadata/android/en-US/changelogs/2011000.txt1
15 files changed, 436 insertions, 40 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 0a0628a9..f44b56bc 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -13,8 +13,8 @@ android {
applicationId "it.niedermann.owncloud.notes"
minSdkVersion 14
targetSdkVersion 29
- versionCode 81
- versionName "2.10.3"
+ versionCode 2011000
+ versionName "2.11.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@@ -34,8 +34,7 @@ android {
}
dependencies {
- implementation "com.github.nextcloud:Android-SingleSignOn:0.5.0-rc3"
- implementation 'com.github.stefan-niedermann:nextcloud-commons:0.0.2'
+ implementation "com.github.nextcloud:Android-SingleSignOn:0.5.0"
implementation 'com.yydcdut:markdown-processor:0.1.3'
implementation 'com.yydcdut:rxmarkdown-wrapper:0.1.3'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3e640093..14ad435e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -7,7 +7,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
- android:name="it.niedermann.owncloud.notes.util.Notes"
+ android:name=".util.Notes"
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="@mipmap/ic_launcher"
@@ -19,7 +19,7 @@
tools:targetApi="n">
<activity
- android:name="it.niedermann.owncloud.notes.android.activity.SplashscreenActivity"
+ android:name=".android.activity.SplashscreenActivity"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -31,7 +31,7 @@
</activity>
<activity
- android:name="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity"
+ android:name=".android.activity.NotesListViewActivity"
android:label="@string/app_name">
<intent-filter>
@@ -43,24 +43,24 @@
android:resource="@xml/searchable" />
<meta-data
android:name="android.app.default_searchable"
- android:value="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity" />
+ android:value=".android.activity.NotesListViewActivity" />
</activity>
<activity
- android:name="it.niedermann.owncloud.notes.android.activity.ExceptionActivity"
+ android:name=".android.activity.ExceptionActivity"
android:label="@string/app_name" />
<activity
- android:name="it.niedermann.owncloud.notes.android.activity.PreferencesActivity"
+ android:name=".android.activity.PreferencesActivity"
android:label="@string/action_settings"
- android:parentActivityName="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity"
+ android:parentActivityName=".android.activity.NotesListViewActivity"
android:windowSoftInputMode="stateHidden" />
<activity
- android:name="it.niedermann.owncloud.notes.android.activity.EditNoteActivity"
+ android:name=".android.activity.EditNoteActivity"
android:label="@string/simple_edit"
android:launchMode="singleTask"
- android:parentActivityName="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity"
+ android:parentActivityName=".android.activity.NotesListViewActivity"
android:windowSoftInputMode="stateHidden">
<intent-filter android:label="@string/action_create">
<action android:name="android.intent.action.SEND" />
@@ -84,9 +84,9 @@
</activity>
<activity
- android:name="it.niedermann.owncloud.notes.android.activity.AboutActivity"
+ android:name=".android.activity.AboutActivity"
android:label="@string/simple_about"
- android:parentActivityName="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity" />
+ android:parentActivityName=".android.activity.NotesListViewActivity" />
<activity android:name=".android.activity.SelectSingleNoteActivity">
<intent-filter>
@@ -115,7 +115,7 @@
</receiver>
<receiver
- android:name="it.niedermann.owncloud.notes.android.appwidget.SingleNoteWidget"
+ android:name=".android.appwidget.SingleNoteWidget"
android:label="@string/widget_single_note_title">
<intent-filter>
@@ -128,7 +128,7 @@
</receiver>
<receiver
- android:name="it.niedermann.owncloud.notes.android.appwidget.NoteListWidget"
+ android:name=".android.appwidget.NoteListWidget"
android:label="@string/widget_note_list_title">
<intent-filter>
@@ -149,7 +149,7 @@
android:permission="android.permission.BIND_REMOTEVIEWS" />
<service
- android:name="it.niedermann.owncloud.notes.android.quicksettings.NewNoteTileService"
+ android:name=".android.quicksettings.NewNoteTileService"
android:description="@string/action_create"
android:icon="@drawable/ic_quicksettings_new"
android:label="@string/action_create"
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/ExceptionHandler.java b/app/src/main/java/it/niedermann/owncloud/notes/ExceptionHandler.java
new file mode 100644
index 00000000..8fdc2ebb
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/ExceptionHandler.java
@@ -0,0 +1,48 @@
+package it.niedermann.owncloud.notes;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import it.niedermann.owncloud.notes.android.activity.ExceptionActivity;
+
+
+public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
+
+ private static final String TAG = ExceptionHandler.class.getCanonicalName();
+ private Context context;
+ private Class<? extends Activity> errorActivity;
+ public static final String KEY_THROWABLE = "T";
+
+ public ExceptionHandler(Context context) {
+ super();
+ this.context = context;
+ this.errorActivity = ExceptionActivity.class;
+ }
+
+ public ExceptionHandler(Context context, Class<? extends Activity> errorActivity) {
+ super();
+ this.context = context;
+ this.errorActivity = errorActivity;
+ }
+
+ @Override
+ public void uncaughtException(@NonNull Thread t, @NonNull Throwable e) {
+ Log.e(TAG, e.getMessage(), e);
+ Intent intent = new Intent(context.getApplicationContext(), errorActivity);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ Bundle extras = new Bundle();
+ intent.putExtra(KEY_THROWABLE, e);
+ extras.putSerializable(KEY_THROWABLE, e);
+ intent.putExtras(extras);
+ context.getApplicationContext().startActivity(intent);
+ if (context instanceof Activity) {
+ ((Activity) context).finish();
+ }
+ Runtime.getRuntime().exit(0);
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/ExceptionUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/ExceptionUtil.java
new file mode 100644
index 00000000..c5de5d13
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/ExceptionUtil.java
@@ -0,0 +1,72 @@
+package it.niedermann.owncloud.notes;
+
+import android.app.Activity;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+
+import com.nextcloud.android.sso.helper.VersionCheckHelper;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ExceptionUtil {
+
+ private ExceptionUtil() {
+
+ }
+
+ public static String getDebugInfos(Activity activity, Throwable throwable) {
+ List<Throwable> throwables = new ArrayList<>();
+ throwables.add(throwable);
+ return getDebugInfos(activity, throwables);
+ }
+
+ public static String getDebugInfos(Activity activity, List<Throwable> throwables) {
+ StringBuilder debugInfos = new StringBuilder(""
+ + getAppVersions(activity)
+ + "\n\n---\n"
+ + getDeviceInfos()
+ + "\n\n---"
+ + "\n\n");
+ for (Throwable throwable : throwables) {
+ debugInfos.append(getStacktraceOf(throwable));
+ }
+ return debugInfos.toString();
+ }
+
+ private static String getAppVersions(Activity activity) {
+ String versions = "";
+ try {
+ PackageInfo pInfo = activity.getApplicationContext().getPackageManager().getPackageInfo(activity.getApplicationContext().getPackageName(), 0);
+ versions += "App Version: " + pInfo.versionName;
+ versions += "\nApp Version Code: " + pInfo.versionCode;
+ } catch (PackageManager.NameNotFoundException e) {
+ versions += "\nApp Version: " + e.getMessage();
+ e.printStackTrace();
+ }
+
+ try {
+ versions += "\nFiles App Version Code: " + VersionCheckHelper.getNextcloudFilesVersionCode(activity);
+ } catch (PackageManager.NameNotFoundException e) {
+ versions += "\nFiles App Version Code: " + e.getMessage();
+ e.printStackTrace();
+ }
+ return versions;
+ }
+
+ private static String getDeviceInfos() {
+ return ""
+ + "\nOS Version: " + System.getProperty("os.version") + "(" + android.os.Build.VERSION.INCREMENTAL + ")"
+ + "\nOS API Level: " + android.os.Build.VERSION.SDK_INT
+ + "\nDevice: " + android.os.Build.DEVICE
+ + "\nModel (and Product): " + android.os.Build.MODEL + " (" + android.os.Build.PRODUCT + ")";
+ }
+
+ private static String getStacktraceOf(Throwable e) {
+ StringWriter sw = new StringWriter();
+ e.printStackTrace(new PrintWriter(sw));
+ return sw.toString();
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/ExceptionActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/ExceptionActivity.java
index 3a8b5652..4b232cc4 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/ExceptionActivity.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/ExceptionActivity.java
@@ -4,51 +4,47 @@ import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.os.Bundle;
-import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
import java.util.Objects;
-import it.niedermann.nextcloud.exception.ExceptionUtil;
+import it.niedermann.owncloud.notes.ExceptionUtil;
import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.databinding.ActivityExceptionBinding;
+
+import static it.niedermann.owncloud.notes.ExceptionHandler.KEY_THROWABLE;
-import static it.niedermann.nextcloud.exception.ExceptionHandler.KEY_THROWABLE;
public class ExceptionActivity extends AppCompatActivity {
- private TextView stacktrace;
+ private ActivityExceptionBinding binding;
@SuppressLint("SetTextI18n") // only used for logging
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_exception);
- super.onCreate(savedInstanceState);
-
- Toolbar toolbar = findViewById(R.id.toolbar);
- TextView message = findViewById(R.id.message);
- stacktrace = findViewById(R.id.stacktrace);
+ binding = ActivityExceptionBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
- findViewById(R.id.copy).setOnClickListener((v) -> copyStacktraceToClipboard());
- findViewById(R.id.close).setOnClickListener((v) -> close());
+ binding.copy.setOnClickListener((v) -> copyStacktraceToClipboard());
+ binding.close.setOnClickListener((v) -> close());
- setSupportActionBar(toolbar);
+ setSupportActionBar(binding.toolbar);
Throwable throwable = (Throwable) Objects.requireNonNull(getIntent().getSerializableExtra(KEY_THROWABLE));
throwable.printStackTrace();
- toolbar.setTitle(getString(R.string.simple_error));
- message.setText(throwable.getMessage());
- stacktrace.setText(ExceptionUtil.getDebugInfos(this, throwable));
+ binding.toolbar.setTitle(getString(R.string.simple_error));
+ binding.message.setText(throwable.getMessage());
+ binding.stacktrace.setText(ExceptionUtil.getDebugInfos(this, throwable));
}
private void copyStacktraceToClipboard() {
final ClipboardManager clipboardManager = (ClipboardManager) Objects.requireNonNull(getSystemService(CLIPBOARD_SERVICE));
- ClipData clipData = ClipData.newPlainText(getString(R.string.simple_exception), "```\n" + this.stacktrace.getText() + "\n```");
+ ClipData clipData = ClipData.newPlainText(getString(R.string.simple_exception), "```\n" + binding.stacktrace.getText() + "\n```");
clipboardManager.setPrimaryClip(clipData);
Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show();
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java
index 346d7cfe..0a96cd1d 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java
@@ -10,7 +10,7 @@ import android.util.Log;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
-import it.niedermann.nextcloud.exception.ExceptionHandler;
+import it.niedermann.owncloud.notes.ExceptionHandler;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.util.Notes;
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java
index 623adbc3..0c4fea97 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java
@@ -128,6 +128,8 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ Integer.parseInt("as");
+
binding = DrawerLayoutBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
this.coordinatorLayout = binding.activityNotesListView.activityNotesListView;
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SelectSingleNoteActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SelectSingleNoteActivity.java
index 877514bd..97626182 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SelectSingleNoteActivity.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SelectSingleNoteActivity.java
@@ -12,7 +12,7 @@ import android.view.View;
import androidx.appcompat.widget.Toolbar;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
-import it.niedermann.nextcloud.exception.ExceptionHandler;
+import it.niedermann.owncloud.notes.ExceptionHandler;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.appwidget.SingleNoteWidget;
import it.niedermann.owncloud.notes.model.DBNote;
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SplashscreenActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SplashscreenActivity.java
index c6b8ad98..c05f5b47 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SplashscreenActivity.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SplashscreenActivity.java
@@ -5,7 +5,7 @@ import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
-import it.niedermann.nextcloud.exception.ExceptionHandler;
+import it.niedermann.owncloud.notes.ExceptionHandler;
/**
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/glide/SingleSignOnLibraryGlideModule.java b/app/src/main/java/it/niedermann/owncloud/notes/glide/SingleSignOnLibraryGlideModule.java
new file mode 100644
index 00000000..4c265701
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/glide/SingleSignOnLibraryGlideModule.java
@@ -0,0 +1,33 @@
+package it.niedermann.owncloud.notes.glide;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.Registry;
+import com.bumptech.glide.annotation.GlideModule;
+import com.bumptech.glide.load.model.GlideUrl;
+import com.bumptech.glide.module.LibraryGlideModule;
+
+import java.io.InputStream;
+
+/**
+ * Registers OkHttp related classes via Glide's annotation processor.
+ *
+ * <p>For Applications that depend on this library and include an {@link LibraryGlideModule} and Glide's
+ * annotation processor, this class will be automatically included.
+ */
+@GlideModule
+public final class SingleSignOnLibraryGlideModule extends LibraryGlideModule {
+
+ private static final String TAG = SingleSignOnLibraryGlideModule.class.getCanonicalName();
+
+ @Override
+ public void registerComponents(
+ @NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
+ Log.v(TAG, "Replacing default implementation for " + GlideUrl.class.getSimpleName() + ".");
+ registry.replace(GlideUrl.class, InputStream.class, new SingleSignOnUrlLoader.Factory(context));
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/glide/SingleSignOnStreamFetcher.java b/app/src/main/java/it/niedermann/owncloud/notes/glide/SingleSignOnStreamFetcher.java
new file mode 100644
index 00000000..a70c816c
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/glide/SingleSignOnStreamFetcher.java
@@ -0,0 +1,81 @@
+package it.niedermann.owncloud.notes.glide;
+
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.bumptech.glide.Priority;
+import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.data.DataFetcher;
+import com.bumptech.glide.load.model.GlideUrl;
+import com.nextcloud.android.sso.aidl.NextcloudRequest;
+import com.nextcloud.android.sso.api.NextcloudAPI;
+import com.nextcloud.android.sso.api.Response;
+
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Fetches an {@link InputStream} using the sso library.
+ */
+public class SingleSignOnStreamFetcher implements DataFetcher<InputStream> {
+
+ private final NextcloudAPI client;
+ private final GlideUrl url;
+
+ // Public API.
+ @SuppressWarnings("WeakerAccess")
+ public SingleSignOnStreamFetcher(NextcloudAPI client, GlideUrl url) {
+ this.client = client;
+ this.url = url;
+ }
+
+ @Override
+ public void loadData(@NonNull Priority priority, @NonNull final DataCallback<? super InputStream> callback) {Log.v("yey", "yey fetcher");
+ try {
+ NextcloudRequest.Builder requestBuilder = new NextcloudRequest.Builder()
+ .setMethod("GET")
+ .setUrl(url.toURL().getPath());
+ Map<String, List<String>> header = new HashMap<>();
+ for (Map.Entry<String, String> headerEntry : url.getHeaders().entrySet()) {
+ header.put(headerEntry.getKey(), Collections.singletonList(headerEntry.getValue()));
+ }
+ requestBuilder.setHeader(header);
+ NextcloudRequest nextcloudRequest = requestBuilder.build();
+ Response response = client.performNetworkRequestV2(nextcloudRequest);
+ callback.onDataReady(response.getBody());
+ } catch (MalformedURLException e) {
+ callback.onLoadFailed(e);
+ } catch (Exception e) {
+ callback.onLoadFailed(e);
+ }
+
+ }
+
+ @Override
+ public void cleanup() {
+
+ }
+
+ @Override
+ public void cancel() {
+
+ }
+
+ @NonNull
+ @Override
+ public Class<InputStream> getDataClass() {
+ return InputStream.class;
+ }
+
+ @NonNull
+ @Override
+ public DataSource getDataSource() {
+ return DataSource.REMOTE;
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/glide/SingleSignOnUrlLoader.java b/app/src/main/java/it/niedermann/owncloud/notes/glide/SingleSignOnUrlLoader.java
new file mode 100644
index 00000000..a9a57875
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/glide/SingleSignOnUrlLoader.java
@@ -0,0 +1,88 @@
+package it.niedermann.owncloud.notes.glide;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.bumptech.glide.load.Options;
+import com.bumptech.glide.load.model.GlideUrl;
+import com.bumptech.glide.load.model.ModelLoader;
+import com.bumptech.glide.load.model.ModelLoaderFactory;
+import com.bumptech.glide.load.model.MultiModelLoaderFactory;
+import com.google.gson.GsonBuilder;
+import com.nextcloud.android.sso.api.NextcloudAPI;
+import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
+import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
+import com.nextcloud.android.sso.helper.SingleAccountHelper;
+
+import java.io.InputStream;
+
+/**
+ * A simple model loader for fetching media over http/https using OkHttp.
+ */
+public class SingleSignOnUrlLoader implements ModelLoader<GlideUrl, InputStream> {
+
+ private static final String TAG = SingleSignOnUrlLoader.class.getCanonicalName();
+ private final NextcloudAPI client;
+
+ // Public API.
+ @SuppressWarnings("WeakerAccess")
+ public SingleSignOnUrlLoader(@NonNull NextcloudAPI client) {
+ this.client = client;
+ }
+
+ @Override
+ public boolean handles(@NonNull GlideUrl url) {
+ return true;
+ }
+
+ @Override
+ public LoadData<InputStream> buildLoadData(
+ @NonNull GlideUrl model, int width, int height, @NonNull Options options) {
+ return new LoadData<>(model, new SingleSignOnStreamFetcher(client, model));
+ }
+
+ /**
+ * The default factory for {@link SingleSignOnUrlLoader}s.
+ */
+ // Public API.
+ @SuppressWarnings("WeakerAccess")
+ public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
+ private SingleSignOnUrlLoader loader;
+
+ /**
+ * Constructor for a new Factory that runs requests using given client.
+ */
+ public Factory(@NonNull Context context) {
+ try {
+ loader = new SingleSignOnUrlLoader(new NextcloudAPI(context, SingleAccountHelper.getCurrentSingleSignOnAccount(context), new GsonBuilder().create(), new NextcloudAPI.ApiConnectedListener() {
+ @Override
+ public void onConnected() {
+ Log.v(TAG, "SSO API successfully initialized");
+ }
+
+ @Override
+ public void onError(Exception ex) {
+ Log.e(TAG, ex.getMessage(), ex);
+ }
+ }));
+ } catch (NextcloudFilesAppAccountNotFoundException e) {
+ e.printStackTrace();
+ } catch (NoCurrentAccountSelectedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @NonNull
+ @Override
+ public ModelLoader<GlideUrl, InputStream> build(MultiModelLoaderFactory multiFactory) {
+ return loader;
+ }
+
+ @Override
+ public void teardown() {
+ // Do nothing, this instance doesn't own the client.
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java
index e499e95a..26088d77 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java
@@ -42,7 +42,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
-import it.niedermann.nextcloud.exception.ExceptionUtil;
+import it.niedermann.owncloud.notes.ExceptionUtil;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.model.CloudNote;
import it.niedermann.owncloud.notes.model.DBNote;
diff --git a/app/src/main/res/layout/activity_exception.xml b/app/src/main/res/layout/activity_exception.xml
new file mode 100644
index 00000000..cbee5779
--- /dev/null
+++ b/app/src/main/res/layout/activity_exception.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <androidx.appcompat.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="?attr/colorPrimary"
+ android:theme="@style/toolbarStyle"
+ app:contentInsetStartWithNavigation="0dp"
+ app:elevation="4dp"
+ app:titleMarginStart="0dp"
+ tools:title="@string/simple_exception" />
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="@dimen/activity_margin"
+ android:hint="An error appeared."
+ tools:ignore="HardcodedText" />
+
+ <TextView
+ android:id="@+id/stacktrace"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginStart="@dimen/activity_margin"
+ android:layout_marginLeft="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginRight="16dp"
+ android:layout_weight="1"
+ android:background="@color/bg_highlighted"
+ android:padding="8dp"
+ android:scrollbars="horizontal|vertical"
+ android:textIsSelectable="true"
+ android:typeface="monospace"
+ tools:text="@string/android_get_accounts_permission_not_granted_exception_message" />
+
+ <LinearLayout
+ style="?android:buttonBarStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="16dp"
+ android:gravity="end"
+ android:orientation="horizontal"
+ android:weightSum="1.0">
+
+ <Button
+ android:id="@+id/close"
+ style="?android:buttonBarButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_weight=".5"
+ android:text="@string/simple_close" />
+
+ <Button
+ android:id="@+id/copy"
+ style="?android:buttonBarButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ android:layout_weight=".5"
+ android:background="@color/primary"
+ android:foreground="?attr/selectableItemBackground"
+ android:text="@string/simple_copy"
+ android:textColor="@color/fg_contrast"
+ tools:ignore="UnusedAttribute" />
+
+ </LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/2011000.txt b/fastlane/metadata/android/en-US/changelogs/2011000.txt
new file mode 100644
index 00000000..e4ae4069
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/2011000.txt
@@ -0,0 +1 @@
+- 🔒 Password protection (#354) - special thanks to @beatbrot