cicy-desktop 2.1.280 → 2.1.285

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.
@@ -25,6 +25,8 @@ const tr = (key, fallback, params) => {
25
25
  const TOKEN_KEY = "cicy_token";
26
26
  const ACCESS_TOKEN_KEY = "cicy_access_token";
27
27
  const USER_ID_KEY = "cicy_user_id";
28
+ // 未登录直接进入(离线/访客):只用本地能力(自定义团队、本地 Docker 团队),云端功能等登录。
29
+ const GUEST_KEY = "cicy_guest";
28
30
  const CLOUD_BASE = "https://cicy-ai.com";
29
31
 
30
32
  // cicy-ai 云端页面(我的钱包/团队帐单/新加团队)统一开在 **profile 1** 的
@@ -343,6 +345,10 @@ export default function App() {
343
345
  // True while we ask main for a durably-saved login (origin-independent).
344
346
  // Prevents the login card from flashing on every launch before restore.
345
347
  const [authRestoring, setAuthRestoring] = useState(() => !safeGet(TOKEN_KEY));
348
+ // 访客模式:跳过登录进入主界面(本地功能可用)。登录成功即退出访客态。
349
+ const [guest, setGuest] = useState(() => safeGet(GUEST_KEY) === "1");
350
+ const enterGuest = () => { try { localStorage.setItem(GUEST_KEY, "1"); } catch {} setGuest(true); };
351
+ const leaveGuest = () => { try { localStorage.removeItem(GUEST_KEY); } catch {} setGuest(false); };
346
352
  const [loggingIn, setLoggingIn] = useState(false);
347
353
  const [loginBusy, setLoginBusy] = useState(false); // login 请求在途:按钮 disable+loading,防重复点击,出错恢复
348
354
  const [loginUrl, setLoginUrl] = useState(""); // shown as a manual fallback when the browser doesn't auto-open
@@ -718,6 +724,8 @@ export default function App() {
718
724
  setProfileError("");
719
725
  try { localStorage.setItem(TOKEN_KEY, payload.token); } catch {}
720
726
  setToken(payload.token);
727
+ try { localStorage.removeItem(GUEST_KEY); } catch {}
728
+ setGuest(false);
721
729
  if (payload.accessToken) {
722
730
  try { localStorage.setItem(ACCESS_TOKEN_KEY, payload.accessToken); } catch {}
723
731
  setAccessToken(payload.accessToken);
@@ -826,8 +834,9 @@ export default function App() {
826
834
  );
827
835
  }
828
836
 
829
- // Not logged in yet → centered login card.
830
- if (!token) {
837
+ // Not logged in yet → centered login card (unless the user chose to continue
838
+ // as a guest: local-only features, login available from the header).
839
+ if (!token && !guest) {
831
840
  return (
832
841
  <div className="shell">
833
842
  <div className="glow" aria-hidden />
@@ -866,6 +875,12 @@ export default function App() {
866
875
  <button className="btn-ghost" data-id="BrowserLoginBtn" onClick={handleLogin} disabled={loginBusy}>
867
876
  {loginBusy ? tr("auth.opening", "打开中…") : tr("auth.browserLogin", "用浏览器登录(Google / SSO,仅同一台电脑)")}
868
877
  </button>
878
+ {/* 不登录也能用本地能力:自定义团队(连已有 cicy-code 地址)、本地 Docker 团队。 */}
879
+ <button type="button" className="btn-ghost" data-id="SkipLoginBtn" onClick={enterGuest} disabled={loginBusy}
880
+ style={{ marginTop: 8, opacity: .85 }}>
881
+ {tr("auth.skipLogin", "先不登录,添加自定义团队")}
882
+ </button>
883
+ <p className="hint" data-id="SkipLoginHint">{tr("auth.skipLoginHint", "不登录只能使用本地功能;云端团队、账单等需登录后使用")}</p>
869
884
  </>
870
885
  )}
871
886
  {emailSent && (
@@ -965,6 +980,7 @@ export default function App() {
965
980
  <div className="glow glow--app" aria-hidden />
966
981
  <div className="shell__left">
967
982
  <Header me={me} welcome={welcome} onLogout={handleLogout}
983
+ guest={!token && guest} onLogin={leaveGuest}
968
984
  mitmTeam={localList.length > 0 ? localList[0] : null} />
969
985
  <UpdateBanner />
970
986
  <main className="main">
@@ -1008,10 +1024,10 @@ export default function App() {
1008
1024
  <div style={{ fontSize: 13, fontWeight: 600 }}>{tr("teams.addCustom", "自定义团队")}</div>
1009
1025
  <div style={{ fontSize: 11, opacity: .6, marginTop: 2 }}>{tr("teams.addCustomSub", "手动输入地址和名称(只存本地)")}</div>
1010
1026
  </button>
1011
- <button type="button" data-id="AddTeamMenu-private" className="bcard__menu-item" style={{ display: "block", width: "100%", textAlign: "left", padding: "11px 14px", border: "none", borderTop: "1px solid var(--border, #2c2f36)", background: "transparent", cursor: "pointer", color: "inherit" }}
1012
- onClick={() => { setAddMenuOpen(false); openCloudPage("?tab=private"); }}>
1027
+ <button type="button" data-id="AddTeamMenu-private" className="bcard__menu-item" style={{ display: "block", width: "100%", textAlign: "left", padding: "11px 14px", border: "none", borderTop: "1px solid var(--border, #2c2f36)", background: "transparent", cursor: "pointer", color: "inherit", opacity: (!token && guest) ? .55 : 1 }}
1028
+ onClick={() => { setAddMenuOpen(false); if (!token && guest) { leaveGuest(); return; } openCloudPage("?tab=private"); }}>
1013
1029
  <div style={{ fontSize: 13, fontWeight: 600 }}>{tr("teams.addPrivate", "私有云团队")}</div>
1014
- <div style={{ fontSize: 11, opacity: .6, marginTop: 2 }}>{tr("teams.addPrivateSub", "去云端团队中心添加")}</div>
1030
+ <div style={{ fontSize: 11, opacity: .6, marginTop: 2 }}>{(!token && guest) ? tr("teams.addPrivateNeedLogin", "需要登录") : tr("teams.addPrivateSub", "去云端团队中心添加")}</div>
1015
1031
  </button>
1016
1032
  </div>
1017
1033
  </>
@@ -1373,7 +1389,7 @@ function AuditLogModal({ onClose }) {
1373
1389
  );
1374
1390
  }
1375
1391
 
1376
- function Header({ me, welcome, onLogout, mitmTeam }) {
1392
+ function Header({ me, welcome, onLogout, mitmTeam, guest = false, onLogin }) {
1377
1393
  const name = me?.display_name || me?.username || "…";
1378
1394
  const initials = (name || "?").slice(0, 1).toUpperCase();
1379
1395
  const [open, setOpen] = useState(false);
@@ -1470,7 +1486,13 @@ function Header({ me, welcome, onLogout, mitmTeam }) {
1470
1486
  {planTxt}
1471
1487
  </span>
1472
1488
  )}
1473
- {!me ? (
1489
+ {guest ? (
1490
+ // 访客:没有账号可显示,给一个明显的「登录」入口(回到登录卡)
1491
+ <button type="button" data-id="UserChip-login" className="btn-primary" onClick={onLogin}
1492
+ style={{ padding: "6px 14px", fontSize: 13 }}>
1493
+ {tr("auth.loginNow", "登录")}
1494
+ </button>
1495
+ ) : !me ? (
1474
1496
  // 首次打开:profile 还没拉到 → avatar/名字用 skeleton 占位
1475
1497
  <div className="user-chip__trigger user-chip__trigger--skel" data-id="UserChip-skeleton" aria-hidden>
1476
1498
  <div className="skel skel--avatar" />