mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-02 18:39:05 +01:00
merge main
This commit is contained in:
commit
6613f480e3
@ -18,7 +18,8 @@ export const ConfirmKey_HideShellPrompt = "hideshellprompt";
|
|||||||
|
|
||||||
export const NoStrPos = -1;
|
export const NoStrPos = -1;
|
||||||
|
|
||||||
export const RemotePtyRows = 8; // also in main.tsx
|
export const RemotePtyRows = 8;
|
||||||
|
export const RemotePtyTotalRows = 25;
|
||||||
export const RemotePtyCols = 80;
|
export const RemotePtyCols = 80;
|
||||||
export const ProdServerEndpoint = "http://127.0.0.1:1619";
|
export const ProdServerEndpoint = "http://127.0.0.1:1619";
|
||||||
export const ProdServerWsEndpoint = "ws://127.0.0.1:1623";
|
export const ProdServerWsEndpoint = "ws://127.0.0.1:1623";
|
||||||
|
@ -370,7 +370,11 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
|
|||||||
ref={this.termRef}
|
ref={this.termRef}
|
||||||
data-remoteid={remote.remoteid}
|
data-remoteid={remote.remoteid}
|
||||||
style={{
|
style={{
|
||||||
height: textmeasure.termHeightFromRows(appconst.RemotePtyRows, termFontSize),
|
height: textmeasure.termHeightFromRows(
|
||||||
|
appconst.RemotePtyRows,
|
||||||
|
termFontSize,
|
||||||
|
appconst.RemotePtyTotalRows
|
||||||
|
),
|
||||||
width: termWidth,
|
width: termWidth,
|
||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
|
@ -388,7 +388,7 @@ class LineCmd extends React.Component<
|
|||||||
let height = 45 + 24; // height of zero height terminal
|
let height = 45 + 24; // height of zero height terminal
|
||||||
const usedRows = screen.getUsedRows(lineutil.getRendererContext(line), line, cmd, width);
|
const usedRows = screen.getUsedRows(lineutil.getRendererContext(line), line, cmd, width);
|
||||||
if (usedRows > 0) {
|
if (usedRows > 0) {
|
||||||
height = 48 + 24 + termHeightFromRows(usedRows, GlobalModel.termFontSize.get());
|
height = 48 + 24 + termHeightFromRows(usedRows, GlobalModel.termFontSize.get(), cmd.getTermMaxRows());
|
||||||
}
|
}
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
@ -75,10 +75,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.meta.meta-line1 {
|
.meta.meta-line1 {
|
||||||
margin-left: 2px;
|
|
||||||
color: rgba(@base-color, 0.6) !important;
|
color: rgba(@base-color, 0.6) !important;
|
||||||
font-size: var(--termfontsize);
|
font-size: var(--termfontsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.meta.meta-line2 {
|
||||||
|
margin-left: -2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.has-rtnstate .terminal-wrapper {
|
||||||
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-wrapper {
|
.image-wrapper {
|
||||||
@ -438,6 +445,7 @@
|
|||||||
padding: 0 0 10px 0;
|
padding: 0 0 10px 0;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
overflow-x: hidden;
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
|
@ -18,8 +18,6 @@ let MagicLayout = {
|
|||||||
ScreenMinContentSize: 100,
|
ScreenMinContentSize: 100,
|
||||||
ScreenMaxContentSize: 5000,
|
ScreenMaxContentSize: 5000,
|
||||||
|
|
||||||
// the 3 is for descenders, which get cut off in the terminal without this
|
|
||||||
TermDescendersHeight: 3,
|
|
||||||
TermWidthBuffer: 15,
|
TermWidthBuffer: 15,
|
||||||
|
|
||||||
TabWidth: 154,
|
TabWidth: 154,
|
||||||
|
@ -119,7 +119,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.middle {
|
.middle {
|
||||||
max-height: calc(100vh - 32em);
|
|
||||||
padding: 4px 6px 8px 6px;
|
padding: 4px 6px 8px 6px;
|
||||||
border-bottom: 1px solid @base-border;
|
border-bottom: 1px solid @base-border;
|
||||||
.item {
|
.item {
|
||||||
@ -142,9 +141,10 @@
|
|||||||
|
|
||||||
.bottom {
|
.bottom {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 2em;
|
bottom: 2rem;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
padding-top: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
|
@ -64,7 +64,7 @@ interface MainSideBarProps {
|
|||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class MainSideBar extends React.Component<MainSideBarProps, {}> {
|
class MainSideBar extends React.Component<MainSideBarProps, {}> {
|
||||||
sidebarRef = React.createRef<HTMLDivElement>();
|
middleHeightSubtractor = mobx.observable.box(404);
|
||||||
|
|
||||||
handleSessionClick(sessionId: string) {
|
handleSessionClick(sessionId: string) {
|
||||||
GlobalCommandRunner.switchSession(sessionId);
|
GlobalCommandRunner.switchSession(sessionId);
|
||||||
@ -203,14 +203,37 @@ class MainSideBar extends React.Component<MainSideBarProps, {}> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the subtractor portion for the middle div's height calculation, which should be `100vh - subtractor`.
|
||||||
|
*/
|
||||||
|
setMiddleHeightSubtractor() {
|
||||||
|
const windowHeight = window.innerHeight;
|
||||||
|
const bottomHeight = windowHeight - window.document.getElementById("sidebar-bottom")?.offsetTop;
|
||||||
|
const middleTop = document.getElementById("sidebar-middle")?.offsetTop;
|
||||||
|
const newMiddleHeightSubtractor = bottomHeight + middleTop;
|
||||||
|
if (!Number.isNaN(newMiddleHeightSubtractor)) {
|
||||||
|
mobx.action(() => {
|
||||||
|
this.middleHeightSubtractor.set(newMiddleHeightSubtractor);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setMiddleHeightSubtractor();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
this.setMiddleHeightSubtractor();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let clientData = this.props.clientData;
|
const clientData = this.props.clientData;
|
||||||
let needsUpdate = false;
|
let needsUpdate = false;
|
||||||
if (!clientData?.clientopts.noreleasecheck && !isBlank(clientData?.releaseinfo?.latestversion)) {
|
if (!clientData?.clientopts.noreleasecheck && !isBlank(clientData?.releaseinfo?.latestversion)) {
|
||||||
needsUpdate = compareLoose(appconst.VERSION, clientData.releaseinfo.latestversion) < 0;
|
needsUpdate = compareLoose(appconst.VERSION, clientData.releaseinfo.latestversion) < 0;
|
||||||
}
|
}
|
||||||
let mainSidebar = GlobalModel.mainSidebarModel;
|
const mainSidebar = GlobalModel.mainSidebarModel;
|
||||||
let isCollapsed = mainSidebar.getCollapsed();
|
const isCollapsed = mainSidebar.getCollapsed();
|
||||||
return (
|
return (
|
||||||
<ResizableSidebar
|
<ResizableSidebar
|
||||||
className="main-sidebar"
|
className="main-sidebar"
|
||||||
@ -271,8 +294,16 @@ class MainSideBar extends React.Component<MainSideBarProps, {}> {
|
|||||||
</CenteredIcon>,
|
</CenteredIcon>,
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<div className="middle hideScrollbarUntillHover">{this.getSessions()}</div>
|
<div
|
||||||
<div className="bottom">
|
className="middle hideScrollbarUntillHover"
|
||||||
|
id="sidebar-middle"
|
||||||
|
style={{
|
||||||
|
maxHeight: `calc(100vh - ${this.middleHeightSubtractor.get()}px)`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{this.getSessions()}
|
||||||
|
</div>
|
||||||
|
<div className="bottom" id="sidebar-bottom">
|
||||||
<If condition={needsUpdate}>
|
<If condition={needsUpdate}>
|
||||||
<SideBarItem
|
<SideBarItem
|
||||||
key="update-available"
|
key="update-available"
|
||||||
|
@ -109,6 +109,7 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
|
|||||||
return <div className="screen-view" ref={this.screenViewRef}></div>;
|
return <div className="screen-view" ref={this.screenViewRef}></div>;
|
||||||
}
|
}
|
||||||
let fontSize = GlobalModel.termFontSize.get();
|
let fontSize = GlobalModel.termFontSize.get();
|
||||||
|
let dprStr = sprintf("%0.3f", GlobalModel.devicePixelRatio.get());
|
||||||
let viewOpts = screen.viewOpts.get();
|
let viewOpts = screen.viewOpts.get();
|
||||||
let hasSidebar = viewOpts?.sidebar?.open;
|
let hasSidebar = viewOpts?.sidebar?.open;
|
||||||
let winWidth = "100%";
|
let winWidth = "100%";
|
||||||
@ -145,7 +146,7 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
|
|||||||
return (
|
return (
|
||||||
<div className="screen-view" data-screenid={screen.screenId} ref={this.screenViewRef}>
|
<div className="screen-view" data-screenid={screen.screenId} ref={this.screenViewRef}>
|
||||||
<ScreenWindowView
|
<ScreenWindowView
|
||||||
key={screen.screenId + ":" + fontSize}
|
key={screen.screenId + ":" + fontSize + ":" + dprStr}
|
||||||
session={session}
|
session={session}
|
||||||
screen={screen}
|
screen={screen}
|
||||||
width={winWidth}
|
width={winWidth}
|
||||||
|
@ -177,6 +177,7 @@ function readAuthKey() {
|
|||||||
return authKeyStr.trim();
|
return authKeyStr.trim();
|
||||||
}
|
}
|
||||||
const reloadAcceleratorKey = unamePlatform == "darwin" ? "Option+R" : "Super+R";
|
const reloadAcceleratorKey = unamePlatform == "darwin" ? "Option+R" : "Super+R";
|
||||||
|
let cmdOrAlt = process.platform === "darwin" ? "Cmd" : "Alt";
|
||||||
let menuTemplate: Electron.MenuItemConstructorOptions[] = [
|
let menuTemplate: Electron.MenuItemConstructorOptions[] = [
|
||||||
{
|
{
|
||||||
role: "appMenu",
|
role: "appMenu",
|
||||||
@ -205,9 +206,41 @@ let menuTemplate: Electron.MenuItemConstructorOptions[] = [
|
|||||||
{ role: "reload", accelerator: reloadAcceleratorKey },
|
{ role: "reload", accelerator: reloadAcceleratorKey },
|
||||||
{ role: "toggleDevTools" },
|
{ role: "toggleDevTools" },
|
||||||
{ type: "separator" },
|
{ type: "separator" },
|
||||||
{ role: "resetZoom" },
|
{
|
||||||
{ role: "zoomIn" },
|
label: "Actual Size",
|
||||||
{ role: "zoomOut" },
|
accelerator: cmdOrAlt + "+0",
|
||||||
|
click: () => {
|
||||||
|
if (MainWindow == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MainWindow.webContents.setZoomFactor(1);
|
||||||
|
MainWindow.webContents.send("zoom-changed");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Zoom In",
|
||||||
|
accelerator: cmdOrAlt + "+Plus",
|
||||||
|
click: () => {
|
||||||
|
if (MainWindow == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const zoomFactor = MainWindow.webContents.getZoomFactor();
|
||||||
|
MainWindow.webContents.setZoomFactor(zoomFactor * 1.1);
|
||||||
|
MainWindow.webContents.send("zoom-changed");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Zoom Out",
|
||||||
|
accelerator: cmdOrAlt + "+-",
|
||||||
|
click: () => {
|
||||||
|
if (MainWindow == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const zoomFactor = MainWindow.webContents.getZoomFactor();
|
||||||
|
MainWindow.webContents.setZoomFactor(zoomFactor / 1.1);
|
||||||
|
MainWindow.webContents.send("zoom-changed");
|
||||||
|
},
|
||||||
|
},
|
||||||
{ type: "separator" },
|
{ type: "separator" },
|
||||||
{ role: "togglefullscreen" },
|
{ role: "togglefullscreen" },
|
||||||
],
|
],
|
||||||
@ -375,6 +408,9 @@ function createMainWindow(clientData: ClientDataType | null) {
|
|||||||
win.on("close", () => {
|
win.on("close", () => {
|
||||||
MainWindow = null;
|
MainWindow = null;
|
||||||
});
|
});
|
||||||
|
win.webContents.on("zoom-changed", (e) => {
|
||||||
|
win.webContents.send("zoom-changed");
|
||||||
|
});
|
||||||
win.webContents.setWindowOpenHandler(({ url, frameName }) => {
|
win.webContents.setWindowOpenHandler(({ url, frameName }) => {
|
||||||
if (url.startsWith("https://docs.waveterm.dev/")) {
|
if (url.startsWith("https://docs.waveterm.dev/")) {
|
||||||
console.log("openExternal docs", url);
|
console.log("openExternal docs", url);
|
||||||
|
@ -21,6 +21,7 @@ contextBridge.exposeInMainWorld("api", {
|
|||||||
onWCmd: (callback) => ipcRenderer.on("w-cmd", callback),
|
onWCmd: (callback) => ipcRenderer.on("w-cmd", callback),
|
||||||
onPCmd: (callback) => ipcRenderer.on("p-cmd", callback),
|
onPCmd: (callback) => ipcRenderer.on("p-cmd", callback),
|
||||||
onRCmd: (callback) => ipcRenderer.on("r-cmd", callback),
|
onRCmd: (callback) => ipcRenderer.on("r-cmd", callback),
|
||||||
|
onZoomChanged: (callback) => ipcRenderer.on("zoom-changed", callback),
|
||||||
onMetaArrowUp: (callback) => ipcRenderer.on("meta-arrowup", callback),
|
onMetaArrowUp: (callback) => ipcRenderer.on("meta-arrowup", callback),
|
||||||
onMetaArrowDown: (callback) => ipcRenderer.on("meta-arrowdown", callback),
|
onMetaArrowDown: (callback) => ipcRenderer.on("meta-arrowdown", callback),
|
||||||
onMetaPageUp: (callback) => ipcRenderer.on("meta-pageup", callback),
|
onMetaPageUp: (callback) => ipcRenderer.on("meta-pageup", callback),
|
||||||
|
@ -21,14 +21,9 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
let reactElem = React.createElement(App, null, null);
|
let reactElem = React.createElement(App, null, null);
|
||||||
let elem = document.getElementById("app");
|
let elem = document.getElementById("app");
|
||||||
let root = createRoot(elem);
|
let root = createRoot(elem);
|
||||||
let isFontLoaded = document.fonts.check("12px 'JetBrains Mono'");
|
document.fonts.ready.then(() => {
|
||||||
if (isFontLoaded) {
|
|
||||||
root.render(reactElem);
|
root.render(reactElem);
|
||||||
} else {
|
});
|
||||||
document.fonts.ready.then(() => {
|
|
||||||
root.render(reactElem);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
(window as any).mobx = mobx;
|
(window as any).mobx = mobx;
|
||||||
|
@ -88,6 +88,11 @@ class Cmd {
|
|||||||
return this.data.get().termopts;
|
return this.data.get().termopts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTermMaxRows(): number {
|
||||||
|
let termOpts = this.getTermOpts();
|
||||||
|
return termOpts?.rows;
|
||||||
|
}
|
||||||
|
|
||||||
getCmdStr(): string {
|
getCmdStr(): string {
|
||||||
return this.data.get().cmdstr;
|
return this.data.get().cmdstr;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ class HistoryViewModel {
|
|||||||
} else {
|
} else {
|
||||||
this.activeItem.set(hitem.historyid);
|
this.activeItem.set(hitem.historyid);
|
||||||
let width = termWidthFromCols(80, this.globalModel.termFontSize.get());
|
let width = termWidthFromCols(80, this.globalModel.termFontSize.get());
|
||||||
let height = termHeightFromRows(25, this.globalModel.termFontSize.get());
|
let height = termHeightFromRows(25, this.globalModel.termFontSize.get(), 25);
|
||||||
this.specialLineContainer = new SpecialLineContainer(
|
this.specialLineContainer = new SpecialLineContainer(
|
||||||
this,
|
this,
|
||||||
{ width, height },
|
{ width, height },
|
||||||
@ -149,7 +149,7 @@ class HistoryViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_deleteSelected(): void {
|
_deleteSelected(): void {
|
||||||
let lineIds = Array.from(this.selectedItems.keys());
|
let lineIds: string[] = Array.from(this.selectedItems.keys());
|
||||||
let prtn = GlobalCommandRunner.historyPurgeLines(lineIds);
|
let prtn = GlobalCommandRunner.historyPurgeLines(lineIds);
|
||||||
prtn.then((result: CommandRtnType) => {
|
prtn.then((result: CommandRtnType) => {
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
|
@ -32,13 +32,8 @@ import { MainSidebarModel } from "./mainsidebar";
|
|||||||
import { Screen } from "./screen";
|
import { Screen } from "./screen";
|
||||||
import { Cmd } from "./cmd";
|
import { Cmd } from "./cmd";
|
||||||
import { GlobalCommandRunner } from "./global";
|
import { GlobalCommandRunner } from "./global";
|
||||||
|
import { clearMonoFontCache } from "@/util/textmeasure";
|
||||||
type KeyModsType = {
|
import type { TermWrap } from "@/plugins/terminal/term";
|
||||||
meta?: boolean;
|
|
||||||
ctrl?: boolean;
|
|
||||||
alt?: boolean;
|
|
||||||
shift?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
type SWLinePtr = {
|
type SWLinePtr = {
|
||||||
line: LineType;
|
line: LineType;
|
||||||
@ -46,36 +41,6 @@ type SWLinePtr = {
|
|||||||
screen: Screen;
|
screen: Screen;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ElectronApi = {
|
|
||||||
getId: () => string;
|
|
||||||
getIsDev: () => boolean;
|
|
||||||
getPlatform: () => string;
|
|
||||||
getAuthKey: () => string;
|
|
||||||
getWaveSrvStatus: () => boolean;
|
|
||||||
restartWaveSrv: () => boolean;
|
|
||||||
reloadWindow: () => void;
|
|
||||||
openExternalLink: (url: string) => void;
|
|
||||||
reregisterGlobalShortcut: (shortcut: string) => void;
|
|
||||||
onTCmd: (callback: (mods: KeyModsType) => void) => void;
|
|
||||||
onICmd: (callback: (mods: KeyModsType) => void) => void;
|
|
||||||
onLCmd: (callback: (mods: KeyModsType) => void) => void;
|
|
||||||
onHCmd: (callback: (mods: KeyModsType) => void) => void;
|
|
||||||
onPCmd: (callback: (mods: KeyModsType) => void) => void;
|
|
||||||
onRCmd: (callback: (mods: KeyModsType) => void) => void;
|
|
||||||
onWCmd: (callback: (mods: KeyModsType) => void) => void;
|
|
||||||
onMenuItemAbout: (callback: () => void) => void;
|
|
||||||
onMetaArrowUp: (callback: () => void) => void;
|
|
||||||
onMetaArrowDown: (callback: () => void) => void;
|
|
||||||
onMetaPageUp: (callback: () => void) => void;
|
|
||||||
onMetaPageDown: (callback: () => void) => void;
|
|
||||||
onBracketCmd: (callback: (event: any, arg: { relative: number }, mods: KeyModsType) => void) => void;
|
|
||||||
onDigitCmd: (callback: (event: any, arg: { digit: number }, mods: KeyModsType) => void) => void;
|
|
||||||
contextScreen: (screenOpts: { screenId: string }, position: { x: number; y: number }) => void;
|
|
||||||
contextEditMenu: (position: { x: number; y: number }, opts: ContextMenuOpts) => void;
|
|
||||||
onWaveSrvStatusChange: (callback: (status: boolean, pid: number) => void) => void;
|
|
||||||
getLastLogs: (numOfLines: number, callback: (logs: any) => void) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
function getApi(): ElectronApi {
|
function getApi(): ElectronApi {
|
||||||
return (window as any).api;
|
return (window as any).api;
|
||||||
}
|
}
|
||||||
@ -133,7 +98,10 @@ class Model {
|
|||||||
});
|
});
|
||||||
lineSettingsModal: OV<number> = mobx.observable.box(null, {
|
lineSettingsModal: OV<number> = mobx.observable.box(null, {
|
||||||
name: "lineSettingsModal",
|
name: "lineSettingsModal",
|
||||||
}); // linenum
|
});
|
||||||
|
devicePixelRatio: OV<number> = mobx.observable.box(window.devicePixelRatio, {
|
||||||
|
name: "devicePixelRatio",
|
||||||
|
});
|
||||||
remotesModel: RemotesModel;
|
remotesModel: RemotesModel;
|
||||||
|
|
||||||
inputModel: InputModel;
|
inputModel: InputModel;
|
||||||
@ -200,6 +168,7 @@ class Model {
|
|||||||
getApi().onPCmd(this.onPCmd.bind(this));
|
getApi().onPCmd(this.onPCmd.bind(this));
|
||||||
getApi().onWCmd(this.onWCmd.bind(this));
|
getApi().onWCmd(this.onWCmd.bind(this));
|
||||||
getApi().onRCmd(this.onRCmd.bind(this));
|
getApi().onRCmd(this.onRCmd.bind(this));
|
||||||
|
getApi().onZoomChanged(this.onZoomChanged.bind(this));
|
||||||
getApi().onMenuItemAbout(this.onMenuItemAbout.bind(this));
|
getApi().onMenuItemAbout(this.onMenuItemAbout.bind(this));
|
||||||
getApi().onMetaArrowUp(this.onMetaArrowUp.bind(this));
|
getApi().onMetaArrowUp(this.onMetaArrowUp.bind(this));
|
||||||
getApi().onMetaArrowDown(this.onMetaArrowDown.bind(this));
|
getApi().onMetaArrowDown(this.onMetaArrowDown.bind(this));
|
||||||
@ -512,6 +481,30 @@ class Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onZoomChanged(): void {
|
||||||
|
mobx.action(() => {
|
||||||
|
this.devicePixelRatio.set(window.devicePixelRatio);
|
||||||
|
clearMonoFontCache();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
// for debuggin
|
||||||
|
getSelectedTermWrap(): TermWrap {
|
||||||
|
let screen = this.getActiveScreen();
|
||||||
|
if (screen == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let lineNum = screen.selectedLine.get();
|
||||||
|
if (lineNum == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let line = screen.getLineByNum(lineNum);
|
||||||
|
if (line == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return screen.getTermWrap(line.lineid);
|
||||||
|
}
|
||||||
|
|
||||||
clearModals(): boolean {
|
clearModals(): boolean {
|
||||||
let didSomething = false;
|
let didSomething = false;
|
||||||
mobx.action(() => {
|
mobx.action(() => {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -410,7 +410,7 @@ class Screen {
|
|||||||
getMaxContentSize(): WindowSize {
|
getMaxContentSize(): WindowSize {
|
||||||
if (this.lastScreenSize == null) {
|
if (this.lastScreenSize == null) {
|
||||||
let width = termWidthFromCols(80, this.globalModel.termFontSize.get());
|
let width = termWidthFromCols(80, this.globalModel.termFontSize.get());
|
||||||
let height = termHeightFromRows(25, this.globalModel.termFontSize.get());
|
let height = termHeightFromRows(25, this.globalModel.termFontSize.get(), 25);
|
||||||
return { width, height };
|
return { width, height };
|
||||||
}
|
}
|
||||||
let winSize = this.lastScreenSize;
|
let winSize = this.lastScreenSize;
|
||||||
@ -424,7 +424,7 @@ class Screen {
|
|||||||
getIdealContentSize(): WindowSize {
|
getIdealContentSize(): WindowSize {
|
||||||
if (this.lastScreenSize == null) {
|
if (this.lastScreenSize == null) {
|
||||||
let width = termWidthFromCols(80, this.globalModel.termFontSize.get());
|
let width = termWidthFromCols(80, this.globalModel.termFontSize.get());
|
||||||
let height = termHeightFromRows(25, this.globalModel.termFontSize.get());
|
let height = termHeightFromRows(25, this.globalModel.termFontSize.get(), 25);
|
||||||
return { width, height };
|
return { width, height };
|
||||||
}
|
}
|
||||||
let winSize = this.lastScreenSize;
|
let winSize = this.lastScreenSize;
|
||||||
|
@ -148,7 +148,7 @@ class TerminalRenderer extends React.Component<
|
|||||||
.get();
|
.get();
|
||||||
let cmd = screen.getCmd(line); // will not be null
|
let cmd = screen.getCmd(line); // will not be null
|
||||||
let usedRows = screen.getUsedRows(lineutil.getRendererContext(line), line, cmd, width);
|
let usedRows = screen.getUsedRows(lineutil.getRendererContext(line), line, cmd, width);
|
||||||
let termHeight = termHeightFromRows(usedRows, GlobalModel.termFontSize.get());
|
let termHeight = termHeightFromRows(usedRows, GlobalModel.termFontSize.get(), cmd.getTermMaxRows());
|
||||||
if (usedRows === 0) {
|
if (usedRows === 0) {
|
||||||
termHeight = 0;
|
termHeight = 0;
|
||||||
}
|
}
|
||||||
@ -164,6 +164,7 @@ class TerminalRenderer extends React.Component<
|
|||||||
{ "zero-height": termHeight == 0 },
|
{ "zero-height": termHeight == 0 },
|
||||||
{ collapsed: collapsed }
|
{ collapsed: collapsed }
|
||||||
)}
|
)}
|
||||||
|
data-usedrows={usedRows}
|
||||||
>
|
>
|
||||||
<If condition={!isFocused}>
|
<If condition={!isFocused}>
|
||||||
<div key="term-block" className="term-block" onClick={this.clickTermBlock}></div>
|
<div key="term-block" className="term-block" onClick={this.clickTermBlock}></div>
|
||||||
|
38
src/types/custom.d.ts
vendored
38
src/types/custom.d.ts
vendored
@ -833,6 +833,44 @@ declare global {
|
|||||||
isLineIdInSidebar(lineId: string): boolean;
|
isLineIdInSidebar(lineId: string): boolean;
|
||||||
getContainerType(): LineContainerStrs;
|
getContainerType(): LineContainerStrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type KeyModsType = {
|
||||||
|
meta?: boolean;
|
||||||
|
ctrl?: boolean;
|
||||||
|
alt?: boolean;
|
||||||
|
shift?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ElectronApi = {
|
||||||
|
getId: () => string;
|
||||||
|
getIsDev: () => boolean;
|
||||||
|
getPlatform: () => string;
|
||||||
|
getAuthKey: () => string;
|
||||||
|
getWaveSrvStatus: () => boolean;
|
||||||
|
restartWaveSrv: () => boolean;
|
||||||
|
reloadWindow: () => void;
|
||||||
|
openExternalLink: (url: string) => void;
|
||||||
|
reregisterGlobalShortcut: (shortcut: string) => void;
|
||||||
|
onTCmd: (callback: (mods: KeyModsType) => void) => void;
|
||||||
|
onICmd: (callback: (mods: KeyModsType) => void) => void;
|
||||||
|
onLCmd: (callback: (mods: KeyModsType) => void) => void;
|
||||||
|
onHCmd: (callback: (mods: KeyModsType) => void) => void;
|
||||||
|
onPCmd: (callback: (mods: KeyModsType) => void) => void;
|
||||||
|
onRCmd: (callback: (mods: KeyModsType) => void) => void;
|
||||||
|
onWCmd: (callback: (mods: KeyModsType) => void) => void;
|
||||||
|
onZoomChanged: (callback: () => void) => void;
|
||||||
|
onMenuItemAbout: (callback: () => void) => void;
|
||||||
|
onMetaArrowUp: (callback: () => void) => void;
|
||||||
|
onMetaArrowDown: (callback: () => void) => void;
|
||||||
|
onMetaPageUp: (callback: () => void) => void;
|
||||||
|
onMetaPageDown: (callback: () => void) => void;
|
||||||
|
onBracketCmd: (callback: (event: any, arg: { relative: number }, mods: KeyModsType) => void) => void;
|
||||||
|
onDigitCmd: (callback: (event: any, arg: { digit: number }, mods: KeyModsType) => void) => void;
|
||||||
|
contextScreen: (screenOpts: { screenId: string }, position: { x: number; y: number }) => void;
|
||||||
|
contextEditMenu: (position: { x: number; y: number }, opts: ContextMenuOpts) => void;
|
||||||
|
onWaveSrvStatusChange: (callback: (status: boolean, pid: number) => void) => void;
|
||||||
|
getLastLogs: (numOfLines: number, callback: (logs: any) => void) => void;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export {};
|
export {};
|
||||||
|
@ -30,6 +30,10 @@ function getMonoFontSize(fontSize: number): { height: number; width: number } {
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearMonoFontCache(): void {
|
||||||
|
MonoFontSizes = [];
|
||||||
|
}
|
||||||
|
|
||||||
function measureText(
|
function measureText(
|
||||||
text: string,
|
text: string,
|
||||||
textOpts?: { pre?: boolean; mono?: boolean; fontSize?: number | string }
|
textOpts?: { pre?: boolean; mono?: boolean; fontSize?: number | string }
|
||||||
@ -57,8 +61,9 @@ function measureText(
|
|||||||
throw new Error("cannot measure text, no #measure div");
|
throw new Error("cannot measure text, no #measure div");
|
||||||
}
|
}
|
||||||
measureDiv.replaceChildren(textElem);
|
measureDiv.replaceChildren(textElem);
|
||||||
let rect = textElem.getBoundingClientRect();
|
let height = textElem.offsetHeight;
|
||||||
return { width: rect.width, height: Math.ceil(rect.height) };
|
let width = textElem.offsetWidth;
|
||||||
|
return { width: width, height: Math.ceil(height) };
|
||||||
}
|
}
|
||||||
|
|
||||||
function windowWidthToCols(width: number, fontSize: number): number {
|
function windowWidthToCols(width: number, fontSize: number): number {
|
||||||
@ -82,10 +87,27 @@ function termWidthFromCols(cols: number, fontSize: number): number {
|
|||||||
return Math.ceil(dr.width * cols) + MagicLayout.TermWidthBuffer;
|
return Math.ceil(dr.width * cols) + MagicLayout.TermWidthBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
function termHeightFromRows(rows: number, fontSize: number): number {
|
// we need to match the xtermjs calculation in CharSizeService.ts and DomRenderer.ts
|
||||||
|
// it does some crazy rounding depending on the value of window.devicePixelRatio
|
||||||
|
// works out to `realHeight = round(ceil(height * dpr) * rows / dpr) / rows`
|
||||||
|
// their calculation is based off the "totalRows" (so that argument has been added)
|
||||||
|
function termHeightFromRows(rows: number, fontSize: number, totalRows: number): number {
|
||||||
let dr = getMonoFontSize(fontSize);
|
let dr = getMonoFontSize(fontSize);
|
||||||
// TODO: replace the TermDescendersHeight with some calculation based on termFontSize.
|
const dpr = window.devicePixelRatio;
|
||||||
return Math.ceil(dr.height * rows) + MagicLayout.TermDescendersHeight;
|
if (totalRows == null || totalRows == 0) {
|
||||||
|
totalRows = rows > 25 ? rows : 25;
|
||||||
|
}
|
||||||
|
let realHeight = Math.round((Math.ceil(dr.height * dpr) * totalRows) / dpr) / totalRows;
|
||||||
|
return Math.ceil(realHeight * rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { measureText, getMonoFontSize, windowWidthToCols, windowHeightToRows, termWidthFromCols, termHeightFromRows };
|
export {
|
||||||
|
measureText,
|
||||||
|
getMonoFontSize,
|
||||||
|
windowWidthToCols,
|
||||||
|
windowHeightToRows,
|
||||||
|
termWidthFromCols,
|
||||||
|
termHeightFromRows,
|
||||||
|
clearMonoFontCache,
|
||||||
|
MonoFontSizes,
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user