Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
| ca34e026fb |
8 changed files with 78 additions and 10 deletions
|
|
@ -38,8 +38,8 @@ versionCode = major * 1_000_000 + minor * 1_000 + patch
|
||||||
- **Service Worker stays active.** Critical for authenticated Matrix media (MSC3916 / Matrix spec v1.11+). DO NOT disable. `resolveServiceWorkerRequests` default `true`.
|
- **Service Worker stays active.** Critical for authenticated Matrix media (MSC3916 / Matrix spec v1.11+). DO NOT disable. `resolveServiceWorkerRequests` default `true`.
|
||||||
- **Edge-to-edge.** `EdgeToEdge.enable()` in `MainActivity.java` + `windowLayoutInDisplayCutoutMode: shortEdges`.
|
- **Edge-to-edge.** `EdgeToEdge.enable()` in `MainActivity.java` + `windowLayoutInDisplayCutoutMode: shortEdges`.
|
||||||
- **External links.** Opened via `@capacitor/browser` plugin — see [`src/app/utils/capacitor.ts`](../../src/app/utils/capacitor.ts).
|
- **External links.** Opened via `@capacitor/browser` plugin — see [`src/app/utils/capacitor.ts`](../../src/app/utils/capacitor.ts).
|
||||||
- **Safe-area coloring.** `body` background-color is bound to the folds theme variable `var(--oq6d070)` for consistent safe-area coloring.
|
- **Safe-area coloring.** `body` background-color reads `--vojo-safe-area-bg` (set on `:root` in [`src/app/styles/global.css.ts`](../../src/app/styles/global.css.ts), default `#0d0e11` = chat-list tone). [`Room.tsx`](../../src/app/features/room/Room.tsx) retunes the var to `#181a20` (chat-surface tone) while a chat is mounted so the status-bar / gesture-bar zones never show a seam against the active surface.
|
||||||
- **Safe-area insets.** Applied on `#root` (not `body`) so the theme background extends behind the system bars.
|
- **Safe-area insets — top / left / right only on `#root`.** Bottom inset is intentionally **not** applied at `#root` so the app renders edge-to-edge under the Android gesture pill / 3-button bar / iOS home indicator (mirrors WhatsApp / Telegram). Components that anchor interactive UI at the screen bottom MUST add `padding-bottom: var(--vojo-safe-bottom)` themselves — covered: chat composer ([`RoomView.css.ts`](../../src/app/features/room/RoomView.css.ts)), PageNav inner column ([`Page.tsx`](../../src/app/components/page/Page.tsx) → catches SelfRow / WorkspaceFooter / etc.), bottom call rail ([`HorseshoeContainer.css.ts`](../../src/app/pages/HorseshoeContainer.css.ts)), AuthFooter ([`auth/styles.css.ts`](../../src/app/pages/auth/styles.css.ts)). New screens with a bottom CTA must follow this rule or the button lands behind a system 3-button nav bar.
|
||||||
|
|
||||||
## VSCode tasks
|
## VSCode tasks
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,11 @@ export function PageNav({
|
||||||
grow="Yes"
|
grow="Yes"
|
||||||
direction="Column"
|
direction="Column"
|
||||||
className={horseshoe ? css.PageNavInnerWebHorseshoe : undefined}
|
className={horseshoe ? css.PageNavInnerWebHorseshoe : undefined}
|
||||||
|
// Bottom inset for native: keeps any nav-footer row (SelfRow,
|
||||||
|
// WorkspaceFooter, …) clear of the Android gesture pill / 3-button
|
||||||
|
// bar / iOS home indicator after `#root` stopped reserving the
|
||||||
|
// inset itself. `var(--vojo-safe-bottom)` resolves to 0 on web.
|
||||||
|
style={{ paddingBottom: 'var(--vojo-safe-bottom)' }}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -268,6 +273,10 @@ function ResizablePageNav({ children }: { children: ReactNode }) {
|
||||||
grow="Yes"
|
grow="Yes"
|
||||||
direction="Column"
|
direction="Column"
|
||||||
className={horseshoe ? css.PageNavInnerWebHorseshoe : undefined}
|
className={horseshoe ? css.PageNavInnerWebHorseshoe : undefined}
|
||||||
|
// See twin block in `PageNav` above — same native safe-area
|
||||||
|
// protection for any footer row mounted inside a resizable
|
||||||
|
// page-nav. On web `var(--vojo-safe-bottom)` is 0.
|
||||||
|
style={{ paddingBottom: 'var(--vojo-safe-bottom)' }}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback, useEffect } from 'react';
|
||||||
import { Box, Line, toRem } from 'folds';
|
import { Box, Line, toRem } from 'folds';
|
||||||
import { useMatch, useParams } from 'react-router-dom';
|
import { useMatch, useParams } from 'react-router-dom';
|
||||||
import { isKeyHotkey } from 'is-hotkey';
|
import { isKeyHotkey } from 'is-hotkey';
|
||||||
|
|
@ -112,6 +112,28 @@ export function Room({ renderRoomView }: RoomProps) {
|
||||||
const profileOpen = !!useAtomValue(userRoomProfileAtom);
|
const profileOpen = !!useAtomValue(userRoomProfileAtom);
|
||||||
const showProfileHorseshoe = profileOpen && !isMobile && !showThreadDrawer;
|
const showProfileHorseshoe = profileOpen && !isMobile && !showThreadDrawer;
|
||||||
|
|
||||||
|
// Re-tune the Android edge-to-edge safe-area bg while a Room is on
|
||||||
|
// screen. The default value from `app/styles/global.css.ts` paints
|
||||||
|
// the chat-list tone (#0d0e11) into the status bar / nav bar zones —
|
||||||
|
// fine when the chat list is showing, but produces a visible seam
|
||||||
|
// once the chat itself (SurfaceVariant.Container, #181a20) is opened.
|
||||||
|
//
|
||||||
|
// Value is hardcoded for the SAME reason `global.css.ts` hardcodes
|
||||||
|
// `#0d0e11`: folds tokens (`color.SurfaceVariant.Container = var(--xxx)`)
|
||||||
|
// are scoped to the `.dark-theme` / `.lightTheme` class which ThemeManager
|
||||||
|
// applies to `document.body`, not to `:root`. Writing the var on `:root`
|
||||||
|
// means folds' `--xxx` doesn't resolve there and the whole declaration
|
||||||
|
// becomes invalid (body falls back to the `#0d0e11` literal in `index.css`).
|
||||||
|
// `#181a20` is `SurfaceVariant.Container` from the dark Dawn palette —
|
||||||
|
// kept in sync with `colors.css.ts` line 40 if the palette tone changes.
|
||||||
|
useEffect(() => {
|
||||||
|
const root = document.documentElement;
|
||||||
|
root.style.setProperty('--vojo-safe-area-bg', '#181a20');
|
||||||
|
return () => {
|
||||||
|
root.style.removeProperty('--vojo-safe-area-bg');
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
useKeyDown(
|
useKeyDown(
|
||||||
window,
|
window,
|
||||||
useCallback(
|
useCallback(
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,19 @@ globalStyle(`${ChatComposer} .${Editor}`, {
|
||||||
// Top-left mirror (curve at y=19 from top is ~2.8px from left, text-left
|
// Top-left mirror (curve at y=19 from top is ~2.8px from left, text-left
|
||||||
// at 28px → ~25px clearance) is even more generous, which fits the
|
// at 28px → ~25px clearance) is even more generous, which fits the
|
||||||
// single-line composer that grows downward when wrapping.
|
// single-line composer that grows downward when wrapping.
|
||||||
padding: `${toRem(6)} ${toRem(16)}`,
|
//
|
||||||
|
// Bottom padding ALSO carries the safe-area inset (`--vojo-safe-bottom`)
|
||||||
|
// so the action row (Plus / Smiley / Send) stays clear of the Android
|
||||||
|
// gesture pill / 3-button bar / iOS home indicator now that `#root`
|
||||||
|
// stopped reserving the inset itself (see src/index.css). The card's
|
||||||
|
// bg simply grows downward to fill the safe-area zone, which is the
|
||||||
|
// edge-to-edge pattern used by every mainstream messenger. The
|
||||||
|
// ResizeObserver in `RoomView` measures the wrap's full height
|
||||||
|
// (incl. this padding) and feeds it to `RoomTimeline`, so the
|
||||||
|
// bottom scroll-padding still ends right above the visible card
|
||||||
|
// top — no extra whitespace appears between the last message and
|
||||||
|
// the card.
|
||||||
|
padding: `${toRem(6)} ${toRem(16)} calc(${toRem(6)} + var(--vojo-safe-bottom))`,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Visual alignment goal: typed-text glyph-start and Plus-icon glyph-start
|
// Visual alignment goal: typed-text glyph-start and Plus-icon glyph-start
|
||||||
|
|
|
||||||
|
|
@ -50,13 +50,18 @@ export const appShellBottomRound = style({
|
||||||
|
|
||||||
// === Bottom horseshoe (call rail) ===
|
// === Bottom horseshoe (call rail) ===
|
||||||
//
|
//
|
||||||
// Rounded *top* corners only because it sits flush against the
|
// Rounded *top* corners only — the rail's bottom edge is the screen
|
||||||
// safe-area inset; the bottom is the screen edge. `position: relative`
|
// edge. `position: relative` carries the absolute-positioned orbit
|
||||||
// carries the absolute-positioned orbit border.
|
// border. Bottom padding carries the native safe-area inset so the
|
||||||
|
// call action buttons (accept / decline / hang up) stay clear of the
|
||||||
|
// Android gesture pill / 3-button bar / iOS home indicator after
|
||||||
|
// `#root` stopped reserving the inset (src/index.css). The rail's bg
|
||||||
|
// continues underneath the inset for visual continuity.
|
||||||
export const bottomRail = style({
|
export const bottomRail = style({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
|
paddingBottom: 'var(--vojo-safe-bottom)',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const bottomRailActive = style({
|
export const bottomRailActive = style({
|
||||||
|
|
|
||||||
|
|
@ -271,7 +271,10 @@ export const AuthFooter = style({
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
padding: '20px 24px 10px',
|
// Bottom padding folds in the native safe-area inset so the footer
|
||||||
|
// text/links stay clear of the Android gesture pill / 3-button bar /
|
||||||
|
// iOS home indicator after `#root` stopped reserving the inset.
|
||||||
|
padding: '20px 24px calc(10px + var(--vojo-safe-bottom))',
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
color: 'rgba(232, 228, 223, 0.55)',
|
color: 'rgba(232, 228, 223, 0.55)',
|
||||||
letterSpacing: '0.02em',
|
letterSpacing: '0.02em',
|
||||||
|
|
|
||||||
|
|
@ -23,5 +23,15 @@ import { globalStyle } from '@vanilla-extract/css';
|
||||||
globalStyle(':root', {
|
globalStyle(':root', {
|
||||||
vars: {
|
vars: {
|
||||||
'--vojo-safe-area-bg': '#0d0e11',
|
'--vojo-safe-area-bg': '#0d0e11',
|
||||||
|
// Mirror of `env(safe-area-inset-bottom)` exposed as a regular CSS
|
||||||
|
// variable so consumers don't repeat the `env(..., 0px)` fallback
|
||||||
|
// boilerplate. Used as `padding-bottom` by every component that
|
||||||
|
// anchors interactive UI at the bottom of the viewport (chat
|
||||||
|
// composer, PageNav footer rows, AuthFooter, bottom call rail).
|
||||||
|
// Required since `src/index.css` no longer adds bottom safe-area
|
||||||
|
// padding to `#root` (apps render edge-to-edge under the Android
|
||||||
|
// gesture pill / iOS home indicator). On web env() resolves to 0,
|
||||||
|
// so the variable is a no-op outside native / PWA.
|
||||||
|
'--vojo-safe-bottom': 'env(safe-area-inset-bottom, 0px)',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,15 @@ body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom)
|
/* Top / left / right insets keep app chrome (status icons, sidebar
|
||||||
env(safe-area-inset-left);
|
rail) clear of system bars and display cutouts. Bottom inset is
|
||||||
|
intentionally zero: on Android edge-to-edge the gesture bar is a
|
||||||
|
translucent overlay, not a reserved strip — leaving #root padded
|
||||||
|
there reserves a tall band of body bg below the chat surface and
|
||||||
|
prevents the composer / call rail from reaching the screen edge.
|
||||||
|
Components that genuinely need bottom safe-area clearance (e.g.
|
||||||
|
SyncIndicator) read env(safe-area-inset-bottom) themselves. */
|
||||||
|
padding: env(safe-area-inset-top) env(safe-area-inset-right) 0 env(safe-area-inset-left);
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue