Skip to content

Commit 05b421d

Browse files
Add merge segment ID list and auto-submit to merge bar; shorten post-to-chat
Merge bar now shows scrollable pills with queued segment ID pairs scraped from neuroglancer's DOM. Added auto-submit checkbox that toggles NG's native autoSubmit state. Post-to-chat notifications now show only the title with "check your notifications for details" instead of the full body. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 53e9709 commit 05b421d

File tree

3 files changed

+125
-4
lines changed

3 files changed

+125
-4
lines changed

src/components/SplitMergeOverlay.vue

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const resultIsSuccess = computed(() => store.resultFlash === 'success');
2020
const resultIsError = computed(() => store.resultFlash === 'error');
2121
// Show inline result on bar (merge mode stays open, shows temporary result)
2222
const hasInlineResult = computed(() => hasResult.value && !store.pendingClose);
23+
const hasMergeSegments = computed(() => store.mergeSegments.length > 0);
2324
2425
const contextHint = computed(() => {
2526
if (store.statusMessage) return store.statusMessage;
@@ -62,6 +63,14 @@ function clearPoints() {
6263
}
6364
}
6465
66+
/** Toggle NG's native auto-submit checkbox */
67+
function toggleAutoSubmit() {
68+
const mergeEl = document.querySelector('.graphene-merge-segments');
69+
if (!mergeEl) return;
70+
const checkbox = mergeEl.querySelector('label input[type="checkbox"]') as HTMLInputElement | null;
71+
if (checkbox) checkbox.click();
72+
}
73+
6574
/** Exit the current split/merge tool (cancel the operation). */
6675
function cancelTool() {
6776
exitGrapheneTool();
@@ -132,9 +141,22 @@ function cancelTool() {
132141
MERGE MODE
133142
</div>
134143

144+
<!-- Merge segment list (scrollable pills) -->
145+
<div v-if="hasMergeSegments" class="nge-smo-merge-list">
146+
<div v-for="(pair, i) in store.mergeSegments" :key="i" class="nge-smo-merge-pair">
147+
<span class="nge-smo-seg-id">{{ pair[0] }}</span>
148+
<span v-if="pair[1]" class="nge-smo-merge-arrow">⇄</span>
149+
<span v-if="pair[1]" class="nge-smo-seg-id">{{ pair[1] }}</span>
150+
</div>
151+
</div>
152+
135153
<div class="nge-smo-hint merge-hint" :class="{ 'error-hint': hasInlineResult && resultIsError }">{{ contextHint }}</div>
136154

137155
<div class="nge-smo-actions" v-if="!isSubmitting">
156+
<label class="nge-smo-auto-submit" title="Auto-submit merges when both points are placed" @click.prevent="toggleAutoSubmit">
157+
<span class="nge-smo-checkbox" :class="{ checked: store.autoSubmit }">{{ store.autoSubmit ? '☑' : '☐' }}</span>
158+
auto-submit
159+
</label>
138160
<span class="nge-smo-key-hint"><kbd>Ctrl+Click</kbd> Set points</span>
139161
<span class="nge-smo-key-hint"><kbd>Enter</kbd> Submit</span>
140162
<button class="nge-smo-action-btn cancel-btn" @click="cancelTool" title="Exit merge mode"><kbd>Esc</kbd> Cancel</button>
@@ -169,7 +191,7 @@ function cancelTool() {
169191
align-items: center;
170192
gap: 16px;
171193
padding: 8px 20px;
172-
height: 48px;
194+
min-height: 48px;
173195
font-family: 'Inter', 'Roboto', sans-serif;
174196
font-size: 13px;
175197
color: #e0e0e0;
@@ -452,6 +474,81 @@ function cancelTool() {
452474
line-height: 1.4;
453475
}
454476
477+
/* ── Merge segment list ── */
478+
.nge-smo-merge-list {
479+
display: flex;
480+
align-items: center;
481+
gap: 6px;
482+
max-width: 40%;
483+
overflow-x: auto;
484+
overflow-y: hidden;
485+
flex-shrink: 1;
486+
scrollbar-width: thin;
487+
scrollbar-color: rgba(0, 220, 120, 0.3) transparent;
488+
padding: 2px 0;
489+
}
490+
491+
.nge-smo-merge-list::-webkit-scrollbar {
492+
height: 3px;
493+
}
494+
495+
.nge-smo-merge-list::-webkit-scrollbar-thumb {
496+
background: rgba(0, 220, 120, 0.3);
497+
border-radius: 2px;
498+
}
499+
500+
.nge-smo-merge-pair {
501+
display: flex;
502+
align-items: center;
503+
gap: 3px;
504+
flex-shrink: 0;
505+
padding: 2px 8px;
506+
background: rgba(0, 220, 120, 0.12);
507+
border: 1px solid rgba(0, 220, 120, 0.25);
508+
border-radius: 4px;
509+
}
510+
511+
.nge-smo-seg-id {
512+
font-family: 'JetBrains Mono', 'Fira Code', monospace;
513+
font-size: 10px;
514+
color: #90e8c0;
515+
white-space: nowrap;
516+
}
517+
518+
.nge-smo-merge-arrow {
519+
color: rgba(0, 220, 120, 0.5);
520+
font-size: 10px;
521+
}
522+
523+
/* ── Auto-submit checkbox ── */
524+
.nge-smo-auto-submit {
525+
display: flex;
526+
align-items: center;
527+
gap: 4px;
528+
pointer-events: auto;
529+
cursor: pointer;
530+
color: #aaa;
531+
font-size: 12px;
532+
margin-right: 8px;
533+
white-space: nowrap;
534+
transition: color 0.15s ease;
535+
}
536+
537+
.nge-smo-auto-submit:hover {
538+
color: #80ffc0;
539+
}
540+
541+
.nge-smo-checkbox {
542+
font-size: 14px;
543+
color: #666;
544+
transition: color 0.15s ease;
545+
}
546+
547+
.nge-smo-checkbox.checked {
548+
color: #80ffc0;
549+
text-shadow: 0 0 6px rgba(0, 220, 120, 0.5);
550+
}
551+
455552
/* Error hint styling */
456553
.nge-smo-hint.error-hint {
457554
color: #ffb0b0;

src/main.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,10 +564,28 @@ function observeSplitMergeTools() {
564564
wasMulticutActive = false;
565565
wasMergeActive = true;
566566

567-
// Count merge submissions
567+
// Count merge submissions and scrape segment IDs
568568
const submissions = mergeEl.querySelectorAll('.graphene-merge-segments-submission');
569569
store.mergeSubmissionCount = submissions.length;
570570

571+
// Scrape segment IDs from each submission pair
572+
const segments: string[][] = [];
573+
submissions.forEach(sub => {
574+
const points = sub.querySelectorAll('.graphene-merge-segments-point');
575+
const pair: string[] = [];
576+
points.forEach(pt => {
577+
// Segment ID is in the text of the widget (first line of the double-line entry)
578+
const text = (pt.textContent || '').trim().split('\n')[0].trim();
579+
if (text) pair.push(text);
580+
});
581+
if (pair.length > 0) segments.push(pair);
582+
});
583+
store.mergeSegments = segments;
584+
585+
// Scrape auto-submit checkbox state
586+
const autoSubmitCheckbox = mergeEl.querySelector('label input[type="checkbox"]') as HTMLInputElement | null;
587+
store.autoSubmit = autoSubmitCheckbox?.checked ?? false;
588+
571589
// Scrape per-submission status from .graphene-merge-segments-submission-status
572590
const statusEls = mergeEl.querySelectorAll('.graphene-merge-segments-submission-status');
573591
const currentStatuses: string[] = [];

src/store.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,10 @@ export const useSplitMergeOverlayStore = defineStore('splitMergeOverlay', () =>
15381538
const redPointCount = ref(0);
15391539
const bluePointCount = ref(0);
15401540
const mergeSubmissionCount = ref(0);
1541+
/** Scraped merge pairs: each entry is [sinkId, sourceId] or [sinkId] if incomplete */
1542+
const mergeSegments = ref<string[][]>([]);
1543+
/** Whether NG's auto-submit checkbox is checked */
1544+
const autoSubmit = ref(false);
15411545
const submitting = ref(false);
15421546
/** Status message scraped from neuroglancer's tool UI */
15431547
const statusMessage = ref('');
@@ -1559,6 +1563,8 @@ export const useSplitMergeOverlayStore = defineStore('splitMergeOverlay', () =>
15591563
redPointCount.value = 0;
15601564
bluePointCount.value = 0;
15611565
mergeSubmissionCount.value = 0;
1566+
mergeSegments.value = [];
1567+
autoSubmit.value = false;
15621568
submitting.value = false;
15631569
statusMessage.value = '';
15641570
}
@@ -1614,7 +1620,7 @@ export const useSplitMergeOverlayStore = defineStore('splitMergeOverlay', () =>
16141620

16151621
return {
16161622
toolActive, activeGroup, redPointCount, bluePointCount,
1617-
mergeSubmissionCount, submitting, statusMessage, resultFlash, resultText,
1623+
mergeSubmissionCount, mergeSegments, autoSubmit, submitting, statusMessage, resultFlash, resultText,
16181624
pendingClose, closingTool,
16191625
setToolState, setActiveGroup, updatePointCounts, setStatusMessage,
16201626
showResult, beginSuccessClose,
@@ -2396,7 +2402,7 @@ export const useProofreadingBackendStore = defineStore('proofreadingBackend', ()
23962402
try {
23972403
const chatStore = useChatStore();
23982404
if (chatStore.connected) {
2399-
chatStore.sendMessage(`📢 ${data.title}: ${data.body.slice(0, 200)}${data.body.length > 200 ? '...' : ''}`);
2405+
chatStore.sendMessage(`📢 ${data.title} — check your notifications for details!`);
24002406
}
24012407
} catch (e) { console.warn('[admin] post_to_chat failed:', e); }
24022408
}

0 commit comments

Comments
 (0)