mirror of
https://github.com/zadam/trilium.git
synced 2026-02-26 08:10:56 +01:00
Compare commits
32 Commits
feat/ui/ge
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a3c4fec98 | ||
|
|
6bda7837d6 | ||
|
|
ab9144972b | ||
|
|
bcb646f42b | ||
|
|
0db75a6cdb | ||
|
|
76c7b8692d | ||
|
|
1061aba212 | ||
|
|
d4eb6f07bd | ||
|
|
f1a83124a8 | ||
|
|
2ad30c6a3d | ||
|
|
0f1533d0a0 | ||
|
|
bf5caaebb5 | ||
|
|
2d989dcfe3 | ||
|
|
8e8e6f9ed1 | ||
|
|
e1de98c4ae | ||
|
|
fc59ee6e93 | ||
|
|
5ec9770b07 | ||
|
|
1c1895b2eb | ||
|
|
416825c9c2 | ||
|
|
6762539b4d | ||
|
|
ae9827c436 | ||
|
|
33622cd3fe | ||
|
|
e69b85a988 | ||
|
|
aabc9ec4df | ||
|
|
598501e3f6 | ||
|
|
bfa344a839 | ||
|
|
c466d7ee9f | ||
|
|
2e9c07d3d6 | ||
|
|
3a15878629 | ||
|
|
021a908c9c | ||
|
|
c09ef3af80 | ||
|
|
3151e6dafc |
@@ -16,7 +16,7 @@
|
||||
"license": "AGPL-3.0-only",
|
||||
"packageManager": "pnpm@10.30.2",
|
||||
"devDependencies": {
|
||||
"@redocly/cli": "2.19.1",
|
||||
"@redocly/cli": "2.19.2",
|
||||
"archiver": "7.0.1",
|
||||
"fs-extra": "11.3.3",
|
||||
"js-yaml": "4.1.1",
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "17.0.3",
|
||||
"mermaid": "11.12.3",
|
||||
"mind-elixir": "5.9.0",
|
||||
"mind-elixir": "5.9.1",
|
||||
"normalize.css": "8.0.1",
|
||||
"panzoom": "9.4.3",
|
||||
"preact": "10.28.4",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -647,10 +647,10 @@ html .note-detail-editable-text :not(figure, .include-note, hr):first-child {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:root .ck-content hr {
|
||||
margin-block: 5px;
|
||||
height: 0;
|
||||
border: thin solid var(--main-border-color);
|
||||
.ck-content hr {
|
||||
margin: 5px 0;
|
||||
height: 1px;
|
||||
background-color: var(--main-border-color);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -372,6 +372,10 @@ body[dir=ltr] #launcher-container {
|
||||
.calendar-dropdown-widget .calendar-header [data-calendar-input="month"] {
|
||||
--input-background-color: transparent;
|
||||
--menu-background-color: transparent;
|
||||
|
||||
text-align: center;
|
||||
font-size: 1.4em;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.calendar-dropdown-widget .calendar-header input:not(:focus) {
|
||||
@@ -421,6 +425,8 @@ body[dir=ltr] #launcher-container {
|
||||
}
|
||||
|
||||
.calendar-dropdown-widget .calendar-week span {
|
||||
font-size: 0.85em;
|
||||
font-weight: 500;
|
||||
color: var(--calendar-weekday-labels-color);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
height: 100%;
|
||||
display: flex;
|
||||
gap: 1em;
|
||||
margin-inline: var(--content-margin-inline);
|
||||
padding-inline: 12px;
|
||||
padding-block: 4px;
|
||||
align-items: flex-start;
|
||||
overflow-x: auto;
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
--fc-border-color: var(--main-border-color);
|
||||
--fc-neutral-bg-color: var(--launcher-pane-background-color);
|
||||
--fc-list-event-hover-bg-color: var(--left-pane-item-hover-background);
|
||||
padding: 0 var(--content-margin-inline);
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.calendar-container .fc-list-sticky .fc-list-day > * {
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
.table-view-container {
|
||||
height: 100%;
|
||||
margin-inline-start: var(--content-margin-inline);
|
||||
}
|
||||
|
||||
.search-result-widget-content .table-view {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
.calendar-dropdown-widget .calendar-header {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
padding: 0 0.5rem 1rem 0.5rem;
|
||||
padding: 0 0.5rem 0.5rem 0.5rem;
|
||||
}
|
||||
|
||||
.calendar-dropdown-widget .calendar-header>div {
|
||||
@@ -65,14 +65,8 @@
|
||||
border: 0;
|
||||
border-inline-start: unset;
|
||||
background-color: var(--menu-background-color);
|
||||
font-weight: 400;
|
||||
font-weight: bold;
|
||||
outline: 0;
|
||||
font-weight: 300;
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
.calendar-dropdown-widget .calendar-header .dropdown-toggle {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.calendar-dropdown-widget .calendar-header .dropdown-toggle::after {
|
||||
@@ -88,20 +82,18 @@
|
||||
.calendar-dropdown-widget .calendar-week span {
|
||||
flex-direction: column;
|
||||
flex: 0 0 12.5%;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
max-width: 12.5%;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
font-size: .85em;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.calendar-dropdown-widget .calendar-body {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
min-height: 250px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.calendar-dropdown-widget .calendar-week-number {
|
||||
|
||||
@@ -4,11 +4,10 @@ body.experimental-feature-new-layout {
|
||||
}
|
||||
|
||||
.title-actions {
|
||||
--title-actions-padding-start: var(--content-margin-inline);
|
||||
--title-actions-padding-end: var(--content-margin-inline);
|
||||
--title-actions-padding-start: 12px;
|
||||
--title-actions-padding-end: 8px;
|
||||
|
||||
display: flex;
|
||||
width: 100%;
|
||||
max-width: var(--max-content-width);
|
||||
flex-direction: column;
|
||||
gap: 0.5em;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
position: relative;
|
||||
top: 5px;
|
||||
padding: .25em 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow-x: auto;
|
||||
|
||||
@@ -26,6 +26,7 @@ export default function NoteTitleWidget(props: {className?: string}) {
|
||||
|| note === undefined
|
||||
|| (note.isProtected && !protected_session_holder.isProtectedSessionAvailable())
|
||||
|| isLaunchBarConfig(note.noteId)
|
||||
|| note.noteId.startsWith("_help_")
|
||||
|| viewScope?.viewMode !== "default";
|
||||
setReadOnly(isReadOnly);
|
||||
}, [ note, note?.noteId, note?.isProtected, viewScope?.viewMode ]);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1383,3 +1383,28 @@ export function useGetContextDataFrom<K extends keyof NoteContextDataMap>(
|
||||
return data;
|
||||
}
|
||||
|
||||
export function useColorScheme() {
|
||||
const themeStyle = getThemeStyle();
|
||||
const defaultValue = themeStyle === "auto" ? (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) : themeStyle === "dark";
|
||||
const [ prefersDark, setPrefersDark ] = useState(defaultValue);
|
||||
|
||||
useEffect(() => {
|
||||
if (themeStyle !== "auto") return;
|
||||
const mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
const listener = (e: MediaQueryListEvent) => setPrefersDark(e.matches);
|
||||
|
||||
mediaQueryList.addEventListener("change", listener);
|
||||
return () => mediaQueryList.removeEventListener("change", listener);
|
||||
}, [ themeStyle ]);
|
||||
|
||||
return prefersDark ? "dark" : "light";
|
||||
}
|
||||
|
||||
function getThemeStyle() {
|
||||
const style = window.getComputedStyle(document.body);
|
||||
const themeStyle = style.getPropertyValue("--theme-style");
|
||||
if (style.getPropertyValue("--theme-style-auto") !== "true" && (themeStyle === "light" || themeStyle === "dark")) {
|
||||
return themeStyle as "light" | "dark";
|
||||
}
|
||||
return "auto";
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ export default function ScrollPadding() {
|
||||
const [height, setHeight] = useState<number>(10);
|
||||
const isEnabled = ["text", "code"].includes(note?.type ?? "")
|
||||
&& viewScope?.viewMode === "default"
|
||||
&& note?.isContentAvailable()
|
||||
&& !note?.isTriliumSqlite();
|
||||
|
||||
const refreshHeight = () => {
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
contain: none !important;
|
||||
}
|
||||
|
||||
.search-result-widget .note-list-wrapper {
|
||||
margin-inline: var(--content-margin-inline);
|
||||
.search-result-widget .note-list {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.note-split.type-search .scrolling-container {
|
||||
|
||||
@@ -6,12 +6,12 @@ import "./MindMap.css";
|
||||
import nodeMenu from "@mind-elixir/node-menu";
|
||||
import { DISPLAYABLE_LOCALE_IDS } from "@triliumnext/commons";
|
||||
import { snapdom } from "@zumer/snapdom";
|
||||
import { default as VanillaMindElixir,MindElixirData, MindElixirInstance, Operation, Options } from "mind-elixir";
|
||||
import { default as VanillaMindElixir,MindElixirData, MindElixirInstance, Operation, Options, THEME as LIGHT_THEME, DARK_THEME } from "mind-elixir";
|
||||
import { HTMLAttributes, RefObject } from "preact";
|
||||
import { useCallback, useEffect, useRef } from "preact/hooks";
|
||||
|
||||
import utils from "../../services/utils";
|
||||
import { useEditorSpacedUpdate, useNoteLabelBoolean, useSyncedRef, useTriliumEvent, useTriliumEvents, useTriliumOption } from "../react/hooks";
|
||||
import { useColorScheme, useEditorSpacedUpdate, useNoteLabelBoolean, useSyncedRef, useTriliumEvent, useTriliumEvents, useTriliumOption } from "../react/hooks";
|
||||
import { refToJQuerySelector } from "../react/react_utils";
|
||||
import { TypeWidgetProps } from "./type_widget";
|
||||
|
||||
@@ -85,9 +85,11 @@ export default function MindMap({ note, ntxId, noteContext }: TypeWidgetProps) {
|
||||
},
|
||||
onContentChange: (content) => {
|
||||
let newContent: MindElixirData;
|
||||
|
||||
if (content) {
|
||||
try {
|
||||
newContent = JSON.parse(content) as MindElixirData;
|
||||
delete newContent.theme; // The theme is managed internally by the widget, so we remove it from the loaded content to avoid inconsistencies.
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
console.debug("Wrong JSON content: ", content);
|
||||
@@ -151,6 +153,7 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef
|
||||
const containerRef = useSyncedRef<HTMLDivElement>(externalContainerRef, null);
|
||||
const apiRef = useRef<MindElixirInstance>(null);
|
||||
const [ locale ] = useTriliumOption("locale");
|
||||
const colorScheme = useColorScheme();
|
||||
|
||||
function reinitialize() {
|
||||
if (!containerRef.current) return;
|
||||
@@ -158,7 +161,8 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef
|
||||
const mind = new VanillaMindElixir({
|
||||
el: containerRef.current,
|
||||
locale: LOCALE_MAPPINGS[locale as DISPLAYABLE_LOCALE_IDS] ?? undefined,
|
||||
editable
|
||||
editable,
|
||||
theme: LIGHT_THEME
|
||||
});
|
||||
|
||||
if (editable) {
|
||||
@@ -179,6 +183,14 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef
|
||||
};
|
||||
}, []);
|
||||
|
||||
// React to theme changes.
|
||||
useEffect(() => {
|
||||
if (!apiRef.current) return;
|
||||
const newTheme = colorScheme === "dark" ? DARK_THEME : LIGHT_THEME;
|
||||
if (apiRef.current.theme === newTheme) return; // Avoid unnecessary theme changes, which can be expensive to render.
|
||||
apiRef.current.changeTheme(newTheme);
|
||||
}, [ colorScheme ]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = apiRef.current?.getData();
|
||||
reinitialize();
|
||||
|
||||
@@ -3,8 +3,4 @@
|
||||
margin-inline: 40px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
label {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Excalidraw } from "@excalidraw/excalidraw";
|
||||
import { TypeWidgetProps } from "../type_widget";
|
||||
import "@excalidraw/excalidraw/index.css";
|
||||
import { useNoteLabelBoolean, useTriliumOption } from "../../react/hooks";
|
||||
import { useColorScheme, useNoteLabelBoolean, useTriliumOption } from "../../react/hooks";
|
||||
import { useCallback, useMemo, useRef } from "preact/hooks";
|
||||
import { type ExcalidrawImperativeAPI, type AppState } from "@excalidraw/excalidraw/types";
|
||||
import options from "../../../services/options";
|
||||
@@ -19,12 +19,9 @@ window.EXCALIDRAW_ASSET_PATH = `${window.location.pathname}/node_modules/@excali
|
||||
export default function Canvas({ note, noteContext }: TypeWidgetProps) {
|
||||
const apiRef = useRef<ExcalidrawImperativeAPI>(null);
|
||||
const [ isReadOnly ] = useNoteLabelBoolean(note, "readOnly");
|
||||
const themeStyle = useMemo(() => {
|
||||
const documentStyle = window.getComputedStyle(document.documentElement);
|
||||
return documentStyle.getPropertyValue("--theme-style")?.trim() as AppState["theme"];
|
||||
}, []);
|
||||
const colorScheme = useColorScheme();
|
||||
const [ locale ] = useTriliumOption("locale");
|
||||
const persistence = useCanvasPersistence(note, noteContext, apiRef, themeStyle, isReadOnly);
|
||||
const persistence = useCanvasPersistence(note, noteContext, apiRef, colorScheme, isReadOnly);
|
||||
|
||||
/** Use excalidraw's native zoom instead of the global zoom. */
|
||||
const onWheel = useCallback((e: MouseEvent) => {
|
||||
@@ -54,7 +51,7 @@ export default function Canvas({ note, noteContext }: TypeWidgetProps) {
|
||||
<div className="excalidraw-wrapper">
|
||||
<Excalidraw
|
||||
excalidrawAPI={api => apiRef.current = api}
|
||||
theme={themeStyle}
|
||||
theme={colorScheme}
|
||||
viewModeEnabled={isReadOnly || options.is("databaseReadonly")}
|
||||
zenModeEnabled={false}
|
||||
isCollaborating={false}
|
||||
|
||||
@@ -19,12 +19,4 @@
|
||||
.tn-link {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"@triliumnext/commons": "workspace:*",
|
||||
"@triliumnext/server": "workspace:*",
|
||||
"copy-webpack-plugin": "13.0.1",
|
||||
"electron": "40.6.0",
|
||||
"electron": "40.6.1",
|
||||
"@electron-forge/cli": "7.11.1",
|
||||
"@electron-forge/maker-deb": "7.11.1",
|
||||
"@electron-forge/maker-dmg": "7.11.1",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"@triliumnext/desktop": "workspace:*",
|
||||
"@types/fs-extra": "11.0.4",
|
||||
"copy-webpack-plugin": "13.0.1",
|
||||
"electron": "40.6.0",
|
||||
"electron": "40.6.1",
|
||||
"fs-extra": "11.3.3"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:24.13.1-bullseye-slim AS builder
|
||||
FROM node:24.14.0-bullseye-slim AS builder
|
||||
RUN corepack enable
|
||||
|
||||
# Install native dependencies since we might be building cross-platform.
|
||||
@@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
|
||||
# We have to use --no-frozen-lockfile due to CKEditor patches
|
||||
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
||||
|
||||
FROM node:24.13.1-bullseye-slim
|
||||
FROM node:24.14.0-bullseye-slim
|
||||
# Install only runtime dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:24.13.1-alpine AS builder
|
||||
FROM node:24.14.0-alpine AS builder
|
||||
RUN corepack enable
|
||||
|
||||
# Install native dependencies since we might be building cross-platform.
|
||||
@@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
|
||||
# We have to use --no-frozen-lockfile due to CKEditor patches
|
||||
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
||||
|
||||
FROM node:24.13.1-alpine
|
||||
FROM node:24.14.0-alpine
|
||||
# Install runtime dependencies
|
||||
RUN apk add --no-cache su-exec shadow
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:24.13.1-alpine AS builder
|
||||
FROM node:24.14.0-alpine AS builder
|
||||
RUN corepack enable
|
||||
|
||||
# Install native dependencies since we might be building cross-platform.
|
||||
@@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
|
||||
# We have to use --no-frozen-lockfile due to CKEditor patches
|
||||
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
||||
|
||||
FROM node:24.13.1-alpine
|
||||
FROM node:24.14.0-alpine
|
||||
# Create a non-root user with configurable UID/GID
|
||||
ARG USER=trilium
|
||||
ARG UID=1001
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:24.13.1-bullseye-slim AS builder
|
||||
FROM node:24.14.0-bullseye-slim AS builder
|
||||
RUN corepack enable
|
||||
|
||||
# Install native dependencies since we might be building cross-platform.
|
||||
@@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
|
||||
# We have to use --no-frozen-lockfile due to CKEditor patches
|
||||
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
||||
|
||||
FROM node:24.13.1-bullseye-slim
|
||||
FROM node:24.14.0-bullseye-slim
|
||||
# Create a non-root user with configurable UID/GID
|
||||
ARG USER=trilium
|
||||
ARG UID=1001
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
"debounce": "3.0.0",
|
||||
"debug": "4.4.3",
|
||||
"ejs": "4.0.1",
|
||||
"electron": "40.6.0",
|
||||
"electron": "40.6.1",
|
||||
"electron-debug": "4.1.0",
|
||||
"electron-window-state": "5.0.3",
|
||||
"escape-html": "1.0.3",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"keywords": [],
|
||||
"packageManager": "pnpm@10.30.2",
|
||||
"devDependencies": {
|
||||
"@wxt-dev/auto-icons": "1.1.0",
|
||||
"@wxt-dev/auto-icons": "1.1.1",
|
||||
"wxt": "0.20.18"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"ckeditor5-premium-features": "47.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@smithy/middleware-retry": "4.4.36",
|
||||
"@smithy/middleware-retry": "4.4.37",
|
||||
"@types/jquery": "4.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
795
pnpm-lock.yaml
generated
795
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user