super-productivity/docs
Johannes Millan ad149e138c
docs(android): document SDK 28 (API 28) behind-keyboard add-task bar root cause (#8528)
* docs(android): document SDK 28 (API 28) behind-keyboard add-task bar root cause

After #8508 (patch removed in 18.12.0) a user on Android 9 / API 28 reports the
global add-task bar sitting behind the soft keyboard — the device class open
item #4 predicted.

Capture the precise root cause (edge-to-edge forces no system resize; Type.ime()
unreliable < API 30; old WebView VisualViewport doesn't shrink, so
--keyboard-height stays 0) and why a web-side height fallback is the reverted
#8295 trap (obscured ≈ 0 in both the resized and non-resized cases). Record the
correct resize-detecting native fix recipe and the device-matrix gate it needs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017gqH2i456UwdTJXwW5YHPs

* fix(android): lift add-task bar above keyboard on API < 30 (#8508 follow-up)

On Android 9 / API 28 under enforced edge-to-edge (targetSdk 36) the system
does not resize the window for the IME and WindowInsetsCompat.Type.ime() is
unreliable, so the edge-to-edge plugin never insets the WebView and neither the
window nor VisualViewport shrinks. --keyboard-height stays 0 and the
position:fixed add-task bar sits behind the keyboard.

Add a resize-detecting native inset in CapacitorMainActivity, driven from the
existing keyboard OnGlobalLayoutListener: measure the keyboard via
getWindowVisibleDisplayFrame (reliable on every API level) and, only when the
WebView actually extends behind the keyboard, lift it by the exact overlap via
bottomMargin (matching the plugin), self-correcting as the keyboard height
changes and restoring the captured margin on hide. Gated Build.VERSION.SDK_INT
< 30 so it is a strict no-op on every device #8508/18.12.0 verified.

Web-side height fallback was rejected: obscured = innerHeight - vvHeight is ~0
in both the resized and non-resized cases, so disambiguating requires the
baseline-innerHeight + max(obscured, nativeKb - layoutShrink) math that was
reverted as #8295. Native has the unambiguous geometry.

Needs on-device validation across the matrix in docs/android-edge-to-edge-keyboard.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017gqH2i456UwdTJXwW5YHPs

* fix(android): harden SDK < 30 keyboard inset after review

Address findings from a multi-agent review of adjustWebViewForKeyboardBelowApi30:

- Bound the feedback loop: clamp appliedKeyboardInsetPx to [0, keypadHeight]
  (the lift never needs to exceed the keyboard height) and skip redundant
  layoutParams writes, so a WebView height that doesn't respond to the margin
  (e.g. the edge-to-edge plugin rewriting it) can't drive an endless
  requestLayout loop.
- Ignore stale/pre-layout geometry while the keyboard is open (webView.height
  == 0) so an already-applied inset isn't collapsed to 0 for a frame; only the
  genuine keyboard-closed path restores the margin.
- Make the dead-band density-relative (8dp) instead of a fixed 16px so it's
  visually constant across densities.

The reviews confirmed the central risk is absent: shrinking the WebView via
bottomMargin shrinks both innerHeight and visualViewport.height, so the web
side's obscured stays under its 100px floor and does not add a second lift
(no #8295 double-count). Still pending on-device validation per the docs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017gqH2i456UwdTJXwW5YHPs

* fix(android): resize WebView via height for SDK<30 keyboard inset

On API < 30 under enforced edge-to-edge the system does not resize the
window for the IME, so the add-task bar sat behind the keyboard (#8508
follow-up, Android 9 / API 28).

The edge-to-edge plugin owns webView.bottomMargin and rewrites it to 0 on
every inset dispatch while the IME is visible, so correcting the margin
from a second writer flickers; WebView padding does not move the web
layout viewport; and fully replacing the plugin's inset listener stops it
re-painting its color overlays (white navbar gap).

Instead set an explicit WebView layout height to the keyboard top while
the IME is up and restore the resting height on hide. Height is a
different property than the margin the plugin manages and, for an
explicit-height view, the margin does not change the view size — so the
two never fight and the plugin keeps doing everything else (insets +
color overlays). Gated SDK_INT < 30, so API >= 30 is untouched.

Also documents the root cause, the approaches that failed, and the
upstream status, plus a handover/plan for migrating to Capacitor's
built-in SystemBars.

* fix(android): guard zero-height + reuse loc buffer in keyboard inset

Multi-review follow-ups for the SDK<30 keyboard WebView-height workaround:

- Skip the write when the computed keyboard-top height is <= 0 instead of
  coercing to 0. A 0 would collapse the WebView, and the existing
  height==0 guard would then latch and stop recomputing until the keyboard
  hides.
- Reuse a single IntArray for getLocationOnScreen instead of allocating
  one on every layout pass while the IME is up (hot path).
- Document the implicit coupling with StartupOverlayManager: both read/
  mutate webView.height from layout listeners and only coexist because the
  overlay early-returns once its input bar is visible. Cross-referenced in
  both files so the guard isn't removed later.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-22 13:27:45 +02:00
..
long-term-plans refactor: retire GET /api/sync/snapshot, re-scope GET /api/sync/status as diagnostic (#8496) 2026-06-20 12:02:58 +02:00
plans docs(android): document SDK 28 (API 28) behind-keyboard add-task bar root cause (#8528) 2026-06-22 13:27:45 +02:00
promotion build: better organize stuff 2025-06-27 09:03:16 +02:00
research feat(task-repeat): RFC 5545 RRULE recurring schedules — EPIC · Phase 1/13 (Closes #4020) (#7948) 2026-06-09 11:25:35 +02:00
screens docs/wiki content v0.8 (#7068) 2026-04-01 12:40:28 +02:00
sync-and-op-log refactor(sync): remove unused error classes, dialog, and constructor-time logging (phase 1, #8325) (#8510) 2026-06-20 13:36:56 +02:00
wiki fix(sync): clarify Nextcloud connection-test 404 (wrong user ID) (#7617) (#8513) 2026-06-20 15:18:53 +02:00
add-new-integration.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
android-edge-to-edge-keyboard.md docs(android): document SDK 28 (API 28) behind-keyboard add-task bar root cause (#8528) 2026-06-22 13:27:45 +02:00
apple-release-automation.md ci: auto-submit iOS and macOS App Store builds for review (#7857) 2026-06-01 11:42:16 +02:00
build-and-publish-notes.md fix(ci): prevent duplicate unsigned exe files in GitHub Releases 2026-03-19 18:58:52 +01:00
documentation-guide.md Housekeeping for various docs, templates, and actions (#7451) 2026-05-02 13:58:25 +02:00
ENV_SETUP.md build: final approach 2025-07-14 20:52:51 +02:00
github-access-token-instructions.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
gitlab-access-token-instructions.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
how-to-rate.md feat(rate-dialog): action-aware prompt with feedback split 2026-05-04 17:27:11 +02:00
howto-refresh-snap-credentials.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
i18n-script-usage.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
legacy-webview-analysis.md 16.2.1 2025-11-01 13:22:58 +01:00
mac-app-store-code-signing-guide.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
performance-project-tag-report.md docs: add performance report 2025-11-13 18:23:50 +01:00
plainspace-api-extension-plan.md feat(plainspace): add integration for shared projects (#8424) 2026-06-18 17:58:06 +02:00
plainspace-integration-plan.md refactor(sync): remove unused error classes, dialog, and constructor-time logging (phase 1, #8325) (#8510) 2026-06-20 13:36:56 +02:00
plugin-development.md fix(plugins): expose focused task API to iframe plugins (#8291) 2026-06-15 14:57:34 +02:00
styling-guide.md fix(onboarding): harden sync setup dismissal 2026-06-03 19:54:14 +02:00
theming-contract.md feat(theme): add Plainspace built-in theme 2026-06-15 14:06:21 +02:00
TRANSLATING.md Fix frequency translations (#8000) 2026-06-05 10:53:26 +02:00
unused-translations-analysis.md chore(i18n): remove additional 86 orphan translation keys 2026-01-09 14:59:05 +01:00
update-android-app.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
update-mac-certificates.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00