From 6a126508bd36d97affa17f85ff65c2f5a7bbfaca Mon Sep 17 00:00:00 2001 From: alperozturk Date: Fri, 22 Aug 2025 14:33:41 +0200 Subject: [PATCH 1/5] add: nextcloud network exception check Signed-off-by: alperozturk --- app/build.gradle | 8 +++-- .../owncloud/notes/NotesApplication.java | 2 +- .../owncloud/notes/main/menu/MenuAdapter.java | 6 ++-- .../persistence/NotesServerSyncTask.java | 26 +++++++++------ .../notes/persistence/sync/NotesAPI.java | 3 +- build.gradle | 1 + gradle/verification-metadata.xml | 32 +++++++++++++++++++ 7 files changed, 62 insertions(+), 16 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8d8b7f3ab..22dcb8e23 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -120,8 +120,12 @@ dependencies { // Nextcloud SSO implementation 'com.github.nextcloud.android-common:ui:0.28.0' - implementation 'com.github.nextcloud:Android-SingleSignOn:1.3.2' - implementation "com.github.stefan-niedermann.android-commons:shared-preferences:$androidCommonsVersion" + implementation("com.github.nextcloud:Android-SingleSignOn:$singleSignOnVersion") { + version { + strictly(singleSignOnVersion) + } + } + implementation "com.github.stefan-niedermann.android-commons:shared-preferences:$androidCommonsVersion" implementation "com.github.stefan-niedermann.android-commons:reactive-livedata:$androidCommonsVersion" implementation "com.github.stefan-niedermann.android-commons:util:$androidCommonsVersion" implementation "com.github.stefan-niedermann.nextcloud-commons:sso-glide:$commonsVersion" diff --git a/app/src/main/java/it/niedermann/owncloud/notes/NotesApplication.java b/app/src/main/java/it/niedermann/owncloud/notes/NotesApplication.java index 5d4795e0a..423525fc6 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/NotesApplication.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/NotesApplication.java @@ -61,7 +61,7 @@ private void registerFilesAppType() { return; } - FilesAppTypeRegistry.getInstance().init(new FilesAppType(packageId, accountType, FilesAppType.Type.PROD)); + FilesAppTypeRegistry.getInstance().init(new FilesAppType(packageId, accountType, FilesAppType.Stage.PROD)); } public static BrandingUtil brandingUtil() { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/menu/MenuAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/main/menu/MenuAdapter.java index 17bb9dcdc..58e413031 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/menu/MenuAdapter.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/menu/MenuAdapter.java @@ -87,8 +87,8 @@ private static Intent generateTrashbinIntent(@NonNull Context context, @NonNull // https://github.com/nextcloud/android/pull/8405#issuecomment-852966877 final int minVersionCode = 30170090; try { - Optional prod = FilesAppTypeRegistry.getInstance().getTypes().stream().filter(t -> t.type == FilesAppType.Type.PROD).findFirst(); - Optional dev = FilesAppTypeRegistry.getInstance().getTypes().stream().filter(t -> t.type == FilesAppType.Type.DEV).findFirst(); + Optional prod = FilesAppTypeRegistry.getInstance().getTypes().stream().filter(t -> t.stage() == FilesAppType.Stage.PROD).findFirst(); + Optional dev = FilesAppTypeRegistry.getInstance().getTypes().stream().filter(t -> t.stage() == FilesAppType.Stage.DEV).findFirst(); if (prod.isPresent() && VersionCheckHelper.getNextcloudFilesVersionCode(context, prod.get()) > minVersionCode) { return generateTrashbinAppIntent(context, account, prod.get()); } else if (dev.isPresent() && VersionCheckHelper.getNextcloudFilesVersionCode(context, dev.get()) > minVersionCode) { @@ -105,7 +105,7 @@ private static Intent generateTrashbinIntent(@NonNull Context context, @NonNull private static Intent generateTrashbinAppIntent(@NonNull Context context, @NonNull Account account, FilesAppType type) throws PackageManager.NameNotFoundException { final var packageManager = context.getPackageManager(); - final String packageName = type.packageId; + final String packageName = type.packageId(); final var intent = new Intent(); intent.setClassName(packageName, "com.owncloud.android.ui.trashbin.TrashbinActivity"); if (packageManager.resolveActivity(intent, 0) != null) { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java index cbfe06d1f..c2e487438 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java @@ -6,18 +6,25 @@ */ package it.niedermann.owncloud.notes.persistence; +import static java.net.HttpURLConnection.HTTP_NOT_FOUND; +import static java.net.HttpURLConnection.HTTP_NOT_MODIFIED; +import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; +import static it.niedermann.owncloud.notes.shared.model.DBStatus.LOCAL_DELETED; +import static it.niedermann.owncloud.notes.shared.util.NoteUtil.generateNoteExcerpt; + import android.content.Context; import android.util.Log; import androidx.annotation.NonNull; import com.nextcloud.android.sso.AccountImporter; -import com.nextcloud.android.sso.api.ParsedResponse; import com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException; import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException; +import com.nextcloud.android.sso.exceptions.NextcloudNetworkException; import com.nextcloud.android.sso.exceptions.TokenMismatchException; import com.nextcloud.android.sso.model.SingleSignOnAccount; +import com.owncloud.android.lib.common.utils.Log_OC; import java.util.ArrayList; import java.util.Calendar; @@ -26,7 +33,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import it.niedermann.owncloud.notes.BuildConfig; import it.niedermann.owncloud.notes.persistence.entity.Account; @@ -36,13 +42,6 @@ import it.niedermann.owncloud.notes.shared.model.ISyncCallback; import it.niedermann.owncloud.notes.shared.model.SyncResultStatus; import it.niedermann.owncloud.notes.shared.util.ApiVersionUtil; -import retrofit2.Response; - -import static it.niedermann.owncloud.notes.shared.model.DBStatus.LOCAL_DELETED; -import static it.niedermann.owncloud.notes.shared.util.NoteUtil.generateNoteExcerpt; -import static java.net.HttpURLConnection.HTTP_NOT_FOUND; -import static java.net.HttpURLConnection.HTTP_NOT_MODIFIED; -import static java.net.HttpURLConnection.HTTP_UNAVAILABLE; /** @@ -221,6 +220,11 @@ private boolean pullRemoteChanges() { } localAccount.setModified(accountFromDatabase.getModified()); localAccount.setETag(accountFromDatabase.getETag()); + final var modified = localAccount.getModified(); + if (modified == null) { + Log_OC.e(TAG, "modified is null cannot fetch notes"); + return false; + } final var fetchResponse = notesAPI.getNotes(localAccount.getModified(), localAccount.getETag()).blockingSingle(); final var remoteNotes = fetchResponse.getResponse(); @@ -289,7 +293,11 @@ private boolean pullRemoteChanges() { } else if (cause.getClass() == NextcloudApiNotRespondingException.class || cause instanceof NextcloudApiNotRespondingException) { apiProvider.invalidateAPICache(ssoAccount); } + } else if (t.getClass() == NextcloudNetworkException.class) { + Log.w(TAG, "Network connectivity issue during sync"); + return true; } + exceptions.add(t); return false; } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java index 9f0189931..0b3d67b6b 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java @@ -15,6 +15,7 @@ import com.nextcloud.android.sso.api.EmptyResponse; import com.nextcloud.android.sso.api.NextcloudAPI; import com.nextcloud.android.sso.api.ParsedResponse; +import com.nextcloud.android.sso.exceptions.NextcloudNetworkException; import java.util.Calendar; import java.util.HashMap; @@ -68,7 +69,7 @@ public NotesAPI(@NonNull NextcloudAPI nextcloudAPI, @Nullable ApiVersion preferr } } - public Observable>> getNotes(@NonNull Calendar lastModified, String lastETag) { + public Observable>> getNotes(@NonNull Calendar lastModified, String lastETag) throws NextcloudNetworkException { if (ApiVersion.API_VERSION_1_0.equals(usedApiVersion)) { return notesAPI_1_0.getNotes(lastModified.getTimeInMillis() / 1_000, lastETag); } else if (ApiVersion.API_VERSION_0_2.equals(usedApiVersion)) { diff --git a/build.gradle b/build.gradle index 8b973f337..500897703 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,7 @@ buildscript { kotlinVersion = '2.2.20' commonsVersion = '2.3.7' androidCommonsVersion = '1.1.0' + singleSignOnVersion = "1d31061d17" } repositories { mavenCentral() diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 938a165af..fb3779f3a 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -239,6 +239,7 @@ + @@ -10217,6 +10218,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -13002,6 +13029,11 @@ + + + + + From 438844383e4dd62948d3999b24337b29f73fe8cd Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 11 Sep 2025 15:17:41 +0200 Subject: [PATCH 2/5] chore: use single sign on 1.3.3 rc1 Signed-off-by: alperozturk --- build.gradle | 2 +- gradle/verification-metadata.xml | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 500897703..39f36191d 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ buildscript { kotlinVersion = '2.2.20' commonsVersion = '2.3.7' androidCommonsVersion = '1.1.0' - singleSignOnVersion = "1d31061d17" + singleSignOnVersion = "17df25ce03d98b9d868249b41f7300bff6c54f3e" } repositories { mavenCentral() diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index fb3779f3a..29f1703f1 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -10218,6 +10218,14 @@ + + + + + + + + From 6c566b13c82cd62f075c31e75325c4cd188fa4fb Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 11 Sep 2025 15:19:43 +0200 Subject: [PATCH 3/5] fix: get notes test Signed-off-by: alperozturk --- .../it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java index 0b3d67b6b..256ddc54e 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/NotesAPI.java @@ -69,7 +69,7 @@ public NotesAPI(@NonNull NextcloudAPI nextcloudAPI, @Nullable ApiVersion preferr } } - public Observable>> getNotes(@NonNull Calendar lastModified, String lastETag) throws NextcloudNetworkException { + public Observable>> getNotes(@NonNull Calendar lastModified, String lastETag) { if (ApiVersion.API_VERSION_1_0.equals(usedApiVersion)) { return notesAPI_1_0.getNotes(lastModified.getTimeInMillis() / 1_000, lastETag); } else if (ApiVersion.API_VERSION_0_2.equals(usedApiVersion)) { From 56fdbf58f8e364cc2bbb90d456c2456e028d6030 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 11 Sep 2025 15:22:36 +0200 Subject: [PATCH 4/5] fix: get notes test Signed-off-by: alperozturk --- .../owncloud/notes/persistence/NotesServerSyncTask.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java index c2e487438..f26042bd9 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java @@ -292,10 +292,10 @@ private boolean pullRemoteChanges() { } } else if (cause.getClass() == NextcloudApiNotRespondingException.class || cause instanceof NextcloudApiNotRespondingException) { apiProvider.invalidateAPICache(ssoAccount); + } else if (cause.getClass() == NextcloudNetworkException.class) { + Log.w(TAG, "Network connectivity issue during sync"); + return true; } - } else if (t.getClass() == NextcloudNetworkException.class) { - Log.w(TAG, "Network connectivity issue during sync"); - return true; } exceptions.add(t); From a31e5dc699045e54283eded7efbc9002d6168f5e Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 11 Sep 2025 16:13:55 +0200 Subject: [PATCH 5/5] fix: test pull remote changes Signed-off-by: alperozturk --- .../owncloud/notes/persistence/NotesServerSyncTask.java | 2 +- .../owncloud/notes/persistence/NotesServerSyncTaskTest.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java index f26042bd9..03d151a77 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTask.java @@ -226,7 +226,7 @@ private boolean pullRemoteChanges() { return false; } - final var fetchResponse = notesAPI.getNotes(localAccount.getModified(), localAccount.getETag()).blockingSingle(); + final var fetchResponse = notesAPI.getNotes(modified, localAccount.getETag()).blockingSingle(); final var remoteNotes = fetchResponse.getResponse(); final var remoteIDs = new HashSet(); // pull remote changes: update or create each remote note diff --git a/app/src/test/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTaskTest.java b/app/src/test/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTaskTest.java index d7112f91c..00eef05d9 100644 --- a/app/src/test/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTaskTest.java +++ b/app/src/test/java/it/niedermann/owncloud/notes/persistence/NotesServerSyncTaskTest.java @@ -88,6 +88,7 @@ public void testPushLocalChanges() { @Test public void testPullRemoteChanges() { + when(account.getModified()).thenReturn(Calendar.getInstance()); when(repo.getAccountById(anyLong())).thenReturn(account); when(repo.getIdMap(anyLong())).thenReturn(Map.of(1000L, 1L, 2000L, 2L)); when(repo.updateIfNotModifiedLocallyAndAnyRemoteColumnHasChanged(anyLong(), anyLong(), anyString(), anyBoolean(), anyString(), anyString(), anyString(), anyString())).thenReturn(1);