aidevops 3.30.0 → 3.31.1
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 +1 -1
- package/VERSION +1 -1
- package/aidevops.sh +1 -1
- package/package.json +1 -1
- package/packages/gui-desktop/scripts/install-macos-app.sh +11 -5
- package/packages/gui-web/src/ScreenshotCaptureNotification.tsx +22 -6
- package/packages/gui-web/src/styles.css +31 -12
- package/setup.sh +1 -1
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ The result: an AI operations platform that manages projects across every busines
|
|
|
58
58
|
[](https://github.com/marcusquinn)
|
|
59
59
|
|
|
60
60
|
<!-- Release & Version Info -->
|
|
61
|
-
[](https://github.com/marcusquinn/aidevops/releases)
|
|
62
62
|
[](https://www.npmjs.com/package/aidevops)
|
|
63
63
|
[](https://github.com/marcusquinn/homebrew-tap)
|
|
64
64
|
[](https://github.com/marcusquinn/aidevops)
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.31.1
|
package/aidevops.sh
CHANGED
package/package.json
CHANGED
|
@@ -813,7 +813,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, WKNavigationDelegate,
|
|
|
813
813
|
toggleButton.centerYAnchor.constraint(equalTo: overlay.centerYAnchor, constant: 3.5),
|
|
814
814
|
toggleButton.heightAnchor.constraint(equalToConstant: 22),
|
|
815
815
|
toggleButton.widthAnchor.constraint(equalToConstant: 22),
|
|
816
|
-
cameraButton.trailingAnchor.constraint(equalTo: overlay.trailingAnchor, constant: -
|
|
816
|
+
cameraButton.trailingAnchor.constraint(equalTo: overlay.trailingAnchor, constant: -24),
|
|
817
817
|
cameraButton.centerYAnchor.constraint(equalTo: overlay.centerYAnchor, constant: 3.5),
|
|
818
818
|
cameraButton.heightAnchor.constraint(equalToConstant: 22),
|
|
819
819
|
cameraButton.widthAnchor.constraint(equalToConstant: 22)
|
|
@@ -1010,8 +1010,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, WKNavigationDelegate,
|
|
|
1010
1010
|
let offsetKey = Int(actualOffset.rounded())
|
|
1011
1011
|
var nextCapturedOffsets = capturedOffsets
|
|
1012
1012
|
if capturedOffsets.contains(offsetKey) {
|
|
1013
|
-
self.
|
|
1014
|
-
self.saveScreenshot(image: composite, nameComponent: pageName)
|
|
1013
|
+
self.savePageScreenshotAfterRestoringScroll(image: composite, nameComponent: pageName, scrollTop: originalScrollTop)
|
|
1015
1014
|
return
|
|
1016
1015
|
}
|
|
1017
1016
|
nextCapturedOffsets.insert(offsetKey)
|
|
@@ -1027,8 +1026,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, WKNavigationDelegate,
|
|
|
1027
1026
|
}
|
|
1028
1027
|
|
|
1029
1028
|
if actualOffset + viewportHeight >= contentHeight - 1 {
|
|
1030
|
-
self.
|
|
1031
|
-
self.saveScreenshot(image: composite, nameComponent: pageName)
|
|
1029
|
+
self.savePageScreenshotAfterRestoringScroll(image: composite, nameComponent: pageName, scrollTop: originalScrollTop)
|
|
1032
1030
|
} else {
|
|
1033
1031
|
let nextOffset = min(contentHeight - viewportHeight, actualOffset + viewportHeight)
|
|
1034
1032
|
self.captureWorkspaceChunk(rect: rect, contentHeight: contentHeight, viewportHeight: viewportHeight, originalScrollTop: originalScrollTop, targetOffset: nextOffset, pageName: pageName, composite: composite, capturedOffsets: nextCapturedOffsets)
|
|
@@ -1042,6 +1040,14 @@ final class AppDelegate: NSObject, NSApplicationDelegate, WKNavigationDelegate,
|
|
|
1042
1040
|
webView.evaluateJavaScript("document.querySelector('.workspace-scroll')?.scrollTo({ top: \(Int(scrollTop)), behavior: 'instant' }); true;", completionHandler: nil)
|
|
1043
1041
|
}
|
|
1044
1042
|
|
|
1043
|
+
private func savePageScreenshotAfterRestoringScroll(image: NSImage, nameComponent: String, scrollTop: CGFloat) {
|
|
1044
|
+
webView.evaluateJavaScript("document.querySelector('.workspace-scroll')?.scrollTo({ top: \(Int(scrollTop)), behavior: 'instant' }); true;") { [weak self] _, _ in
|
|
1045
|
+
DispatchQueue.main.async {
|
|
1046
|
+
self?.saveScreenshot(image: image, nameComponent: nameComponent)
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1045
1051
|
private func saveScreenshot(image: NSImage, nameComponent: String) {
|
|
1046
1052
|
guard let tiff = image.tiffRepresentation,
|
|
1047
1053
|
let bitmap = NSBitmapImageRep(data: tiff),
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { type ReactElement, useEffect, useState } from "react";
|
|
1
|
+
import { type ReactElement, useEffect, useRef, useState } from "react";
|
|
2
2
|
|
|
3
3
|
export interface ScreenshotCapturedDetail {
|
|
4
4
|
path: string;
|
|
5
5
|
url: string;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
interface ScreenshotCapturedNotification extends ScreenshotCapturedDetail {
|
|
9
|
+
id: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
8
12
|
interface WebKitExternalLinkWindow extends Window {
|
|
9
13
|
webkit?: {
|
|
10
14
|
messageHandlers?: {
|
|
@@ -25,21 +29,23 @@ export function ScreenshotCaptureNotification({ notification, onDismiss }: { not
|
|
|
25
29
|
<div className="screenshot-capture-notification" role="status">
|
|
26
30
|
<div>
|
|
27
31
|
<strong>Screenshot captured</strong>
|
|
28
|
-
<span>Saved to <button onClick={revealScreenshot} type="button">{notification.path}</button>; path copied to clipboard.</span>
|
|
32
|
+
<span>Saved to <button className="screenshot-path-button" onClick={revealScreenshot} title={notification.path} type="button">{notification.path}</button>; path copied to clipboard.</span>
|
|
29
33
|
</div>
|
|
30
|
-
<button aria-label="Dismiss screenshot notification" onClick={onDismiss} type="button">×</button>
|
|
34
|
+
<button aria-label="Dismiss screenshot notification" className="screenshot-dismiss-button" onClick={onDismiss} type="button">×</button>
|
|
31
35
|
</div>
|
|
32
36
|
);
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
export function ScreenshotCaptureNotificationHost(): ReactElement | null {
|
|
36
|
-
const
|
|
40
|
+
const nextNotificationId = useRef(0);
|
|
41
|
+
const [screenshotNotifications, setScreenshotNotifications] = useState<ScreenshotCapturedNotification[]>([]);
|
|
37
42
|
|
|
38
43
|
useEffect(() => {
|
|
39
44
|
const showScreenshotNotification = (event: Event) => {
|
|
40
45
|
const detail = (event as CustomEvent<Partial<ScreenshotCapturedDetail>>).detail;
|
|
41
46
|
if (detail !== undefined && typeof detail.path === "string" && typeof detail.url === "string") {
|
|
42
|
-
|
|
47
|
+
nextNotificationId.current += 1;
|
|
48
|
+
setScreenshotNotifications((current) => [...current, { id: nextNotificationId.current, path: detail.path, url: detail.url }]);
|
|
43
49
|
}
|
|
44
50
|
};
|
|
45
51
|
|
|
@@ -47,5 +53,15 @@ export function ScreenshotCaptureNotificationHost(): ReactElement | null {
|
|
|
47
53
|
return () => window.removeEventListener("aidevops:screenshot-captured", showScreenshotNotification);
|
|
48
54
|
}, []);
|
|
49
55
|
|
|
50
|
-
return
|
|
56
|
+
return screenshotNotifications.length > 0 ? (
|
|
57
|
+
<div className="screenshot-capture-notification-stack">
|
|
58
|
+
{screenshotNotifications.map((notification) => (
|
|
59
|
+
<ScreenshotCaptureNotification
|
|
60
|
+
key={notification.id}
|
|
61
|
+
notification={notification}
|
|
62
|
+
onDismiss={() => setScreenshotNotifications((current) => current.filter((item) => item.id !== notification.id))}
|
|
63
|
+
/>
|
|
64
|
+
))}
|
|
65
|
+
</div>
|
|
66
|
+
) : null;
|
|
51
67
|
}
|
|
@@ -298,6 +298,18 @@ code {
|
|
|
298
298
|
z-index: 20;
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
+
.screenshot-capture-notification-stack {
|
|
302
|
+
display: grid;
|
|
303
|
+
gap: 8px;
|
|
304
|
+
left: 50%;
|
|
305
|
+
max-width: min(840px, calc(100vw - 48px));
|
|
306
|
+
position: fixed;
|
|
307
|
+
top: calc(var(--desktop-titlebar-height) + 10px);
|
|
308
|
+
transform: translateX(-50%);
|
|
309
|
+
width: max-content;
|
|
310
|
+
z-index: 40;
|
|
311
|
+
}
|
|
312
|
+
|
|
301
313
|
.screenshot-capture-notification {
|
|
302
314
|
align-items: center;
|
|
303
315
|
background: color-mix(in srgb, var(--surface-elevated) 94%, transparent);
|
|
@@ -307,13 +319,9 @@ code {
|
|
|
307
319
|
color: var(--text-secondary);
|
|
308
320
|
display: flex;
|
|
309
321
|
gap: 12px;
|
|
310
|
-
left: 50%;
|
|
311
322
|
max-width: min(720px, calc(100vw - 48px));
|
|
312
323
|
padding: 8px 10px 8px 14px;
|
|
313
|
-
|
|
314
|
-
top: calc(var(--desktop-titlebar-height) + 10px);
|
|
315
|
-
transform: translateX(-50%);
|
|
316
|
-
z-index: 40;
|
|
324
|
+
width: 100%;
|
|
317
325
|
}
|
|
318
326
|
|
|
319
327
|
.screenshot-capture-notification > div {
|
|
@@ -333,31 +341,42 @@ code {
|
|
|
333
341
|
line-height: 1.25;
|
|
334
342
|
overflow: hidden;
|
|
335
343
|
text-overflow: ellipsis;
|
|
336
|
-
white-space: nowrap;
|
|
337
344
|
}
|
|
338
345
|
|
|
339
|
-
.screenshot-capture-notification button {
|
|
346
|
+
.screenshot-capture-notification .screenshot-path-button {
|
|
340
347
|
background: transparent;
|
|
341
348
|
border: 0;
|
|
342
349
|
color: var(--accent);
|
|
343
350
|
font: inherit;
|
|
344
351
|
padding: 0;
|
|
345
352
|
text-decoration: underline;
|
|
353
|
+
overflow-wrap: anywhere;
|
|
354
|
+
text-align: left;
|
|
346
355
|
}
|
|
347
356
|
|
|
348
|
-
.screenshot-capture-notification
|
|
357
|
+
.screenshot-capture-notification .screenshot-dismiss-button {
|
|
349
358
|
align-items: center;
|
|
350
359
|
background: var(--surface-muted);
|
|
351
|
-
border: 1px solid
|
|
360
|
+
border: 1px solid var(--border);
|
|
352
361
|
border-radius: 999px;
|
|
353
362
|
color: var(--text-secondary);
|
|
354
363
|
display: inline-flex;
|
|
355
364
|
flex: 0 0 auto;
|
|
356
|
-
font
|
|
357
|
-
|
|
365
|
+
font: inherit;
|
|
366
|
+
font-size: 1.1rem;
|
|
367
|
+
height: 38px;
|
|
358
368
|
justify-content: center;
|
|
359
369
|
line-height: 1;
|
|
360
|
-
|
|
370
|
+
padding: 0;
|
|
371
|
+
text-decoration: none;
|
|
372
|
+
width: 38px;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.screenshot-capture-notification .screenshot-dismiss-button:hover,
|
|
376
|
+
.screenshot-capture-notification .screenshot-dismiss-button:focus-visible {
|
|
377
|
+
border-color: var(--border-accent);
|
|
378
|
+
color: var(--accent);
|
|
379
|
+
outline: none;
|
|
361
380
|
}
|
|
362
381
|
|
|
363
382
|
.machine-rail,
|
package/setup.sh
CHANGED
|
@@ -12,7 +12,7 @@ shopt -s inherit_errexit 2>/dev/null || true
|
|
|
12
12
|
# AI Assistant Server Access Framework Setup Script
|
|
13
13
|
# Helps developers set up the framework for their infrastructure
|
|
14
14
|
#
|
|
15
|
-
# Version: 3.
|
|
15
|
+
# Version: 3.31.1
|
|
16
16
|
#
|
|
17
17
|
# Quick Install:
|
|
18
18
|
# npm install -g aidevops && aidevops update (recommended)
|