Compare commits
2 Commits
v0.3.5-bet
...
v0.3.5-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
436d5c6149 | ||
|
|
5a9edc076e |
8
web/package-lock.json
generated
8
web/package-lock.json
generated
@@ -12,7 +12,7 @@
|
||||
"@xterm/addon-unicode11": "^0.10.0-beta.203",
|
||||
"@xterm/addon-web-links": "^0.12.0",
|
||||
"@xterm/addon-webgl": "^0.20.0-beta.202",
|
||||
"@xterm/xterm": "^6.0.0",
|
||||
"@xterm/xterm": "^6.1.0-beta.203",
|
||||
"lucide-react": "^1.8.0",
|
||||
"react": "^19.2.5",
|
||||
"react-dom": "^19.2.5"
|
||||
@@ -453,9 +453,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@xterm/xterm": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-6.0.0.tgz",
|
||||
"integrity": "sha512-TQwDdQGtwwDt+2cgKDLn0IRaSxYu1tSUjgKarSDkUM0ZNiSRXFpjxEsvc/Zgc5kq5omJ+V0a8/kIM2WD3sMOYg==",
|
||||
"version": "6.1.0-beta.203",
|
||||
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-6.1.0-beta.203.tgz",
|
||||
"integrity": "sha512-Ctqf05M6fPWZkfKxC4hy2+PP5P2BlVnJLbIsXZMpkCz/MjJvcf5OwwsGkq+nzhFDuojSX+rc2RxIetLONUBGqw==",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"addons/*"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"@xterm/addon-unicode11": "^0.10.0-beta.203",
|
||||
"@xterm/addon-web-links": "^0.12.0",
|
||||
"@xterm/addon-webgl": "^0.20.0-beta.202",
|
||||
"@xterm/xterm": "^6.0.0",
|
||||
"@xterm/xterm": "^6.1.0-beta.203",
|
||||
"lucide-react": "^1.8.0",
|
||||
"react": "^19.2.5",
|
||||
"react-dom": "^19.2.5"
|
||||
|
||||
@@ -94,6 +94,10 @@ export default function App() {
|
||||
shell: [
|
||||
{ keys: `${layout.keys.ctrl}+${layout.keys.shift}+C`, desc: t('statusbar.copy') },
|
||||
{ keys: `${layout.keys.ctrl}+${layout.keys.shift}+V`, desc: t('statusbar.paste') },
|
||||
{ keys: `${layout.keys.ctrl}+F`, desc: t('statusbar.search') },
|
||||
{ keys: `${layout.keys.ctrl}+/Ctrl−`, desc: t('statusbar.zoom') },
|
||||
{ keys: `Alt+1-7`, desc: t('statusbar.switchTab') },
|
||||
{ keys: `${layout.keys.shift}+Tab`, desc: t('statusbar.nextTab') },
|
||||
{ keys: layout.keys.enter, desc: t('statusbar.runCommand') },
|
||||
{ keys: `${layout.keys.up}/${layout.keys.down}`, desc: t('statusbar.commandHistory') },
|
||||
],
|
||||
|
||||
@@ -255,6 +255,27 @@ function createTerminal(container, settings = {}) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (ctrl && (e.key === '=' || e.key === '+')) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
window.dispatchEvent(new CustomEvent('shell-zoom', { detail: 1 }))
|
||||
return false
|
||||
}
|
||||
|
||||
if (ctrl && e.key === '-') {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
window.dispatchEvent(new CustomEvent('shell-zoom', { detail: -1 }))
|
||||
return false
|
||||
}
|
||||
|
||||
if (ctrl && e.key === '0') {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
window.dispatchEvent(new CustomEvent('shell-zoom', { detail: 0 }))
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
@@ -387,9 +408,36 @@ export default function Shell({ api }) {
|
||||
const [searchText, setSearchText] = useState('')
|
||||
const searchInputRef = useRef(null)
|
||||
const searchDecorationsRef = useRef(null)
|
||||
const [zoomLevel, setZoomLevel] = useState(0)
|
||||
const baseFontSizeRef = useRef(12)
|
||||
|
||||
useEffect(() => { settingsRef.current = terminalSettings }, [terminalSettings])
|
||||
|
||||
useEffect(() => {
|
||||
baseFontSizeRef.current = terminalSettings.fontSize || 12
|
||||
}, [terminalSettings.fontSize])
|
||||
|
||||
useEffect(() => {
|
||||
const handler = (e) => {
|
||||
const direction = e.detail
|
||||
setZoomLevel(prev => {
|
||||
let next
|
||||
if (direction === 0) next = 0
|
||||
else next = Math.max(-8, Math.min(10, prev + direction))
|
||||
const newSize = baseFontSizeRef.current + next * 2
|
||||
for (const entry of Object.values(tabsRef.current)) {
|
||||
if (entry.term && !entry.term._disposed) {
|
||||
entry.term.options.fontSize = newSize
|
||||
try { entry.fitAddon.fit() } catch {}
|
||||
}
|
||||
}
|
||||
return next
|
||||
})
|
||||
}
|
||||
window.addEventListener('shell-zoom', handler)
|
||||
return () => window.removeEventListener('shell-zoom', handler)
|
||||
}, [])
|
||||
|
||||
const [sshForm, setSshForm] = useState({
|
||||
name: '', host: '', port: 22, user: '', key_path: '',
|
||||
})
|
||||
@@ -1059,6 +1107,11 @@ export default function Shell({ api }) {
|
||||
</div>
|
||||
|
||||
<div className="shell-tab-actions">
|
||||
{zoomLevel !== 0 && (
|
||||
<span className="shell-zoom-badge">
|
||||
{zoomLevel > 0 ? '+' : ''}{zoomLevel > 0 ? zoomLevel * 2 : zoomLevel * 2}px
|
||||
</span>
|
||||
)}
|
||||
{tabs.length < MAX_TABS && (
|
||||
<div className="shell-new-tab-wrapper">
|
||||
<button className="shell-new-tab-btn" onClick={() => setShowMenu(!showMenu)} title={t('shell.newTab')}>
|
||||
|
||||
@@ -18,6 +18,10 @@ const en = {
|
||||
newLine: 'New line',
|
||||
copy: 'Copy',
|
||||
paste: 'Paste',
|
||||
search: 'Search',
|
||||
zoom: 'Zoom +/−',
|
||||
switchTab: 'Switch tab',
|
||||
nextTab: 'Next tab',
|
||||
runCommand: 'Run command',
|
||||
commandHistory: 'Command history',
|
||||
},
|
||||
|
||||
@@ -18,6 +18,10 @@ const fr = {
|
||||
newLine: 'Nouvelle ligne',
|
||||
copy: 'Copier',
|
||||
paste: 'Coller',
|
||||
search: 'Rechercher',
|
||||
zoom: 'Zoom +/\u2212',
|
||||
switchTab: 'Changer d\u2019onglet',
|
||||
nextTab: 'Onglet suivant',
|
||||
runCommand: 'Ex\u00e9cuter',
|
||||
commandHistory: 'Historique',
|
||||
},
|
||||
|
||||
@@ -329,6 +329,14 @@ input::placeholder { color: var(--text-disabled); }
|
||||
|
||||
.shell-tab-actions { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
|
||||
|
||||
.shell-zoom-badge {
|
||||
font-size: 10px; font-family: var(--font-mono); font-weight: 600;
|
||||
color: var(--accent); background: var(--accent-bg);
|
||||
padding: 2px 6px; border-radius: 3px;
|
||||
border: 1px solid var(--accent-dim);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.shell-new-tab-wrapper { position: relative; }
|
||||
.shell-new-tab-btn {
|
||||
display: flex; align-items: center; gap: 2px;
|
||||
|
||||
Reference in New Issue
Block a user