@nocturnium/svelte-ide 1.0.0 → 1.0.2
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.
- package/README.md +43 -47
- package/dist/components/agents/AgentActivityPanel.svelte +3 -1
- package/dist/components/agents/AgentAvatar.svelte +127 -35
- package/dist/components/agents/AgentCursor.svelte +15 -5
- package/dist/components/agents/AgentPresenceBar.svelte +7 -2
- package/dist/components/ai/AIConversationList.svelte +39 -34
- package/dist/components/ai/AIInlineEdit.svelte +1 -3
- package/dist/components/ai/AIMessage.svelte +5 -5
- package/dist/components/ai/AIMessageActions.svelte +18 -3
- package/dist/components/ai/AIMessageContent.svelte +22 -20
- package/dist/components/ai/AIPanel.svelte +17 -9
- package/dist/components/ai/AISuggestionWidget.svelte +1 -3
- package/dist/components/ai/AIToolCallDisplay.svelte +10 -14
- package/dist/components/core/Badge.svelte +9 -1
- package/dist/components/core/ConnectionStatus.svelte +73 -68
- package/dist/components/core/ErrorBoundary.svelte +56 -56
- package/dist/components/core/ErrorBoundary.svelte.d.ts +5 -5
- package/dist/components/core/Icon.svelte +22 -11
- package/dist/components/core/ResizeHandle.svelte +1 -1
- package/dist/components/core/Tooltip.svelte +1 -7
- package/dist/components/editor/AIFocusLayer.svelte +15 -7
- package/dist/components/editor/Breadcrumbs.svelte +18 -6
- package/dist/components/editor/BreakpointLayer.svelte +51 -60
- package/dist/components/editor/CognitiveLoadMeter.svelte +4 -2
- package/dist/components/editor/CollaborativeEditor.svelte +1 -5
- package/dist/components/editor/CommandPalette.svelte +1 -4
- package/dist/components/editor/ComplexityLayer.svelte +8 -6
- package/dist/components/editor/ConflictZoneLayer.svelte +2 -8
- package/dist/components/editor/ContextLens.svelte +1 -4
- package/dist/components/editor/CustomEditor.svelte +85 -41
- package/dist/components/editor/DebugConsole.svelte +8 -17
- package/dist/components/editor/EchoCursorLayer.svelte +3 -1
- package/dist/components/editor/EditorGutter.svelte +8 -2
- package/dist/components/editor/EditorLines.svelte +6 -3
- package/dist/components/editor/EditorPane.svelte +1 -6
- package/dist/components/editor/EditorSelections.svelte +29 -11
- package/dist/components/editor/FileExplorer.svelte +26 -4
- package/dist/components/editor/FileIcon.svelte +3 -1
- package/dist/components/editor/FindReplace.svelte +16 -4
- package/dist/components/editor/GhostBracketLayer.svelte +2 -2
- package/dist/components/editor/GitBlameLayer.svelte +2 -1
- package/dist/components/editor/InlineDiagnosticsLayer.svelte +4 -13
- package/dist/components/editor/InlineDiffLayer.svelte +18 -9
- package/dist/components/editor/Minimap.svelte +16 -9
- package/dist/components/editor/PluginPreviewSandbox.svelte +3 -2
- package/dist/components/editor/ProblemsPanel.svelte +11 -35
- package/dist/components/editor/QuickActionsMenu.svelte +5 -14
- package/dist/components/editor/SnippetPalette.svelte +11 -12
- package/dist/components/editor/StructureMap.svelte +2 -1
- package/dist/components/editor/SymbolOutline.svelte +14 -19
- package/dist/components/editor/TimelineScrubber.svelte +7 -6
- package/dist/components/editor/core/complexity-analyzer.js +42 -12
- package/dist/components/editor/core/conflict-predictor.js +2 -4
- package/dist/components/editor/core/folding.d.ts +9 -0
- package/dist/components/editor/core/folding.js +40 -5
- package/dist/components/editor/core/multi-cursor.js +4 -8
- package/dist/components/editor/core/navigation.js +2 -6
- package/dist/components/editor/core/quick-actions.js +22 -17
- package/dist/components/editor/core/search.js +2 -6
- package/dist/components/editor/core/semantic-analyzer.js +1 -3
- package/dist/components/editor/core/snippet-manager.js +4 -3
- package/dist/components/editor/core/state.js +2 -2
- package/dist/components/editor/core/timeline.js +1 -3
- package/dist/components/editor/editor-input.js +9 -6
- package/dist/components/editor/editor-multicursor.js +2 -2
- package/dist/components/editor/tokenizer/languages/css.js +146 -24
- package/dist/components/editor/tokenizer/languages/go.js +76 -13
- package/dist/components/editor/tokenizer/languages/javascript.d.ts +13 -2
- package/dist/components/editor/tokenizer/languages/javascript.js +278 -84
- package/dist/components/editor/tokenizer/languages/python.js +116 -19
- package/dist/components/editor/tokenizer/languages/svelte.js +20 -7
- package/dist/components/layout/IDELayout.svelte +6 -2
- package/dist/components/layout/StatusBar.svelte +32 -20
- package/dist/components/lsp/AutocompleteWidget.svelte +19 -19
- package/dist/components/lsp/DiagnosticMarker.svelte +61 -52
- package/dist/components/lsp/DiagnosticsPanel.svelte +45 -27
- package/dist/components/lsp/HoverTooltip.svelte +56 -61
- package/dist/components/lsp/LSPEditor.svelte +7 -18
- package/dist/components/lsp/SignatureHelpWidget.svelte +12 -9
- package/dist/components/plugins/PluginCard.svelte +3 -13
- package/dist/components/plugins/PluginProposalForm.svelte +19 -31
- package/dist/components/vfs/LockConflictDialog.svelte +112 -45
- package/dist/components/vfs/LockIndicator.svelte +0 -1
- package/dist/components/vfs/LockOverlay.svelte +53 -53
- package/dist/components/vfs/LockOverlay.svelte.d.ts +5 -5
- package/dist/components/vfs/VersionConflictDialog.svelte +107 -77
- package/dist/services/error-handling.js +1 -7
- package/dist/services/mock-ai.js +9 -7
- package/dist/stores/agents.svelte.js +50 -10
- package/dist/stores/ai.svelte.js +66 -18
- package/dist/stores/collaboration.svelte.js +70 -14
- package/dist/stores/editor.svelte.js +50 -10
- package/dist/stores/plugin.svelte.js +60 -12
- package/dist/stores/vfs.svelte.js +77 -19
- package/dist/styles/theme.css +16 -7
- package/package.json +186 -1
|
@@ -69,7 +69,12 @@
|
|
|
69
69
|
}
|
|
70
70
|
</script>
|
|
71
71
|
|
|
72
|
-
<div
|
|
72
|
+
<div
|
|
73
|
+
class="plugin-form-overlay"
|
|
74
|
+
onclick={onClose}
|
|
75
|
+
onkeydown={(e) => e.key === 'Escape' && onClose()}
|
|
76
|
+
role="presentation"
|
|
77
|
+
>
|
|
73
78
|
<div
|
|
74
79
|
class="plugin-form"
|
|
75
80
|
onclick={(e) => e.stopPropagation()}
|
|
@@ -85,7 +90,13 @@
|
|
|
85
90
|
</Button>
|
|
86
91
|
</div>
|
|
87
92
|
|
|
88
|
-
<form
|
|
93
|
+
<form
|
|
94
|
+
class="plugin-form__content"
|
|
95
|
+
onsubmit={(e) => {
|
|
96
|
+
e.preventDefault();
|
|
97
|
+
handleSubmit();
|
|
98
|
+
}}
|
|
99
|
+
>
|
|
89
100
|
{#if error}
|
|
90
101
|
<div class="plugin-form__error">
|
|
91
102
|
<Icon name="error" size={14} />
|
|
@@ -95,12 +106,7 @@
|
|
|
95
106
|
|
|
96
107
|
<div class="plugin-form__field">
|
|
97
108
|
<label for="name">Name *</label>
|
|
98
|
-
<Input
|
|
99
|
-
id="name"
|
|
100
|
-
bind:value={name}
|
|
101
|
-
placeholder="my-awesome-plugin"
|
|
102
|
-
fullWidth
|
|
103
|
-
/>
|
|
109
|
+
<Input id="name" bind:value={name} placeholder="my-awesome-plugin" fullWidth />
|
|
104
110
|
</div>
|
|
105
111
|
|
|
106
112
|
<div class="plugin-form__field">
|
|
@@ -116,11 +122,7 @@
|
|
|
116
122
|
|
|
117
123
|
<div class="plugin-form__field">
|
|
118
124
|
<label for="category">Category</label>
|
|
119
|
-
<select
|
|
120
|
-
id="category"
|
|
121
|
-
class="plugin-form__select"
|
|
122
|
-
bind:value={category}
|
|
123
|
-
>
|
|
125
|
+
<select id="category" class="plugin-form__select" bind:value={category}>
|
|
124
126
|
{#each categories as cat (cat.value)}
|
|
125
127
|
<option value={cat.value}>{cat.label}</option>
|
|
126
128
|
{/each}
|
|
@@ -129,31 +131,17 @@
|
|
|
129
131
|
|
|
130
132
|
<div class="plugin-form__field">
|
|
131
133
|
<label for="tags">Tags</label>
|
|
132
|
-
<Input
|
|
133
|
-
id="tags"
|
|
134
|
-
bind:value={tags}
|
|
135
|
-
placeholder="comma, separated, tags"
|
|
136
|
-
fullWidth
|
|
137
|
-
/>
|
|
134
|
+
<Input id="tags" bind:value={tags} placeholder="comma, separated, tags" fullWidth />
|
|
138
135
|
</div>
|
|
139
136
|
|
|
140
137
|
<div class="plugin-form__field">
|
|
141
138
|
<label for="author">Author *</label>
|
|
142
|
-
<Input
|
|
143
|
-
id="author"
|
|
144
|
-
bind:value={author}
|
|
145
|
-
placeholder="your@email.com"
|
|
146
|
-
fullWidth
|
|
147
|
-
/>
|
|
139
|
+
<Input id="author" bind:value={author} placeholder="your@email.com" fullWidth />
|
|
148
140
|
</div>
|
|
149
141
|
|
|
150
142
|
<div class="plugin-form__actions">
|
|
151
|
-
<Button variant="ghost" onclick={onClose} disabled={isSubmitting}>
|
|
152
|
-
|
|
153
|
-
</Button>
|
|
154
|
-
<Button variant="primary" type="submit" loading={isSubmitting}>
|
|
155
|
-
Create Proposal
|
|
156
|
-
</Button>
|
|
143
|
+
<Button variant="ghost" onclick={onClose} disabled={isSubmitting}>Cancel</Button>
|
|
144
|
+
<Button variant="primary" type="submit" loading={isSubmitting}>Create Proposal</Button>
|
|
157
145
|
</div>
|
|
158
146
|
</form>
|
|
159
147
|
</div>
|
|
@@ -111,7 +111,14 @@
|
|
|
111
111
|
<!-- Header -->
|
|
112
112
|
<header class="lock-dialog__header">
|
|
113
113
|
<div class="lock-dialog__icon">
|
|
114
|
-
<svg
|
|
114
|
+
<svg
|
|
115
|
+
viewBox="0 0 24 24"
|
|
116
|
+
fill="none"
|
|
117
|
+
stroke="currentColor"
|
|
118
|
+
stroke-width="2"
|
|
119
|
+
stroke-linecap="round"
|
|
120
|
+
stroke-linejoin="round"
|
|
121
|
+
>
|
|
115
122
|
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
|
|
116
123
|
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
117
124
|
</svg>
|
|
@@ -120,11 +127,7 @@
|
|
|
120
127
|
<h2 id="lock-dialog-title">File is Locked</h2>
|
|
121
128
|
<p class="lock-dialog__filename">{fileName}</p>
|
|
122
129
|
</div>
|
|
123
|
-
<button
|
|
124
|
-
class="lock-dialog__close"
|
|
125
|
-
onclick={onClose}
|
|
126
|
-
aria-label="Close dialog"
|
|
127
|
-
>
|
|
130
|
+
<button class="lock-dialog__close" onclick={onClose} aria-label="Close dialog">
|
|
128
131
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
129
132
|
<path d="M18 6 6 18M6 6l12 12" />
|
|
130
133
|
</svg>
|
|
@@ -158,7 +161,14 @@
|
|
|
158
161
|
{/if}
|
|
159
162
|
</div>
|
|
160
163
|
<div class="lock-holder__timer">
|
|
161
|
-
<svg
|
|
164
|
+
<svg
|
|
165
|
+
viewBox="0 0 24 24"
|
|
166
|
+
fill="none"
|
|
167
|
+
stroke="currentColor"
|
|
168
|
+
stroke-width="2"
|
|
169
|
+
width="14"
|
|
170
|
+
height="14"
|
|
171
|
+
>
|
|
162
172
|
<circle cx="12" cy="12" r="10" />
|
|
163
173
|
<polyline points="12 6 12 12 16 14" />
|
|
164
174
|
</svg>
|
|
@@ -170,7 +180,14 @@
|
|
|
170
180
|
<!-- Error message -->
|
|
171
181
|
{#if errorMessage}
|
|
172
182
|
<div class="lock-dialog__error" role="alert">
|
|
173
|
-
<svg
|
|
183
|
+
<svg
|
|
184
|
+
viewBox="0 0 24 24"
|
|
185
|
+
fill="none"
|
|
186
|
+
stroke="currentColor"
|
|
187
|
+
stroke-width="2"
|
|
188
|
+
width="16"
|
|
189
|
+
height="16"
|
|
190
|
+
>
|
|
174
191
|
<circle cx="12" cy="12" r="10" />
|
|
175
192
|
<line x1="12" y1="8" x2="12" y2="12" />
|
|
176
193
|
<line x1="12" y1="16" x2="12.01" y2="16" />
|
|
@@ -183,7 +200,14 @@
|
|
|
183
200
|
<div class="lock-dialog__reassurance">
|
|
184
201
|
{#if pendingChanges > 0}
|
|
185
202
|
<div class="reassurance-item reassurance-item--saved">
|
|
186
|
-
<svg
|
|
203
|
+
<svg
|
|
204
|
+
viewBox="0 0 24 24"
|
|
205
|
+
fill="none"
|
|
206
|
+
stroke="currentColor"
|
|
207
|
+
stroke-width="2"
|
|
208
|
+
width="14"
|
|
209
|
+
height="14"
|
|
210
|
+
>
|
|
187
211
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
|
|
188
212
|
<polyline points="22 4 12 14.01 9 11.01" />
|
|
189
213
|
</svg>
|
|
@@ -192,7 +216,14 @@
|
|
|
192
216
|
{/if}
|
|
193
217
|
{#if lastSyncDisplay}
|
|
194
218
|
<div class="reassurance-item">
|
|
195
|
-
<svg
|
|
219
|
+
<svg
|
|
220
|
+
viewBox="0 0 24 24"
|
|
221
|
+
fill="none"
|
|
222
|
+
stroke="currentColor"
|
|
223
|
+
stroke-width="2"
|
|
224
|
+
width="14"
|
|
225
|
+
height="14"
|
|
226
|
+
>
|
|
196
227
|
<polyline points="23 4 23 10 17 10" />
|
|
197
228
|
<path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10" />
|
|
198
229
|
</svg>
|
|
@@ -207,11 +238,15 @@
|
|
|
207
238
|
<!-- Safe options row -->
|
|
208
239
|
<div class="action-row action-row--safe">
|
|
209
240
|
{#if onOpenReadOnly}
|
|
210
|
-
<button
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
241
|
+
<button class="action-btn action-btn--safe" onclick={onOpenReadOnly}>
|
|
242
|
+
<svg
|
|
243
|
+
viewBox="0 0 24 24"
|
|
244
|
+
fill="none"
|
|
245
|
+
stroke="currentColor"
|
|
246
|
+
stroke-width="2"
|
|
247
|
+
width="18"
|
|
248
|
+
height="18"
|
|
249
|
+
>
|
|
215
250
|
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
|
|
216
251
|
<circle cx="12" cy="12" r="3" />
|
|
217
252
|
</svg>
|
|
@@ -219,11 +254,15 @@
|
|
|
219
254
|
</button>
|
|
220
255
|
{/if}
|
|
221
256
|
{#if onWait}
|
|
222
|
-
<button
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
257
|
+
<button class="action-btn action-btn--safe" onclick={onWait}>
|
|
258
|
+
<svg
|
|
259
|
+
viewBox="0 0 24 24"
|
|
260
|
+
fill="none"
|
|
261
|
+
stroke="currentColor"
|
|
262
|
+
stroke-width="2"
|
|
263
|
+
width="18"
|
|
264
|
+
height="18"
|
|
265
|
+
>
|
|
227
266
|
<circle cx="12" cy="12" r="10" />
|
|
228
267
|
<polyline points="12 6 12 12 16 14" />
|
|
229
268
|
</svg>
|
|
@@ -234,11 +273,15 @@
|
|
|
234
273
|
|
|
235
274
|
<!-- Primary action -->
|
|
236
275
|
{#if onRequestAccess}
|
|
237
|
-
<button
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
276
|
+
<button class="action-btn action-btn--primary" onclick={onRequestAccess}>
|
|
277
|
+
<svg
|
|
278
|
+
viewBox="0 0 24 24"
|
|
279
|
+
fill="none"
|
|
280
|
+
stroke="currentColor"
|
|
281
|
+
stroke-width="2"
|
|
282
|
+
width="18"
|
|
283
|
+
height="18"
|
|
284
|
+
>
|
|
242
285
|
<line x1="22" y1="2" x2="11" y2="13" />
|
|
243
286
|
<polygon points="22 2 15 22 11 13 2 9 22 2" />
|
|
244
287
|
</svg>
|
|
@@ -250,27 +293,30 @@
|
|
|
250
293
|
<!-- Dangerous action (gated) -->
|
|
251
294
|
{#if canForceUnlock && onForceUnlock}
|
|
252
295
|
{#if !showForceSection}
|
|
253
|
-
<button
|
|
254
|
-
class="action-toggle"
|
|
255
|
-
onclick={() => showForceSection = true}
|
|
256
|
-
>
|
|
296
|
+
<button class="action-toggle" onclick={() => (showForceSection = true)}>
|
|
257
297
|
More options...
|
|
258
298
|
</button>
|
|
259
299
|
{:else}
|
|
260
300
|
<div class="force-section">
|
|
261
301
|
<div class="force-warning">
|
|
262
|
-
<svg
|
|
263
|
-
|
|
302
|
+
<svg
|
|
303
|
+
viewBox="0 0 24 24"
|
|
304
|
+
fill="none"
|
|
305
|
+
stroke="currentColor"
|
|
306
|
+
stroke-width="2"
|
|
307
|
+
width="16"
|
|
308
|
+
height="16"
|
|
309
|
+
>
|
|
310
|
+
<path
|
|
311
|
+
d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"
|
|
312
|
+
/>
|
|
264
313
|
<line x1="12" y1="9" x2="12" y2="13" />
|
|
265
314
|
<line x1="12" y1="17" x2="12.01" y2="17" />
|
|
266
315
|
</svg>
|
|
267
316
|
<span>Force unlock may cause data loss for the current editor</span>
|
|
268
317
|
</div>
|
|
269
318
|
<label class="force-confirm">
|
|
270
|
-
<input
|
|
271
|
-
type="checkbox"
|
|
272
|
-
bind:checked={forceUnlockConfirmed}
|
|
273
|
-
/>
|
|
319
|
+
<input type="checkbox" bind:checked={forceUnlockConfirmed} />
|
|
274
320
|
<span>I understand the risks</span>
|
|
275
321
|
</label>
|
|
276
322
|
<button
|
|
@@ -278,7 +324,14 @@
|
|
|
278
324
|
onclick={handleForceUnlock}
|
|
279
325
|
disabled={!forceUnlockConfirmed}
|
|
280
326
|
>
|
|
281
|
-
<svg
|
|
327
|
+
<svg
|
|
328
|
+
viewBox="0 0 24 24"
|
|
329
|
+
fill="none"
|
|
330
|
+
stroke="currentColor"
|
|
331
|
+
stroke-width="2"
|
|
332
|
+
width="18"
|
|
333
|
+
height="18"
|
|
334
|
+
>
|
|
282
335
|
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
|
|
283
336
|
<path d="M7 11V7a5 5 0 0 1 9.9-1" />
|
|
284
337
|
</svg>
|
|
@@ -291,9 +344,7 @@
|
|
|
291
344
|
|
|
292
345
|
<!-- Footer -->
|
|
293
346
|
<footer class="lock-dialog__footer">
|
|
294
|
-
<button class="cancel-btn" onclick={onClose}>
|
|
295
|
-
Cancel
|
|
296
|
-
</button>
|
|
347
|
+
<button class="cancel-btn" onclick={onClose}> Cancel </button>
|
|
297
348
|
</footer>
|
|
298
349
|
</div>
|
|
299
350
|
</div>
|
|
@@ -314,8 +365,12 @@
|
|
|
314
365
|
}
|
|
315
366
|
|
|
316
367
|
@keyframes fade-in {
|
|
317
|
-
from {
|
|
318
|
-
|
|
368
|
+
from {
|
|
369
|
+
opacity: 0;
|
|
370
|
+
}
|
|
371
|
+
to {
|
|
372
|
+
opacity: 1;
|
|
373
|
+
}
|
|
319
374
|
}
|
|
320
375
|
|
|
321
376
|
.lock-dialog {
|
|
@@ -324,14 +379,22 @@
|
|
|
324
379
|
background: var(--ide-bg-secondary);
|
|
325
380
|
border: 1px solid var(--ide-border);
|
|
326
381
|
border-radius: var(--ide-radius-xl);
|
|
327
|
-
box-shadow:
|
|
382
|
+
box-shadow:
|
|
383
|
+
var(--ide-shadow-xl),
|
|
384
|
+
0 0 60px rgba(0, 0, 0, 0.3);
|
|
328
385
|
animation: slide-up 0.2s ease-out;
|
|
329
386
|
overflow: hidden;
|
|
330
387
|
}
|
|
331
388
|
|
|
332
389
|
@keyframes slide-up {
|
|
333
|
-
from {
|
|
334
|
-
|
|
390
|
+
from {
|
|
391
|
+
opacity: 0;
|
|
392
|
+
transform: translateY(20px) scale(0.98);
|
|
393
|
+
}
|
|
394
|
+
to {
|
|
395
|
+
opacity: 1;
|
|
396
|
+
transform: translateY(0) scale(1);
|
|
397
|
+
}
|
|
335
398
|
}
|
|
336
399
|
|
|
337
400
|
/* Header */
|
|
@@ -558,7 +621,11 @@
|
|
|
558
621
|
.action-btn--primary {
|
|
559
622
|
flex-direction: column;
|
|
560
623
|
gap: 4px;
|
|
561
|
-
background: linear-gradient(
|
|
624
|
+
background: linear-gradient(
|
|
625
|
+
135deg,
|
|
626
|
+
var(--ide-interactive) 0%,
|
|
627
|
+
var(--ide-interactive-active) 100%
|
|
628
|
+
);
|
|
562
629
|
color: white;
|
|
563
630
|
padding: 14px 16px;
|
|
564
631
|
}
|
|
@@ -1,58 +1,58 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import type { VFSFileLock } from '../../types';
|
|
10
|
-
|
|
11
|
-
interface Props {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
let { lock, onRequestAccess, onOpenReadOnly, onClose, showActions = true }: Props = $props();
|
|
20
|
-
|
|
21
|
-
// Calculate time remaining
|
|
22
|
-
let timeRemaining = $derived.by(() => {
|
|
23
|
-
const expires = new Date(lock.expiresAt).getTime();
|
|
24
|
-
const now = Date.now();
|
|
25
|
-
const remaining = Math.max(0, expires - now);
|
|
26
|
-
|
|
27
|
-
if (remaining === 0) return 'Expired';
|
|
28
|
-
|
|
29
|
-
const minutes = Math.floor(remaining / 60000);
|
|
30
|
-
const seconds = Math.floor((remaining % 60000) / 1000);
|
|
31
|
-
|
|
32
|
-
if (minutes > 0) {
|
|
33
|
-
return `${minutes}m ${seconds}s remaining`;
|
|
2
|
+
/**
|
|
3
|
+
* LockOverlay Component
|
|
4
|
+
*
|
|
5
|
+
* Displays a read-only overlay when a file is locked by another user/agent.
|
|
6
|
+
* Shows lock holder info, time remaining, and options to request access.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { VFSFileLock } from '../../types';
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
lock: VFSFileLock;
|
|
13
|
+
onRequestAccess?: () => void;
|
|
14
|
+
onOpenReadOnly?: () => void;
|
|
15
|
+
onClose?: () => void;
|
|
16
|
+
showActions?: boolean;
|
|
34
17
|
}
|
|
35
|
-
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
//
|
|
39
|
-
let
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
18
|
+
|
|
19
|
+
let { lock, onRequestAccess, onOpenReadOnly, onClose, showActions = true }: Props = $props();
|
|
20
|
+
|
|
21
|
+
// Calculate time remaining
|
|
22
|
+
let timeRemaining = $derived.by(() => {
|
|
23
|
+
const expires = new Date(lock.expiresAt).getTime();
|
|
24
|
+
const now = Date.now();
|
|
25
|
+
const remaining = Math.max(0, expires - now);
|
|
26
|
+
|
|
27
|
+
if (remaining === 0) return 'Expired';
|
|
28
|
+
|
|
29
|
+
const minutes = Math.floor(remaining / 60000);
|
|
30
|
+
const seconds = Math.floor((remaining % 60000) / 1000);
|
|
31
|
+
|
|
32
|
+
if (minutes > 0) {
|
|
33
|
+
return `${minutes}m ${seconds}s remaining`;
|
|
34
|
+
}
|
|
35
|
+
return `${seconds}s remaining`;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Lock holder display name
|
|
39
|
+
let holderDisplay = $derived(lock.holderType === 'agent' ? `AI: ${lock.holder}` : lock.holder);
|
|
40
|
+
|
|
41
|
+
// Lock purpose display
|
|
42
|
+
let purposeDisplay = $derived.by(() => {
|
|
43
|
+
switch (lock.purpose) {
|
|
44
|
+
case 'edit':
|
|
45
|
+
return 'Editing';
|
|
46
|
+
case 'refactor':
|
|
47
|
+
return 'Refactoring';
|
|
48
|
+
case 'delete':
|
|
49
|
+
return 'Deleting';
|
|
50
|
+
case 'rename':
|
|
51
|
+
return 'Renaming';
|
|
52
|
+
default:
|
|
53
|
+
return 'Modifying';
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
56
|
</script>
|
|
57
57
|
|
|
58
58
|
<div class="lock-overlay">
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
* LockOverlay Component
|
|
3
|
+
*
|
|
4
|
+
* Displays a read-only overlay when a file is locked by another user/agent.
|
|
5
|
+
* Shows lock holder info, time remaining, and options to request access.
|
|
6
|
+
*/
|
|
7
7
|
import type { VFSFileLock } from '../../types';
|
|
8
8
|
interface Props {
|
|
9
9
|
lock: VFSFileLock;
|