mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-02 18:39:05 +01:00
new wave modal (#781)
This commit is contained in:
parent
b0025e4b1f
commit
a221655027
@ -9,6 +9,7 @@ export const LINE_SETTINGS = "lineSettings";
|
|||||||
export const CLIENT_SETTINGS = "clientSettings";
|
export const CLIENT_SETTINGS = "clientSettings";
|
||||||
export const TAB_SWITCHER = "tabSwitcher";
|
export const TAB_SWITCHER = "tabSwitcher";
|
||||||
export const USER_INPUT = "userInput";
|
export const USER_INPUT = "userInput";
|
||||||
|
export const NEW_WAVE = "newWave";
|
||||||
|
|
||||||
export const LineContainer_Main = "main";
|
export const LineContainer_Main = "main";
|
||||||
export const LineContainer_History = "history";
|
export const LineContainer_History = "history";
|
||||||
|
322
src/app/assets/new-wave-screenshot.svg
Normal file
322
src/app/assets/new-wave-screenshot.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 13 MiB |
@ -10,3 +10,4 @@ export { SessionSettingsModal } from "./sessionsettings";
|
|||||||
export { ScreenSettingsModal } from "./screensettings";
|
export { ScreenSettingsModal } from "./screensettings";
|
||||||
export { LineSettingsModal } from "./linesettings";
|
export { LineSettingsModal } from "./linesettings";
|
||||||
export { UserInputModal } from "./userinput";
|
export { UserInputModal } from "./userinput";
|
||||||
|
export { NewWaveModal } from "./newwave";
|
||||||
|
95
src/app/common/modals/newwave.less
Normal file
95
src/app/common/modals/newwave.less
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
.newwave-modal {
|
||||||
|
width: 640px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 0.5px solid rgba(255, 255, 255, 0.12);
|
||||||
|
background: #232323;
|
||||||
|
box-shadow: 0px 8px 32px 0px rgba(0, 0, 0, 0.25);
|
||||||
|
|
||||||
|
.wave-modal-content .wave-modal-body {
|
||||||
|
padding: 0;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.wave-modal-body-inner {
|
||||||
|
gap: 24px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
header.newwave-header {
|
||||||
|
padding: 24px 32px 0;
|
||||||
|
position: relative;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
border-bottom: none;
|
||||||
|
|
||||||
|
.modal-title {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close {
|
||||||
|
position: absolute;
|
||||||
|
right: 32px;
|
||||||
|
top: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content.newwave-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 0;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
width: 100%;
|
||||||
|
line-height: 19px;
|
||||||
|
font-weight: 400;
|
||||||
|
padding-left: 32px;
|
||||||
|
padding-right: 32px;
|
||||||
|
|
||||||
|
&.image-item {
|
||||||
|
padding: 0 0;
|
||||||
|
height: 360px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: -45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
padding: 0 32px 24px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.button-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
button {
|
||||||
|
font-size: 15px;
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button.disabled-button {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
78
src/app/common/modals/newwave.tsx
Normal file
78
src/app/common/modals/newwave.tsx
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2023, Command Line Inc.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import * as mobxReact from "mobx-react";
|
||||||
|
import { boundMethod } from "autobind-decorator";
|
||||||
|
import { Modal, Button } from "@/elements";
|
||||||
|
import { getApi } from "@/models";
|
||||||
|
|
||||||
|
import newwave from "@/assets/new-wave-screenshot.svg";
|
||||||
|
|
||||||
|
import "./newwave.less";
|
||||||
|
|
||||||
|
@mobxReact.observer
|
||||||
|
class NewWaveModal extends React.Component<{ onClose: () => void }, {}> {
|
||||||
|
@boundMethod
|
||||||
|
handleDownloadOldWave(): void {
|
||||||
|
getApi().openExternalLink("https://www.waveterm.dev/download-legacy");
|
||||||
|
}
|
||||||
|
|
||||||
|
@boundMethod
|
||||||
|
handleDownloadNewWave(): void {
|
||||||
|
getApi().openExternalLink("https://www.waveterm.dev/download");
|
||||||
|
}
|
||||||
|
|
||||||
|
@boundMethod
|
||||||
|
handleClose(): void {
|
||||||
|
this.props.onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Modal className="newwave-modal">
|
||||||
|
<div className="wave-modal-body">
|
||||||
|
<div className="wave-modal-body-inner">
|
||||||
|
<header className="newwave-header unselectable">
|
||||||
|
<div className="modal-title">A New Wave is Coming!</div>
|
||||||
|
<i className="fa-regular fa-xmark-large close" onClick={this.handleClose}></i>
|
||||||
|
</header>
|
||||||
|
<div className="content newwave-content unselectable">
|
||||||
|
<div className="item">
|
||||||
|
We are excited to share that after 3-months of work, and almost 1000 new commits, Wave
|
||||||
|
v0.8 is now available. It features a new layout engine for screen splitting, improved
|
||||||
|
remote file browsing and previewing, improved performance, and a new design. We've also
|
||||||
|
removed some of the more controversial features that took over the shell experience and
|
||||||
|
overrode things like completions, history, and prompts.
|
||||||
|
</div>
|
||||||
|
<div className="item">
|
||||||
|
The new build is a fresh start, and a clean break from the current version. As such,
|
||||||
|
your history, settings, and configuration will <i>not</i> be carried over. If you'd like
|
||||||
|
to continue to run the legacy version, you will need to download it separately.
|
||||||
|
</div>
|
||||||
|
<div className="item image-item">
|
||||||
|
<img src={newwave} height="400px" />
|
||||||
|
</div>
|
||||||
|
<div className="item">
|
||||||
|
You can download Wave v0.8 now or wait for an auto-update next week. The legacy version
|
||||||
|
will be available via separate download page.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer className="unselectable">
|
||||||
|
<div className="button-wrapper">
|
||||||
|
<Button className="secondary" onClick={this.handleDownloadOldWave}>
|
||||||
|
Legacy Download
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="button-wrapper">
|
||||||
|
<Button onClick={this.handleDownloadNewWave}>Upgrade to Wave v0.8</Button>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { NewWaveModal };
|
@ -5,14 +5,34 @@ import * as React from "react";
|
|||||||
import * as mobxReact from "mobx-react";
|
import * as mobxReact from "mobx-react";
|
||||||
import { GlobalModel } from "@/models";
|
import { GlobalModel } from "@/models";
|
||||||
import { TosModal } from "./tos";
|
import { TosModal } from "./tos";
|
||||||
|
import { NewWaveModal } from "./newwave";
|
||||||
|
|
||||||
|
const SessionStorageKey = "newWaveRendered";
|
||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class ModalsProvider extends React.Component {
|
class ModalsProvider extends React.Component<{}, {}> {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.handleNewWaveOnClose = this.handleNewWaveOnClose.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleNewWaveOnClose() {
|
||||||
|
sessionStorage.setItem(SessionStorageKey, "1");
|
||||||
|
this.forceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let store = GlobalModel.modalsModel.store.slice();
|
let store = GlobalModel.modalsModel.store.slice();
|
||||||
|
|
||||||
if (GlobalModel.needsTos()) {
|
if (GlobalModel.needsTos()) {
|
||||||
return <TosModal />;
|
return <TosModal />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const newWaveRendered = sessionStorage.getItem(SessionStorageKey);
|
||||||
|
if (!newWaveRendered) {
|
||||||
|
return <NewWaveModal onClose={this.handleNewWaveOnClose} />;
|
||||||
|
}
|
||||||
|
|
||||||
let rtn: JSX.Element[] = [];
|
let rtn: JSX.Element[] = [];
|
||||||
for (let i = 0; i < store.length; i++) {
|
for (let i = 0; i < store.length; i++) {
|
||||||
let entry = store[i];
|
let entry = store[i];
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
ScreenSettingsModal,
|
ScreenSettingsModal,
|
||||||
LineSettingsModal,
|
LineSettingsModal,
|
||||||
UserInputModal,
|
UserInputModal,
|
||||||
|
NewWaveModal,
|
||||||
} from "@/modals";
|
} from "@/modals";
|
||||||
import * as constants from "@/app/appconst";
|
import * as constants from "@/app/appconst";
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ const modalsRegistry: { [key: string]: React.ComponentType } = {
|
|||||||
[constants.LINE_SETTINGS]: LineSettingsModal,
|
[constants.LINE_SETTINGS]: LineSettingsModal,
|
||||||
[constants.TAB_SWITCHER]: TabSwitcherModal,
|
[constants.TAB_SWITCHER]: TabSwitcherModal,
|
||||||
[constants.USER_INPUT]: UserInputModal,
|
[constants.USER_INPUT]: UserInputModal,
|
||||||
|
[constants.NEW_WAVE]: NewWaveModal,
|
||||||
};
|
};
|
||||||
|
|
||||||
export { modalsRegistry };
|
export { modalsRegistry };
|
||||||
|
@ -167,7 +167,14 @@ func SendTelemetry(ctx context.Context, force bool) error {
|
|||||||
log.Printf("[pcloud] sending telemetry data\n")
|
log.Printf("[pcloud] sending telemetry data\n")
|
||||||
dayStr := telemetry.GetCurDayStr()
|
dayStr := telemetry.GetCurDayStr()
|
||||||
defaultShellType := shellapi.DetectLocalShellType()
|
defaultShellType := shellapi.DetectLocalShellType()
|
||||||
input := TelemetryInputType{UserId: clientData.UserId, ClientId: clientData.ClientId, CurDay: dayStr, DefaultShell: defaultShellType, Activity: activity}
|
input := TelemetryInputType{
|
||||||
|
UserId: clientData.UserId,
|
||||||
|
ClientId: clientData.ClientId,
|
||||||
|
AppType: "wave",
|
||||||
|
CurDay: dayStr,
|
||||||
|
DefaultShell: defaultShellType,
|
||||||
|
Activity: activity,
|
||||||
|
}
|
||||||
req, err := makeAnonPostReq(ctx, TelemetryUrl, input)
|
req, err := makeAnonPostReq(ctx, TelemetryUrl, input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -22,6 +22,7 @@ type NoTelemetryInputType struct {
|
|||||||
type TelemetryInputType struct {
|
type TelemetryInputType struct {
|
||||||
UserId string `json:"userid"`
|
UserId string `json:"userid"`
|
||||||
ClientId string `json:"clientid"`
|
ClientId string `json:"clientid"`
|
||||||
|
AppType string `json:"apptype"`
|
||||||
CurDay string `json:"curday"`
|
CurDay string `json:"curday"`
|
||||||
DefaultShell string `json:"defaultshell"`
|
DefaultShell string `json:"defaultshell"`
|
||||||
Activity []*telemetry.ActivityType `json:"activity"`
|
Activity []*telemetry.ActivityType `json:"activity"`
|
||||||
|
Loading…
Reference in New Issue
Block a user