Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ Project-specific skills live in `./.claude/skills/<skill-name>/`. Load a skill w
- **`android-java-to-kotlin`** (`./.claude/skills/android-java-to-kotlin/SKILL.md`) β€” Completes a Java-to-Kotlin conversion in this Android app. Use it when finishing a conversion, when the user mentions "java to kotlin", "j2k", "convert java", or "make it idiomatic", or when a freshly IDE-converted `.kt` file needs cleanup. The workflow is two-person: the developer first runs the Android Studio converter (`Code > Convert Java File to Kotlin File`), then the agent drives the idiomatic second pass β€” fail-fast control flow, function decomposition, `lifecycleScope`/coroutines instead of Java threads, modern Android APIs, and project conventions (SPDX headers, no magic numbers, `@JvmStatic`). The conversion must preserve behaviour, and the agent must write a behaviour-locking test before declaring it done.
- **`android-activity-to-navigator-fragment`** (`./.claude/skills/android-activity-to-navigator-fragment/SKILL.md`) β€” Converts a standalone Activity (typically a drawer destination) into a Fragment hosted by `NavigatorActivity`. Use it when the user mentions "navigator", `NavigatorActivity`, `NavigatorScreen`, or "convert activity to fragment". It covers registering the `NavigatorScreen`, the fragment and its layout, decoupling collaborators from `FileActivity`, rewiring every entry point with `NavigatorActivity.intent(...)`, DI and manifest cleanup, and migrating the screenshot test.

### Android Skills

Agent skills for Android development at https://github.com/android/skills (overview: https://developer.android.com/tools/agents/android-skills). Use them when a task matches their trigger and no project-specific skill above covers it. Install one with the Android CLI (`android skills add <skill-name>`) or read its `SKILL.md` directly from the repository. Project-specific skills and the rules in this file take precedence over the official skills.

- **`r8-analyzer`** (https://github.com/android/skills/tree/main/performance/r8-analyzer) β€” Analyzes the R8 configuration and keep rules for redundant, overly broad, or library-subsumed rules. Use it when changing the keep rules in `app/src/main/keepRules/` or the `optimization {}` blocks in `app/build.gradle.kts`.

## General Guidance

Every new file needs to get a SPDX header in the first rows according to this template.
Expand Down
4 changes: 3 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,11 @@ android {

buildTypes {
release {
optimization {
enable = true
}
buildConfigField("String", "NC_TEST_SERVER_DATA_STRING", "\"\"")
}

debug {
enableUnitTestCoverage = project.hasProperty("coverage")
enableAndroidTestCoverage = project.hasProperty("coverage")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
import android.content.SharedPreferences;
import android.content.res.Configuration;

import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.nextcloud.appReview.AppReviewShownModel;
import com.nextcloud.client.account.User;
import com.nextcloud.client.account.UserAccountManager;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import android.view.ViewOutlineProvider
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.doOnLayout
import androidx.core.view.updatePadding
import com.google.android.material.behavior.HideViewOnScrollBehavior

Expand Down Expand Up @@ -81,7 +82,7 @@ fun View?.slideHideBottomBehavior(visible: Boolean) {
if (params?.behavior !is HideViewOnScrollBehavior<*>) return

val behavior = HideViewOnScrollBehavior.from(view)
view.post {
view.doOnLayout {
if (visible) behavior.slideIn(view) else behavior.slideOut(view)
}
}
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/keepRules/ezvcard.keep
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Nextcloud - Android Client
#
# SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
# SPDX-License-Identifier: AGPL-3.0-or-later

-keepclassmembers class * extends ezvcard.parameter.VCardParameter {
public static <fields>;
<init>(java.lang.String);
<init>(java.lang.String, ezvcard.VCardVersion[]);
<init>(java.lang.String, java.lang.String, java.lang.String);
}
25 changes: 25 additions & 0 deletions app/src/main/keepRules/gson-models.keep
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Nextcloud - Android Client
#
# SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
# SPDX-License-Identifier: AGPL-3.0-or-later

-keepclassmembers class com.owncloud.android.authentication.AuthObject,
com.owncloud.android.authentication.Poll,
com.owncloud.android.authentication.LoginUrlInfo,
com.owncloud.android.authentication.EnforcedServer,
com.owncloud.android.datamodel.PushConfigurationState,
com.owncloud.android.datamodel.MediaFoldersModel,
com.owncloud.android.datamodel.DecryptedPushMessage,
com.nextcloud.client.jobs.LogEntry,
com.nextcloud.appReview.AppReviewShownModel,
com.nextcloud.client.NominatimClient$Companion$ReverseGeocodingResult,
com.nextcloud.model.OfflineOperationType$* {
!static !transient <fields>;
<init>(...);
}

-keepclassmembers class com.owncloud.android.datamodel.e2e.**,
com.owncloud.android.datamodel.EncryptedFiledrop {
<fields>;
<init>(...);
}
14 changes: 14 additions & 0 deletions app/src/main/keepRules/ical4j.keep
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Nextcloud - Android Client
#
# SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
# SPDX-License-Identifier: AGPL-3.0-or-later

-keep class com.nextcloud.utils.ical.AndroidCompatTimeZoneRegistryFactory,
net.fortuna.ical4j.util.MapTimeZoneCache {
<init>();
}

-keeppackagenames net.fortuna.ical4j.transform.compliance

-dontwarn java.time.zone.ZoneRulesProvider
-dontwarn org.joda.convert.ToString
15 changes: 15 additions & 0 deletions app/src/main/keepRules/legacy-http.keep
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Nextcloud - Android Client
#
# SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
# SPDX-License-Identifier: AGPL-3.0-or-later

-keep class org.apache.commons.httpclient.auth.AuthPolicy
-keep class org.apache.commons.httpclient.cookie.CookiePolicy
-keep class * implements org.apache.commons.httpclient.auth.AuthScheme {
public <init>();
}
-keep class * implements org.apache.commons.httpclient.cookie.CookieSpec {
public <init>();
}

-keeppackagenames org.apache.jackrabbit.webdav
12 changes: 12 additions & 0 deletions app/src/main/keepRules/nextcloud-library.keep
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Nextcloud - Android Client
#
# SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
# SPDX-License-Identifier: AGPL-3.0-or-later

-keepclassmembers class com.owncloud.android.lib.**, com.nextcloud.android.lib.** {
!static !transient <fields>;
<init>(...);
}

-keep,allowobfuscation,allowshrinking class com.owncloud.android.lib.ocs.ServerResponse,
com.owncloud.android.lib.ocs.OCSResponse
14 changes: 14 additions & 0 deletions app/src/main/keepRules/sso.keep
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Nextcloud - Android Client
#
# SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
# SPDX-License-Identifier: AGPL-3.0-or-later

-keep class com.nextcloud.android.sso.aidl.NextcloudRequest,
com.nextcloud.android.sso.QueryParam,
com.nextcloud.android.sso.PlainHeader {
static final long serialVersionUID;
!static !transient <fields>;
<init>(...);
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
}
Loading