mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-31 18:18:02 +01:00
about modal (#244)
This commit is contained in:
parent
534fcc5d0a
commit
964c422a02
@ -690,7 +690,10 @@ function getAppMenu() {
|
|||||||
];
|
];
|
||||||
const appMenu: Electron.MenuItemConstructorOptions[] = [
|
const appMenu: Electron.MenuItemConstructorOptions[] = [
|
||||||
{
|
{
|
||||||
role: "about",
|
label: "About Wave Terminal",
|
||||||
|
click: (_, window) => {
|
||||||
|
window?.webContents.send("menu-item-about");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Check for Updates",
|
label: "Check for Updates",
|
||||||
|
@ -24,6 +24,7 @@ contextBridge.exposeInMainWorld("api", {
|
|||||||
onUpdaterStatusChange: (callback) => ipcRenderer.on("app-update-status", (_event, status) => callback(status)),
|
onUpdaterStatusChange: (callback) => ipcRenderer.on("app-update-status", (_event, status) => callback(status)),
|
||||||
getUpdaterStatus: () => ipcRenderer.sendSync("get-app-update-status"),
|
getUpdaterStatus: () => ipcRenderer.sendSync("get-app-update-status"),
|
||||||
installAppUpdate: () => ipcRenderer.send("install-app-update"),
|
installAppUpdate: () => ipcRenderer.send("install-app-update"),
|
||||||
|
onMenuItemAbout: (callback) => ipcRenderer.on("menu-item-about", callback),
|
||||||
updateWindowControlsOverlay: (rect) => ipcRenderer.send("update-window-controls-overlay", rect),
|
updateWindowControlsOverlay: (rect) => ipcRenderer.send("update-window-controls-overlay", rect),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2,20 +2,30 @@
|
|||||||
/* SPDX-License-Identifier: Apache-2.0 */
|
/* SPDX-License-Identifier: Apache-2.0 */
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
|
padding: 1px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&.focus {
|
||||||
|
border: 1px solid var(--button-focus-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-inner {
|
||||||
background: var(--accent-color);
|
background: var(--accent-color);
|
||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
outline: inherit;
|
outline: inherit;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 6px 16px;
|
padding: 8px 20px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
height: auto;
|
height: auto;
|
||||||
line-height: 1.5;
|
line-height: 16px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
font-weight: 500;
|
font-size: 14px;
|
||||||
|
|
||||||
color: var(--main-text-color);
|
color: var(--main-text-color);
|
||||||
|
|
||||||
@ -42,45 +52,6 @@
|
|||||||
color: #000000;
|
color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.primary.outlined,
|
|
||||||
&.primary.greyoutlined {
|
|
||||||
background: none;
|
|
||||||
border: 1px solid var(--accent-color);
|
|
||||||
|
|
||||||
i {
|
|
||||||
fill: var(--accent-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.primary.greyoutlined {
|
|
||||||
border-color: var(--secondary-text-color);
|
|
||||||
|
|
||||||
i {
|
|
||||||
fill: var(--secondary-text-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.primary.outlined.danger {
|
|
||||||
border-color: var(--error-color);
|
|
||||||
|
|
||||||
i {
|
|
||||||
fill: var(--error-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.primary.outlined,
|
|
||||||
&.primary.greyoutlined {
|
|
||||||
&.hover-danger:hover {
|
|
||||||
color: var(--main-text-color);
|
|
||||||
border-color: var(--error-color);
|
|
||||||
background: var(--error-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.greytext {
|
|
||||||
color: var(--secondary-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.primary.ghost {
|
&.primary.ghost {
|
||||||
background: none;
|
background: none;
|
||||||
|
|
||||||
@ -95,19 +66,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.secondary {
|
&.secondary,
|
||||||
|
&.link-button {
|
||||||
background: var(--highlight-bg-color);
|
background: var(--highlight-bg-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.secondary.outlined {
|
|
||||||
background: none;
|
|
||||||
border: 1px solid var(--main-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.secondary.outlined.danger {
|
|
||||||
border-color: var(--error-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.secondary.ghost {
|
&.secondary.ghost {
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
@ -116,36 +79,25 @@
|
|||||||
color: var(--error-color);
|
color: var(--error-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.small {
|
|
||||||
padding: 4px 8px;
|
|
||||||
font-size: 12px;
|
|
||||||
border-radius: 3.6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.term-inline {
|
|
||||||
padding: 2px 8px;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.link {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.border-radius-4 {
|
/*
|
||||||
|
* customs styles here
|
||||||
|
*/
|
||||||
|
.border-radius-4 {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vertical-padding-2 {
|
.vertical-padding-2 {
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
padding-bottom: 2px;
|
padding-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.horizontal-padding-10 {
|
.horizontal-padding-10 {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,9 @@ const Button = React.memo(({ className = "primary", children, disabled, ...props
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div className="button">
|
||||||
<button
|
<button
|
||||||
className={clsx("button", className, {
|
className={clsx("button-inner", className, {
|
||||||
disabled,
|
disabled,
|
||||||
hasIcon,
|
hasIcon,
|
||||||
})}
|
})}
|
||||||
@ -24,6 +25,7 @@ const Button = React.memo(({ className = "primary", children, disabled, ...props
|
|||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
12
frontend/app/element/linkbutton.less
Normal file
12
frontend/app/element/linkbutton.less
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// Copyright 2024, Command Line Inc.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
.button {
|
||||||
|
&.link-button {
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
.button-inner {
|
||||||
|
padding: 8px 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
frontend/app/element/linkbutton.tsx
Normal file
37
frontend/app/element/linkbutton.tsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2024, Command Line Inc.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import { clsx } from "clsx";
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
import "./linkbutton.less";
|
||||||
|
|
||||||
|
interface LinkButtonProps {
|
||||||
|
href: string;
|
||||||
|
rel?: string;
|
||||||
|
target?: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
disabled?: boolean;
|
||||||
|
leftIcon?: React.ReactNode;
|
||||||
|
rightIcon?: React.ReactNode;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
autoFocus?: boolean;
|
||||||
|
className?: string;
|
||||||
|
termInline?: boolean;
|
||||||
|
title?: string;
|
||||||
|
onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LinkButton = ({ leftIcon, rightIcon, children, className, ...rest }: LinkButtonProps) => {
|
||||||
|
return (
|
||||||
|
<a {...rest} className="button link-button">
|
||||||
|
<span className={clsx("button-inner", className)}>
|
||||||
|
{leftIcon && <span className="icon-left">{leftIcon}</span>}
|
||||||
|
{children}
|
||||||
|
{rightIcon && <span className="icon-right">{rightIcon}</span>}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { LinkButton };
|
61
frontend/app/modals/about.less
Normal file
61
frontend/app/modals/about.less
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2024, Command Line Inc.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
.about-modal {
|
||||||
|
width: 445px;
|
||||||
|
padding-bottom: 34px;
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
margin-bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 24px;
|
||||||
|
|
||||||
|
.section-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 26px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
align-self: stretch;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&.logo-section {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.app-name {
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-standard {
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section:nth-child(3) {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 7px;
|
||||||
|
|
||||||
|
.wave-button-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
frontend/app/modals/about.tsx
Normal file
61
frontend/app/modals/about.tsx
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import Logo from "@/app/asset/logo.svg";
|
||||||
|
import { LinkButton } from "@/app/element/linkbutton";
|
||||||
|
import { modalsModel } from "@/app/store/modalmodel";
|
||||||
|
import { Modal } from "./modal";
|
||||||
|
|
||||||
|
import "./about.less";
|
||||||
|
|
||||||
|
interface AboutModalProps {}
|
||||||
|
|
||||||
|
const AboutModal = ({}: AboutModalProps) => {
|
||||||
|
const currentDate = new Date();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal className="about-modal" title="About" onClose={() => modalsModel.popModal()}>
|
||||||
|
<div className="section-wrapper">
|
||||||
|
<div className="section logo-section">
|
||||||
|
<Logo />
|
||||||
|
<div className="app-name">Wave Terminal</div>
|
||||||
|
<div className="text-standard">
|
||||||
|
Open-Source AI-Native Terminal
|
||||||
|
<br />
|
||||||
|
Built for Seamless Workflows
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="section text-standard">Client Version 0.1.8 (20240615-002636)</div>
|
||||||
|
<div className="section">
|
||||||
|
<LinkButton
|
||||||
|
className="secondary solid"
|
||||||
|
href="https://github.com/wavetermdev/waveterm"
|
||||||
|
target="_blank"
|
||||||
|
leftIcon={<i className="fa-brands fa-github"></i>}
|
||||||
|
>
|
||||||
|
Github
|
||||||
|
</LinkButton>
|
||||||
|
<LinkButton
|
||||||
|
className="secondary solid"
|
||||||
|
href="https://www.waveterm.dev/"
|
||||||
|
target="_blank"
|
||||||
|
leftIcon={<i className="fa-sharp fa-light fa-globe"></i>}
|
||||||
|
>
|
||||||
|
Website
|
||||||
|
</LinkButton>
|
||||||
|
<LinkButton
|
||||||
|
className="secondary solid"
|
||||||
|
href="https://github.com/wavetermdev/waveterm/blob/main/acknowledgements/README.md"
|
||||||
|
target="_blank"
|
||||||
|
rel={"noopener"}
|
||||||
|
leftIcon={<i className="fa-sharp fa-light fa-heart"></i>}
|
||||||
|
>
|
||||||
|
Acknowledgements
|
||||||
|
</LinkButton>
|
||||||
|
</div>
|
||||||
|
<div className="section text-standard">© {currentDate.getFullYear()} Command Line Inc.</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
AboutModal.displayName = "AboutModal";
|
||||||
|
|
||||||
|
export { AboutModal };
|
@ -24,24 +24,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal {
|
.modal {
|
||||||
|
position: relative;
|
||||||
z-index: var(--zindex-modal);
|
z-index: var(--zindex-modal);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 16px;
|
gap: 32px;
|
||||||
border-radius: 10px;
|
padding: 24px 16px 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 0.5px solid var(--modal-border-color);
|
||||||
background: var(--modal-bg-color);
|
background: var(--modal-bg-color);
|
||||||
border: 1px solid var(--border-color);
|
box-shadow: 0px 8px 32px 0px rgba(0, 0, 0, 0.25);
|
||||||
box-shadow: 0px 5px 5px 5px rgba(0, 0, 0, 0.1);
|
|
||||||
|
.header-content-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
.modal-header {
|
.modal-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px 14px 12px 20px;
|
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
line-height: 20px;
|
|
||||||
border-bottom: 1px solid var(--modal-header-bottom-border-color);
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
.modal-title {
|
.modal-title {
|
||||||
@ -50,25 +55,30 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
padding-right: 4px !important;
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
|
top: 8px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
|
||||||
i {
|
i {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.modal-content {
|
||||||
.modal-body {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0px 20px;
|
padding: 0px 20px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.modal-footer {
|
.modal-footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0 20px 20px;
|
padding-top: 16px;
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
|
||||||
button:last-child {
|
.button:last-child {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,19 +2,18 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { Button } from "@/app/element/button";
|
import { Button } from "@/app/element/button";
|
||||||
|
import clsx from "clsx";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
|
|
||||||
import "./modal.less";
|
import "./modal.less";
|
||||||
|
|
||||||
interface ModalHeaderProps {
|
interface ModalHeaderProps {
|
||||||
title: React.ReactNode;
|
|
||||||
description?: string;
|
description?: string;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModalHeader = ({ onClose, title, description }: ModalHeaderProps) => (
|
const ModalHeader = ({ onClose, description }: ModalHeaderProps) => (
|
||||||
<header className="modal-header">
|
<header className="modal-header">
|
||||||
{typeof title === "string" ? <h3 className="modal-title">{title}</h3> : title}
|
|
||||||
{description && <p>{description}</p>}
|
{description && <p>{description}</p>}
|
||||||
{onClose && (
|
{onClose && (
|
||||||
<Button className="secondary ghost" onClick={onClose} title="Close (ESC)">
|
<Button className="secondary ghost" onClick={onClose} title="Close (ESC)">
|
||||||
@ -39,10 +38,11 @@ interface ModalFooterProps {
|
|||||||
onCancel?: () => void;
|
onCancel?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModalFooter = ({ onCancel, onOk, cancelLabel = "Cancel", okLabel = "Ok" }: ModalFooterProps) => (
|
const ModalFooter = ({ onCancel, onOk, cancelLabel = "Cancel", okLabel = "Ok" }: ModalFooterProps) => {
|
||||||
|
return (
|
||||||
<footer className="modal-footer">
|
<footer className="modal-footer">
|
||||||
{onCancel && (
|
{onCancel && (
|
||||||
<Button className="secondary" onClick={onCancel}>
|
<Button className="secondary ghost" onClick={onCancel}>
|
||||||
{cancelLabel}
|
{cancelLabel}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
@ -52,7 +52,8 @@ const ModalFooter = ({ onCancel, onOk, cancelLabel = "Cancel", okLabel = "Ok" }:
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
interface ModalProps {
|
interface ModalProps {
|
||||||
title: string;
|
title: string;
|
||||||
@ -81,13 +82,21 @@ const Modal = ({
|
|||||||
}: ModalProps) => {
|
}: ModalProps) => {
|
||||||
const renderBackdrop = (onClick) => <div className="modal-backdrop" onClick={onClick}></div>;
|
const renderBackdrop = (onClick) => <div className="modal-backdrop" onClick={onClick}></div>;
|
||||||
|
|
||||||
|
const renderFooter = () => {
|
||||||
|
return onOk || onCancel;
|
||||||
|
};
|
||||||
|
|
||||||
const renderModal = () => (
|
const renderModal = () => (
|
||||||
<div className="modal-wrapper">
|
<div className="modal-wrapper">
|
||||||
{renderBackdrop(onClickBackdrop)}
|
{renderBackdrop(onClickBackdrop)}
|
||||||
<div className={`modal ${className}`}>
|
<div className={clsx(`modal`, className)}>
|
||||||
<ModalHeader title={title} onClose={onClose} description={description} />
|
<div className="header-content-wrapper">
|
||||||
|
<ModalHeader onClose={onClose} description={description} />
|
||||||
<ModalContent>{children}</ModalContent>
|
<ModalContent>{children}</ModalContent>
|
||||||
|
</div>
|
||||||
|
{renderFooter() && (
|
||||||
<ModalFooter onCancel={onCancel} onOk={onOk} cancelLabel={cancelLabel} okLabel={okLabel} />
|
<ModalFooter onCancel={onCancel} onOk={onOk} cancelLabel={cancelLabel} okLabel={okLabel} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
// Copyright 2023, Command Line Inc.
|
// Copyright 2023, Command Line Inc.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import { AboutModal } from "./about";
|
||||||
import { TosModal } from "./tos";
|
import { TosModal } from "./tos";
|
||||||
import { UserInputModal } from "./userinputmodal";
|
import { UserInputModal } from "./userinputmodal";
|
||||||
|
|
||||||
const modalRegistry: { [key: string]: React.ComponentType<any> } = {
|
const modalRegistry: { [key: string]: React.ComponentType<any> } = {
|
||||||
[TosModal.displayName || "TosModal"]: TosModal,
|
[TosModal.displayName || "TosModal"]: TosModal,
|
||||||
[UserInputModal.displayName || "UserInputModal"]: UserInputModal,
|
[UserInputModal.displayName || "UserInputModal"]: UserInputModal,
|
||||||
|
[AboutModal.displayName || "AboutModal"]: AboutModal,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getModalComponent = (key: string): React.ComponentType<any> | undefined => {
|
export const getModalComponent = (key: string): React.ComponentType<any> | undefined => {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
.tos-modal {
|
.tos-modal {
|
||||||
width: 640px;
|
width: 640px;
|
||||||
|
border-radius: 10px;
|
||||||
|
|
||||||
.modal-inner {
|
.modal-inner {
|
||||||
padding: 40px 76px;
|
padding: 40px 76px;
|
||||||
@ -16,6 +17,8 @@
|
|||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-title {
|
.modal-title {
|
||||||
|
@ -62,6 +62,15 @@ function initGlobalAtoms(initOpts: GlobalInitOptions) {
|
|||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const showAboutModalAtom = jotai.atom(false) as jotai.PrimitiveAtom<boolean>;
|
||||||
|
try {
|
||||||
|
getApi().onMenuItemAbout(() => {
|
||||||
|
modalsModel.pushModal("AboutModal");
|
||||||
|
});
|
||||||
|
} catch (_) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
const clientAtom: jotai.Atom<Client> = jotai.atom((get) => {
|
const clientAtom: jotai.Atom<Client> = jotai.atom((get) => {
|
||||||
const clientId = get(clientIdAtom);
|
const clientId = get(clientIdAtom);
|
||||||
if (clientId == null) {
|
if (clientId == null) {
|
||||||
|
@ -64,14 +64,19 @@
|
|||||||
// xterm-decoration-top: 2
|
// xterm-decoration-top: 2
|
||||||
|
|
||||||
/* modal colors */
|
/* modal colors */
|
||||||
--modal-bg-color: rgb(26, 28, 26);
|
--modal-bg-color: #232323;
|
||||||
--modal-header-bottom-border-color: rgba(241, 246, 243, 0.15);
|
--modal-header-bottom-border-color: rgba(241, 246, 243, 0.15);
|
||||||
|
--modal-border-color: rgba(255, 255, 255, 0.12) /* toggle colors */ --toggle-bg-color: var(--border-color);
|
||||||
|
|
||||||
/* toggle colors */
|
|
||||||
--toggle-bg-color: var(--border-color);
|
|
||||||
--toggle-thumb-color: var(--main-text-color);
|
--toggle-thumb-color: var(--main-text-color);
|
||||||
--toggle-checked-bg-color: var(--accent-color);
|
--toggle-checked-bg-color: var(--accent-color);
|
||||||
|
|
||||||
/* link color */
|
/* link color */
|
||||||
--link-color: #58c142;
|
--link-color: #58c142;
|
||||||
|
|
||||||
|
/* button colors */
|
||||||
|
--button-primary-color: #58c142;
|
||||||
|
--button-secondary-color: rgba(255, 255, 255, 0.1);
|
||||||
|
--button-danger-color: #d43434;
|
||||||
|
--button-focus-border-color: rgba(88, 193, 66, 0.8);
|
||||||
}
|
}
|
||||||
|
1
frontend/types/custom.d.ts
vendored
1
frontend/types/custom.d.ts
vendored
@ -68,6 +68,7 @@ declare global {
|
|||||||
onUpdaterStatusChange: (callback: (status: UpdaterStatus) => void) => void;
|
onUpdaterStatusChange: (callback: (status: UpdaterStatus) => void) => void;
|
||||||
getUpdaterStatus: () => UpdaterStatus;
|
getUpdaterStatus: () => UpdaterStatus;
|
||||||
installAppUpdate: () => void;
|
installAppUpdate: () => void;
|
||||||
|
onMenuItemAbout: (callback: () => void) => void;
|
||||||
updateWindowControlsOverlay: (rect: Dimensions) => void;
|
updateWindowControlsOverlay: (rect: Dimensions) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user