Skip to content

Conversation

@zerox80
Copy link
Contributor

@zerox80 zerox80 commented Nov 6, 2025

Pull Request: Feature/Thumbnail Cache Fix & Login Improvements

Summary

This PR consolidates several critical improvements and fixes, including a complete migration of the thumbnail caching system to Coil, fixes for authentication state loss, and enhancements to the TUS upload mechanism.

Key Changes

1. Full Coil Migration (Thumbnail Caching)

  • Objective: Replace the legacy, blocking ThumbnailsCacheManager with the modern, efficient Coil image loading library.
  • Changes:
    • Removed: ThumbnailsCacheManager.java and DiskLruImageCache.java (Legacy blocking cache).
    • Migrated: All remaining components (ReceiveExternalFilesAdapter, ShareFileFragment, RemoveFilesDialogFragment, FileDetailsFragment, AvatarUtils) now use ThumbnailsRequester (Coil).
    • Performance: Removed blocking initialization in MainApp.kt, significantly improving app startup time.
    • Avatars: Refactored AvatarUtils to use Coil for on-demand avatar fetching and caching.

2. Authentication State Fix

  • Objective: Prevent the app from resetting to the login screen when switching apps during authentication.
  • Changes:
    • Implemented state saving/restoring in LoginActivity.kt for serverBaseUrl and oidcSupported.
    • Ensured the login flow persists across activity recreation.

Verification

  • Startup: App starts immediately without blocking on cache init.
  • Thumbnails: Images load correctly in the file list, share dialogs, and details view.
  • Avatars: User avatars load correctly in the drawer.
  • Login: Authentication flow completes successfully even after backgrounding the app.

To accelerate development, parts of the caching logic mechanisms were drafted with the assistance of Gemini 3 Pro. I have refined and validated the code to ensure it matches our standards. Please review with a focus on edge cases.

@zerox80 zerox80 mentioned this pull request Nov 6, 2025
@zerox80 zerox80 force-pushed the feature/thumbnail-cache-fix branch from c3c46ff to 6844583 Compare November 20, 2025 23:26
@zerox80 zerox80 changed the title fix(cache): add LruCache and null-safe disk cache init for thumbnails Feature: Thumbnail Cache Improvements & Critical Login Fixes Nov 20, 2025
@zerox80 zerox80 force-pushed the feature/thumbnail-cache-fix branch from 2758a89 to 4b68373 Compare November 21, 2025 01:27
@guruz
Copy link
Contributor

guruz commented Nov 21, 2025

I haven't looked at the code, but I don't think this should be one PR.
Or is the login/auth using the thumbnail cache somehow?

@zerox80
Copy link
Contributor Author

zerox80 commented Nov 21, 2025

I haven't looked at the code, but I don't think this should be one PR. Or is the login/auth using the thumbnail cache somehow?

Im experimenting here, can u look forward to the upload cancellation and improvement? i already noted it, im just playing around here and gonna split it! dont worry :)

@zerox80 zerox80 force-pushed the feature/thumbnail-cache-fix branch 2 times, most recently from badec2f to 6db3309 Compare November 21, 2025 08:47
@zerox80 zerox80 changed the title Feature: Thumbnail Cache Improvements & Critical Login Fixes Feature: Thumbnail Cache Improvements Nov 21, 2025
@zerox80
Copy link
Contributor Author

zerox80 commented Nov 21, 2025

solved
#60

@zerox80
Copy link
Contributor Author

zerox80 commented Nov 21, 2025

I will give feedback if its "perfect" I am still facing issues.

Its not that consistent / stable. Sometimes it stops loading thumbnails, when i set an avatar on opencloud it doesn't show that Avatar on the App.

But otherwise, its really far!

@zerox80
Copy link
Contributor Author

zerox80 commented Nov 21, 2025

Its solved :D works good now.

Fix: Thumbnail Loading Issue

Problem

Thumbnails intermittently fail to load, requiring a full app restart to resolve. This occurs because:

  1. ThumbnailsRequester.kt caches ImageLoader instances per account in a ConcurrentHashMap
  2. Each cached ImageLoader has a CoilRequestHeaderInterceptor with static authentication headers captured at creation time from openCloudClient.credentials.headerAuth
  3. When credentials are refreshed (e.g., after token expiration), SingleSessionManager.refreshCredentialsForAccount() updates the credentials in the managed OpenCloudClient
  4. However, the cached ImageLoader instances still use the old, stale authorization headers
  5. Thumbnail requests fail with authentication errors until the app is restarted, which clears the in-memory cache

Root Cause

File: ThumbnailsRequester.kt

fun getCoilImageLoader(account: Account): ImageLoader {
    val accountName = account.name
    return imageLoaders.getOrPut(accountName) {
        val openCloudClient = clientManager.getClientForCoilThumbnails(accountName)

        val coilRequestHeaderInterceptor = CoilRequestHeaderInterceptor(
            requestHeaders = hashMapOf(
                AUTHORIZATION_HEADER to openCloudClient.credentials.headerAuth,  // ⚠️ STATIC VALUE
                // ...
            )
        )
        // ... ImageLoader is cached with static credentials
    }
}

The AUTHORIZATION_HEADER is copied from openCloudClient.credentials.headerAuth at the time the ImageLoader is created and never updated.


Solution

ThumbnailsRequester.kt

Strategy: Make credential retrieval dynamic instead of static by modifying CoilRequestHeaderInterceptor to fetch fresh credentials on each request.

Changes Made

  1. Modified CoilRequestHeaderInterceptor constructor to accept a ClientManager and accountName instead of static headers
  2. Updated intercept() method to fetch fresh credentials from the current OpenCloudClient on each request
  3. Updated getCoilImageLoader() to pass ClientManager and accountName to the interceptor

Modified Constructor

private class CoilRequestHeaderInterceptor(
    private val clientManager: ClientManager,
    private val accountName: String
) : Interceptor {
    
    override fun intercept(chain: Interceptor.Chain): Response {
        val openCloudClient = clientManager.getClientForCoilThumbnails(accountName)
        val requestHeaders = hashMapOf(
            AUTHORIZATION_HEADER to openCloudClient.credentials.headerAuth,
            ACCEPT_ENCODING_HEADER to ACCEPT_ENCODING_IDENTITY,
            USER_AGENT_HEADER to SingleSessionManager.getUserAgent(),
            OC_X_REQUEST_ID to RandomUtils.generateRandomUUID(),
        )
        
        val request = chain.request().newBuilder()
        requestHeaders.toHeaders().forEach { request.addHeader(it.first, it.second) }
        return chain.proceed(request.build()).newBuilder()
            .removeHeader("Cache-Control")
            .addHeader("Cache-Control", "max-age=5000, must-revalidate")
            .build()
            .also { Timber.d("Header :" + it.headers) }
    }
}

Modified getCoilImageLoader()

fun getCoilImageLoader(account: Account): ImageLoader {
    val accountName = account.name
    return imageLoaders.getOrPut(accountName) {
        val openCloudClient = clientManager.getClientForCoilThumbnails(accountName)

        val coilRequestHeaderInterceptor = CoilRequestHeaderInterceptor(
            clientManager = clientManager,
            accountName = accountName
        )

        ImageLoader(appContext).newBuilder().okHttpClient(
            okHttpClient = openCloudClient.okHttpClient.newBuilder()
                .addNetworkInterceptor(coilRequestHeaderInterceptor).build()
        ).logger(DebugLogger())
            .memoryCache {
                getSharedMemoryCache()
            }
            .diskCache {
                getSharedDiskCache()
            }
            .build()
    }
}

Verification Plan

Manual Testing

Important

This bug requires specific conditions to reproduce reliably. Manual testing should be performed to verify the fix.

Test Scenario:

  1. Log into the app with an account
  2. Navigate to a folder with images that have thumbnails
  3. Verify thumbnails load correctly
  4. Trigger a credential refresh scenario:
    • Switch to another app for an extended period (to allow token expiration)
    • OR force-clear credentials via developer tools if available
    • OR wait for the natural token expiration period
  5. Return to the app and navigate to different folders
  6. Expected Result: Thumbnails should continue to load without requiring an app restart

Testing Notes:

  • The original issue manifested intermittently when tokens expired
  • With the fix, fresh credentials are fetched dynamically on each request
  • No app restart should be needed for thumbnails to work after credential refresh

Code Review

The fix should be reviewed to ensure:

  • Credentials are fetched dynamically on each image request
  • No performance degradation (fetching from ClientManager should be fast as clients are cached)
  • The interceptor correctly builds fresh headers for each request

@zerox80
Copy link
Contributor Author

zerox80 commented Nov 21, 2025

100% battle-tested. It seems to be perfect now. Only the avatar issue is still there. But Image thumbnails etc are cached for around 1,5 hours. (ensures that if the Server has the exact same name for a File but the File itself is different it won't give wrong thumbnail... )

@zerox80 zerox80 force-pushed the feature/thumbnail-cache-fix branch 2 times, most recently from 40d99b2 to b0f73b6 Compare November 21, 2025 14:14
@zerox80
Copy link
Contributor Author

zerox80 commented Nov 22, 2025

solved, if server sends header it respects that with fallback to 5000 secs.
it should work now perfectly :)

@zerox80 zerox80 force-pushed the feature/thumbnail-cache-fix branch 2 times, most recently from 1e74b97 to 63923ac Compare November 27, 2025 14:01
zerox80 added 4 commits December 2, 2025 17:14
Comprehensive update addressing thumbnail caching, avatar display, and login state management:

- Dynamic credential retrieval for thumbnail loading
- Account-specific ImageLoaders with shared caches
- Removed deprecated AvatarManager

- Fixed invisible avatars
- Moved avatar loading off main thread
- Fixed startup crashes

- Removed duplicate methods
- Code cleanup and refactoring
@zerox80 zerox80 force-pushed the feature/thumbnail-cache-fix branch from 9403687 to cfe9ae5 Compare December 2, 2025 18:12
@zerox80
Copy link
Contributor Author

zerox80 commented Dec 2, 2025

we need to figure out in new PR how to solve the Avatar loading issue, it's also not working on iOS. But the Caching works so far. Limit: 100 MB, 25% RAM Usage for Caching. It's totally fine for todays Smartphones.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants