From ed5954ba453b6f192bc408ba2e65f23774ef44bd Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Fri, 2 Oct 2026 16:27:50 +0200 Subject: [PATCH] fix(activity): Use long as id for activity This is already incorrect when there is more than 4.000.000 activity entries in an instance and get even more incorrect once activities are ported to snowflake ids. Assisted-by: ClaudeCode:claude-sonnet-5-5 Signed-off-by: Carl Schwan --- .../activities/ActivitiesServiceApiImpl.kt | 19 +++++---- .../ActivitiesServiceApiImplTest.kt | 42 +++++++++++++++++++ 2 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 app/src/test/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApiImplTest.kt diff --git a/app/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApiImpl.kt b/app/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApiImpl.kt index cfec43c3420f..d2c86dba4e16 100644 --- a/app/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApiImpl.kt +++ b/app/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApiImpl.kt @@ -9,6 +9,7 @@ */ package com.owncloud.android.ui.activities.data.activities +import androidx.annotation.VisibleForTesting import com.nextcloud.client.account.UserAccountManager import com.nextcloud.common.NextcloudClient import com.owncloud.android.MainApp @@ -59,13 +60,7 @@ class ActivitiesServiceApiImpl(private val accountManager: UserAccountManager) : val client = OwnCloudClientManagerFactory.getDefaultSingleton() .getNextcloudClientFor(ocAccount, context) - val operation = if (lastGiven > 0) { - GetActivitiesRemoteOperation(lastGiven) - } else { - GetActivitiesRemoteOperation() - } - - val result = operation.execute(client) + val result = createOperation(lastGiven).execute(client) if (result.isSuccess && result.getData() != null) { val data = result.getData() @@ -87,5 +82,15 @@ class ActivitiesServiceApiImpl(private val accountManager: UserAccountManager) : companion object { private val TAG: String = ActivitiesServiceApiImpl::class.java.simpleName + + // Without a file ID the operation does not filter the activities by file + private const val NO_FILE_ID = -1L + + @VisibleForTesting + internal fun createOperation(lastGiven: Long): GetActivitiesRemoteOperation = if (lastGiven > 0) { + GetActivitiesRemoteOperation(NO_FILE_ID, lastGiven) + } else { + GetActivitiesRemoteOperation() + } } } diff --git a/app/src/test/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApiImplTest.kt b/app/src/test/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApiImplTest.kt new file mode 100644 index 000000000000..0db537726238 --- /dev/null +++ b/app/src/test/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApiImplTest.kt @@ -0,0 +1,42 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.owncloud.android.ui.activities.data.activities + +import com.owncloud.android.lib.resources.activities.GetActivitiesRemoteOperation +import org.junit.Assert.assertEquals +import org.junit.Test + +class ActivitiesServiceApiImplTest { + + private fun GetActivitiesRemoteOperation.longField(name: String): Long = + GetActivitiesRemoteOperation::class.java.getDeclaredField(name).let { + it.isAccessible = true + it.getLong(this) + } + + @Test + fun firstPageHasNoFilter() { + val operation = ActivitiesServiceApiImpl.createOperation(0) + + assertEquals(-1L, operation.longField("fileId")) + assertEquals(-1L, operation.longField("lastGiven")) + } + + @Test + fun nextPageKeepsTheFullActivityIdWithoutFilteringByFile() { + val operation = ActivitiesServiceApiImpl.createOperation(SNOWFLAKE_ACTIVITY_ID) + + assertEquals(-1L, operation.longField("fileId")) + assertEquals(SNOWFLAKE_ACTIVITY_ID, operation.longField("lastGiven")) + } + + companion object { + // Snowflake IDs need more than 32 bits + private const val SNOWFLAKE_ACTIVITY_ID = 130_000_000_000_000_123L + } +}