Android tablet remote UI: styling pass, color picker, arrange mode indicator, connection gating
- Button styling standardization with green ring state indicators (Connect, Rescan, Log, Clear Layout, Reset ALL) - Input field labels with proper DP-based padding and spacing - Feedback & title widget color picker with 7-color palette and persistence layer - Font weight selection for text widgets (deferred visual implementation) - Hide/Show and Reset Size buttons in context menu - Flashing pink border around entire app when Arrange mode is ON (500ms fade in/out cycle) - Arrange button disabled until connected to desktop app, with alpha indicator - WidgetLayoutState now persists color and fontWeight properties - Arrange mode visual debugging with smooth fade animation instead of harsh strobe Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
# iOS Feature Parity Tracker
|
||||
|
||||
Tracks what `remote-client-ios` (source of truth) actually does vs. what
|
||||
`remote-client-android` has built, so gaps get found by checking this list
|
||||
against the iOS source, not by surprise mid-conversation.
|
||||
|
||||
**Status:** ✅ Matched · ⚠️ Partial/Different (deliberate or otherwise) · ❌ Not built · ❓ iOS behavior not yet verified against source
|
||||
|
||||
## Top button row
|
||||
- ✅ Single horizontal row, natural (not stretched) size, iOS's chained trailing/leading order
|
||||
- ❌ `tabletIdField` — iOS has a live editable field; Android hardcodes `TABLET_DEST_ID = 1`
|
||||
- ❌ `autoSwitchButton` — auto preset-switching toggle, not built
|
||||
- ❌ `gridButton` — visual grid-overlay toggle, not built (no grid overlay exists at all)
|
||||
- ❌ `cancelChangesButton` — revert unsaved Arrange-mode edits, not built
|
||||
- ❌ Preset-switch confirmation alert (`isLocked==false && isNewPreset` → "Save & Switch"/"Discard & Switch") — Android just always re-renders silently
|
||||
|
||||
## Networking / protocol
|
||||
- ✅ WebSocket connect/dispatch, Bonjour discovery, `control`/`control_f` sends
|
||||
- ⚠️ `save_layout` — iOS **never sends this over the wire**, it's 100% local (`UserDefaults`) only. Android sends `save_layout` to the desktop on every drag/resize. Known, deliberate-at-the-time divergence, not yet reconciled.
|
||||
- ❌ `widget_visibility` on Hide — iOS sends `{"event":"widget_visibility","uid":...,"dest_id":0}` on hide, telling the desktop to un-route that widget (unchecks its remote checkbox there). Android's Hide is local-only, desktop has no idea.
|
||||
|
||||
## Widgets — regular (preset-routed)
|
||||
- ⚠️ `FaderWidget` — confirmed against source: iOS's regular fader has the same `modeButton` (REL/ABS) and 90dp top/bottom `padHeight` dead zone as `FocusFaderWidget`, both fit inside the same 540dp total (not additive) — ported to Android's `FaderWidgetView` (now `FrameLayout`-based, mirroring `FocusFaderWidgetView`'s structure). Android's total height is 540+180=720dp (not iOS's literal 540) to keep the active drag range unshrunk — deliberate, pre-existing divergence, not a bug. Android's regular fader also got a **FINE** button, which iOS's regular `FaderWidget` does NOT have (FINE is Focus-only on iOS) — added by direct request, an intentional Android-only addition beyond parity.
|
||||
- ✅ `ToggleWidget`/`TransportWidget` — 75×75dp, matched
|
||||
- ✅ `FeedbackWidget` — 220×100dp, matched. (Verified 2026-07-29: this is really "matched by both being unused" — `FeedbackWidget.swift` exists on iOS but is never instantiated, and Android has no regular-feedback view or model. The 220×100 constant only ever applied to the *Focus* feedback widget.)
|
||||
- ✅ `TitleWidget` — confirmed against source: iOS hardcodes a single `uid = "title-big"` instance too (`idx` in `defaultFrame(idx:)` is unused for title — leftover grid-placement signature shared with faders/toggles/feedbacks). Android's one-title-per-preset binding matches.
|
||||
|
||||
## Widgets — Channel Focus
|
||||
- ✅ `FocusFaderWidget` — REL/ABS + FINE buttons, dead-zone touch math
|
||||
- ✅ Focus Fader length rescale context-menu options ("50% Longer" / "70% Longer" / "Reset Length") — height-only, bottom-edge anchored, multiplier applied to default (not current) height.
|
||||
- ✅ `FocusToggleWidget` — momentary mode + Gray/White non-darkenable color quirk
|
||||
- ✅ `FocusFeedbackWidget` — chrome-less (transparent background, no resting card border, no caption view, 8dp padding), 32sp monospace semibold at `#EBEBEB`, single line. Box is a pure function of (font size, text) via `fittedSize`, re-fit center-anchored on every `widget_feedback`. Pinch drives **font size**, not the box; "Reset size" restores 32sp; min 12sp. Font size is not persisted — it's back-derived from the saved height on load, matching iOS exactly (see "Networking" note: no schema change). Two knowing approximations: iOS's `.semibold` (weight 600) is only expressible from API 28, so API 24–27 falls back to BOLD; and Android still flashes the activity ring green on incoming `widget_feedback` where iOS's `applyFeedbackText` doesn't flash at all.
|
||||
- Perf note (2026-07-29): re-fitting calls `setLayoutParams()`, which on Android `requestLayout()`s up the tree — unlike iOS's `bounds.size`, which costs siblings nothing. This was briefly suspected of causing fader stutter and reverted; the stutter turned out to persist without this code, so it was reinstated. The unproven suspect is instead the faders' own `setLayerType(LAYER_TYPE_SOFTWARE)` plus per-`onDraw` `LinearGradient` allocation. If this widget ever *does* need optimizing, the cheap fix is skipping the re-fit when the newly measured size equals the current one — monospace means most readout updates measure identical.
|
||||
- ⚠️ `LogWidget` — iOS is a draggable, pinch-resizable floating console with **In/Out/Local category tabs**, only rebuilding its TextView when the visible category matches what's being logged (the actual reason it doesn't have Android's perf problem). Android's log panel is a fixed bottom overlay, single combined stream, no categories, no drag/resize.
|
||||
|
||||
## Context menu (long-press, Arrange mode only)
|
||||
- ❌ Align Left/Center/Right (`TextAlignableWidget`) — not built
|
||||
- ❌ Text Color (`TextColorableWidget`, from the named palette matching desktop's `palette.py`) — not built, local-only styling on iOS (no wire event)
|
||||
- ⚠️ Hide — present on Android but wrong semantics (see "Networking" above: no `widget_visibility` send)
|
||||
- ✅ Reset Size — box dimensions for regular widgets, font size for `FocusFeedbackWidget` (matching iOS, which means two different things by the same menu item).
|
||||
- ✅ Focus Fader length rescale (see above) — `remote-client-android/.../arrange/{ArrangeCardView,ArrangeUILayout,ArrangeFunctionsAlerts}.java`
|
||||
|
||||
## Arrange mode / layout
|
||||
- ✅ Free 2D drag, pinch-resize (generic, top-left anchored)
|
||||
- ✅ Per-preset + Channel Focus separate layout persistence
|
||||
- ✅ Clear Layout (per-mode) + Reset ALL Layouts (Android-only addition, flagged as an iOS backlog item in memory)
|
||||
- ⚠️ Default placement: iOS uses `defaultFrame(idx:)` per-type grids at fixed screen-relative coordinates (with real overlap between types by iOS's own design). Android stacks everything at `(0,0)` — simpler, deliberately chosen over Android's earlier over-engineered fit-to-screen algorithm.
|
||||
|
||||
---
|
||||
**When picking something off this list to build:** re-read the actual iOS source file first (don't assume from this doc alone — it's a snapshot, not guaranteed current), confirm the ❓ items against source before treating them as gaps.
|
||||
Reference in New Issue
Block a user