diff --git a/__mocks__/xterm.ts b/__mocks__/xterm.ts index 12387eb0..29daed19 100644 --- a/__mocks__/xterm.ts +++ b/__mocks__/xterm.ts @@ -9,6 +9,10 @@ export class Terminal { } element = { addEventListener: vi.fn(), + parentElement: { + clientHeight: 480, + clientWidth: 640 + } } constructor (props) { this.out = "" @@ -62,5 +66,18 @@ export class Terminal { const ev = new KeyboardEvent("keydown", { key }) this.keyHandler( { domEvent: ev } ) } + resize:(columns: number, rows: number) => void = vi.fn(); + _core = { + _renderService: { + dimensions: { + css: { + cell: { + width: 5, + height: 11 + } + } + } + } + } } diff --git a/aatp/http_webrtc/http_webrtc.spec.ts b/aatp/http_webrtc/http_webrtc.spec.ts index 256dd238..ebf276ce 100644 --- a/aatp/http_webrtc/http_webrtc.spec.ts +++ b/aatp/http_webrtc/http_webrtc.spec.ts @@ -100,8 +100,8 @@ pinch_max_y_velocity = 0.1` await page.screenshot({ path: `/result/2.png` }) await expect(page.locator('.pane')).toHaveCount(2) }) - test('a pane can be close', async() => { - sleep(500) + test('a pane can be closed', async() => { + await sleep(500) const exitState = await page.evaluate(() => { try { window.terminal7.activeG.activeW.activeP.d.send("exit\n") @@ -120,7 +120,7 @@ pinch_max_y_velocity = 0.1` await page.screenshot({ path: `/result/second.png` }) const lines = await page.evaluate(() => window.terminal7.activeG.activeW.activeP.t.buffer.active.length) - expect(lines).toEqual(38) + await expect(lines).toEqual(38) await page.evaluate(async() => { const gate = window.terminal7.activeG gate.disengage().then(() => { diff --git a/aatp/ui/ui.spec.ts b/aatp/ui/ui.spec.ts index dfb864b2..3bc0717b 100644 --- a/aatp/ui/ui.spec.ts +++ b/aatp/ui/ui.spec.ts @@ -89,7 +89,6 @@ insecure=true`) await expect(page.locator('#t0')).toBeVisible() await sleep(500) await page.keyboard.press('ArrowDown') - await page.keyboard.press('ArrowDown') await page.keyboard.press('Enter') await expect(page.locator('.windows-container')).toBeHidden() }) @@ -104,7 +103,7 @@ insecure=true`) await page.screenshot({ path: `/result/2.png` }) await page.locator('.tabbar .reset').click() await expect(page.locator('#t0')).toBeVisible() - sleep(20) + await sleep(20) await page.keyboard.press('Enter') await expect(page.locator('#t0')).toBeHidden() await expect(page.locator('.pane')).toHaveCount(1) diff --git a/src/gate.ts b/src/gate.ts index 4c0efb7a..4bc05ffa 100644 --- a/src/gate.ts +++ b/src/gate.ts @@ -376,7 +376,7 @@ export class Gate { /* * returns an array of panes */ - panes() { + panes(): Pane[] { const r = [] this.t7.cells.forEach(c => { if (c instanceof Pane && (c.gate == this)) @@ -388,10 +388,11 @@ export class Gate { reset() { this.t7.map.shell.runCommand("reset", [this.name]) } - setLayout(state: ServerPayload = null) { + setLayout(state: ServerPayload = null, fromPresenter = false) { console.log("in setLayout", state) const winLen = this.windows.length - this.fontScale = 1 + if(this.fitScreen) + this.fontScale = 1 // got an empty state if ((state == null) || !(state.windows instanceof Array) || (state.windows.length == 0)) { // create the first window and pane @@ -410,7 +411,7 @@ export class Gate { if (this.layoutWidth != state.width || this.layoutHeight != state.height) { this.layoutWidth = state.width this.layoutHeight = state.height - this.fitScreen = false + if (fromPresenter) this.fitScreen = false this.scaleContainer() } state.windows.forEach(w => { @@ -476,7 +477,9 @@ export class Gate { container.style.transformOrigin = "top left" } this.panes().forEach(p => { - p.t.options.fontSize = Math.floor(scale * p.fontSize) + // NOTE: the step of changing the font size is 0.5, there is no visual change when doing smaller steps + const fontSize = p.fontSize * scale + p.t.options.fontSize = Math.floor(fontSize) + (String(fontSize).includes('.') ? .5 : 0) }) this.fontScale = scale } @@ -698,7 +701,7 @@ export class Gate { this.session.onStateChange = (state, failure?) => this.onSessionState(state, failure) this.session.onCMD = msg => { if (msg.type == "set_payload") { - this.setLayout(msg.args.payload) + this.setLayout(msg.args.payload, true) } } this.t7.log("opening session") diff --git a/src/pane.ts b/src/pane.ts index c42b1338..75a71eab 100644 --- a/src/pane.ts +++ b/src/pane.ts @@ -36,6 +36,19 @@ const ABIT = 10, caseSensitive: true, } +export interface SerializedPane { + sx: number, + sy: number, + xoff: number, + yoff: number, + fontSize: number, + channelID: number, + active: boolean, + zoomed: boolean, + rows: number, + cols: number +} + export class Pane extends Cell { active = false aLeader = false @@ -201,7 +214,8 @@ export class Pane extends Cell { this.fontSize += by if (this.fontSize < 6) this.fontSize = 6 else if (this.fontSize > 30) this.fontSize = 30 - this.t.options.fontSize = this.fontSize * this.gate.fontScale + const fontSize = this.fontSize * this.gate.fontScale + this.t.options.fontSize = Math.floor(fontSize) + (String(fontSize).includes('.') ? .5 : 0) this.fit() this.gate.sendState() } @@ -298,7 +312,7 @@ export class Pane extends Cell { // returns true is size was changed // TODO: make it async fit(cb = null) { - if (!this.t) { + if (!this.t || !this.gate?.fitScreen) { if (cb instanceof Function) cb(this) return @@ -307,7 +321,7 @@ export class Pane extends Cell { const oldc = this.t.cols // there's no point in fitting when in the middle of a restore - // it happens in the eend anyway + // it happens in the end anyway try { this.fitAddon.fit() } catch (e) { @@ -706,7 +720,7 @@ export class Pane extends Cell { this.unzoom() super.close() } - dump() { + dump(): SerializedPane { const cell = { sx: this.sx, sy: this.sy, @@ -715,14 +729,16 @@ export class Pane extends Cell { fontSize: this.fontSize, channelID: null, active: false, - zoomed: false + zoomed: false, + rows: this.t.rows, + cols: this.t.cols } cell.channelID = this.channelID if (this.w.activeP && this == this.w.activeP) cell.active = true if (this.zoomed) cell.zoomed = true - return cell as this + return cell } // listening for terminal selection changes selectionChanged() { diff --git a/src/window.ts b/src/window.ts index dc453b38..65bf53f2 100644 --- a/src/window.ts +++ b/src/window.ts @@ -262,8 +262,22 @@ export class Window { thisCell.yoff = thatCell.yoff thisCell.fontSize = thatCell.fontSize if (thisCell.t) { - thisCell.t.options.fontSize = thatCell.fontSize * this.gate.fontScale - thisCell.fit() + // NOTE: the step of changing the font size is 0.5, there is no visual change when doing smaller steps + const fontSize = thatCell.fontSize * this.gate.fontScale + thisCell.t.options.fontSize = Math.floor(fontSize) + (String(fontSize).includes('.') ? .5 : 0) + + const availableHeight = thisCell.t.element.parentElement.clientHeight + const availableWidth = thisCell.t.element.parentElement.clientWidth + + const adjustFontSize = (availableWidth: number, availableHeight: number) => { + const charDims: { width: number, height: number } = thisCell.t._core._renderService.dimensions.css.cell + if (charDims.width * thatCell.cols > availableWidth || charDims.height * thatCell.rows > availableHeight) { + thisCell.t.options.fontSize -= .5 + adjustFontSize(availableWidth, availableHeight) + } + } + adjustFontSize(availableWidth, availableHeight) + thisCell.t.resize(thatCell.cols, thatCell.rows) } if (thatCell.active) thisCell.focus() @@ -275,6 +289,7 @@ export class Window { setTimeout(() => zoomed.zoom(), 100) console.log("will zoom in 100ms") } + newLayout.refreshDividers() return newLayout }