feat(react/dialogs): port incorrect_cpu_arch

This commit is contained in:
Elian Doran 2025-08-05 15:39:49 +03:00
parent 8f0a9f91c1
commit 79c5d479fc
No known key found for this signature in database
4 changed files with 65 additions and 63 deletions

View File

@ -1,59 +0,0 @@
import BasicWidget from "../basic_widget.js";
import { Modal } from "bootstrap";
import utils from "../../services/utils.js";
import { t } from "../../services/i18n.js";
const TPL = /*html*/`
<div class="cpu-arch-dialog modal mx-auto" tabindex="-1" role="dialog" style="z-index: 2000;">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">${t("cpu_arch_warning.title")}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>${utils.isMac() ? t("cpu_arch_warning.message_macos") : t("cpu_arch_warning.message_windows")}</p>
<p>${t("cpu_arch_warning.recommendation")}</p>
</div>
<div class="modal-footer d-flex justify-content-between align-items-center">
<button class="download-correct-version-button btn btn-primary btn-lg me-2">
<span class="bx bx-download"></span>
${t("cpu_arch_warning.download_link")}
</button>
<button class="btn btn-secondary" data-bs-dismiss="modal">${t("cpu_arch_warning.continue_anyway")}</button>
</div>
</div>
</div>
</div>`;
export default class IncorrectCpuArchDialog extends BasicWidget {
private modal!: Modal;
private $downloadButton!: JQuery<HTMLElement>;
doRender() {
this.$widget = $(TPL);
this.modal = Modal.getOrCreateInstance(this.$widget[0]);
this.$downloadButton = this.$widget.find(".download-correct-version-button");
this.$downloadButton.on("click", () => {
// Open the releases page where users can download the correct version
if (utils.isElectron()) {
const { shell } = utils.dynamicRequire("electron");
shell.openExternal("https://github.com/TriliumNext/Trilium/releases/latest");
} else {
window.open("https://github.com/TriliumNext/Trilium/releases/latest", "_blank");
}
});
// Auto-focus the download button when shown
this.$widget.on("shown.bs.modal", () => {
this.$downloadButton.trigger("focus");
});
}
showCpuArchWarningEvent() {
this.modal.show();
}
}

View File

@ -0,0 +1,53 @@
import { useRef } from "react";
import { openDialog } from "../../services/dialog.js";
import { t } from "../../services/i18n.js";
import utils from "../../services/utils.js";
import Button from "../react/Button.js";
import Modal from "../react/Modal.js";
import ReactBasicWidget from "../react/ReactBasicWidget.js";
function IncorrectCpuArchDialogComponent() {
const downloadButtonRef = useRef<HTMLButtonElement>(null);
return (
<Modal
className="cpu-arch-dialog"
size="lg"
title={t("cpu_arch_warning.title")}
onShown={() => downloadButtonRef.current?.focus()}
footerAlignment="between"
footer={<>
<Button
buttonRef={downloadButtonRef}
text={t("cpu_arch_warning.download_link")}
icon="bx bx-download"
onClick={() => {
// Open the releases page where users can download the correct version
if (utils.isElectron()) {
const { shell } = utils.dynamicRequire("electron");
shell.openExternal("https://github.com/TriliumNext/Trilium/releases/latest");
} else {
window.open("https://github.com/TriliumNext/Trilium/releases/latest", "_blank");
}
}}/>
<Button text={t("cpu_arch_warning.continue_anyway")}
onClick={() => openDialog(null)} />
</>}
>
<p>{utils.isMac() ? t("cpu_arch_warning.message_macos") : t("cpu_arch_warning.message_windows")}</p>
<p>{t("cpu_arch_warning.recommendation")}</p>
</Modal>
)
}
export default class IncorrectCpuArchDialog extends ReactBasicWidget {
get component() {
return <IncorrectCpuArchDialogComponent />
}
showCpuArchWarningEvent() {
openDialog(this.$widget);
}
}

View File

@ -6,12 +6,13 @@ interface ButtonProps {
buttonRef?: RefObject<HTMLButtonElement>; buttonRef?: RefObject<HTMLButtonElement>;
text: string; text: string;
className?: string; className?: string;
icon?: string;
keyboardShortcut?: string; keyboardShortcut?: string;
/** Called when the button is clicked. If not set, the button will submit the form (if any). */ /** Called when the button is clicked. If not set, the button will submit the form (if any). */
onClick?: () => void; onClick?: () => void;
} }
export default function Button({ buttonRef: _buttonRef, className, text, onClick, keyboardShortcut }: ButtonProps) { export default function Button({ buttonRef: _buttonRef, className, text, onClick, keyboardShortcut, icon }: ButtonProps) {
const classes: string[] = ["btn"]; const classes: string[] = ["btn"];
classes.push("btn-primary"); classes.push("btn-primary");
if (className) { if (className) {
@ -28,6 +29,7 @@ export default function Button({ buttonRef: _buttonRef, className, text, onClick
onClick={onClick} onClick={onClick}
ref={buttonRef} ref={buttonRef}
> >
{icon && <span className={`bx ${icon}`}></span>}
{text} {keyboardShortcut && ( {text} {keyboardShortcut && (
splitShortcut.map((key, index) => ( splitShortcut.map((key, index) => (
<> <>

View File

@ -9,6 +9,7 @@ interface ModalProps {
size: "lg" | "md" | "sm"; size: "lg" | "md" | "sm";
children: ComponentChildren; children: ComponentChildren;
footer?: ComponentChildren; footer?: ComponentChildren;
footerAlignment?: "right" | "between";
maxWidth?: number; maxWidth?: number;
zIndex?: number; zIndex?: number;
/** /**
@ -30,7 +31,7 @@ interface ModalProps {
helpPageId?: string; helpPageId?: string;
} }
export default function Modal({ children, className, size, title, footer, onShown, onSubmit, helpPageId, maxWidth, zIndex, scrollable, onHidden: onHidden }: ModalProps) { export default function Modal({ children, className, size, title, footer, footerAlignment, onShown, onSubmit, helpPageId, maxWidth, zIndex, scrollable, onHidden: onHidden }: ModalProps) {
const modalRef = useRef<HTMLDivElement>(null); const modalRef = useRef<HTMLDivElement>(null);
if (onShown || onHidden) { if (onShown || onHidden) {
@ -100,7 +101,12 @@ export default function Modal({ children, className, size, title, footer, onShow
); );
} }
function ModalInner({ children, footer }: Pick<ModalProps, "children" | "footer">) { function ModalInner({ children, footer, footerAlignment }: Pick<ModalProps, "children" | "footer" | "footerAlignment">) {
const footerStyle: CSSProperties = {};
if (footerAlignment === "between") {
footerStyle.justifyContent = "space-between";
}
return ( return (
<> <>
<div className="modal-body"> <div className="modal-body">
@ -108,7 +114,7 @@ function ModalInner({ children, footer }: Pick<ModalProps, "children" | "footer"
</div> </div>
{footer && ( {footer && (
<div className="modal-footer"> <div className="modal-footer" style={footerStyle}>
{footer} {footer}
</div> </div>
)} )}