mirror of
https://github.com/zadam/trilium.git
synced 2026-02-28 09:33:38 +01:00
Mobile fixes (#8832)
Some checks failed
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
Deploy Documentation / Build and Deploy Documentation (push) Has been cancelled
Deploy web clipper extension / Build web clipper extension (push) Has been cancelled
Some checks failed
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
Deploy Documentation / Build and Deploy Documentation (push) Has been cancelled
Deploy web clipper extension / Build web clipper extension (push) Has been cancelled
This commit is contained in:
commit
6a3c4fec98
@ -2630,7 +2630,7 @@ iframe.print-iframe {
|
||||
}
|
||||
}
|
||||
|
||||
#root-widget.virtual-keyboard-opened .note-split:not(.active) {
|
||||
body:not(.ios) #root-widget.virtual-keyboard-opened .note-split:not(.active) {
|
||||
max-height: 80px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import "./NoteDetail.css";
|
||||
|
||||
import clsx from "clsx";
|
||||
import { note } from "mermaid/dist/rendering-util/rendering-elements/shapes/note.js";
|
||||
import { isValidElement, VNode } from "preact";
|
||||
import { useEffect, useRef, useState } from "preact/hooks";
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 20px;
|
||||
top: calc(env(safe-area-inset-top) + 20px);
|
||||
pointer-events: none;
|
||||
contain: none;
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ import { LOCALES } from "@triliumnext/commons";
|
||||
import { EventData } from "../../components/app_context.js";
|
||||
import { getEnabledExperimentalFeatureIds } from "../../services/experimental_features.js";
|
||||
import options from "../../services/options.js";
|
||||
import utils, { isMobile } from "../../services/utils.js";
|
||||
import utils, { isIOS, isMobile } from "../../services/utils.js";
|
||||
import { readCssVar } from "../../utils/css-var.js";
|
||||
import type BasicWidget from "../basic_widget.js";
|
||||
import FlexContainer from "./flex_container.js";
|
||||
@ -19,9 +19,12 @@ import FlexContainer from "./flex_container.js";
|
||||
*/
|
||||
export default class RootContainer extends FlexContainer<BasicWidget> {
|
||||
|
||||
private originalWindowHeight: number;
|
||||
|
||||
constructor(isHorizontalLayout: boolean) {
|
||||
super(isHorizontalLayout ? "column" : "row");
|
||||
|
||||
this.originalWindowHeight = window.innerHeight ?? 0;
|
||||
this.id("root-widget");
|
||||
this.css("height", "100dvh");
|
||||
}
|
||||
@ -31,6 +34,7 @@ export default class RootContainer extends FlexContainer<BasicWidget> {
|
||||
window.visualViewport?.addEventListener("resize", () => this.#onMobileResize());
|
||||
}
|
||||
|
||||
this.#setDeviceSpecificClasses();
|
||||
this.#setMaxContentWidth();
|
||||
this.#setMotion();
|
||||
this.#setShadows();
|
||||
@ -65,7 +69,7 @@ export default class RootContainer extends FlexContainer<BasicWidget> {
|
||||
|
||||
#onMobileResize() {
|
||||
const viewportHeight = window.visualViewport?.height ?? window.innerHeight;
|
||||
const windowHeight = window.innerHeight;
|
||||
const windowHeight = Math.max(window.innerHeight, this.originalWindowHeight); // inner height changes when keyboard is opened, we need to compare with the original height to detect it.
|
||||
|
||||
// If viewport is significantly smaller, keyboard is likely open
|
||||
const isKeyboardOpened = windowHeight - viewportHeight > 150;
|
||||
@ -117,6 +121,12 @@ export default class RootContainer extends FlexContainer<BasicWidget> {
|
||||
document.body.dir = correspondingLocale?.rtl ? "rtl" : "ltr";
|
||||
}
|
||||
|
||||
#setDeviceSpecificClasses() {
|
||||
if (isIOS()) {
|
||||
document.body.classList.add("ios");
|
||||
}
|
||||
}
|
||||
|
||||
#initPWATopbarColor() {
|
||||
if (!utils.isPWA()) return;
|
||||
const tracker = $("#background-color-tracker");
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import FlexContainer from "./containers/flex_container.js";
|
||||
import utils from "../services/utils.js";
|
||||
import attributeService from "../services/attributes.js";
|
||||
import type BasicWidget from "./basic_widget.js";
|
||||
import type { EventData } from "../components/app_context.js";
|
||||
import type NoteContext from "../components/note_context.js";
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import attributeService from "../services/attributes.js";
|
||||
import { getLocaleById } from "../services/i18n.js";
|
||||
import utils from "../services/utils.js";
|
||||
import type BasicWidget from "./basic_widget.js";
|
||||
import FlexContainer from "./containers/flex_container.js";
|
||||
|
||||
export default class NoteWrapperWidget extends FlexContainer<BasicWidget> {
|
||||
|
||||
@ -43,11 +43,16 @@ export default class NoteWrapperWidget extends FlexContainer<BasicWidget> {
|
||||
|
||||
refresh() {
|
||||
const isHiddenExt = this.isHiddenExt(); // preserve through class reset
|
||||
const isActive = this.$widget.hasClass("active");
|
||||
|
||||
this.$widget.removeClass();
|
||||
|
||||
this.toggleExt(!isHiddenExt);
|
||||
|
||||
if (isActive) {
|
||||
this.$widget.addClass("active");
|
||||
}
|
||||
|
||||
this.$widget.addClass("component note-split");
|
||||
|
||||
const note = this.noteContext?.note;
|
||||
@ -92,7 +97,7 @@ export default class NoteWrapperWidget extends FlexContainer<BasicWidget> {
|
||||
#hasBackgroundEffects(note: FNote): boolean {
|
||||
const MIME_TYPES_WITH_BACKGROUND_EFFECTS = [
|
||||
"application/pdf"
|
||||
]
|
||||
];
|
||||
|
||||
const COLLECTIONS_WITH_BACKGROUND_EFFECTS = [
|
||||
"grid",
|
||||
|
||||
@ -2,22 +2,14 @@ body.mobile {
|
||||
.classic-toolbar-outer-container {
|
||||
contain: none !important;
|
||||
}
|
||||
|
||||
|
||||
.classic-toolbar-outer-container.visible {
|
||||
height: 38px;
|
||||
background-color: var(--main-background-color);
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
#root-widget.virtual-keyboard-opened .classic-toolbar-outer-container.ios {
|
||||
position: absolute;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
.classic-toolbar-widget {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
@ -28,27 +20,27 @@ body.mobile {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
user-select: none;
|
||||
touch-action: pan-x;
|
||||
scrollbar-width: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
.classic-toolbar-widget::-webkit-scrollbar:horizontal {
|
||||
height: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
.classic-toolbar-widget.dropdown-active {
|
||||
height: 50vh;
|
||||
}
|
||||
|
||||
|
||||
.classic-toolbar-widget .ck.ck-toolbar {
|
||||
--ck-color-toolbar-background: transparent;
|
||||
--ck-color-toolbar-background: var(--main-background-color);
|
||||
--ck-color-button-default-background: transparent;
|
||||
--ck-color-button-default-disabled-background: transparent;
|
||||
position: absolute;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
.classic-toolbar-widget .ck.ck-button.ck-disabled {
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,11 +66,22 @@ export default function MobileEditorToolbar({ inPopupEditor }: MobileEditorToolb
|
||||
}
|
||||
|
||||
function usePositioningOniOS(enabled: boolean, wrapperRef: MutableRef<HTMLDivElement | null>) {
|
||||
// Capture the baseline offset (Safari nav bar height) before the keyboard opens.
|
||||
const baselineOffset = useRef(window.innerHeight - (window.visualViewport?.height ?? window.innerHeight));
|
||||
|
||||
const adjustPosition = useCallback(() => {
|
||||
if (!wrapperRef.current) return;
|
||||
const bottom = window.innerHeight - (window.visualViewport?.height || 0);
|
||||
wrapperRef.current.style.bottom = `${bottom}px`;
|
||||
}, []);
|
||||
const viewport = window.visualViewport;
|
||||
if (!viewport) return;
|
||||
// Subtract the baseline so only the keyboard's contribution remains.
|
||||
const bottom = window.innerHeight - viewport.height - viewport.offsetTop;
|
||||
if (bottom - baselineOffset.current <= 0) {
|
||||
// Keyboard is hidden — clear the inline style so CSS controls positioning.
|
||||
wrapperRef.current.style.removeProperty("bottom");
|
||||
} else {
|
||||
wrapperRef.current.style.bottom = `${bottom}px`;
|
||||
}
|
||||
}, [ wrapperRef ]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isIOS() || !enabled) return;
|
||||
@ -82,7 +93,7 @@ function usePositioningOniOS(enabled: boolean, wrapperRef: MutableRef<HTMLDivEle
|
||||
window.visualViewport?.removeEventListener("resize", adjustPosition);
|
||||
window.removeEventListener("scroll", adjustPosition);
|
||||
};
|
||||
}, [ enabled ]);
|
||||
}, [ enabled, adjustPosition ]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user