mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 05:28:59 +01:00 
			
		
		
		
	feat(react): port about dialog
This commit is contained in:
		
							parent
							
								
									efeb9b90ca
								
							
						
					
					
						commit
						a7f5702221
					
				@ -2005,5 +2005,8 @@
 | 
			
		||||
  },
 | 
			
		||||
  "content_renderer": {
 | 
			
		||||
    "open_externally": "Open externally"
 | 
			
		||||
  },
 | 
			
		||||
  "modal": {
 | 
			
		||||
    "close": "Close"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,117 +0,0 @@
 | 
			
		||||
import { formatDateTime } from "../../utils/formatters.js";
 | 
			
		||||
import { t } from "../../services/i18n.js";
 | 
			
		||||
import BasicWidget from "../basic_widget.js";
 | 
			
		||||
import openService from "../../services/open.js";
 | 
			
		||||
import server from "../../services/server.js";
 | 
			
		||||
import utils from "../../services/utils.js";
 | 
			
		||||
import { openDialog } from "../../services/dialog.js";
 | 
			
		||||
 | 
			
		||||
interface AppInfo {
 | 
			
		||||
    appVersion: string;
 | 
			
		||||
    dbVersion: number;
 | 
			
		||||
    syncVersion: number;
 | 
			
		||||
    buildDate: string;
 | 
			
		||||
    buildRevision: string;
 | 
			
		||||
    dataDirectory: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const TPL = /*html*/`
 | 
			
		||||
<div class="about-dialog modal fade mx-auto" tabindex="-1" role="dialog">
 | 
			
		||||
    <div class="modal-dialog modal-lg" role="document">
 | 
			
		||||
        <div class="modal-content">
 | 
			
		||||
            <div class="modal-header">
 | 
			
		||||
                <h5 class="modal-title">${t("about.title")}</h5>
 | 
			
		||||
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("about.close")}"></button>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="modal-body">
 | 
			
		||||
                <table class="table table-borderless">
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th>${t("about.homepage")}</th>
 | 
			
		||||
                        <td><a class="tn-link" href="https://github.com/TriliumNext/Trilium" class="external">https://github.com/TriliumNext/Trilium</a></td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th>${t("about.app_version")}</th>
 | 
			
		||||
                        <td class="app-version"></td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th>${t("about.db_version")}</th>
 | 
			
		||||
                        <td class="db-version"></td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th>${t("about.sync_version")}</th>
 | 
			
		||||
                        <td class="sync-version"></td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th>${t("about.build_date")}</th>
 | 
			
		||||
                        <td class="build-date"></td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th>${t("about.build_revision")}</th>
 | 
			
		||||
                        <td><a class="tn-link build-revision external" href="" target="_blank"></a></td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th>${t("about.data_directory")}</th>
 | 
			
		||||
                        <td class="data-directory"></td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                </table>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
.about-dialog a {
 | 
			
		||||
    word-break: break-all;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
export default class AboutDialog extends BasicWidget {
 | 
			
		||||
    private $appVersion!: JQuery<HTMLElement>;
 | 
			
		||||
    private $dbVersion!: JQuery<HTMLElement>;
 | 
			
		||||
    private $syncVersion!: JQuery<HTMLElement>;
 | 
			
		||||
    private $buildDate!: JQuery<HTMLElement>;
 | 
			
		||||
    private $buildRevision!: JQuery<HTMLElement>;
 | 
			
		||||
    private $dataDirectory!: JQuery<HTMLElement>;
 | 
			
		||||
 | 
			
		||||
    doRender(): void {
 | 
			
		||||
        this.$widget = $(TPL);
 | 
			
		||||
        this.$appVersion = this.$widget.find(".app-version");
 | 
			
		||||
        this.$dbVersion = this.$widget.find(".db-version");
 | 
			
		||||
        this.$syncVersion = this.$widget.find(".sync-version");
 | 
			
		||||
        this.$buildDate = this.$widget.find(".build-date");
 | 
			
		||||
        this.$buildRevision = this.$widget.find(".build-revision");
 | 
			
		||||
        this.$dataDirectory = this.$widget.find(".data-directory");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async refresh() {
 | 
			
		||||
        const appInfo = await server.get<AppInfo>("app-info");
 | 
			
		||||
 | 
			
		||||
        this.$appVersion.text(appInfo.appVersion);
 | 
			
		||||
        this.$dbVersion.text(appInfo.dbVersion.toString());
 | 
			
		||||
        this.$syncVersion.text(appInfo.syncVersion.toString());
 | 
			
		||||
        this.$buildDate.text(formatDateTime(appInfo.buildDate));
 | 
			
		||||
        this.$buildRevision.text(appInfo.buildRevision);
 | 
			
		||||
        this.$buildRevision.attr("href", `https://github.com/TriliumNext/Trilium/commit/${appInfo.buildRevision}`);
 | 
			
		||||
        if (utils.isElectron()) {
 | 
			
		||||
            this.$dataDirectory.html(
 | 
			
		||||
                $("<a></a>", {
 | 
			
		||||
                    href: "#",
 | 
			
		||||
                    class: "tn-link",
 | 
			
		||||
                    text: appInfo.dataDirectory
 | 
			
		||||
                }).prop("outerHTML")
 | 
			
		||||
            );
 | 
			
		||||
            this.$dataDirectory.find("a").on("click", (event: JQuery.ClickEvent) => {
 | 
			
		||||
                event.preventDefault();
 | 
			
		||||
                openService.openDirectory(appInfo.dataDirectory);
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
            this.$dataDirectory.text(appInfo.dataDirectory);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async openAboutDialogEvent() {
 | 
			
		||||
        await this.refresh();
 | 
			
		||||
        openDialog(this.$widget);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										98
									
								
								apps/client/src/widgets/dialogs/about.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								apps/client/src/widgets/dialogs/about.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,98 @@
 | 
			
		||||
import { openDialog } from "../../services/dialog.js";
 | 
			
		||||
import ReactBasicWidget from "../react/ReactBasicWidget.js";
 | 
			
		||||
import Modal from "../react/Modal.js";
 | 
			
		||||
import { t } from "../../services/i18n.js";
 | 
			
		||||
import { formatDateTime } from "../../utils/formatters.js";
 | 
			
		||||
import { useState } from "react";
 | 
			
		||||
import server from "../../services/server.js";
 | 
			
		||||
import utils from "../../services/utils.js";
 | 
			
		||||
import openService from "../../services/open.js";
 | 
			
		||||
 | 
			
		||||
interface AppInfo {
 | 
			
		||||
    appVersion: string;
 | 
			
		||||
    dbVersion: number;
 | 
			
		||||
    syncVersion: number;
 | 
			
		||||
    buildDate: string;
 | 
			
		||||
    buildRevision: string;
 | 
			
		||||
    dataDirectory: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function AboutDialogComponent() {
 | 
			
		||||
    let [appInfo, setAppInfo] = useState<AppInfo | null>(null);
 | 
			
		||||
 | 
			
		||||
    async function onShown() {
 | 
			
		||||
        const appInfo = await server.get<AppInfo>("app-info");
 | 
			
		||||
        setAppInfo(appInfo);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const forceWordBreak = { wordBreak: "break-all" };
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <Modal className="about-dialog" size="lg" title={t("about.title")} onShown={onShown}>
 | 
			
		||||
            {(appInfo !== null) ? (
 | 
			
		||||
                <table className="table table-borderless">
 | 
			
		||||
                    <tbody>
 | 
			
		||||
                        <tr>
 | 
			
		||||
                            <th>{t("about.homepage")}</th>
 | 
			
		||||
                            <td><a className="tn-link external" href="https://github.com/TriliumNext/Trilium" style={forceWordBreak}>https://github.com/TriliumNext/Trilium</a></td>
 | 
			
		||||
                        </tr>
 | 
			
		||||
                        <tr>
 | 
			
		||||
                            <th>{t("about.app_version")}</th>
 | 
			
		||||
                            <td className="app-version">{appInfo.appVersion}</td>
 | 
			
		||||
                        </tr>
 | 
			
		||||
                        <tr>
 | 
			
		||||
                            <th>{t("about.db_version")}</th>
 | 
			
		||||
                            <td className="db-version">{appInfo.dbVersion}</td>
 | 
			
		||||
                        </tr>
 | 
			
		||||
                        <tr>
 | 
			
		||||
                            <th>{t("about.sync_version")}</th>
 | 
			
		||||
                            <td className="sync-version">{appInfo.syncVersion}</td>
 | 
			
		||||
                        </tr>
 | 
			
		||||
                        <tr>
 | 
			
		||||
                            <th>{t("about.build_date")}</th>
 | 
			
		||||
                            <td className="build-date">{formatDateTime(appInfo.buildDate)}</td>
 | 
			
		||||
                        </tr>
 | 
			
		||||
                        <tr>
 | 
			
		||||
                            <th>{t("about.build_revision")}</th>
 | 
			
		||||
                            <td>
 | 
			
		||||
                                <a className="tn-link build-revision external" href={`https://github.com/TriliumNext/Trilium/commit/${appInfo.buildRevision}`} target="_blank" style={forceWordBreak}>{appInfo.buildRevision}</a>
 | 
			
		||||
                            </td>
 | 
			
		||||
                        </tr>
 | 
			
		||||
                        <tr>
 | 
			
		||||
                            <th>{t("about.data_directory")}</th>
 | 
			
		||||
                            <td className="data-directory">
 | 
			
		||||
                                <DirectoryLink directory={appInfo.dataDirectory} style={forceWordBreak} />
 | 
			
		||||
                            </td>
 | 
			
		||||
                        </tr>
 | 
			
		||||
                    </tbody>
 | 
			
		||||
                </table>
 | 
			
		||||
            ) : (
 | 
			
		||||
                <div className="loading-spinner"></div>
 | 
			
		||||
            )}
 | 
			
		||||
        </Modal>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function DirectoryLink({ directory, style }: { directory: string, style?: React.CSSProperties }) {
 | 
			
		||||
    if (utils.isElectron()) {
 | 
			
		||||
        const onClick = (e: React.MouseEvent) => {
 | 
			
		||||
            e.preventDefault();
 | 
			
		||||
            openService.openDirectory(directory);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return <a className="tn-link" href="#" onClick={onClick} style={style}></a>
 | 
			
		||||
    } else {
 | 
			
		||||
        return <span style={style}>{directory}</span>;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default class AboutDialog extends ReactBasicWidget {
 | 
			
		||||
 | 
			
		||||
    get component() {
 | 
			
		||||
        return <AboutDialogComponent />;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async openAboutDialogEvent() {
 | 
			
		||||
        openDialog(this.$widget);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,9 +1,39 @@
 | 
			
		||||
export default function Modal({ children }) {
 | 
			
		||||
import { useEffect, useRef } from "preact/hooks";
 | 
			
		||||
import { t } from "../../services/i18n";
 | 
			
		||||
import { ComponentChildren } from "preact";
 | 
			
		||||
 | 
			
		||||
interface ModalProps {
 | 
			
		||||
    className: string;
 | 
			
		||||
    title: string;
 | 
			
		||||
    size: "lg" | "sm";
 | 
			
		||||
    children: ComponentChildren;
 | 
			
		||||
    onShown?: () => void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default function Modal({ children, className, size, title, onShown }: ModalProps) {
 | 
			
		||||
    const modalRef = useRef<HTMLDivElement>(null);
 | 
			
		||||
 | 
			
		||||
    if (onShown) {
 | 
			
		||||
        useEffect(() => {
 | 
			
		||||
            const modalElement = modalRef.current;
 | 
			
		||||
            if (modalElement) {
 | 
			
		||||
                modalElement.addEventListener("shown.bs.modal", onShown);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div className="modal fade mx-auto" tabIndex={-1} role="dialog">
 | 
			
		||||
            <div className="modal-dialog" role="document">
 | 
			
		||||
        <div className={`modal fade mx-auto ${className}`} tabIndex={-1} role="dialog" ref={modalRef}>
 | 
			
		||||
            <div className={`modal-dialog modal-${size}`} role="document">
 | 
			
		||||
                <div className="modal-content">
 | 
			
		||||
                    {children}
 | 
			
		||||
                    <div className="modal-header">
 | 
			
		||||
                        <h5 className="modal-title">{title}</h5>
 | 
			
		||||
                        <button type="button" className="btn-close" data-bs-dismiss="modal" aria-label={t("modal.close")}></button>
 | 
			
		||||
                    </div>
 | 
			
		||||
 | 
			
		||||
                    <div className="modal-body">
 | 
			
		||||
                        {children}
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user