@dickpy/dsh-imagegen 1.0.4 → 1.0.6
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 +12 -6
- package/docs/images/image-generation-studio-four.png +0 -0
- package/docs/images/image-generation-studio-single.png +0 -0
- package/lib/client.js +130 -105
- package/lib/client.js.map +1 -1
- package/lib/index.js +1 -1
- package/package.json +1 -1
- package/src/client/ImageGenPanel.tsx +28 -6
- package/src/client/panel.module.css +16 -23
- package/src/protocol.ts +1 -1
package/lib/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { spawn } from "node:child_process";
|
|
|
14
14
|
/** Settings namespace this plugin owns (host settings seam + bridge). */
|
|
15
15
|
const IMAGEGEN_SETTINGS_NAMESPACE = "dsh-imagegen";
|
|
16
16
|
/** Published package version shared by the host updater and the client UI. */
|
|
17
|
-
const PLUGIN_VERSION = "1.0.
|
|
17
|
+
const PLUGIN_VERSION = "1.0.6";
|
|
18
18
|
/** Same-origin route family (loopback-only, mirroring the dsh-ssh fence). */
|
|
19
19
|
const SETTINGS_API = {
|
|
20
20
|
describe: "/api/dsh-imagegen/settings/describe",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dickpy/dsh-imagegen",
|
|
3
3
|
"description": "AI 生图 (image generation) plugin for the dsh web GUI: text-to-image and image-to-image through a configurable OpenAI-compatible endpoint (gpt-image-2 / gpt-image-1 / dall-e-3), with a settings card for api_url / api_key and a sidebar entry opening a split-pane generation studio.",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.6",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -147,6 +147,7 @@ export function ImageGenPanel(props: {
|
|
|
147
147
|
const [updateMessage, setUpdateMessage] = useState<string | null>(null)
|
|
148
148
|
const [updateResult, setUpdateResult] = useState<'success' | 'failed' | null>(null)
|
|
149
149
|
const fileInput = useRef<HTMLInputElement>(null)
|
|
150
|
+
const previewStage = useRef<HTMLDivElement>(null)
|
|
150
151
|
const elapsed = useElapsed(generating, startedAt)
|
|
151
152
|
|
|
152
153
|
// Load the host-persisted history once on mount (it lives in ~/.dsh on the
|
|
@@ -287,6 +288,19 @@ export function ImageGenPanel(props: {
|
|
|
287
288
|
return () => window.removeEventListener('keydown', onKey)
|
|
288
289
|
}, [preview])
|
|
289
290
|
|
|
291
|
+
// A scaled image owns real scrollable space, rather than being visually
|
|
292
|
+
// transformed and clipped. Recenter the viewport after every zoom or slide.
|
|
293
|
+
useEffect(() => {
|
|
294
|
+
if (preview === null) return
|
|
295
|
+
const frame = window.requestAnimationFrame(() => {
|
|
296
|
+
const stage = previewStage.current
|
|
297
|
+
if (stage === null) return
|
|
298
|
+
stage.scrollLeft = Math.max(0, (stage.scrollWidth - stage.clientWidth) / 2)
|
|
299
|
+
stage.scrollTop = Math.max(0, (stage.scrollHeight - stage.clientHeight) / 2)
|
|
300
|
+
})
|
|
301
|
+
return () => window.cancelAnimationFrame(frame)
|
|
302
|
+
}, [preview, previewScale])
|
|
303
|
+
|
|
290
304
|
/** Load a past generation's images into the canvas. */
|
|
291
305
|
const viewHistoryEntry = async (entry: HistoryEntry): Promise<void> => {
|
|
292
306
|
try {
|
|
@@ -343,6 +357,8 @@ export function ImageGenPanel(props: {
|
|
|
343
357
|
const generateDisabled = generating || !enabled || !configured
|
|
344
358
|
const viewingEntry = viewingHistoryId === null ? null : history.find(entry => entry.id === viewingHistoryId) ?? null
|
|
345
359
|
const previewImage = preview === null ? null : preview.images[preview.index] ?? null
|
|
360
|
+
const previewFrameScale = Math.max(1, previewScale)
|
|
361
|
+
const previewImageScale = previewScale / previewFrameScale
|
|
346
362
|
|
|
347
363
|
const copyPreviewPrompt = async (text: string): Promise<void> => {
|
|
348
364
|
try {
|
|
@@ -750,18 +766,24 @@ export function ImageGenPanel(props: {
|
|
|
750
766
|
) : null}
|
|
751
767
|
<figure className={css.lightboxFigure} onClick={(event) => { event.stopPropagation() }}>
|
|
752
768
|
<div
|
|
769
|
+
ref={previewStage}
|
|
753
770
|
className={css.lightboxStage}
|
|
754
771
|
onWheel={(event) => {
|
|
755
772
|
event.preventDefault()
|
|
756
773
|
setPreviewScale(current => clampPreviewScale(current + (event.deltaY < 0 ? PREVIEW_SCALE_STEP : -PREVIEW_SCALE_STEP)))
|
|
757
774
|
}}
|
|
758
775
|
>
|
|
759
|
-
<
|
|
760
|
-
className={css.
|
|
761
|
-
style={{
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
776
|
+
<div
|
|
777
|
+
className={css.lightboxScaleFrame}
|
|
778
|
+
style={{ width: `${previewFrameScale * 100}%`, height: `${previewFrameScale * 100}%` }}
|
|
779
|
+
>
|
|
780
|
+
<img
|
|
781
|
+
className={css.lightboxImage}
|
|
782
|
+
style={{ width: `${previewImageScale * 100}%`, height: `${previewImageScale * 100}%` }}
|
|
783
|
+
src={srcOf(previewImage)}
|
|
784
|
+
alt={previewImage.revisedPrompt ?? tt('preview.title')}
|
|
785
|
+
/>
|
|
786
|
+
</div>
|
|
765
787
|
</div>
|
|
766
788
|
<div className={css.lightboxTools} role="group" aria-label={tt('preview.zoomControls')}>
|
|
767
789
|
<button type="button" className={css.lightboxTool} aria-label={tt('preview.zoomOut')} title={tt('preview.zoomOut')} onClick={() => { setPreviewScale(current => clampPreviewScale(current - PREVIEW_SCALE_STEP)) }}>
|
|
@@ -801,26 +801,12 @@ html[data-dsh-imagegen-active]:not([data-dsh-taskboard-active]):not([data-dsh-ss
|
|
|
801
801
|
flex: 1;
|
|
802
802
|
min-height: 0;
|
|
803
803
|
gap: 14px;
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
.grid[data-count='1'] {
|
|
807
|
-
grid-template-columns: minmax(0, 1fr);
|
|
808
|
-
grid-template-rows: minmax(0, 1fr);
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
.grid[data-count='2'] {
|
|
812
804
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
813
|
-
grid-template-rows: minmax(0, 1fr);
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
.grid[data-count='3'] {
|
|
817
|
-
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
818
|
-
grid-template-rows: minmax(0, 1fr);
|
|
805
|
+
grid-template-rows: repeat(2, minmax(0, 1fr));
|
|
819
806
|
}
|
|
820
807
|
|
|
821
|
-
.grid[data-count='
|
|
822
|
-
grid-
|
|
823
|
-
grid-template-rows: repeat(2, minmax(0, 1fr));
|
|
808
|
+
.grid[data-count='1'] .imageCard {
|
|
809
|
+
grid-area: 1 / 1 / 3 / 3;
|
|
824
810
|
}
|
|
825
811
|
|
|
826
812
|
.imageCard {
|
|
@@ -846,7 +832,7 @@ html[data-dsh-imagegen-active]:not([data-dsh-taskboard-active]):not([data-dsh-ss
|
|
|
846
832
|
flex: 1;
|
|
847
833
|
min-height: 0;
|
|
848
834
|
width: 100%;
|
|
849
|
-
object-fit:
|
|
835
|
+
object-fit: cover;
|
|
850
836
|
background: var(--dsw-alias-bg-base);
|
|
851
837
|
}
|
|
852
838
|
|
|
@@ -1014,20 +1000,27 @@ html[data-dsh-imagegen-active]:not([data-dsh-taskboard-active]):not([data-dsh-ss
|
|
|
1014
1000
|
.lightboxStage {
|
|
1015
1001
|
flex: 1;
|
|
1016
1002
|
min-height: 0;
|
|
1017
|
-
|
|
1018
|
-
place-items: center;
|
|
1003
|
+
position: relative;
|
|
1019
1004
|
overflow: auto;
|
|
1020
1005
|
border-radius: 10px;
|
|
1021
1006
|
background: rgba(255, 255, 255, 0.04);
|
|
1022
1007
|
}
|
|
1023
1008
|
|
|
1009
|
+
.lightboxScaleFrame {
|
|
1010
|
+
display: flex;
|
|
1011
|
+
align-items: center;
|
|
1012
|
+
justify-content: center;
|
|
1013
|
+
min-width: 100%;
|
|
1014
|
+
min-height: 100%;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1024
1017
|
.lightboxImage {
|
|
1025
|
-
|
|
1026
|
-
max-
|
|
1018
|
+
display: block;
|
|
1019
|
+
max-width: 100%;
|
|
1020
|
+
max-height: 100%;
|
|
1027
1021
|
object-fit: contain;
|
|
1028
1022
|
border-radius: 10px;
|
|
1029
1023
|
box-shadow: 0 24px 80px rgba(0, 0, 0, 0.5);
|
|
1030
|
-
transition: transform 120ms ease;
|
|
1031
1024
|
}
|
|
1032
1025
|
|
|
1033
1026
|
.lightboxTools {
|
package/src/protocol.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
export const IMAGEGEN_SETTINGS_NAMESPACE = 'dsh-imagegen'
|
|
9
9
|
|
|
10
10
|
/** Published package version shared by the host updater and the client UI. */
|
|
11
|
-
export const PLUGIN_VERSION = '1.0.
|
|
11
|
+
export const PLUGIN_VERSION = '1.0.6'
|
|
12
12
|
|
|
13
13
|
/** Same-origin route family (loopback-only, mirroring the dsh-ssh fence). */
|
|
14
14
|
export const SETTINGS_API = {
|