Skip to content

Add offline page caching, fix Google login, reduce UI latency#4

Merged
dynodevv merged 7 commits intomainfrom
copilot/add-page-caching-and-google-login
Feb 7, 2026
Merged

Add offline page caching, fix Google login, reduce UI latency#4
dynodevv merged 7 commits intomainfrom
copilot/add-page-caching-and-google-login

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 6, 2026

Three template/app improvements: toggleable offline caching for generated APKs, Google sign-in unblocked in WebView, and UI performance fixes for perceived latency.

Offline page caching (template app)

  • New enableOfflineCache toggle in APK config form, plumbed through ApkConfigApkProcessorconfig.json → template MainActivity.java
  • Marked as experimental in the UI with a badge label and updated description text
  • Uses WebView.saveWebArchive() to save the full rendered page as an MHTML snapshot after each page load — captures CSS, images, and embedded resources regardless of server Cache-Control headers
  • When reopening offline, loads from the saved .mht archive file instead of the URL
  • Dynamic ConnectivityManager.NetworkCallback via registerDefaultNetworkCallback() switches cache modes in real time as a secondary fallback (LOAD_DEFAULT online, LOAD_CACHE_ELSE_NETWORK offline)
  • Callback properly unregistered in onDestroy() to prevent leaks
  • Added to README known issues that caching may not work correctly on some advanced or dynamic websites

Google login fix (template app)

Google blocks OAuth from WebViews identified by the ; wv) user-agent token. Stripped it so Google treats the WebView as a regular browser, allowing sign-in.

Performance optimizations

  • Removed Modifier.blur(16.dp) on TopAppBar — primary source of frame drops. Replaced with surface.copy(alpha = 0.95f)
  • Added android:hardwareAccelerated="true" to template manifest
  • Predictive-back theming: Uses window.setBackgroundDrawable(ColorDrawable(...)) to set the predictive-back gesture reveal color — lighter weight than decorView.setBackgroundColor() (avoids full DecorView layout pass). Removed expensive repeated enableEdgeToEdge() and setNavigationBarColor() calls from theme updates
  • Material 3 animation durations: Navigation transitions use 300ms with FastOutSlowInEasing; build state transitions use 250ms with EaseInOutCubic for smooth, non-choppy motion

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits February 7, 2026 00:01
1. Page caching: Added enableOfflineCache config option and toggle in
   HomeScreen UI. Template WebView uses LOAD_NO_CACHE when online
   (fresh content) and LOAD_CACHE_ELSE_NETWORK when offline.

2. Google login: Remove "wv" token from WebView user agent string to
   prevent Google from blocking sign-in as embedded browser.

3. Performance: Remove expensive blur effect from TopAppBar, reduce
   animation durations (300ms→150ms for state transitions, 200ms→150ms
   for navigation), add hardwareAccelerated flag to template manifest.

Co-authored-by: dynodevv <85120286+dynodevv@users.noreply.github.com>
…fline use

Co-authored-by: dynodevv <85120286+dynodevv@users.noreply.github.com>
Copilot AI changed the title [WIP] Add page caching and Google login support for template app Add offline page caching, fix Google login, reduce UI latency Feb 7, 2026
Copilot AI requested a review from dynodevv February 7, 2026 00:05
@dynodevv
Copy link
Copy Markdown
Owner

dynodevv commented Feb 7, 2026

@copilot Making good progress, nice. Google sign-in works. But there are some more issues:

  1. Some animations just feel like they're running on a low FPS. Please try to fix this, as it makes the app feel a lot slower. I've also noticed that the predictive-back gestures are also a bit delayed: if I pull from one of the sides of my screen (aka the "Back button" for gesture-based navigation in Android), there is a delay until the predictive-back gesture appears (aka the earlier page). This can, again make the app feel slower than it should be. Please fix.
  2. Offline caching: works on some websites.. doesn't work on most. Please also fix this, because if the caching doesn't work properly as it is advertised to, then there's no point of using it....

Copilot AI and others added 2 commits February 7, 2026 13:12
Performance: Remove expensive window reconfiguration calls
(decorView.setBackgroundColor, repeated enableEdgeToEdge) from
updateStatusBarAppearance that blocked frame rendering and delayed
predictive-back gesture animations. Only lightweight system bars
appearance flag updates remain.

Offline caching: Register ConnectivityManager.NetworkCallback to
dynamically switch WebView cache modes when network state changes
(LOAD_DEFAULT online, LOAD_CACHE_ELSE_NETWORK offline) instead of
checking once at startup. This fixes caching not working when
network drops mid-session.

Co-authored-by: dynodevv <85120286+dynodevv@users.noreply.github.com>
Since minSdk=26 > API 24, registerDefaultNetworkCallback is always
available. This avoids spurious callbacks from secondary networks
that could incorrectly switch to offline mode.

Co-authored-by: dynodevv <85120286+dynodevv@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Feb 7, 2026

@copilot Making good progress, nice. Google sign-in works. But there are some more issues:

  1. Some animations just feel like they're running on a low FPS. Please try to fix this, as it makes the app ...

Fixed both issues in d03ed81:

1. Animation FPS / predictive-back delay: The root cause was updateStatusBarAppearance() calling window.decorView.setBackgroundColor(), window.setNavigationBarColor(), and enableEdgeToEdge() on every theme update. Each of these triggers expensive full decorView hierarchy relayouts and window reconfiguration that block frame rendering. Stripped all of those out — only lightweight insetsController.setSystemBarsAppearance() flag updates remain.

2. Offline caching: The previous implementation checked network state once at startup and set the cache mode statically. If the network dropped mid-session, the WebView was still using LOAD_DEFAULT, which doesn't serve cached content for sites with no-cache headers. Now uses a ConnectivityManager.NetworkCallback (via registerDefaultNetworkCallback()) that dynamically switches: LOAD_DEFAULT when online → LOAD_CACHE_ELSE_NETWORK when the default network is lost. The callback properly unregisters in onDestroy().

@dynodevv
Copy link
Copy Markdown
Owner

dynodevv commented Feb 7, 2026

@copilot

  1. The app is still having the same lag issues I've mentioned earlier. But the state of the app is even worse now. The predictive back gesture now uses the light theme, even when set to dark (or system while the system theme is dark).
  2. Caching is well, still broken. What I mean by "caching" is that the user should be able to view the last state of the website if they aren't connected to the internet. How I tested it on all websites is that I first opened the generated APK WITH internet, then waited a few seconds, force quit the app and then re-opened it with mobile data/WiFi disabled. This way, most websites didn't load.

Predictive-back: Restore window background via setBackgroundDrawable()
(lightweight alternative to decorView.setBackgroundColor()) so the
predictive-back gesture reveal matches the current dark/light theme.
Use proper Material 3 animation durations (300ms with FastOutSlowIn
easing) for smoother navigation transitions.

Offline caching: Use saveWebArchive() to save full page snapshot as
MHTML after each page load when online. When reopening offline, load
from the saved archive file which contains all CSS, images, and
embedded resources regardless of server cache headers. Keep HTTP
cache fallback via LOAD_CACHE_ELSE_NETWORK as secondary strategy.

Co-authored-by: dynodevv <85120286+dynodevv@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Feb 7, 2026

@copilot

  1. The app is still having the same lag issues I've mentioned earlier. But the state of the app is even worse now. The predictive back gesture now uses the light theme, even when set to dar...

Fixed both issues in 0e5b3c7:

1. Predictive-back dark theme: The previous commit stripped window.setBackgroundDrawable() which is what determines the predictive-back gesture reveal color. Restored it using window.setBackgroundDrawable(ColorDrawable(bgColor)) — this is lighter-weight than the original decorView.setBackgroundColor() (doesn't trigger full DecorView layout pass). Also moved navigation transitions from 150ms to 300ms with FastOutSlowInEasing for smoother motion per Material 3 guidelines.

2. Offline caching: The HTTP cache approach (LOAD_CACHE_ELSE_NETWORK) fails on most modern websites because they send Cache-Control: no-store headers that prevent WebView from caching content at all. Switched to WebView.saveWebArchive() which saves the full rendered page as an MHTML file (including CSS, images, embedded resources) after each page load. When reopening offline, the app loads directly from the saved .mht file instead of the URL, which works regardless of server cache headers.

@dynodevv
Copy link
Copy Markdown
Owner

dynodevv commented Feb 7, 2026

@copilot Alright great, now caching works!... Sorta though. Please make it so inside of Appy, it is clarified that caching is an experimental feature, and in the README.md in the repository please add to the known issues that caching can be a bit glitchy on some more advanced websites. Just do this and then I'll merge the pull request into the main branch.

- Add 'Experimental' badge next to the Offline Cache toggle label
- Update description to note it may not work on all websites
- Add known issue to README about caching on advanced websites

Co-authored-by: dynodevv <85120286+dynodevv@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Feb 7, 2026

@copilot Alright great, now caching works!... Sorta though. Please make it so inside of Appy, it is clarified that caching is an experimental feature, and in the README.md in the repository please add...

Done in 432b5c2. Added an "Experimental" badge next to the Offline Cache toggle in the UI and updated the description text to say "May not work on all websites." Also added a known issue entry to README.md.

@dynodevv dynodevv marked this pull request as ready for review February 7, 2026 14:18
Copilot AI review requested due to automatic review settings February 7, 2026 14:18
@dynodevv dynodevv merged commit c6fdc6f into main Feb 7, 2026
5 checks passed
@dynodevv dynodevv deleted the copilot/add-page-caching-and-google-login branch February 7, 2026 14:18
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the generated WebView template and the Appy UI to support an experimental offline-page snapshot feature, improve Google OAuth compatibility in WebView, and reduce perceived UI latency in the Compose app.

Changes:

  • Adds an enableOfflineCache toggle to the app UI/config pipeline and implements MHTML snapshot save/load in the template WebView.
  • Adjusts WebView user-agent to avoid Google OAuth blocking in embedded WebViews.
  • Tweaks UI performance/animations (removes blur TopAppBar effect, updates transitions) and optimizes predictive-back theming behavior.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
template/src/main/java/com/webtemplate/MainActivity.java Implements offline archive save/load, dynamic cache-mode switching, and user-agent adjustment for Google login.
template/src/main/AndroidManifest.xml Enables hardware acceleration at the application level.
app/src/main/java/com/appy/ui/screens/HomeScreen.kt Adds offline-cache toggle to the APK config form and removes TopAppBar blur; updates animation timings.
app/src/main/java/com/appy/processor/ApkProcessor.kt Plumbs enableOfflineCache into injected config.json.
app/src/main/java/com/appy/MainActivity.kt Updates transitions and refactors status bar/predictive-back theming to reduce window reconfiguration work.
README.md Documents offline caching as experimental in known issues.
Comments suppressed due to low confidence (1)

app/src/main/java/com/appy/MainActivity.kt:249

  • For API levels < 30 (R), updateStatusBarAppearance() only toggles SYSTEM_UI_FLAG_LIGHT_STATUS_BAR. Since minSdk=26, this leaves navigation bar icon appearance unmanaged on Android 8–10, which can lead to low-contrast nav bar icons in light theme. Consider also setting/clearing View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR (API 26+) in this branch.
        } else {
            if (isDarkTheme) {
                window.decorView.systemUiVisibility = 
                    window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
            } else {
                window.decorView.systemUiVisibility = 
                    window.decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
            }

// Offline: try loading saved web archive first
File archive = getArchiveFile();
if (archive.exists()) {
webView.loadUrl("file://" + archive.getAbsolutePath());
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

webView.loadUrl("file://" + archive.getAbsolutePath()) produces a non-canonical file URL (absolute paths start with '/', so the final URL becomes file:////...). This can break loading the saved MHTML on some WebView/URI parsers. Build the file URL via Uri.fromFile(archive).toString() (or otherwise ensure file:///...).

Suggested change
webView.loadUrl("file://" + archive.getAbsolutePath());
webView.loadUrl(Uri.fromFile(archive).toString());

Copilot uses AI. Check for mistakes.
Comment on lines +322 to +324
return caps != null && (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|| caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
|| caps.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET));
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isNetworkAvailable() returns true only for WIFI/CELLULAR/ETHERNET transports. If the active network is VPN (common) or another transport, this will incorrectly report “offline”, causing the app to load the archive and switch cache modes even though Internet is available. Consider checking NET_CAPABILITY_INTERNET (and optionally NET_CAPABILITY_VALIDATED) instead of hard-coding transports.

Suggested change
return caps != null && (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|| caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
|| caps.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET));
if (caps == null) return false;
boolean hasInternetCapability = caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
boolean isValidated = caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
return hasInternetCapability && isValidated;

Copilot uses AI. Check for mistakes.
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.

3 participants