Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/decodex-app/Sources/DecodexApp/AccountPanelView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,7 @@ private enum AccountPrivacy {

private enum AccountDisplay {
static let randomNames = [
"Alex",
"Avery",
"Bailey",
"Blake",
Expand Down
10 changes: 5 additions & 5 deletions apps/decodex/src/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ use crate::{
};

const ACCOUNT_RANDOM_NAMES: &[&str] = &[
"Avery", "Bailey", "Blake", "Casey", "Charlie", "Clara", "Dana", "Drew", "Eden", "Elliot",
"Emery", "Evan", "Finley", "Harper", "Hayden", "Iris", "Jamie", "Jordan", "Kai", "Kendall",
"Lane", "Liam", "Logan", "Mason", "Maya", "Mia", "Morgan", "Noah", "Nora", "Owen", "Paige",
"Parker", "Quinn", "Reese", "Remy", "Riley", "Rowan", "Sage", "Sasha", "Sidney", "Taylor",
"Theo", "Val",
"Alex", "Avery", "Bailey", "Blake", "Casey", "Charlie", "Clara", "Dana", "Drew", "Eden",
"Elliot", "Emery", "Evan", "Finley", "Harper", "Hayden", "Iris", "Jamie", "Jordan", "Kai",
"Kendall", "Lane", "Liam", "Logan", "Mason", "Maya", "Mia", "Morgan", "Noah", "Nora", "Owen",
"Paige", "Parker", "Quinn", "Reese", "Remy", "Riley", "Rowan", "Sage", "Sasha", "Sidney",
"Taylor", "Theo", "Val",
];

pub(crate) struct AccountLoginRequest {
Expand Down
87 changes: 12 additions & 75 deletions apps/decodex/src/orchestrator/operator_dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -3410,7 +3410,6 @@ <h2 id="recent-title">Run History</h2>
const FOLD_PANEL_ANIMATION_MS = 220;
const THEME_STORAGE_KEY = "decodex.operator.theme";
const ACCOUNT_PRIVACY_STORAGE_KEY = "decodex.operator.accountPrivacy";
const ACCOUNT_NAME_OFFSET_STORAGE_KEY = "decodex.operator.accountNameOffsets";
const ACCOUNT_POOL_SORT_STORAGE_KEY = "decodex.operator.accountSort";
const PROJECT_FILTER_STORAGE_KEY = "decodex.operator.projectFilter";
const PROJECT_LOCATION_PRIVACY_STORAGE_KEY = "decodex.operator.projectLocationPrivacy";
Expand Down Expand Up @@ -3441,6 +3440,7 @@ <h2 id="recent-title">Run History</h2>
const ACCOUNT_IDENTITY_EDGE_CHARS = 6;
const ACCOUNT_IDENTITY_MIN_EDGE_CHARS = 3;
const ACCOUNT_RANDOM_NAMES = [
"Alex",
"Avery",
"Bailey",
"Blake",
Expand Down Expand Up @@ -3556,11 +3556,10 @@ <h2 id="recent-title">Run History</h2>
const reducedMotionQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
let themeSelection = loadThemeSelection();
let accountEmailsHidden = loadAccountPrivacy();
let accountNameOffsets = loadAccountNameOffsets();
let pendingAccountNameOffsets = {};
let accountApiSnapshot = null;
let accountApiRefreshInFlight = false;
let accountApiRefreshedAt = 0;
const pendingAccountNameOffsetSyncs = new Set();
let accountPoolSort = loadAccountPoolSort();
let accountSelectionConfirmation = null;
let projectFilterMode = loadProjectFilterMode();
Expand Down Expand Up @@ -4432,36 +4431,6 @@ <h2 id="recent-title">Run History</h2>
}
}

function loadAccountNameOffsets() {
try {
const stored = window.localStorage.getItem(ACCOUNT_NAME_OFFSET_STORAGE_KEY);
const parsed = stored ? JSON.parse(stored) : {};
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
return {};
}

return Object.fromEntries(
Object.entries(parsed)
.map(([key, value]) => [key, Number(value)])
.filter(([key, value]) => key && Number.isInteger(value))
.map(([key, value]) => [key, normalizeAccountNameOffset(value)]),
);
} catch (_error) {
return {};
}
}

function persistAccountNameOffsets() {
try {
window.localStorage.setItem(
ACCOUNT_NAME_OFFSET_STORAGE_KEY,
JSON.stringify(accountNameOffsets),
);
} catch (_error) {
/* Ignore storage failures and continue with the in-memory choice. */
}
}

function normalizeAccountNameOffset(value) {
const number = Number(value);
if (!Number.isInteger(number)) {
Expand Down Expand Up @@ -6049,13 +6018,13 @@ <h2 id="recent-title">Run History</h2>
return codexAccountIdentityHash(identity).toString(16).padStart(8, "0");
}

function codexAccountStoredRandomNameOffset(account) {
function codexAccountPendingRandomNameOffset(account) {
const key = codexAccountRandomNameKey(account);
if (!Object.prototype.hasOwnProperty.call(accountNameOffsets, key)) {
if (!Object.prototype.hasOwnProperty.call(pendingAccountNameOffsets, key)) {
return null;
}

return normalizeAccountNameOffset(accountNameOffsets[key]);
return normalizeAccountNameOffset(pendingAccountNameOffsets[key]);
}

function codexAccountServerRandomNameOffset(account) {
Expand All @@ -6066,16 +6035,16 @@ <h2 id="recent-title">Run History</h2>

function codexAccountRandomNameOffset(account) {
return (
codexAccountStoredRandomNameOffset(account) ??
codexAccountPendingRandomNameOffset(account) ??
codexAccountServerRandomNameOffset(account) ??
0
);
}

function codexAccountRandomName(account) {
const storedOffset = codexAccountStoredRandomNameOffset(account);
const pendingOffset = codexAccountPendingRandomNameOffset(account);
const serverName = String(account?.random_name || "").trim();
if (storedOffset == null && serverName) {
if (pendingOffset == null && serverName) {
return serverName;
}

Expand All @@ -6091,35 +6060,6 @@ <h2 id="recent-title">Run History</h2>
return ACCOUNT_RANDOM_NAMES[index];
}

function syncStoredAccountNameOffsets(accounts) {
for (const account of accounts) {
const key = codexAccountRandomNameKey(account);
const storedOffset = codexAccountStoredRandomNameOffset(account);
const serverOffset = codexAccountServerRandomNameOffset(account) ?? 0;
if (
storedOffset == null ||
storedOffset === serverOffset ||
pendingAccountNameOffsetSyncs.has(key)
) {
continue;
}

pendingAccountNameOffsetSyncs.add(key);
postAccountNameOffset(account, storedOffset)
.then((updated) => {
if (updated) {
delete accountNameOffsets[key];
persistAccountNameOffsets();
if (lastDashboardRender) {
renderDashboardState(lastDashboardRender);
}
}
})
.catch(() => {})
.finally(() => pendingAccountNameOffsetSyncs.delete(key));
}
}

function codexAccountShowsEmail(account) {
return Boolean(codexAccountEmail(account) && !accountEmailsHidden);
}
Expand Down Expand Up @@ -6921,7 +6861,6 @@ <h2 id="recent-title">Run History</h2>

function renderAccountPool(snapshot) {
const accounts = codexAccountPoolAccounts(snapshot);
syncStoredAccountNameOffsets(accounts);
renderAccountModeControl(snapshot);
renderStableList(nodes.accountPool, renderCodexAccountPool(accounts, snapshot));
syncAccountSelectionConfirmationDom();
Expand Down Expand Up @@ -9896,22 +9835,20 @@ <h4>${escapeHtml(worktree.branch_name)}</h4>
: null;
const current = account
? codexAccountRandomNameOffset(account)
: normalizeAccountNameOffset(accountNameOffsets[key]);
: normalizeAccountNameOffset(pendingAccountNameOffsets[key]);
const next = normalizeAccountNameOffset(current + 1);
accountNameOffsets = {
...accountNameOffsets,
pendingAccountNameOffsets = {
...pendingAccountNameOffsets,
[key]: next,
};
persistAccountNameOffsets();
if (lastDashboardRender) {
renderDashboardState(lastDashboardRender);
}
if (account) {
postAccountNameOffset(account, next)
.then((updated) => {
if (updated) {
delete accountNameOffsets[key];
persistAccountNameOffsets();
delete pendingAccountNameOffsets[key];
if (lastDashboardRender) {
renderDashboardState(lastDashboardRender);
}
Expand Down
13 changes: 8 additions & 5 deletions apps/decodex/src/orchestrator/tests/operator/status/dashboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ fn operator_dashboard_account_privacy_controls_use_compact_identities() {
let response = dashboard_response();

assert!(response.contains("const ACCOUNT_PRIVACY_STORAGE_KEY = \"decodex.operator.accountPrivacy\";"));
assert!(response.contains("const ACCOUNT_NAME_OFFSET_STORAGE_KEY = \"decodex.operator.accountNameOffsets\";"));
assert!(!response.contains("const ACCOUNT_NAME_OFFSET_STORAGE_KEY = \"decodex.operator.accountNameOffsets\";"));
assert!(response.contains("const ACCOUNT_IDENTITY_EDGE_CHARS = 6;"));
assert!(response.contains("const ACCOUNT_IDENTITY_MIN_EDGE_CHARS = 3;"));
assert!(!response.contains("const ACCOUNT_EMAIL_LOCAL_HEAD_CHARS = 5;"));
Expand All @@ -529,13 +529,17 @@ fn operator_dashboard_account_privacy_controls_use_compact_identities() {
assert!(response.contains("function codexAccountEmail(account)"));
assert!(response.contains("function compactAccountEmail(email)"));
assert!(response.contains("function loadAccountPrivacy()"));
assert!(response.contains("function loadAccountNameOffsets()"));
assert!(!response.contains("function loadAccountNameOffsets()"));
assert!(response.contains("function persistAccountPrivacy(hidden)"));
assert!(response.contains("function persistAccountNameOffsets()"));
assert!(!response.contains("function persistAccountNameOffsets()"));
assert!(response.contains("function configuredDashboardAccounts(snapshot)"));
assert!(response.contains("function renderAccountPrivacyToggle()"));
assert!(response.contains("function codexAccountRandomNameKey(account)"));
assert!(response.contains("function codexAccountRandomNameOffset(account)"));
assert!(response.contains("function codexAccountPendingRandomNameOffset(account)"));
assert!(response.contains("let pendingAccountNameOffsets = {};"));
assert!(!response.contains("function codexAccountStoredRandomNameOffset(account)"));
assert!(!response.contains("function syncStoredAccountNameOffsets(accounts)"));
assert!(response.contains("function codexAccountDisplaySource(account, snapshot)"));
assert!(response.contains("function renderCodexAccountRandomNameButton(account)"));
assert!(response.contains("function codexAccountShowsEmail(account)"));
Expand All @@ -560,7 +564,7 @@ fn operator_dashboard_account_privacy_controls_use_compact_identities() {
assert!(response.contains("account-name-reroll"));
assert!(response.contains("data-account-name-reroll"));
assert!(response.contains("aria-label=\"Change account name\""));
assert!(!response.contains("\"Alex\""));
assert!(response.contains("\"Alex\""));
assert!(response.contains("return `${local.slice(0, 3)}...${local.slice(-3)}${domain}`;"));
assert!(response.contains("return ACCOUNT_RANDOM_NAMES[index];"));
assert!(response.contains("return status === \"selected\" ? 1 : 0;"));
Expand All @@ -576,7 +580,6 @@ fn operator_dashboard_account_privacy_controls_use_compact_identities() {
assert!(response.contains("renderAccountPrivacyToggle();"));
assert!(response.contains("renderAccountModeControl(snapshot);"));
assert!(response.contains("persistAccountPrivacy(accountEmailsHidden);"));
assert!(response.contains("persistAccountNameOffsets();"));
assert!(response.contains("let lastDashboardRender = null;"));
assert!(response.contains("lastDashboardRender = {"));
assert!(response.contains("function renderDashboardState({"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1413,7 +1413,7 @@ fn operator_state_endpoint_persists_account_random_name_offset() {

assert_eq!(data["accounts"][0]["random_name_offset"], 1);
assert_eq!(data["accounts"][0]["random_name_key"], "df65f796");
assert_eq!(data["accounts"][0]["random_name"], "Taylor");
assert_eq!(data["accounts"][0]["random_name"], "Logan");
assert!(
fs::read_to_string(accounts_dir.join("config.toml"))
.expect("global config should read")
Expand Down