@termix-ssh/plugin-sdk 1.0.5 → 1.0.7

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/dist/host/ui.js CHANGED
@@ -32,6 +32,7 @@ import {
32
32
  GroupHeading,
33
33
  InlineView,
34
34
  KeyRound,
35
+ LANGUAGES,
35
36
  List,
36
37
  LoaderCircle,
37
38
  Overlay2,
@@ -138,8 +139,8 @@ import {
138
139
  useSurfaceKind,
139
140
  useTheme,
140
141
  verifySecondFactor
141
- } from "./chunk-VETPF5WI.js";
142
- import "./chunk-KOOUKYW3.js";
142
+ } from "./chunk-LKN6OILD.js";
143
+ import "./chunk-DIOJ3KW2.js";
143
144
  import {
144
145
  TabProvider,
145
146
  buildOriginWsUrl,
@@ -178,7 +179,7 @@ import {
178
179
  useTabs,
179
180
  useTabsSafe,
180
181
  verifyPasswordResetCode
181
- } from "./chunk-OEOKIKXC.js";
182
+ } from "./chunk-NZG6HNQH.js";
182
183
  import "./chunk-YC2MAKSP.js";
183
184
 
184
185
  // src/ui/components/alert.tsx
@@ -1501,7 +1502,7 @@ function Switch2({
1501
1502
  {
1502
1503
  "data-slot": "switch",
1503
1504
  className: cn(
1504
- "peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-[background-color,border-color,box-shadow,opacity] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
1505
+ "peer relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center border-2 transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-accent-brand data-[state=checked]:border-accent-brand data-[state=unchecked]:bg-muted data-[state=unchecked]:border-border",
1505
1506
  className
1506
1507
  ),
1507
1508
  ...props,
@@ -1509,9 +1510,7 @@ function Switch2({
1509
1510
  SwitchThumb,
1510
1511
  {
1511
1512
  "data-slot": "switch-thumb",
1512
- className: cn(
1513
- "bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
1514
- )
1513
+ className: "pointer-events-none block h-3 w-3 bg-background shadow-sm transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0.5"
1515
1514
  }
1516
1515
  )
1517
1516
  }
@@ -2050,16 +2049,21 @@ function MiniStat({
2050
2049
 
2051
2050
  // src/ui/components/charts/LineChart.tsx
2052
2051
  import { useRef, useState as useState4, useEffect as useEffect2, useCallback } from "react";
2052
+
2053
+ // src/ui/lib/server-time.ts
2054
+ function parseServerTime(ts) {
2055
+ const bare = /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}(:\d{2}(\.\d+)?)?$/.test(ts);
2056
+ return new Date(bare ? `${ts.replace(" ", "T")}Z` : ts);
2057
+ }
2058
+
2059
+ // src/ui/components/charts/LineChart.tsx
2053
2060
  import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
2054
2061
  var Y_LABEL_W = 44;
2055
2062
  var X_LABEL_H = 20;
2056
2063
  var TOP_PAD = 6;
2057
2064
  var TICK_COUNT = 5;
2058
- function parseTs(ts) {
2059
- return new Date(ts.includes("T") ? ts : ts.replace(" ", "T") + "Z");
2060
- }
2061
2065
  function formatTimestamp(ts, rangeMs) {
2062
- const d = parseTs(ts);
2066
+ const d = parseServerTime(ts);
2063
2067
  if (rangeMs <= 25 * 60 * 60 * 1e3) {
2064
2068
  return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
2065
2069
  }
@@ -2114,7 +2118,7 @@ function LineChart({
2114
2118
  const chartW = Math.max(0, width - Y_LABEL_W);
2115
2119
  const drawH = height - TOP_PAD;
2116
2120
  const svgH = height + X_LABEL_H;
2117
- const rangeMs = timestamps.length >= 2 ? parseTs(timestamps[timestamps.length - 1]).getTime() - parseTs(timestamps[0]).getTime() : 0;
2121
+ const rangeMs = timestamps.length >= 2 ? parseServerTime(timestamps[timestamps.length - 1]).getTime() - parseServerTime(timestamps[0]).getTime() : 0;
2118
2122
  const yTicks = (() => {
2119
2123
  const [lo, hi] = domain;
2120
2124
  const step = (hi - lo) / (TICK_COUNT - 1);
@@ -2323,6 +2327,10 @@ function useIsMobile() {
2323
2327
  void 0
2324
2328
  );
2325
2329
  React5.useEffect(() => {
2330
+ if (isElectron()) {
2331
+ setIsMobile(false);
2332
+ return;
2333
+ }
2326
2334
  const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
2327
2335
  const onChange = () => {
2328
2336
  setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
@@ -3455,6 +3463,7 @@ function isInMobileWebView() {
3455
3463
  function isInElectronWebView() {
3456
3464
  if (isInMobileWebView()) return false;
3457
3465
  if (window.IS_ELECTRON_WEBVIEW) return true;
3466
+ if (!/Termix-Desktop\//.test(navigator.userAgent)) return false;
3458
3467
  try {
3459
3468
  if (window.self !== window.top) return true;
3460
3469
  } catch {
@@ -3477,7 +3486,13 @@ async function getEmbeddedServerFailure() {
3477
3486
  const status = await getStatus();
3478
3487
  const failure = status?.failure;
3479
3488
  if (!failure) return null;
3480
- return failure.reason === "port-in-use" ? { reason: "port-in-use", port: failure.port ?? null } : { reason: "crashed", port: null };
3489
+ if (failure.reason === "port-in-use") {
3490
+ return { reason: "port-in-use", port: failure.port ?? null };
3491
+ }
3492
+ if (failure.reason === "old-database") {
3493
+ return { reason: "old-database", port: null };
3494
+ }
3495
+ return { reason: "crashed", port: null };
3481
3496
  } catch {
3482
3497
  return null;
3483
3498
  }
@@ -4348,12 +4363,15 @@ async function loadNamespaces(summaries) {
4348
4363
  loadedNamespaceVersions.set(summary.id, namespaceVersion(summary));
4349
4364
  }
4350
4365
  }
4366
+ function serverServesAssets(summary) {
4367
+ return summary.enabled && (!summary.state || summary.state === "active");
4368
+ }
4351
4369
  function namespaceVersion(summary) {
4352
4370
  return `${summary.version}|${summary.assetVersion ?? ""}`;
4353
4371
  }
4354
4372
  async function reconcile(summaries) {
4355
4373
  setPluginSummaries(summaries);
4356
- await loadNamespaces(summaries);
4374
+ await loadNamespaces(summaries.filter(serverServesAssets));
4357
4375
  const { order, blocked } = orderForActivation(summaries);
4358
4376
  const wanted = new Map(order.map((summary) => [summary.id, summary]));
4359
4377
  for (const id of [...active.keys()].reverse()) {
@@ -4545,43 +4563,6 @@ function removeSilentSigninFromSearch(search) {
4545
4563
 
4546
4564
  // src/ui/auth/Auth.tsx
4547
4565
  import { Fragment as Fragment5, jsx as jsx40, jsxs as jsxs26 } from "react/jsx-runtime";
4548
- var LANGUAGES = [
4549
- { code: "en", label: "English" },
4550
- { code: "af", label: "Afrikaans" },
4551
- { code: "ar", label: "\u0627\u0644\u0639\u0631\u0628\u064A\u0629" },
4552
- { code: "bn", label: "\u09AC\u09BE\u0982\u09B2\u09BE" },
4553
- { code: "bg", label: "\u0411\u044A\u043B\u0433\u0430\u0440\u0441\u043A\u0438" },
4554
- { code: "ca", label: "Catal\xE0" },
4555
- { code: "zh-CN", label: "\u4E2D\u6587 (\u7B80\u4F53)" },
4556
- { code: "zh-TW", label: "\u4E2D\u6587 (\u7E41\u9AD4)" },
4557
- { code: "cs", label: "\u010Ce\u0161tina" },
4558
- { code: "da", label: "Dansk" },
4559
- { code: "nl", label: "Nederlands" },
4560
- { code: "fi", label: "Suomi" },
4561
- { code: "fr", label: "Fran\xE7ais" },
4562
- { code: "de", label: "Deutsch" },
4563
- { code: "el", label: "\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC" },
4564
- { code: "he", label: "\u05E2\u05D1\u05E8\u05D9\u05EA" },
4565
- { code: "hi", label: "\u0939\u093F\u0928\u094D\u0926\u0940" },
4566
- { code: "hu", label: "Magyar" },
4567
- { code: "id", label: "Indonesia" },
4568
- { code: "it", label: "Italiano" },
4569
- { code: "ja", label: "\u65E5\u672C\u8A9E" },
4570
- { code: "ko", label: "\uD55C\uAD6D\uC5B4" },
4571
- { code: "no", label: "Norsk" },
4572
- { code: "pl", label: "Polski" },
4573
- { code: "pt-PT", label: "Portugu\xEAs (PT)" },
4574
- { code: "pt-BR", label: "Portugu\xEAs (BR)" },
4575
- { code: "ro", label: "Rom\xE2n\u0103" },
4576
- { code: "ru", label: "\u0420\u0443\u0441\u0441\u043A\u0438\u0439" },
4577
- { code: "sr", label: "\u0421\u0440\u043F\u0441\u043A\u0438" },
4578
- { code: "es-ES", label: "Espa\xF1ol" },
4579
- { code: "sv-SE", label: "Svenska" },
4580
- { code: "th", label: "\u0E44\u0E17\u0E22" },
4581
- { code: "tr", label: "T\xFCrk\xE7e" },
4582
- { code: "uk", label: "\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430" },
4583
- { code: "vi", label: "Ti\u1EBFng Vi\u1EC7t" }
4584
- ];
4585
4566
  function LanguageRow({
4586
4567
  label,
4587
4568
  value,
@@ -4832,7 +4813,6 @@ function Auth({ onLogin }) {
4832
4813
  if (attemptNumber >= maxAttempts) {
4833
4814
  setDbConnectionFailed(true);
4834
4815
  setDbHealthChecking(false);
4835
- return;
4836
4816
  }
4837
4817
  const delay = Math.min(500 * 2 ** attemptNumber, 5e3);
4838
4818
  retryTimer = setTimeout(() => {
@@ -5347,7 +5327,7 @@ function Auth({ onLogin }) {
5347
5327
  if (embeddedServerFailure) {
5348
5328
  const detail = embeddedServerFailure.reason === "port-in-use" ? embeddedServerFailure.port !== null ? t2("messages.embeddedServerPortInUse", {
5349
5329
  port: embeddedServerFailure.port
5350
- }) : t2("messages.embeddedServerPortInUseUnknownPort") : t2("messages.embeddedServerCrashed");
5330
+ }) : t2("messages.embeddedServerPortInUseUnknownPort") : embeddedServerFailure.reason === "old-database" ? t2("messages.embeddedServerOldDatabase") : t2("messages.embeddedServerCrashed");
5351
5331
  return /* @__PURE__ */ jsx40("div", { className: "fixed inset-0 flex items-center justify-center bg-background p-6", children: /* @__PURE__ */ jsxs26("div", { className: "flex flex-col gap-5 p-6 border border-border bg-card max-w-sm w-full", children: [
5352
5332
  /* @__PURE__ */ jsxs26("div", { className: "flex flex-col gap-1", children: [
5353
5333
  /* @__PURE__ */ jsx40("p", { className: "font-bold text-destructive", children: t2("errors.embeddedServerFailed") }),
@@ -30174,8 +30154,396 @@ function PassphraseDialog({
30174
30154
  // src/ui/ssh/dialogs/HostKeyVerificationDialog.tsx
30175
30155
  import { useState as useState18 } from "react";
30176
30156
  import { useTranslation as useTranslation18 } from "react-i18next";
30157
+
30158
+ // node_modules/@noble/hashes/_u64.js
30159
+ var fromNumH = (n) => n / 2 ** 32 | 0;
30160
+ var fromNumL = (n) => n >>> 0;
30161
+ function setU64FromNum(view, byteOffset, n, isLE) {
30162
+ const h = fromNumH(n);
30163
+ const l = fromNumL(n);
30164
+ view.setUint32(byteOffset, isLE ? l : h, isLE);
30165
+ view.setUint32(byteOffset + 4, isLE ? h : l, isLE);
30166
+ }
30167
+
30168
+ // node_modules/@noble/hashes/utils.js
30169
+ function isBytes(a) {
30170
+ return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
30171
+ }
30172
+ var atitle = (title) => title ? `"${title}" ` : "";
30173
+ function anumber(n, title = "") {
30174
+ if (typeof n !== "number")
30175
+ throw new TypeError(atitle(title) + "expected number, got " + typeof n);
30176
+ if (!Number.isSafeInteger(n) || n < 0)
30177
+ throw new RangeError(atitle(title) + "expected integer >= 0, got " + n);
30178
+ return n;
30179
+ }
30180
+ function abytes(value, length, title = "") {
30181
+ if (isBytes(value) && (length === void 0 || value.length === length))
30182
+ return value;
30183
+ if (length !== void 0)
30184
+ anumber(length, "length");
30185
+ const bytes = isBytes(value);
30186
+ const ofLen = length !== void 0 ? ` of length ${length}` : "";
30187
+ const got = bytes ? `length=${value.length}` : `type=${typeof value}`;
30188
+ const message = atitle(title) + "expected Uint8Array" + ofLen + ", got " + got;
30189
+ if (!bytes)
30190
+ throw new TypeError(message);
30191
+ throw new RangeError(message);
30192
+ }
30193
+ var aobject = (value, label) => {
30194
+ if (value === null || typeof value !== "object" || Array.isArray(value))
30195
+ throw new TypeError((label === "object" ? "" : `"${label}" `) + "expected object, got type=" + typeof value);
30196
+ };
30197
+ var aopts = (value, label) => {
30198
+ aobject(value, label);
30199
+ const proto = Object.getPrototypeOf(value);
30200
+ if (proto !== Object.prototype && proto !== null)
30201
+ throw new TypeError(`"${label}" expected plain object`);
30202
+ if (Object.hasOwn(value, "__proto__"))
30203
+ throw new TypeError(`"${label}.__proto__" is not allowed`);
30204
+ };
30205
+ function aexists(instance, checkFinished = true) {
30206
+ if (instance.destroyed)
30207
+ throw new Error("hash was destroyed");
30208
+ if (checkFinished && instance.finished)
30209
+ throw new Error("digest() was already called");
30210
+ }
30211
+ function aoutput(out, instance) {
30212
+ abytes(out, void 0, "output");
30213
+ const min = instance.outputLen;
30214
+ if (!(out.length >= min)) {
30215
+ throw new RangeError('"output" expected length >= ' + min);
30216
+ }
30217
+ }
30218
+ function clean(...arrays) {
30219
+ for (let i2 = 0; i2 < arrays.length; i2++) {
30220
+ arrays[i2].fill(0);
30221
+ }
30222
+ }
30223
+ function createView(arr) {
30224
+ return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
30225
+ }
30226
+ function rotr(word, shift2) {
30227
+ return word << 32 - shift2 | word >>> shift2;
30228
+ }
30229
+ function checkOpts(defaults3, opts, title = "opts") {
30230
+ aopts(defaults3, "defaults");
30231
+ if (opts !== void 0)
30232
+ aopts(opts, title);
30233
+ const merged = Object.assign(/* @__PURE__ */ Object.create(null), defaults3, opts);
30234
+ return merged;
30235
+ }
30236
+ function createHasher(hashCons, info = {}) {
30237
+ if (typeof hashCons !== "function")
30238
+ throw new TypeError('"hashCons" expected function, got type=' + typeof hashCons);
30239
+ info = checkOpts({}, info, "info");
30240
+ const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
30241
+ const tmp = hashCons(void 0);
30242
+ hashC.outputLen = tmp.outputLen;
30243
+ hashC.blockLen = tmp.blockLen;
30244
+ hashC.canXOF = tmp.canXOF;
30245
+ hashC.create = (opts) => hashCons(opts);
30246
+ Object.assign(hashC, info);
30247
+ return Object.freeze(hashC);
30248
+ }
30249
+ var oidNist = (suffix) => ({
30250
+ // Current NIST hashAlgs suffixes used here fit in one DER subidentifier octet.
30251
+ // Larger suffix values would need base-128 OID encoding and a different length byte.
30252
+ oid: Uint8Array.from([6, 9, 96, 134, 72, 1, 101, 3, 4, 2, suffix])
30253
+ });
30254
+
30255
+ // node_modules/@noble/hashes/_md.js
30256
+ function Chi(a, b, c) {
30257
+ return a & b ^ ~a & c;
30258
+ }
30259
+ function Maj(a, b, c) {
30260
+ return a & b ^ a & c ^ b & c;
30261
+ }
30262
+ var HashMD = class {
30263
+ blockLen;
30264
+ outputLen;
30265
+ canXOF = false;
30266
+ padOffset;
30267
+ isLE;
30268
+ // For partial updates less than block size
30269
+ buffer;
30270
+ view;
30271
+ finished = false;
30272
+ length = 0;
30273
+ pos = 0;
30274
+ destroyed = false;
30275
+ constructor(blockLen, outputLen, padOffset, isLE) {
30276
+ this.blockLen = blockLen;
30277
+ this.outputLen = outputLen;
30278
+ this.padOffset = padOffset;
30279
+ this.isLE = isLE;
30280
+ this.buffer = new Uint8Array(blockLen);
30281
+ this.view = createView(this.buffer);
30282
+ }
30283
+ update(data) {
30284
+ aexists(this);
30285
+ abytes(data);
30286
+ const { view, buffer, blockLen } = this;
30287
+ const len = data.length;
30288
+ let processed = false;
30289
+ for (let pos = 0; pos < len; ) {
30290
+ const take = Math.min(blockLen - this.pos, len - pos);
30291
+ if (take === blockLen) {
30292
+ const dataView = createView(data);
30293
+ for (; blockLen <= len - pos; pos += blockLen)
30294
+ this.process(dataView, pos);
30295
+ processed = true;
30296
+ continue;
30297
+ }
30298
+ buffer.set(pos === 0 && take === len ? data : data.subarray(pos, pos + take), this.pos);
30299
+ this.pos += take;
30300
+ pos += take;
30301
+ if (this.pos === blockLen) {
30302
+ this.process(view, 0);
30303
+ this.pos = 0;
30304
+ processed = true;
30305
+ }
30306
+ }
30307
+ this.length += data.length;
30308
+ if (processed)
30309
+ this.roundClean();
30310
+ return this;
30311
+ }
30312
+ digestInto(out) {
30313
+ aexists(this);
30314
+ aoutput(out, this);
30315
+ this.finished = true;
30316
+ const { buffer, view, blockLen, isLE } = this;
30317
+ let { pos } = this;
30318
+ buffer[pos++] = 128;
30319
+ buffer.fill(0, pos);
30320
+ if (this.padOffset > blockLen - pos) {
30321
+ this.process(view, 0);
30322
+ buffer.fill(0);
30323
+ }
30324
+ setU64FromNum(view, blockLen - 8, this.length * 8, isLE);
30325
+ this.process(view, 0);
30326
+ this.roundClean();
30327
+ const oview = out === buffer ? view : createView(out);
30328
+ const len = this.outputLen;
30329
+ const outLen = len / 4;
30330
+ const state = this.get();
30331
+ if (len % 4 || outLen > state.length)
30332
+ throw new Error("invalid outputLen");
30333
+ for (let i2 = 0; i2 < outLen; i2++)
30334
+ oview.setUint32(4 * i2, state[i2], isLE);
30335
+ }
30336
+ digest() {
30337
+ const { buffer, outputLen } = this;
30338
+ this.digestInto(buffer);
30339
+ const res = buffer.slice(0, outputLen);
30340
+ this.destroy();
30341
+ return res;
30342
+ }
30343
+ _cloneIntoMeta(to) {
30344
+ const { buffer, length, finished, destroyed, pos } = this;
30345
+ to.destroyed = destroyed;
30346
+ to.finished = finished;
30347
+ to.length = length;
30348
+ to.pos = pos;
30349
+ if (pos)
30350
+ to.buffer.set(buffer);
30351
+ return to;
30352
+ }
30353
+ clone() {
30354
+ return this._cloneInto();
30355
+ }
30356
+ };
30357
+ var SHA256_IV = /* @__PURE__ */ Uint32Array.from([
30358
+ 1779033703,
30359
+ 3144134277,
30360
+ 1013904242,
30361
+ 2773480762,
30362
+ 1359893119,
30363
+ 2600822924,
30364
+ 528734635,
30365
+ 1541459225
30366
+ ]);
30367
+
30368
+ // node_modules/@noble/hashes/sha2.js
30369
+ var SHA256_K = /* @__PURE__ */ Uint32Array.from([
30370
+ 1116352408,
30371
+ 1899447441,
30372
+ 3049323471,
30373
+ 3921009573,
30374
+ 961987163,
30375
+ 1508970993,
30376
+ 2453635748,
30377
+ 2870763221,
30378
+ 3624381080,
30379
+ 310598401,
30380
+ 607225278,
30381
+ 1426881987,
30382
+ 1925078388,
30383
+ 2162078206,
30384
+ 2614888103,
30385
+ 3248222580,
30386
+ 3835390401,
30387
+ 4022224774,
30388
+ 264347078,
30389
+ 604807628,
30390
+ 770255983,
30391
+ 1249150122,
30392
+ 1555081692,
30393
+ 1996064986,
30394
+ 2554220882,
30395
+ 2821834349,
30396
+ 2952996808,
30397
+ 3210313671,
30398
+ 3336571891,
30399
+ 3584528711,
30400
+ 113926993,
30401
+ 338241895,
30402
+ 666307205,
30403
+ 773529912,
30404
+ 1294757372,
30405
+ 1396182291,
30406
+ 1695183700,
30407
+ 1986661051,
30408
+ 2177026350,
30409
+ 2456956037,
30410
+ 2730485921,
30411
+ 2820302411,
30412
+ 3259730800,
30413
+ 3345764771,
30414
+ 3516065817,
30415
+ 3600352804,
30416
+ 4094571909,
30417
+ 275423344,
30418
+ 430227734,
30419
+ 506948616,
30420
+ 659060556,
30421
+ 883997877,
30422
+ 958139571,
30423
+ 1322822218,
30424
+ 1537002063,
30425
+ 1747873779,
30426
+ 1955562222,
30427
+ 2024104815,
30428
+ 2227730452,
30429
+ 2361852424,
30430
+ 2428436474,
30431
+ 2756734187,
30432
+ 3204031479,
30433
+ 3329325298
30434
+ ]);
30435
+ var SHA256_W = /* @__PURE__ */ new Uint32Array(64);
30436
+ var SHA2_32B = class extends HashMD {
30437
+ // We cannot use array here since array allows indexing by variable
30438
+ // which means optimizer/compiler cannot use registers.
30439
+ // Numeric initializers matter: starting the fields as `undefined` changes
30440
+ // V8's field representation and makes sha256 3x slower (measured).
30441
+ A = 0;
30442
+ B = 0;
30443
+ C = 0;
30444
+ D = 0;
30445
+ E = 0;
30446
+ F = 0;
30447
+ G = 0;
30448
+ H = 0;
30449
+ constructor(outputLen, IV) {
30450
+ super(64, outputLen, 8, false);
30451
+ this.A = IV[0] | 0;
30452
+ this.B = IV[1] | 0;
30453
+ this.C = IV[2] | 0;
30454
+ this.D = IV[3] | 0;
30455
+ this.E = IV[4] | 0;
30456
+ this.F = IV[5] | 0;
30457
+ this.G = IV[6] | 0;
30458
+ this.H = IV[7] | 0;
30459
+ }
30460
+ get() {
30461
+ const { A, B, C: C2, D, E, F, G, H } = this;
30462
+ return [A, B, C2, D, E, F, G, H];
30463
+ }
30464
+ // prettier-ignore
30465
+ set(A, B, C2, D, E, F, G, H) {
30466
+ this.A = A | 0;
30467
+ this.B = B | 0;
30468
+ this.C = C2 | 0;
30469
+ this.D = D | 0;
30470
+ this.E = E | 0;
30471
+ this.F = F | 0;
30472
+ this.G = G | 0;
30473
+ this.H = H | 0;
30474
+ }
30475
+ _cloneInto(to) {
30476
+ (to ||= new this.constructor()).set(...this.get());
30477
+ return this._cloneIntoMeta(to);
30478
+ }
30479
+ process(view, offset) {
30480
+ for (let i2 = 0; i2 < 16; i2++, offset += 4)
30481
+ SHA256_W[i2] = view.getUint32(offset, false);
30482
+ for (let i2 = 16; i2 < 64; i2++) {
30483
+ const W15 = SHA256_W[i2 - 15];
30484
+ const W2 = SHA256_W[i2 - 2];
30485
+ const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
30486
+ const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
30487
+ SHA256_W[i2] = s1 + SHA256_W[i2 - 7] + s0 + SHA256_W[i2 - 16] | 0;
30488
+ }
30489
+ let { A, B, C: C2, D, E, F, G, H } = this;
30490
+ for (let i2 = 0; i2 < 64; i2++) {
30491
+ const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
30492
+ const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i2] + SHA256_W[i2] | 0;
30493
+ const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
30494
+ const T2 = sigma0 + Maj(A, B, C2) | 0;
30495
+ H = G;
30496
+ G = F;
30497
+ F = E;
30498
+ E = D + T1 | 0;
30499
+ D = C2;
30500
+ C2 = B;
30501
+ B = A;
30502
+ A = T1 + T2 | 0;
30503
+ }
30504
+ A = A + this.A | 0;
30505
+ B = B + this.B | 0;
30506
+ C2 = C2 + this.C | 0;
30507
+ D = D + this.D | 0;
30508
+ E = E + this.E | 0;
30509
+ F = F + this.F | 0;
30510
+ G = G + this.G | 0;
30511
+ H = H + this.H | 0;
30512
+ this.set(A, B, C2, D, E, F, G, H);
30513
+ }
30514
+ roundClean() {
30515
+ clean(SHA256_W);
30516
+ }
30517
+ destroy() {
30518
+ this.destroyed = true;
30519
+ this.set(0, 0, 0, 0, 0, 0, 0, 0);
30520
+ clean(this.buffer);
30521
+ }
30522
+ };
30523
+ var _SHA256 = class extends SHA2_32B {
30524
+ constructor() {
30525
+ super(32, SHA256_IV);
30526
+ }
30527
+ };
30528
+ var sha256 = /* @__PURE__ */ createHasher(
30529
+ () => new _SHA256(),
30530
+ /* @__PURE__ */ oidNist(1)
30531
+ );
30532
+
30533
+ // src/ui/lib/host-key-fingerprint.ts
30534
+ function hostKeyFingerprint(hex) {
30535
+ if (!hex || hex.length % 2 !== 0 || !/^[0-9a-f]+$/i.test(hex)) return hex;
30536
+ const bytes = new Uint8Array(hex.length / 2);
30537
+ for (let i2 = 0; i2 < bytes.length; i2++) {
30538
+ bytes[i2] = parseInt(hex.slice(i2 * 2, i2 * 2 + 2), 16);
30539
+ }
30540
+ let binary = "";
30541
+ for (const byte of sha256(bytes)) binary += String.fromCharCode(byte);
30542
+ return `SHA256:${btoa(binary).replace(/=+$/, "")}`;
30543
+ }
30544
+
30545
+ // src/ui/ssh/dialogs/HostKeyVerificationDialog.tsx
30177
30546
  import { Fragment as Fragment7, jsx as jsx51, jsxs as jsxs35 } from "react/jsx-runtime";
30178
- var formatFingerprint = (fp) => fp.match(/.{1,2}/g)?.join(":") || fp;
30179
30547
  function FingerprintRow({
30180
30548
  label,
30181
30549
  value,
@@ -30185,8 +30553,8 @@ function FingerprintRow({
30185
30553
  const { t: t2 } = useTranslation18();
30186
30554
  return /* @__PURE__ */ jsxs35("div", { className: "flex flex-col gap-1.5", children: [
30187
30555
  /* @__PURE__ */ jsx51("p", { className: "text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: label }),
30188
- /* @__PURE__ */ jsxs35("div", { className: "flex items-center gap-2", children: [
30189
- /* @__PURE__ */ jsx51("div", { className: "flex-1 bg-muted/50 border border-border p-3 font-mono text-xs break-all", children: formatFingerprint(value) }),
30556
+ /* @__PURE__ */ jsxs35("div", { className: "flex items-stretch gap-2", children: [
30557
+ /* @__PURE__ */ jsx51("div", { className: "flex-1 bg-muted/50 border border-border p-3 font-mono text-xs break-all", children: value }),
30190
30558
  /* @__PURE__ */ jsx51(
30191
30559
  "button",
30192
30560
  {
@@ -30194,7 +30562,7 @@ function FingerprintRow({
30194
30562
  onClick: onCopy,
30195
30563
  title: t2("common.copy"),
30196
30564
  "aria-label": t2("common.copy"),
30197
- className: `${PROMPT_BUTTON} size-8 shrink-0 px-0`,
30565
+ className: "flex w-11 shrink-0 items-center justify-center border border-border text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring",
30198
30566
  children: copied ? /* @__PURE__ */ jsx51(Check, { className: "size-4 text-accent-brand" }) : /* @__PURE__ */ jsx51(Copy, { className: "size-4" })
30199
30567
  }
30200
30568
  )
@@ -30209,7 +30577,6 @@ function HostKeyVerificationDialog({
30209
30577
  hostname,
30210
30578
  fingerprint,
30211
30579
  oldFingerprint,
30212
- algorithm,
30213
30580
  onAccept,
30214
30581
  onReject,
30215
30582
  backgroundColor
@@ -30229,6 +30596,8 @@ function HostKeyVerificationDialog({
30229
30596
  }
30230
30597
  };
30231
30598
  const changed = scenario === "changed";
30599
+ const newPrint = hostKeyFingerprint(fingerprint);
30600
+ const oldPrint = hostKeyFingerprint(oldFingerprint || "");
30232
30601
  return /* @__PURE__ */ jsx51(
30233
30602
  PanePrompt,
30234
30603
  {
@@ -30268,18 +30637,18 @@ function HostKeyVerificationDialog({
30268
30637
  FingerprintRow,
30269
30638
  {
30270
30639
  label: t2("hostKey.previousKey"),
30271
- value: oldFingerprint || "",
30640
+ value: oldPrint,
30272
30641
  copied: copiedOldFingerprint,
30273
- onCopy: () => copyFingerprint(oldFingerprint || "", true)
30642
+ onCopy: () => copyFingerprint(oldPrint, true)
30274
30643
  }
30275
30644
  ),
30276
30645
  /* @__PURE__ */ jsx51(
30277
30646
  FingerprintRow,
30278
30647
  {
30279
30648
  label: t2("hostKey.newFingerprint"),
30280
- value: fingerprint,
30649
+ value: newPrint,
30281
30650
  copied: copiedFingerprint,
30282
- onCopy: () => copyFingerprint(fingerprint)
30651
+ onCopy: () => copyFingerprint(newPrint)
30283
30652
  }
30284
30653
  )
30285
30654
  ] }) : /* @__PURE__ */ jsxs35(Fragment7, { children: [
@@ -30293,10 +30662,10 @@ function HostKeyVerificationDialog({
30293
30662
  /* @__PURE__ */ jsx51(
30294
30663
  FingerprintRow,
30295
30664
  {
30296
- label: `${t2("hostKey.fingerprint")} (${algorithm.toUpperCase()})`,
30297
- value: fingerprint,
30665
+ label: t2("hostKey.fingerprint"),
30666
+ value: newPrint,
30298
30667
  copied: copiedFingerprint,
30299
- onCopy: () => copyFingerprint(fingerprint)
30668
+ onCopy: () => copyFingerprint(newPrint)
30300
30669
  }
30301
30670
  ),
30302
30671
  /* @__PURE__ */ jsx51("p", { className: "text-[10px] text-muted-foreground", children: t2("hostKey.verifyInstructions") })
@@ -31147,7 +31516,7 @@ function gridClass(columns) {
31147
31516
  columns.xl && XL_COLS[columns.xl]
31148
31517
  );
31149
31518
  }
31150
- function DataView({
31519
+ function DataView2({
31151
31520
  items,
31152
31521
  view,
31153
31522
  density,
@@ -31906,7 +32275,7 @@ export {
31906
32275
  ConnectionLogPanel,
31907
32276
  ConnectionLogProvider,
31908
32277
  ConnectionScreen,
31909
- DataView,
32278
+ DataView2 as DataView,
31910
32279
  Dialog,
31911
32280
  DialogClose,
31912
32281
  DialogContent,
@@ -7,7 +7,7 @@ import {
7
7
  resetPermissionsCache,
8
8
  setPermissionsForTesting,
9
9
  usePermissions
10
- } from "./chunk-KOOUKYW3.js";
10
+ } from "./chunk-DIOJ3KW2.js";
11
11
  import "./chunk-YC2MAKSP.js";
12
12
  export {
13
13
  hasPermission,