Skip to content

Commit 4672210

Browse files
committed
Simplify drag handle styles and togg
1 parent 8bde169 commit 4672210

4 files changed

Lines changed: 52 additions & 91 deletions

File tree

frontend/src/App.css

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -648,17 +648,16 @@ select {
648648
}
649649

650650
.account-main-value {
651-
user-select: text;
652-
-webkit-user-select: text;
653-
cursor: text;
651+
user-select: none;
652+
-webkit-user-select: none;
654653
}
655654

656655
.drag-handle {
657656
width: 2.25rem;
658657
height: 2.25rem;
659658
flex: 0 0 auto;
660-
cursor: grab;
661-
pointer-events: auto;
659+
cursor: inherit;
660+
pointer-events: none;
662661
user-select: none;
663662
-webkit-user-select: none;
664663
-moz-user-select: none;

frontend/src/App.tsx

Lines changed: 48 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,8 @@ const runWindowAction = async <T,>(
124124
throw new Error(lastError || `Window action failed: ${actionNames.join(", ")}`);
125125
};
126126

127-
const windowFullscreenGetter = () => window.cm_window_is_fullscreen ?? window.cm_window_is_maximized;
128-
const windowFullscreenToggler = () =>
129-
window.cm_window_toggle_fullscreen ?? window.cm_window_toggle_maximize;
127+
const windowFullscreenGetter = () => window.cm_window_is_fullscreen;
128+
const windowFullscreenToggler = () => window.cm_window_toggle_fullscreen;
130129

131130
const nowEpoch = (): number => Math.floor(Date.now() / 1000);
132131

@@ -291,13 +290,6 @@ const IconRefreshing = () => (
291290
</svg>
292291
);
293292

294-
const IconArchive = () => (
295-
<svg viewBox="0 0 24 24" aria-hidden="true">
296-
<path d="M4 4h16v4H4zM5 8h14v11H5z" />
297-
<path d="M10 12h4" />
298-
</svg>
299-
);
300-
301293
const IconDragHandle = () => (
302294
<svg viewBox="0 0 24 24" aria-hidden="true">
303295
<circle cx="8" cy="7" r="1.2" />
@@ -464,11 +456,7 @@ function App() {
464456

465457
persistStateTimer = window.setTimeout(() => {
466458
persistStateTimer = undefined;
467-
468459
const currentView = view();
469-
if (!currentView) {
470-
return;
471-
}
472460

473461
void saveEmbeddedBootstrapState({
474462
theme: theme(),
@@ -1019,8 +1007,10 @@ function App() {
10191007
};
10201008

10211009
const handleDragOverBucket = (event: DragEvent, bucket: AccountBucket) => {
1010+
allowDrop(event);
10221011
const draggedId = resolveDragId(event);
10231012
if (!draggedId) {
1013+
setDragHover(null);
10241014
return;
10251015
}
10261016
if (!canDropInBucket(draggedId, bucket)) {
@@ -1030,14 +1020,15 @@ function App() {
10301020
}
10311021
return;
10321022
}
1033-
allowDrop(event);
10341023
setDragHoverTarget(bucket, null);
10351024
};
10361025

10371026
const handleDragOverAccount = (event: DragEvent, bucket: AccountBucket, targetId: string) => {
10381027
event.stopPropagation();
1028+
allowDrop(event);
10391029
const draggedId = resolveDragId(event);
10401030
if (!draggedId) {
1031+
setDragHover(null);
10411032
return;
10421033
}
10431034
if (!canDropInBucket(draggedId, bucket)) {
@@ -1047,7 +1038,6 @@ function App() {
10471038
}
10481039
return;
10491040
}
1050-
allowDrop(event);
10511041
if (draggedId === targetId) {
10521042
setDragHoverTarget(bucket, null);
10531043
return;
@@ -1081,11 +1071,40 @@ function App() {
10811071
return element;
10821072
};
10831073

1084-
const dragStartBlocked = (target: EventTarget | null): boolean => {
1085-
if (!(target instanceof Element)) {
1074+
const resolveEventElement = (target: EventTarget | null): Element | null => {
1075+
if (target instanceof Element) {
1076+
return target;
1077+
}
1078+
if (target instanceof Node) {
1079+
return target.parentElement;
1080+
}
1081+
return null;
1082+
};
1083+
1084+
const accountCopySelectionActive = (): boolean => {
1085+
const selection = window.getSelection();
1086+
if (!selection || selection.isCollapsed) {
10861087
return false;
10871088
}
1088-
return Boolean(target.closest("button, input, select, textarea, a, .account-copyable, .account-main-value"));
1089+
1090+
const isCopyableNode = (node: Node | null): boolean => {
1091+
if (!node) {
1092+
return false;
1093+
}
1094+
const element = node instanceof Element ? node : node.parentElement;
1095+
return Boolean(element?.closest(".account-copyable, .account-main-value"));
1096+
};
1097+
1098+
return isCopyableNode(selection.anchorNode) || isCopyableNode(selection.focusNode);
1099+
};
1100+
1101+
const dragStartBlocked = (target: EventTarget | null): boolean => {
1102+
const element = resolveEventElement(target);
1103+
if (element?.closest("button, input, select, textarea, a, .account-copyable, .account-main-value")) {
1104+
return true;
1105+
}
1106+
1107+
return accountCopySelectionActive();
10891108
};
10901109

10911110
const handleDropOnBucket = async (event: DragEvent, bucket: AccountBucket) => {
@@ -1167,26 +1186,6 @@ function App() {
11671186
}
11681187
};
11691188

1170-
const handleDragHandlePointerDown = () => {
1171-
// Keep text from being selected while still allowing native drag events in browsers.
1172-
document.body.classList.add(DRAG_SELECT_LOCK_CLASS);
1173-
};
1174-
1175-
const handleArchive = async (id: string) => {
1176-
const next = await runAction("Moving account to depleted", () =>
1177-
archiveAccount(id, {
1178-
switchAwayFromArchived: AUTO_SWITCH_AWAY_FROM_DEPLETED_OR_FROZEN,
1179-
}),
1180-
);
1181-
1182-
if (!next) {
1183-
return;
1184-
}
1185-
1186-
setViewState(next);
1187-
setNotice("Account moved to depleted.");
1188-
};
1189-
11901189
const handleFreeze = async (id: string) => {
11911190
const targetIndex = frozenAccounts().filter((account) => account.id !== id).length;
11921191
await moveAccountToBucket(id, "frozen", targetIndex);
@@ -1223,7 +1222,7 @@ function App() {
12231222
const refreshWindowState = async () => {
12241223
try {
12251224
const status = await runWindowAction<boolean>(
1226-
["cm_window_is_fullscreen", "cm_window_is_maximized"],
1225+
["cm_window_is_fullscreen"],
12271226
windowFullscreenGetter(),
12281227
);
12291228
setFullscreen(Boolean(status));
@@ -1244,11 +1243,11 @@ function App() {
12441243
const handleToggleFullscreen = async () => {
12451244
try {
12461245
await runWindowAction<boolean>(
1247-
["cm_window_toggle_fullscreen", "cm_window_toggle_maximize"],
1246+
["cm_window_toggle_fullscreen"],
12481247
windowFullscreenToggler(),
12491248
);
12501249
const status = await runWindowAction<boolean>(
1251-
["cm_window_is_fullscreen", "cm_window_is_maximized"],
1250+
["cm_window_is_fullscreen"],
12521251
windowFullscreenGetter(),
12531252
);
12541253
setFullscreen(Boolean(status));
@@ -1285,7 +1284,7 @@ function App() {
12851284

12861285
onMount(async () => {
12871286
const fallbackTheme = localStorage.getItem("codex-manager-theme");
1288-
let initialTheme: Theme = fallbackTheme === "dark" ? "dark" : "light";
1287+
let initialTheme: Theme = embeddedState?.theme === "dark" ? "dark" : fallbackTheme === "dark" ? "dark" : "light";
12891288
try {
12901289
const bridgedTheme = await getSavedTheme();
12911290
if (bridgedTheme) {
@@ -1525,14 +1524,14 @@ function App() {
15251524
} ${isDropBefore("active", account.id) ? "drop-before" : ""}${
15261525
draggingAccountId() && draggingAccountId() !== account.id ? " drag-context" : ""
15271526
}`}
1528-
draggable
1527+
draggable={true}
15291528
onDragStart={(event) => handleDragStart(event, account, "active")}
15301529
onDragEnd={handleDragEnd}
15311530
onDragOver={(event) => handleDragOverAccount(event, "active", account.id)}
15321531
onDrop={(event) => void handleDropBeforeAccount(event, "active", account.id)}
15331532
>
15341533
<header class="account-head">
1535-
<span class="icon-btn drag-handle" aria-hidden="true" onPointerDown={handleDragHandlePointerDown}>
1534+
<span class="icon-btn drag-handle" aria-hidden="true">
15361535
<IconDragHandle />
15371536
</span>
15381537
<div class="account-main">
@@ -1630,15 +1629,6 @@ function App() {
16301629
<IconRefreshing />
16311630
</Show>
16321631
</button>
1633-
<button
1634-
type="button"
1635-
class="icon-btn action"
1636-
onClick={() => handleArchive(account.id)}
1637-
aria-label="Move to depleted"
1638-
title="Move to depleted"
1639-
>
1640-
<IconArchive />
1641-
</button>
16421632
<button
16431633
type="button"
16441634
class="icon-btn action"
@@ -1713,14 +1703,14 @@ function App() {
17131703
class={`account account-depleted archived ${draggingAccountId() === account.id ? "dragging" : ""} ${
17141704
isDropBefore("depleted", account.id) ? "drop-before" : ""
17151705
}${draggingAccountId() && draggingAccountId() !== account.id ? " drag-context" : ""}`}
1716-
draggable
1706+
draggable={true}
17171707
onDragStart={(event) => handleDragStart(event, account, "depleted")}
17181708
onDragEnd={handleDragEnd}
17191709
onDragOver={(event) => handleDragOverAccount(event, "depleted", account.id)}
17201710
onDrop={(event) => void handleDropBeforeAccount(event, "depleted", account.id)}
17211711
>
17221712
<header class="account-head">
1723-
<span class="icon-btn drag-handle" aria-hidden="true" onPointerDown={handleDragHandlePointerDown}>
1713+
<span class="icon-btn drag-handle" aria-hidden="true">
17241714
<IconDragHandle />
17251715
</span>
17261716
<div class="account-main">
@@ -1858,14 +1848,14 @@ function App() {
18581848
class={`account account-frozen archived ${draggingAccountId() === account.id ? "dragging" : ""} ${
18591849
isDropBefore("frozen", account.id) ? "drop-before" : ""
18601850
}${draggingAccountId() && draggingAccountId() !== account.id ? " drag-context" : ""}`}
1861-
draggable
1851+
draggable={true}
18621852
onDragStart={(event) => handleDragStart(event, account, "frozen")}
18631853
onDragEnd={handleDragEnd}
18641854
onDragOver={(event) => handleDragOverAccount(event, "frozen", account.id)}
18651855
onDrop={(event) => void handleDropBeforeAccount(event, "frozen", account.id)}
18661856
>
18671857
<header class="account-head">
1868-
<span class="icon-btn drag-handle" aria-hidden="true" onPointerDown={handleDragHandlePointerDown}>
1858+
<span class="icon-btn drag-handle" aria-hidden="true">
18691859
<IconDragHandle />
18701860
</span>
18711861
<div class="account-main">
@@ -1891,15 +1881,6 @@ function App() {
18911881
</button>
18921882

18931883
<div class="icon-actions">
1894-
<button
1895-
type="button"
1896-
class="icon-btn action"
1897-
onClick={() => handleArchive(account.id)}
1898-
aria-label="Move to depleted"
1899-
title="Move to depleted"
1900-
>
1901-
<IconArchive />
1902-
</button>
19031884
<button
19041885
type="button"
19051886
class="icon-btn danger-icon"

frontend/src/vite-env.d.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ interface Window {
1414
cm_window_minimize?: () => Promise<void> | void;
1515
cm_window_toggle_fullscreen?: () => Promise<boolean> | boolean;
1616
cm_window_is_fullscreen?: () => Promise<boolean> | boolean;
17-
cm_window_toggle_maximize?: () => Promise<boolean> | boolean;
18-
cm_window_is_maximized?: () => Promise<boolean> | boolean;
1917
cm_window_close?: () => Promise<void> | void;
20-
cm_window_start_drag?: () => Promise<void> | void;
2118
webui?: {
2219
call?: (fn: string, ...args: unknown[]) => Promise<string> | string;
2320
};

src/main.zig

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,7 @@ pub fn main() !void {
8989
_ = try window.bind("cm_window_minimize", cmWindowMinimize);
9090
_ = try window.bind("cm_window_toggle_fullscreen", cmWindowToggleFullscreen);
9191
_ = try window.bind("cm_window_is_fullscreen", cmWindowIsFullscreen);
92-
_ = try window.bind("cm_window_toggle_maximize", cmWindowToggleMaximize);
93-
_ = try window.bind("cm_window_is_maximized", cmWindowIsMaximized);
9492
_ = try window.bind("cm_window_close", cmWindowClose);
95-
_ = try window.bind("cm_window_start_drag", cmWindowStartDrag);
9693

9794
// Avoid large inline HTML in showWv; serve desktop bundle over local WebUI server.
9895
window.setFileHandler(customFileHandler);
@@ -340,10 +337,6 @@ fn cmWindowMinimize(e: *webui.Event) void {
340337
sendOk(e, @as(?u8, null));
341338
}
342339

343-
fn cmWindowToggleMaximize(e: *webui.Event) void {
344-
cmWindowToggleFullscreen(e);
345-
}
346-
347340
fn cmWindowToggleFullscreen(e: *webui.Event) void {
348341
if (app_window) |window| {
349342
if (window_is_fullscreen) {
@@ -358,10 +351,6 @@ fn cmWindowToggleFullscreen(e: *webui.Event) void {
358351
sendOk(e, window_is_fullscreen);
359352
}
360353

361-
fn cmWindowIsMaximized(e: *webui.Event) void {
362-
cmWindowIsFullscreen(e);
363-
}
364-
365354
fn cmWindowIsFullscreen(e: *webui.Event) void {
366355
sendOk(e, window_is_fullscreen);
367356
}
@@ -371,11 +360,6 @@ fn cmWindowClose(e: *webui.Event) void {
371360
exitNow();
372361
}
373362

374-
fn cmWindowStartDrag(e: *webui.Event) void {
375-
// Dragging is handled via CSS app-region in the frontend.
376-
sendOk(e, @as(?u8, null));
377-
}
378-
379363
fn cmWindowCloseHandler(_: usize) bool {
380364
exitNow();
381365
}

0 commit comments

Comments
 (0)