cicy-desktop 2.1.39 → 2.1.40

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.
@@ -4,7 +4,7 @@
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
6
  <title>CiCy Desktop</title>
7
- <script type="module" crossorigin src="./assets/index-CzuQdFw8.js"></script>
7
+ <script type="module" crossorigin src="./assets/index-BhLjpIIu.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="./assets/index-CNVsvsZX.css">
9
9
  </head>
10
10
  <body>
@@ -19,6 +19,11 @@ const https = require("https");
19
19
  const { execFile } = require("child_process");
20
20
  const { spawn } = require("child_process");
21
21
  const { BrowserWindow } = require("electron");
22
+ // i18n for the default team name ("Unnamed"/"未命名"/…). Resolved at create
23
+ // time from the app locale; falls back to "Unnamed" if i18n isn't ready.
24
+ let __t;
25
+ try { __t = require("../i18n").t; } catch { __t = null; }
26
+ const unnamedName = () => { try { return (__t && __t("localTeams.unnamed")) || "Unnamed"; } catch { return "Unnamed"; } };
22
27
  const log = require("electron-log");
23
28
 
24
29
  const GLOBAL_JSON = path.join(os.homedir(), "cicy-ai", "global.json");
@@ -264,7 +269,7 @@ async function addTeam(spec) {
264
269
 
265
270
  const now = new Date().toISOString();
266
271
  const patch = {
267
- name: spec.name !== undefined ? String(spec.name || id) : undefined,
272
+ name: spec.name !== undefined ? String(spec.name || unnamedName()) : undefined,
268
273
  base_url: baseUrl,
269
274
  api_token: spec.api_token !== undefined ? String(spec.api_token || "") : undefined,
270
275
  install_source: spec.install_source ?? undefined,
@@ -283,7 +288,7 @@ async function addTeam(spec) {
283
288
  gNext.cicyDesktopNodes[id] = {
284
289
  ...prev,
285
290
  ...patch,
286
- name: patch.name || prev.name || id,
291
+ name: patch.name || prev.name || unnamedName(),
287
292
  added_at: prev.added_at || now,
288
293
  updated_at: now,
289
294
  };
@@ -74,6 +74,11 @@
74
74
  "statusDown": "Down",
75
75
  "statusWarn": "Warning"
76
76
  },
77
+ "localTeams": {
78
+ "unnamed": "Unnamed",
79
+ "rename": "Rename",
80
+ "renameHint": "Double-click or click ✎ to rename"
81
+ },
77
82
  "cli": {
78
83
  "controllerTitle": "cicy - CiCy Desktop Controller",
79
84
  "usage": "Usage: cicy [command] [options]"
@@ -74,6 +74,11 @@
74
74
  "statusDown": "Down",
75
75
  "statusWarn": "Warning"
76
76
  },
77
+ "localTeams": {
78
+ "unnamed": "Sans nom",
79
+ "rename": "Renommer",
80
+ "renameHint": "Double-cliquez ou ✎ pour renommer"
81
+ },
77
82
  "cli": {
78
83
  "controllerTitle": "cicy - CiCy Desktop Controller",
79
84
  "usage": "Usage: cicy [command] [options]"
@@ -74,6 +74,11 @@
74
74
  "statusDown": "Down",
75
75
  "statusWarn": "Warning"
76
76
  },
77
+ "localTeams": {
78
+ "unnamed": "名称未設定",
79
+ "rename": "名前を変更",
80
+ "renameHint": "ダブルクリックまたは ✎ で名前を変更"
81
+ },
77
82
  "cli": {
78
83
  "controllerTitle": "cicy - CiCy Desktop Controller",
79
84
  "usage": "Usage: cicy [command] [options]"
@@ -74,6 +74,11 @@
74
74
  "statusDown": "离线",
75
75
  "statusWarn": "异常"
76
76
  },
77
+ "localTeams": {
78
+ "unnamed": "未命名",
79
+ "rename": "重命名",
80
+ "renameHint": "双击或点 ✎ 改名"
81
+ },
77
82
  "cli": {
78
83
  "controllerTitle": "cicy - CiCy Desktop 控制器",
79
84
  "usage": "用法: cicy [命令] [选项]"
@@ -1,6 +1,14 @@
1
1
  import { useEffect, useState, useCallback, useMemo, useRef } from "react";
2
2
  import "./App.css";
3
3
 
4
+ // i18n bridge exposed by homepage-preload (window.cicyI18n.t, locale from
5
+ // app.getLocale()). Returns the localized string, or `fallback` when the key
6
+ // is missing or we're running outside Electron.
7
+ const tr = (key, fallback) => {
8
+ try { const v = window.cicyI18n?.t?.(key); return v && v !== key ? v : fallback; }
9
+ catch { return fallback; }
10
+ };
11
+
4
12
  const TOKEN_KEY = "cicy_token";
5
13
  const ACCESS_TOKEN_KEY = "cicy_access_token";
6
14
  const USER_ID_KEY = "cicy_user_id";
@@ -213,6 +221,15 @@ export default function App() {
213
221
  setLocalTeamsFetched(true);
214
222
  }
215
223
  }, []);
224
+ // Rename a local team: persist via localTeams.update then refresh the list.
225
+ // Empty name falls back to 未命名 (mirrors local-teams.addTeam default).
226
+ const renameLocalTeam = useCallback(async (id, name) => {
227
+ if (!window.cicy?.localTeams?.update) return;
228
+ try {
229
+ await window.cicy.localTeams.update(id, { name: String(name || "").trim() || tr("localTeams.unnamed", "未命名") });
230
+ } catch {}
231
+ await fetchLocalTeams();
232
+ }, [fetchLocalTeams]);
216
233
  useEffect(() => {
217
234
  let fastTimer;
218
235
  let slowTimer;
@@ -482,7 +499,7 @@ export default function App() {
482
499
  />
483
500
 
484
501
  {showLocal && localTeams && localTeams.map((t) => (
485
- <LocalTeamCard key={"local:" + t.id} team={t} onOpen={() => openLocalTeam(t.id)} />
502
+ <LocalTeamCard key={"local:" + t.id} team={t} onOpen={() => openLocalTeam(t.id)} onRename={renameLocalTeam} />
486
503
  ))}
487
504
  {showCloud && teams && teams.map((t) => (
488
505
  <TeamCard
@@ -700,11 +717,21 @@ function Section({ title, subtitle, icon, children }) {
700
717
  );
701
718
  }
702
719
 
703
- function LocalTeamCard({ team, onOpen }) {
720
+ function LocalTeamCard({ team, onOpen, onRename }) {
704
721
  const statusInfo = LOCAL_STATUS[team.status] || LOCAL_STATUS.error;
705
722
  const tone = statusInfo.tone;
723
+ // Inline rename: double-click the name or click ✎ → edit → Enter/blur saves.
724
+ // All local teams are renamable via window.cicy.localTeams.update(id,{name}).
725
+ const [editing, setEditing] = useState(false);
726
+ const [draft, setDraft] = useState(team.name || "");
727
+ const startEdit = (e) => { e.stopPropagation(); setDraft(team.name || ""); setEditing(true); };
728
+ const commit = async () => {
729
+ setEditing(false);
730
+ const next = String(draft || "").trim();
731
+ if (onRename && next && next !== team.name) await onRename(team.id, next);
732
+ };
706
733
  return (
707
- <div className={`bcard bcard--local${tone === "ok" ? " bcard--online" : ""}`}>
734
+ <div data-id="LocalTeamCard" className={`bcard bcard--local${tone === "ok" ? " bcard--online" : ""}`}>
708
735
  <div className="bcard__accent" />
709
736
  <div className="bcard__top">
710
737
  <div className="bcard__pill">
@@ -713,7 +740,29 @@ function LocalTeamCard({ team, onOpen }) {
713
740
  </div>
714
741
  </div>
715
742
  <div className="bcard__body">
716
- <h3 className="bcard__name" title={team.name}>{team.name}</h3>
743
+ {editing ? (
744
+ <input
745
+ data-id="LocalTeamCard-rename-input"
746
+ autoFocus
747
+ value={draft}
748
+ onChange={(e) => setDraft(e.target.value)}
749
+ onBlur={commit}
750
+ onClick={(e) => e.stopPropagation()}
751
+ onKeyDown={(e) => { if (e.key === "Enter") commit(); else if (e.key === "Escape") setEditing(false); }}
752
+ style={{ width: "100%", font: "inherit", fontWeight: 600, padding: "2px 6px", border: "1px solid #3b82f6", borderRadius: 6, background: "#0d1117", color: "#e6edf3", boxSizing: "border-box" }}
753
+ />
754
+ ) : (
755
+ <h3 className="bcard__name" title={tr("localTeams.renameHint", "双击或点 ✎ 改名")} style={{ display: "flex", alignItems: "center", gap: 6 }} onDoubleClick={startEdit}>
756
+ <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{team.name}</span>
757
+ <button
758
+ type="button"
759
+ data-id="LocalTeamCard-rename-btn"
760
+ title={tr("localTeams.rename", "重命名")}
761
+ onClick={startEdit}
762
+ style={{ flex: "none", cursor: "pointer", border: "none", background: "transparent", color: "#8b949e", fontSize: 13, padding: 0, lineHeight: 1 }}
763
+ >✎</button>
764
+ </h3>
765
+ )}
717
766
  <div className="bcard__host">
718
767
  {team.base_url || "—"}
719
768
  </div>