Wire Android SSO Custom Tabs, carousel-safe swipes, and core saveMedia.
All checks were successful
Build / increment-version (push) Successful in 6s
Build / build-android (push) Successful in 5m41s

Open SSO in Capacitor Browser with paarrot://android return; stop swipe-to-reply stealing carousel scrolls; bump cinny for shared save helpers and register MediaStore from the overlay.
This commit is contained in:
2026-08-09 20:49:05 +10:00
parent a1c6015772
commit bb768911ef
17 changed files with 289 additions and 776 deletions

View File

@@ -45,22 +45,42 @@ type MobileSwipeGestureHostProps = {
children: ReactNode;
};
const IGNORE_BACK_SELECTOR =
'input, textarea, [contenteditable="true"], [data-allow-text-selection="true"], [data-carousel-scroller], [data-disable-swipe-back="true"]';
const IGNORE_REPLY_SELECTOR =
'input, textarea, [contenteditable="true"], [data-allow-text-selection="true"], [data-carousel-scroller], [data-disable-swipe-reply="true"]';
/** True when the touch starts on (or inside) a horizontally scrollable region like an image carousel. */
const isInsideHorizontalScroller = (target: EventTarget | null): boolean => {
if (!(target instanceof Element)) return false;
let el: Element | null = target;
while (el && el !== document.documentElement) {
if (el instanceof HTMLElement) {
const style = window.getComputedStyle(el);
const overflowX = style.overflowX;
if (
(overflowX === 'auto' || overflowX === 'scroll' || overflowX === 'overlay') &&
el.scrollWidth > el.clientWidth + 1
) {
return true;
}
}
el = el.parentElement;
}
return false;
};
const shouldIgnoreBackTarget = (target: EventTarget | null): boolean => {
if (!(target instanceof Element)) return true;
return Boolean(
target.closest(
'input, textarea, [contenteditable="true"], [data-allow-text-selection="true"], [data-carousel-scroller], [data-disable-swipe-back="true"]'
)
);
return Boolean(target.closest(IGNORE_BACK_SELECTOR)) || isInsideHorizontalScroller(target);
};
const shouldIgnoreReplyTarget = (target: EventTarget | null): boolean => {
if (!(target instanceof Element)) return true;
return Boolean(
target.closest(
'input, textarea, [contenteditable="true"], [data-allow-text-selection="true"], [data-carousel-scroller], [data-disable-swipe-reply="true"]'
)
);
return Boolean(target.closest(IGNORE_REPLY_SELECTOR)) || isInsideHorizontalScroller(target);
};
const findMessageElement = (target: EventTarget | null): HTMLElement | null => {