mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-09 08:59:40 +02:00
Merge pull request #274 from jordan8037310/fix/run-menu-recent-sessions
fix(run-menu): make Recent Sessions rows legible on macOS (home-prefix regex + width + worktree)
This commit is contained in:
@@ -490,26 +490,55 @@ Object.assign(CodemanApp.prototype, {
|
|||||||
const timeStr = date.toLocaleDateString('en', { month: 'short', day: 'numeric' })
|
const timeStr = date.toLocaleDateString('en', { month: 'short', day: 'numeric' })
|
||||||
+ ' ' + date.toLocaleTimeString('en', { hour: '2-digit', minute: '2-digit', hour12: false });
|
+ ' ' + date.toLocaleTimeString('en', { hour: '2-digit', minute: '2-digit', hour12: false });
|
||||||
// Shared helper, not a local regex: the copy that used to live here
|
// Shared helper, not a local regex: the copy that used to live here
|
||||||
// matched `/home/<user>/` only, so on macOS every row rendered the same
|
// matched `/home/<user>/` only, so on macOS (`/Users/<user>/`) nothing was
|
||||||
// unabbreviated `/Users/<user>/…` prefix and ellipsized away the tail
|
// stripped and every row spent its first ~19 characters on an identical
|
||||||
// that identifies it (#273).
|
// prefix — with the tail ellipsized, all rows rendered as
|
||||||
|
// `/Users/jordanryan/co…` and became indistinguishable (#273).
|
||||||
const shortDir = this._shortenHomePath(s.workingDir);
|
const shortDir = this._shortenHomePath(s.workingDir);
|
||||||
|
// Lead with the folder that identifies the row; the parent path trails and
|
||||||
|
// is what gets truncated. Truncation must never eat the identity.
|
||||||
|
const lastSlash = shortDir.lastIndexOf('/');
|
||||||
|
const leafName = lastSlash === -1 ? shortDir : shortDir.slice(lastSlash + 1);
|
||||||
|
// `<repo>/.claude/worktrees` in the parent path is pure noise once the pill
|
||||||
|
// says which worktree it is — drop it so the repo stays visible instead.
|
||||||
|
const parentDir = (lastSlash === -1 ? '' : shortDir.slice(0, lastSlash)).replace(/\/\.claude\/worktrees$/, '');
|
||||||
|
|
||||||
const btn = document.createElement('button');
|
const btn = document.createElement('button');
|
||||||
btn.className = 'run-mode-option';
|
btn.className = 'run-mode-option run-mode-hist-row';
|
||||||
btn.title = s.workingDir;
|
btn.title = s.workingDir;
|
||||||
btn.dataset.sessionId = s.sessionId;
|
btn.dataset.sessionId = s.sessionId;
|
||||||
btn.dataset.workingDir = s.workingDir;
|
btn.dataset.workingDir = s.workingDir;
|
||||||
|
|
||||||
const dirSpan = document.createElement('span');
|
const nameSpan = document.createElement('span');
|
||||||
dirSpan.className = 'hist-dir';
|
nameSpan.className = 'hist-name';
|
||||||
dirSpan.textContent = shortDir;
|
nameSpan.textContent = leafName;
|
||||||
|
|
||||||
|
const parts = [nameSpan];
|
||||||
|
|
||||||
|
// Worktree pill, same data the session rows use (#266). A worktree's
|
||||||
|
// directory basename is often just the worktree name, so without this two
|
||||||
|
// worktrees of one repo still read alike.
|
||||||
|
const wt = this._worktreeLabel ? this._worktreeLabel(s) : '';
|
||||||
|
if (wt) {
|
||||||
|
const wtSpan = document.createElement('span');
|
||||||
|
wtSpan.className = 'hist-wt';
|
||||||
|
wtSpan.textContent = wt;
|
||||||
|
parts.push(wtSpan);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parentDir) {
|
||||||
|
const dirSpan = document.createElement('span');
|
||||||
|
dirSpan.className = 'hist-dir';
|
||||||
|
dirSpan.textContent = parentDir;
|
||||||
|
parts.push(dirSpan);
|
||||||
|
}
|
||||||
|
|
||||||
const metaSpan = document.createElement('span');
|
const metaSpan = document.createElement('span');
|
||||||
metaSpan.className = 'hist-meta';
|
metaSpan.className = 'hist-meta';
|
||||||
metaSpan.textContent = timeStr;
|
metaSpan.textContent = timeStr;
|
||||||
|
parts.push(metaSpan);
|
||||||
|
|
||||||
btn.append(dirSpan, metaSpan);
|
btn.append(...parts);
|
||||||
btn.addEventListener('click', (e) => {
|
btn.addEventListener('click', (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this.resumeHistorySession(s.sessionId, s.workingDir, s.name);
|
this.resumeHistorySession(s.sessionId, s.workingDir, s.name);
|
||||||
|
|||||||
@@ -4455,6 +4455,24 @@ body.touch-device .terminal-container .xterm .xterm-helper-textarea {
|
|||||||
max-width: 250px;
|
max-width: 250px;
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Above phone width the menu becomes a full-width drawer across the bottom of the
|
||||||
|
window. The 250px cap above was sized for a `~/<dir>/<repo>` row, which assumed
|
||||||
|
the home prefix had been abbreviated — it never was on macOS, so real rows blew
|
||||||
|
straight through it and ellipsized into `/Users/<user>/co…`, identical on every
|
||||||
|
line. Width is what buys room for the worktree + branch, so the cap is lifted
|
||||||
|
rather than nudged. Phones keep the compact popover: mobile.css positions this
|
||||||
|
menu itself and a viewport-wide drawer there would cover the composer. */
|
||||||
|
@media (min-width: 769px) {
|
||||||
|
.run-mode-menu {
|
||||||
|
max-width: none;
|
||||||
|
width: calc(100vw - 24px);
|
||||||
|
}
|
||||||
|
.run-mode-history {
|
||||||
|
/* More rows are worth showing once each one is legible. */
|
||||||
|
max-height: 320px;
|
||||||
|
}
|
||||||
|
}
|
||||||
.run-mode-menu.active {
|
.run-mode-menu.active {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -4525,6 +4543,31 @@ body.touch-device .terminal-container .xterm .xterm-helper-textarea {
|
|||||||
.run-mode-history .run-mode-option {
|
.run-mode-history .run-mode-option {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
/* Recent-session row: identity first, path last.
|
||||||
|
The row reads <folder> [⑂ worktree · branch] <parent path> <time>
|
||||||
|
with only the parent path allowed to shrink, so truncation can never hide
|
||||||
|
which project (or which worktree) a row refers to. */
|
||||||
|
.run-mode-hist-row {
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.run-mode-option .hist-name {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.run-mode-option .hist-wt {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
font-size: 0.78em;
|
||||||
|
padding: 0 5px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: color-mix(in srgb, var(--accent) 16%, transparent);
|
||||||
|
color: var(--accent);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
.run-mode-option .hist-dir {
|
.run-mode-option .hist-dir {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
/* A flex item's default min-width is auto, so without this the path refuses to
|
/* A flex item's default min-width is auto, so without this the path refuses to
|
||||||
@@ -4534,6 +4577,11 @@ body.touch-device .terminal-container .xterm .xterm-helper-textarea {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
/* The parent path is context, not identity — dim it and let it be the part
|
||||||
|
that loses characters first. */
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 0.85em;
|
||||||
|
text-align: right;
|
||||||
}
|
}
|
||||||
.run-mode-option .hist-meta {
|
.run-mode-option .hist-meta {
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
|
|||||||
Reference in New Issue
Block a user