dsh-ssh-terminal 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -13,7 +13,7 @@ window.__ModuleLoader__.load({
13
13
  return p(d.getHours()) + ":" + p(d.getMinutes()) + ":" + p(d.getSeconds());
14
14
  }
15
15
  const SSH_CSS = `
16
- .dshssh-body{display:flex;flex-direction:column;gap:8px;height:100%;box-sizing:border-box;padding:10px;color:var(--dsw-alias-label-primary,inherit);}
16
+ .dshssh-body{position:relative;display:flex;flex-direction:column;gap:8px;height:100%;box-sizing:border-box;padding:10px;color:var(--dsw-alias-label-primary,inherit);}
17
17
  .dshssh-head{display:flex;align-items:center;gap:8px;}
18
18
  .dshssh-title{font-weight:700;flex:1;}
19
19
  .dshssh-status{font-weight:600;}
@@ -34,7 +34,7 @@ window.__ModuleLoader__.load({
34
34
  .dshssh-pin{color:var(--dsw-alias-accent,#facc15);margin-right:3px;}
35
35
  .dshssh-session-meta{color:var(--dsw-alias-label-tertiary,#94a3b8);font-size:10px;}
36
36
  .dshssh-empty{padding:6px;color:var(--dsw-alias-label-tertiary,#94a3b8);font-size:11px;}
37
- .dshssh-context-menu{position:fixed;z-index:1000;display:flex;flex-direction:column;min-width:140px;padding:4px;border:1px solid var(--dsw-alias-border-l2,rgba(148,163,184,.4));border-radius:7px;background:var(--dsw-alias-bg-layer-3,#252529);box-shadow:0 8px 24px rgba(0,0,0,.35);}
37
+ .dshssh-context-menu{position:absolute;z-index:1000;display:flex;flex-direction:column;min-width:140px;padding:4px;border:1px solid var(--dsw-alias-border-l2,rgba(148,163,184,.4));border-radius:7px;background:var(--dsw-alias-bg-layer-3,#252529);box-shadow:0 8px 24px rgba(0,0,0,.35);}
38
38
  .dshssh-context-menu button{padding:6px 8px;border:0;border-radius:5px;background:transparent;color:var(--dsw-alias-label-primary,inherit);text-align:left;cursor:pointer;font-size:12px;}
39
39
  .dshssh-context-menu button:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(148,163,184,.15));}
40
40
  .dshssh-context-menu button.danger{color:var(--dsw-alias-state-error-primary,#fca5a5);}
@@ -238,8 +238,15 @@ window.__ModuleLoader__.load({
238
238
  onContextMenu: (e) => {
239
239
  e.preventDefault();
240
240
  e.stopPropagation();
241
- const x = Math.min(e.clientX, Math.max(4, window.innerWidth - 160));
242
- const y = Math.min(e.clientY, Math.max(4, window.innerHeight - 80));
241
+ const body = e.currentTarget.closest(".dshssh-body");
242
+ const rect = body ? body.getBoundingClientRect() : {
243
+ left: 0,
244
+ top: 0,
245
+ width: window.innerWidth,
246
+ height: window.innerHeight
247
+ };
248
+ const x = Math.max(4, Math.min(e.clientX - rect.left, rect.width - 160));
249
+ const y = Math.max(4, Math.min(e.clientY - rect.top, rect.height - 80));
243
250
  setContextMenu({
244
251
  connectionId: s.connectionId,
245
252
  x,
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["useState","useRef","createElement"],"sources":["../src/client/index.tsx"],"sourcesContent":["import { createElement, useState, useEffect, useRef } from 'react'\n\nconst API = '/ssh-terminal/api'\n\nfunction fmt(ts) {\n const d = new Date(ts)\n const p = (n) => String(n).padStart(2, '0')\n return p(d.getHours()) + ':' + p(d.getMinutes()) + ':' + p(d.getSeconds())\n}\n\nconst SSH_CSS = `\n.dshssh-body{display:flex;flex-direction:column;gap:8px;height:100%;box-sizing:border-box;padding:10px;color:var(--dsw-alias-label-primary,inherit);}\n.dshssh-head{display:flex;align-items:center;gap:8px;}\n.dshssh-title{font-weight:700;flex:1;}\n.dshssh-status{font-weight:600;}\n.dshssh-status.ok{color:var(--dsw-alias-state-success-primary,#22c55e);}\n.dshssh-status.off{color:var(--dsw-alias-label-tertiary,#94a3b8);}\n.dshssh-layout{display:flex;gap:8px;flex:1;min-height:0;}\n.dshssh-sessions{width:150px;min-width:125px;display:flex;flex-direction:column;gap:6px;min-height:0;}\n.dshssh-session-title{font-size:11px;font-weight:700;color:var(--dsw-alias-label-secondary,#d1d5db);}\n.dshssh-session-list{display:flex;flex-direction:column;gap:5px;overflow:auto;min-height:0;}\n.dshssh-session{display:flex;align-items:center;gap:6px;width:100%;padding:6px 7px;text-align:left;border-radius:7px;border:1px solid transparent;background:var(--dsw-alias-bg-layer-2,rgba(148,163,184,.08));color:var(--dsw-alias-label-primary,inherit);cursor:pointer;font-size:11px;}\n.dshssh-session:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(148,163,184,.15));}\n.dshssh-session.selected{border-color:var(--dsw-alias-accent,#60a5fa);}\n.dshssh-session-dot{width:7px;height:7px;flex:0 0 7px;border-radius:50%;background:var(--dsw-alias-label-tertiary,#94a3b8);}\n.dshssh-session-dot.ok{background:var(--dsw-alias-state-success-primary,#22c55e);}\n.dshssh-session-copy{min-width:0;display:flex;flex-direction:column;gap:2px;}\n.dshssh-session-name,.dshssh-session-meta{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}\n.dshssh-session-name{font-weight:600;}\n.dshssh-pin{color:var(--dsw-alias-accent,#facc15);margin-right:3px;}\n.dshssh-session-meta{color:var(--dsw-alias-label-tertiary,#94a3b8);font-size:10px;}\n.dshssh-empty{padding:6px;color:var(--dsw-alias-label-tertiary,#94a3b8);font-size:11px;}\n.dshssh-context-menu{position:fixed;z-index:1000;display:flex;flex-direction:column;min-width:140px;padding:4px;border:1px solid var(--dsw-alias-border-l2,rgba(148,163,184,.4));border-radius:7px;background:var(--dsw-alias-bg-layer-3,#252529);box-shadow:0 8px 24px rgba(0,0,0,.35);}\n.dshssh-context-menu button{padding:6px 8px;border:0;border-radius:5px;background:transparent;color:var(--dsw-alias-label-primary,inherit);text-align:left;cursor:pointer;font-size:12px;}\n.dshssh-context-menu button:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(148,163,184,.15));}\n.dshssh-context-menu button.danger{color:var(--dsw-alias-state-error-primary,#fca5a5);}\n.dshssh-main{display:flex;flex-direction:column;gap:8px;flex:1;min-width:0;min-height:0;}\n.dshssh-form{display:flex;flex-wrap:wrap;gap:6px;align-items:center;}\n.dshssh-input{padding:4px 7px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2,rgba(148,163,184,.4));background:var(--dsw-alias-bg-layer-3,rgba(2,6,23,.5));color:var(--dsw-alias-label-primary,inherit);font-size:12px;min-width:70px;}\n.dshssh-input::placeholder{color:var(--dsw-alias-label-tertiary,#94a3b8);}\n.dshssh-btn{padding:4px 10px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2,rgba(148,163,184,.4));background:var(--dsw-alias-interactive-bg-hover,rgba(148,163,184,.15));color:var(--dsw-alias-label-primary,inherit);cursor:pointer;font-size:12px;}\n.dshssh-btn:hover{background:var(--dsw-alias-interactive-bg-active,rgba(148,163,184,.28));}\n.dshssh-btn:disabled{opacity:.5;cursor:default;}\n.dshssh-log{flex:1;min-height:120px;overflow:auto;background:var(--dsw-alias-bg-layer-1,rgba(2,6,23,.55));border:1px solid var(--dsw-alias-border-l2,rgba(148,163,184,.25));border-radius:8px;padding:8px;font-family:var(--dsw-font-mono,ui-monospace,SFMono-Regular,Menlo,Consolas,monospace);font-size:12px;line-height:1.45;white-space:pre-wrap;word-break:break-word;}\n.dshssh-step{margin:0 0 6px;}\n.dshssh-cmd{color:var(--dsw-alias-accent,#93c5fd);}\n.dshssh-cmd::before{content:\"❯ \";color:var(--dsw-alias-accent,#60a5fa);}\n.dshssh-out{color:var(--dsw-alias-label-secondary,#d1d5db);}\n.dshssh-connect{color:var(--dsw-alias-state-success-primary,#86efac);}\n.dshssh-disconnect{color:var(--dsw-alias-state-error-primary,#fca5a5);}\n.dshssh-system{color:var(--dsw-alias-label-tertiary,#94a3b8);font-style:italic;}\n.dshssh-err{color:var(--dsw-alias-state-error-primary,#fca5a5);}\n`\n\nasync function callApi(action, extra = undefined) {\n const res = await fetch(API, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ action, ...(extra || {}) }),\n })\n return await res.json()\n}\n\nfunction injectCss() {\n if (typeof document === 'undefined') return\n if (document.querySelector('style[data-plugin-css=\"dsh-ssh-terminal\"]')) return\n const tag = document.createElement('style')\n tag.dataset.plugin = 'dsh-ssh-terminal'\n tag.dataset.pluginCss = 'dsh-ssh-terminal'\n tag.textContent = SSH_CSS\n document.head.appendChild(tag)\n}\n\nfunction SshBody(props) {\n const ctx = props.ctx\n const visible = props.visible === undefined ? true : props.visible\n const [busy, setBusy] = useState(false)\n const [err, setErr] = useState('')\n const [hostV, setHostV] = useState('')\n const [userV, setUserV] = useState('')\n const [portV, setPortV] = useState('22')\n const [passV, setPassV] = useState('')\n const [cmdV, setCmdV] = useState('')\n const [sessions, setSessions] = useState([])\n const [connectionId, setConnectionId] = useState('')\n const [connected, setConnected] = useState(false)\n const [target, setTarget] = useState('')\n const [steps, setSteps] = useState([])\n const [logEl, setLogEl] = useState(null)\n const [contextMenu, setContextMenu] = useState(null)\n const refreshSeq = useRef(0)\n\n const selectedSession = sessions.find((s) => s.connectionId === connectionId)\n const contextSession = contextMenu && sessions.find((s) => s.connectionId === contextMenu.connectionId)\n const canRun = connected && !!selectedSession && !!selectedSession.connected\n\n async function refresh(preferredId) {\n const seq = ++refreshSeq.current\n try {\n const list = await callApi('list')\n if (seq !== refreshSeq.current) return\n const nextSessions = Array.isArray(list && list.sessions) ? list.sessions : []\n setSessions(nextSessions)\n const preferred = preferredId || connectionId\n const selected = nextSessions.some((s) => s.connectionId === preferred)\n ? preferred\n : (list && list.activeConnectionId && nextSessions.some((s) => s.connectionId === list.activeConnectionId)\n ? list.activeConnectionId\n : ((nextSessions.find((s) => s.connected) || nextSessions[0] || {}).connectionId || ''))\n if (selected !== connectionId) setConnectionId(selected)\n if (!selected) {\n if (seq !== refreshSeq.current) return\n setConnected(false)\n setTarget('')\n setSteps([])\n return\n }\n const t = await callApi('status', { connectionId: selected })\n if (seq !== refreshSeq.current) return\n setConnected(!!(t && t.connected))\n setTarget((t && t.target) || '')\n setSteps((t && t.steps) || [])\n } catch (e) {}\n }\n\n useEffect(() => {\n injectCss()\n if (visible === false) { refreshSeq.current += 1; return }\n refresh(connectionId)\n const stop = ctx.interval(() => refresh(connectionId), 600)\n return () => {\n refreshSeq.current += 1\n try { stop() } catch (e) {}\n }\n }, [visible, connectionId])\n\n useEffect(() => {\n const el = logEl\n if (!el) return\n const nearBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 40\n if (nearBottom) el.scrollTop = el.scrollHeight\n }, [steps, logEl])\n\n async function connect() {\n setBusy(true); setErr('')\n try {\n const r = await callApi('connect', { host: hostV, user: userV, port: Number(portV) || 22, password: passV || undefined })\n if (r && r.error) setErr(String(r.error))\n await refresh(r && r.connectionId)\n }\n catch (e) { setErr(String((e && e.message) || e)) } finally { setBusy(false) }\n }\n async function run() {\n setBusy(true); setErr('')\n try {\n const r = await callApi('exec', { connectionId, command: cmdV, waitMs: 15000 })\n if (r && r.error) setErr(String(r.error))\n await refresh(connectionId)\n }\n catch (e) { setErr(String((e && e.message) || e)) } finally { setBusy(false) }\n }\n async function disconnect() {\n setBusy(true); setErr('')\n try { await callApi('disconnect', { connectionId }); await refresh(connectionId) }\n catch (e) { setErr(String((e && e.message) || e)) } finally { setBusy(false) }\n }\n async function clearHistory() {\n try {\n if (window.confirm('确定清空当前连接的 SSH 操作记录吗?')) {\n await callApi('clear', connectionId ? { connectionId } : undefined)\n await refresh(connectionId)\n }\n } catch (e) { setErr(String((e && e.message) || e)) }\n }\n\n async function togglePinned(id) {\n setContextMenu(null)\n try {\n const r = await callApi('pin', { connectionId: id })\n if (r && r.error) setErr(String(r.error))\n await refresh(id)\n } catch (e) { setErr(String((e && e.message) || e)) }\n }\n\n async function deleteRecord(id) {\n const session = sessions.find((s) => s.connectionId === id)\n setContextMenu(null)\n if (!session || !window.confirm('删除该连接记录吗?在线连接不会断开。')) return\n try {\n const r = await callApi('delete', { connectionId: id })\n if (r && r.error) setErr(String(r.error))\n await refresh(id)\n } catch (e) { setErr(String((e && e.message) || e)) }\n }\n\n const onKey = (e) => { if (e.key === 'Enter' && canRun && !busy) run() }\n const status = connected ? ('● ' + target) : (selectedSession ? (selectedSession.exited ? '○ 已退出' : '○ 未连接') : '○ 未选择连接')\n\n return createElement('div', { className: 'dshssh-body', onClick: () => setContextMenu(null) },\n createElement('div', { className: 'dshssh-head' },\n createElement('span', { className: 'dshssh-title' }, 'SSH 远程终端'),\n createElement('span', { className: 'dshssh-status ' + (connected ? 'ok' : 'off') }, status),\n createElement('button', { className: 'dshssh-btn dshssh-clear', onClick: clearHistory }, '清空当前'),\n ),\n createElement('div', { className: 'dshssh-layout' },\n createElement('div', { className: 'dshssh-sessions' },\n createElement('div', { className: 'dshssh-session-title' }, '连接列表 (' + sessions.length + ')'),\n createElement('div', { className: 'dshssh-session-list' },\n sessions.length\n ? sessions.map((s) => createElement('button', {\n key: s.connectionId,\n className: 'dshssh-session' + (s.connectionId === connectionId ? ' selected' : ''),\n onClick: () => { setConnectionId(s.connectionId); setErr('') },\n onContextMenu: (e) => {\n e.preventDefault()\n e.stopPropagation()\n const x = Math.min(e.clientX, Math.max(4, window.innerWidth - 160))\n const y = Math.min(e.clientY, Math.max(4, window.innerHeight - 80))\n setContextMenu({ connectionId: s.connectionId, x, y })\n },\n },\n createElement('span', { className: 'dshssh-session-dot' + (s.connected ? ' ok' : '') }),\n createElement('span', { className: 'dshssh-session-copy' },\n createElement('span', { className: 'dshssh-session-name' },\n s.pinned ? createElement('span', { className: 'dshssh-pin', title: '已置顶' }, '★') : null,\n s.label || s.target || 'SSH 连接',\n ),\n createElement('span', { className: 'dshssh-session-meta' }, s.connected ? (s.busy ? '执行中' : '已连接') : (s.historical ? '历史记录' : '已断开')),\n )))\n : createElement('div', { className: 'dshssh-empty' }, '暂无连接'),\n ),\n ),\n createElement('div', { className: 'dshssh-main' },\n createElement('div', { className: 'dshssh-form' },\n createElement('input', { className: 'dshssh-input', placeholder: '主机', value: hostV, onChange: (e) => setHostV(e.target.value) }),\n createElement('input', { className: 'dshssh-input', placeholder: '用户', value: userV, onChange: (e) => setUserV(e.target.value) }),\n createElement('input', { className: 'dshssh-input', style: { width: 54 }, placeholder: '端口', value: portV, onChange: (e) => setPortV(e.target.value) }),\n createElement('input', { className: 'dshssh-input', style: { width: 96 }, type: 'password', placeholder: '密码(可选)', value: passV, onChange: (e) => setPassV(e.target.value) }),\n createElement('button', { className: 'dshssh-btn', disabled: busy, onClick: connect }, '新建连接'),\n ),\n createElement('div', { className: 'dshssh-form' },\n createElement('input', { className: 'dshssh-input dshssh-cmdline', style: { flex: 1 }, placeholder: '输入命令后回车或点执行', value: cmdV, onChange: (e) => setCmdV(e.target.value), onKeyDown: onKey }),\n createElement('button', { className: 'dshssh-btn', disabled: busy || !canRun, onClick: run }, '执行'),\n createElement('button', { className: 'dshssh-btn', disabled: busy || !canRun, onClick: disconnect }, '断开'),\n ),\n createElement('div', { className: 'dshssh-log', ref: (el) => setLogEl(el) },\n steps.length\n ? steps.map((s, i) => createElement('div', { key: i, className: 'dshssh-step dshssh-' + s.kind }, (fmt(s.ts) + ' ' + s.text)))\n : createElement('div', { className: 'dshssh-step dshssh-system' }, '还没有操作。'),\n ),\n err ? createElement('div', { className: 'dshssh-err' }, String(err)) : null,\n ),\n contextMenu && contextSession\n ? createElement('div', {\n className: 'dshssh-context-menu',\n style: { left: contextMenu.x, top: contextMenu.y },\n onClick: (e) => e.stopPropagation(),\n },\n createElement('button', { type: 'button', onClick: () => togglePinned(contextSession.connectionId) }, contextSession.pinned ? '取消置顶' : '置顶'),\n createElement('button', { type: 'button', className: 'danger', onClick: () => deleteRecord(contextSession.connectionId) }, '删除该连接记录'),\n )\n : null,\n ),\n )\n}\n\nexport const inject = ['timer', 'betterSidebar']\n\nexport function apply(ctx) {\n const bs = ctx.get('betterSidebar')\n if (!bs) return\n ctx.effect(() => bs.registerTab({\n id: 'ssh-remote:terminal',\n title: 'SSH 终端',\n order: 60,\n single: true,\n component: (p) => createElement(SshBody, { ctx, visible: p.visible }),\n }))\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["useState","useRef","createElement"],"sources":["../src/client/index.tsx"],"sourcesContent":["import { createElement, useState, useEffect, useRef } from 'react'\n\nconst API = '/ssh-terminal/api'\n\nfunction fmt(ts) {\n const d = new Date(ts)\n const p = (n) => String(n).padStart(2, '0')\n return p(d.getHours()) + ':' + p(d.getMinutes()) + ':' + p(d.getSeconds())\n}\n\nconst SSH_CSS = `\n.dshssh-body{position:relative;display:flex;flex-direction:column;gap:8px;height:100%;box-sizing:border-box;padding:10px;color:var(--dsw-alias-label-primary,inherit);}\n.dshssh-head{display:flex;align-items:center;gap:8px;}\n.dshssh-title{font-weight:700;flex:1;}\n.dshssh-status{font-weight:600;}\n.dshssh-status.ok{color:var(--dsw-alias-state-success-primary,#22c55e);}\n.dshssh-status.off{color:var(--dsw-alias-label-tertiary,#94a3b8);}\n.dshssh-layout{display:flex;gap:8px;flex:1;min-height:0;}\n.dshssh-sessions{width:150px;min-width:125px;display:flex;flex-direction:column;gap:6px;min-height:0;}\n.dshssh-session-title{font-size:11px;font-weight:700;color:var(--dsw-alias-label-secondary,#d1d5db);}\n.dshssh-session-list{display:flex;flex-direction:column;gap:5px;overflow:auto;min-height:0;}\n.dshssh-session{display:flex;align-items:center;gap:6px;width:100%;padding:6px 7px;text-align:left;border-radius:7px;border:1px solid transparent;background:var(--dsw-alias-bg-layer-2,rgba(148,163,184,.08));color:var(--dsw-alias-label-primary,inherit);cursor:pointer;font-size:11px;}\n.dshssh-session:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(148,163,184,.15));}\n.dshssh-session.selected{border-color:var(--dsw-alias-accent,#60a5fa);}\n.dshssh-session-dot{width:7px;height:7px;flex:0 0 7px;border-radius:50%;background:var(--dsw-alias-label-tertiary,#94a3b8);}\n.dshssh-session-dot.ok{background:var(--dsw-alias-state-success-primary,#22c55e);}\n.dshssh-session-copy{min-width:0;display:flex;flex-direction:column;gap:2px;}\n.dshssh-session-name,.dshssh-session-meta{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}\n.dshssh-session-name{font-weight:600;}\n.dshssh-pin{color:var(--dsw-alias-accent,#facc15);margin-right:3px;}\n.dshssh-session-meta{color:var(--dsw-alias-label-tertiary,#94a3b8);font-size:10px;}\n.dshssh-empty{padding:6px;color:var(--dsw-alias-label-tertiary,#94a3b8);font-size:11px;}\n.dshssh-context-menu{position:absolute;z-index:1000;display:flex;flex-direction:column;min-width:140px;padding:4px;border:1px solid var(--dsw-alias-border-l2,rgba(148,163,184,.4));border-radius:7px;background:var(--dsw-alias-bg-layer-3,#252529);box-shadow:0 8px 24px rgba(0,0,0,.35);}\n.dshssh-context-menu button{padding:6px 8px;border:0;border-radius:5px;background:transparent;color:var(--dsw-alias-label-primary,inherit);text-align:left;cursor:pointer;font-size:12px;}\n.dshssh-context-menu button:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(148,163,184,.15));}\n.dshssh-context-menu button.danger{color:var(--dsw-alias-state-error-primary,#fca5a5);}\n.dshssh-main{display:flex;flex-direction:column;gap:8px;flex:1;min-width:0;min-height:0;}\n.dshssh-form{display:flex;flex-wrap:wrap;gap:6px;align-items:center;}\n.dshssh-input{padding:4px 7px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2,rgba(148,163,184,.4));background:var(--dsw-alias-bg-layer-3,rgba(2,6,23,.5));color:var(--dsw-alias-label-primary,inherit);font-size:12px;min-width:70px;}\n.dshssh-input::placeholder{color:var(--dsw-alias-label-tertiary,#94a3b8);}\n.dshssh-btn{padding:4px 10px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2,rgba(148,163,184,.4));background:var(--dsw-alias-interactive-bg-hover,rgba(148,163,184,.15));color:var(--dsw-alias-label-primary,inherit);cursor:pointer;font-size:12px;}\n.dshssh-btn:hover{background:var(--dsw-alias-interactive-bg-active,rgba(148,163,184,.28));}\n.dshssh-btn:disabled{opacity:.5;cursor:default;}\n.dshssh-log{flex:1;min-height:120px;overflow:auto;background:var(--dsw-alias-bg-layer-1,rgba(2,6,23,.55));border:1px solid var(--dsw-alias-border-l2,rgba(148,163,184,.25));border-radius:8px;padding:8px;font-family:var(--dsw-font-mono,ui-monospace,SFMono-Regular,Menlo,Consolas,monospace);font-size:12px;line-height:1.45;white-space:pre-wrap;word-break:break-word;}\n.dshssh-step{margin:0 0 6px;}\n.dshssh-cmd{color:var(--dsw-alias-accent,#93c5fd);}\n.dshssh-cmd::before{content:\"❯ \";color:var(--dsw-alias-accent,#60a5fa);}\n.dshssh-out{color:var(--dsw-alias-label-secondary,#d1d5db);}\n.dshssh-connect{color:var(--dsw-alias-state-success-primary,#86efac);}\n.dshssh-disconnect{color:var(--dsw-alias-state-error-primary,#fca5a5);}\n.dshssh-system{color:var(--dsw-alias-label-tertiary,#94a3b8);font-style:italic;}\n.dshssh-err{color:var(--dsw-alias-state-error-primary,#fca5a5);}\n`\n\nasync function callApi(action, extra = undefined) {\n const res = await fetch(API, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ action, ...(extra || {}) }),\n })\n return await res.json()\n}\n\nfunction injectCss() {\n if (typeof document === 'undefined') return\n if (document.querySelector('style[data-plugin-css=\"dsh-ssh-terminal\"]')) return\n const tag = document.createElement('style')\n tag.dataset.plugin = 'dsh-ssh-terminal'\n tag.dataset.pluginCss = 'dsh-ssh-terminal'\n tag.textContent = SSH_CSS\n document.head.appendChild(tag)\n}\n\nfunction SshBody(props) {\n const ctx = props.ctx\n const visible = props.visible === undefined ? true : props.visible\n const [busy, setBusy] = useState(false)\n const [err, setErr] = useState('')\n const [hostV, setHostV] = useState('')\n const [userV, setUserV] = useState('')\n const [portV, setPortV] = useState('22')\n const [passV, setPassV] = useState('')\n const [cmdV, setCmdV] = useState('')\n const [sessions, setSessions] = useState([])\n const [connectionId, setConnectionId] = useState('')\n const [connected, setConnected] = useState(false)\n const [target, setTarget] = useState('')\n const [steps, setSteps] = useState([])\n const [logEl, setLogEl] = useState(null)\n const [contextMenu, setContextMenu] = useState(null)\n const refreshSeq = useRef(0)\n\n const selectedSession = sessions.find((s) => s.connectionId === connectionId)\n const contextSession = contextMenu && sessions.find((s) => s.connectionId === contextMenu.connectionId)\n const canRun = connected && !!selectedSession && !!selectedSession.connected\n\n async function refresh(preferredId) {\n const seq = ++refreshSeq.current\n try {\n const list = await callApi('list')\n if (seq !== refreshSeq.current) return\n const nextSessions = Array.isArray(list && list.sessions) ? list.sessions : []\n setSessions(nextSessions)\n const preferred = preferredId || connectionId\n const selected = nextSessions.some((s) => s.connectionId === preferred)\n ? preferred\n : (list && list.activeConnectionId && nextSessions.some((s) => s.connectionId === list.activeConnectionId)\n ? list.activeConnectionId\n : ((nextSessions.find((s) => s.connected) || nextSessions[0] || {}).connectionId || ''))\n if (selected !== connectionId) setConnectionId(selected)\n if (!selected) {\n if (seq !== refreshSeq.current) return\n setConnected(false)\n setTarget('')\n setSteps([])\n return\n }\n const t = await callApi('status', { connectionId: selected })\n if (seq !== refreshSeq.current) return\n setConnected(!!(t && t.connected))\n setTarget((t && t.target) || '')\n setSteps((t && t.steps) || [])\n } catch (e) {}\n }\n\n useEffect(() => {\n injectCss()\n if (visible === false) { refreshSeq.current += 1; return }\n refresh(connectionId)\n const stop = ctx.interval(() => refresh(connectionId), 600)\n return () => {\n refreshSeq.current += 1\n try { stop() } catch (e) {}\n }\n }, [visible, connectionId])\n\n useEffect(() => {\n const el = logEl\n if (!el) return\n const nearBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 40\n if (nearBottom) el.scrollTop = el.scrollHeight\n }, [steps, logEl])\n\n async function connect() {\n setBusy(true); setErr('')\n try {\n const r = await callApi('connect', { host: hostV, user: userV, port: Number(portV) || 22, password: passV || undefined })\n if (r && r.error) setErr(String(r.error))\n await refresh(r && r.connectionId)\n }\n catch (e) { setErr(String((e && e.message) || e)) } finally { setBusy(false) }\n }\n async function run() {\n setBusy(true); setErr('')\n try {\n const r = await callApi('exec', { connectionId, command: cmdV, waitMs: 15000 })\n if (r && r.error) setErr(String(r.error))\n await refresh(connectionId)\n }\n catch (e) { setErr(String((e && e.message) || e)) } finally { setBusy(false) }\n }\n async function disconnect() {\n setBusy(true); setErr('')\n try { await callApi('disconnect', { connectionId }); await refresh(connectionId) }\n catch (e) { setErr(String((e && e.message) || e)) } finally { setBusy(false) }\n }\n async function clearHistory() {\n try {\n if (window.confirm('确定清空当前连接的 SSH 操作记录吗?')) {\n await callApi('clear', connectionId ? { connectionId } : undefined)\n await refresh(connectionId)\n }\n } catch (e) { setErr(String((e && e.message) || e)) }\n }\n\n async function togglePinned(id) {\n setContextMenu(null)\n try {\n const r = await callApi('pin', { connectionId: id })\n if (r && r.error) setErr(String(r.error))\n await refresh(id)\n } catch (e) { setErr(String((e && e.message) || e)) }\n }\n\n async function deleteRecord(id) {\n const session = sessions.find((s) => s.connectionId === id)\n setContextMenu(null)\n if (!session || !window.confirm('删除该连接记录吗?在线连接不会断开。')) return\n try {\n const r = await callApi('delete', { connectionId: id })\n if (r && r.error) setErr(String(r.error))\n await refresh(id)\n } catch (e) { setErr(String((e && e.message) || e)) }\n }\n\n const onKey = (e) => { if (e.key === 'Enter' && canRun && !busy) run() }\n const status = connected ? ('● ' + target) : (selectedSession ? (selectedSession.exited ? '○ 已退出' : '○ 未连接') : '○ 未选择连接')\n\n return createElement('div', { className: 'dshssh-body', onClick: () => setContextMenu(null) },\n createElement('div', { className: 'dshssh-head' },\n createElement('span', { className: 'dshssh-title' }, 'SSH 远程终端'),\n createElement('span', { className: 'dshssh-status ' + (connected ? 'ok' : 'off') }, status),\n createElement('button', { className: 'dshssh-btn dshssh-clear', onClick: clearHistory }, '清空当前'),\n ),\n createElement('div', { className: 'dshssh-layout' },\n createElement('div', { className: 'dshssh-sessions' },\n createElement('div', { className: 'dshssh-session-title' }, '连接列表 (' + sessions.length + ')'),\n createElement('div', { className: 'dshssh-session-list' },\n sessions.length\n ? sessions.map((s) => createElement('button', {\n key: s.connectionId,\n className: 'dshssh-session' + (s.connectionId === connectionId ? ' selected' : ''),\n onClick: () => { setConnectionId(s.connectionId); setErr('') },\n onContextMenu: (e) => {\n e.preventDefault()\n e.stopPropagation()\n const body = e.currentTarget.closest('.dshssh-body')\n const rect = body ? body.getBoundingClientRect() : { left: 0, top: 0, width: window.innerWidth, height: window.innerHeight }\n const x = Math.max(4, Math.min(e.clientX - rect.left, rect.width - 160))\n const y = Math.max(4, Math.min(e.clientY - rect.top, rect.height - 80))\n setContextMenu({ connectionId: s.connectionId, x, y })\n },\n },\n createElement('span', { className: 'dshssh-session-dot' + (s.connected ? ' ok' : '') }),\n createElement('span', { className: 'dshssh-session-copy' },\n createElement('span', { className: 'dshssh-session-name' },\n s.pinned ? createElement('span', { className: 'dshssh-pin', title: '已置顶' }, '★') : null,\n s.label || s.target || 'SSH 连接',\n ),\n createElement('span', { className: 'dshssh-session-meta' }, s.connected ? (s.busy ? '执行中' : '已连接') : (s.historical ? '历史记录' : '已断开')),\n )))\n : createElement('div', { className: 'dshssh-empty' }, '暂无连接'),\n ),\n ),\n createElement('div', { className: 'dshssh-main' },\n createElement('div', { className: 'dshssh-form' },\n createElement('input', { className: 'dshssh-input', placeholder: '主机', value: hostV, onChange: (e) => setHostV(e.target.value) }),\n createElement('input', { className: 'dshssh-input', placeholder: '用户', value: userV, onChange: (e) => setUserV(e.target.value) }),\n createElement('input', { className: 'dshssh-input', style: { width: 54 }, placeholder: '端口', value: portV, onChange: (e) => setPortV(e.target.value) }),\n createElement('input', { className: 'dshssh-input', style: { width: 96 }, type: 'password', placeholder: '密码(可选)', value: passV, onChange: (e) => setPassV(e.target.value) }),\n createElement('button', { className: 'dshssh-btn', disabled: busy, onClick: connect }, '新建连接'),\n ),\n createElement('div', { className: 'dshssh-form' },\n createElement('input', { className: 'dshssh-input dshssh-cmdline', style: { flex: 1 }, placeholder: '输入命令后回车或点执行', value: cmdV, onChange: (e) => setCmdV(e.target.value), onKeyDown: onKey }),\n createElement('button', { className: 'dshssh-btn', disabled: busy || !canRun, onClick: run }, '执行'),\n createElement('button', { className: 'dshssh-btn', disabled: busy || !canRun, onClick: disconnect }, '断开'),\n ),\n createElement('div', { className: 'dshssh-log', ref: (el) => setLogEl(el) },\n steps.length\n ? steps.map((s, i) => createElement('div', { key: i, className: 'dshssh-step dshssh-' + s.kind }, (fmt(s.ts) + ' ' + s.text)))\n : createElement('div', { className: 'dshssh-step dshssh-system' }, '还没有操作。'),\n ),\n err ? createElement('div', { className: 'dshssh-err' }, String(err)) : null,\n ),\n contextMenu && contextSession\n ? createElement('div', {\n className: 'dshssh-context-menu',\n style: { left: contextMenu.x, top: contextMenu.y },\n onClick: (e) => e.stopPropagation(),\n },\n createElement('button', { type: 'button', onClick: () => togglePinned(contextSession.connectionId) }, contextSession.pinned ? '取消置顶' : '置顶'),\n createElement('button', { type: 'button', className: 'danger', onClick: () => deleteRecord(contextSession.connectionId) }, '删除该连接记录'),\n )\n : null,\n ),\n )\n}\n\nexport const inject = ['timer', 'betterSidebar']\n\nexport function apply(ctx) {\n const bs = ctx.get('betterSidebar')\n if (!bs) return\n ctx.effect(() => bs.registerTab({\n id: 'ssh-remote:terminal',\n title: 'SSH 终端',\n order: 60,\n single: true,\n component: (p) => createElement(SshBody, { ctx, visible: p.visible }),\n }))\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-ssh-terminal",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "SSH 远程终端:在 dsh-better-sidebar 侧边栏里连接远程主机,逐步查看命令与输出。",
5
5
  "author": "sunzhyang1616-ui",
6
6
  "license": "MIT",