Compare commits

...

1 Commits

Author SHA1 Message Date
CodeRabbit Fixer
cf399a556f fix: Refactor: Use Galleria lightbox for 'Open Image' instead of new tab (#9156)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 18:02:14 +01:00
5 changed files with 68 additions and 6 deletions

View File

@@ -1,7 +1,8 @@
import { useI18n } from 'vue-i18n'
import { downloadFile, openFileInNewTab } from '@/base/common/downloadUtil'
import { downloadFile } from '@/base/common/downloadUtil'
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import { useMediaAssetGalleryStore } from '@/platform/assets/composables/useMediaAssetGalleryStore'
import { useCommandStore } from '@/stores/commandStore'
import type { MenuOption } from './useMoreOptionsMenu'
@@ -23,7 +24,7 @@ export function useImageMenuOptions() {
if (!img) return
const url = new URL(img.src)
url.searchParams.delete('preview')
void openFileInNewTab(url.toString())
useMediaAssetGalleryStore().openUrl(url.toString())
}
const copyImage = async (node: LGraphNode) => {
@@ -87,7 +88,7 @@ export function useImageMenuOptions() {
},
{
label: t('contextMenu.Open Image'),
icon: 'icon-[lucide--external-link]',
icon: 'icon-[lucide--maximize]',
action: () => openImage(node)
},
{

View File

@@ -160,6 +160,37 @@ describe('useMediaAssetGalleryStore', () => {
})
})
describe('openUrl', () => {
it('should create a ResultItemImpl with overridden url getter', () => {
const store = useMediaAssetGalleryStore()
const testUrl = 'https://example.com/node-image.png'
store.openUrl(testUrl)
expect(ResultItemImpl).toHaveBeenCalledWith({
filename: 'node-image.png',
subfolder: '',
type: 'output',
nodeId: '0',
mediaType: 'images'
})
expect(store.items).toHaveLength(1)
expect(store.items[0].url).toBe(testUrl)
expect(store.activeIndex).toBe(0)
})
it('should handle urls without a filename path', () => {
const store = useMediaAssetGalleryStore()
store.openUrl('https://example.com/')
expect(ResultItemImpl).toHaveBeenCalledWith(
expect.objectContaining({ filename: '' })
)
expect(store.items[0].url).toBe('https://example.com/')
})
})
describe('close', () => {
it('should reset activeIndex to -1', () => {
const store = useMediaAssetGalleryStore()

View File

@@ -37,11 +37,32 @@ export const useMediaAssetGalleryStore = defineStore(
activeIndex.value = 0
}
const openUrl = (url: string) => {
const resultItem = new ResultItemImpl({
filename: url.split('/').pop() ?? '',
subfolder: '',
type: 'output',
nodeId: '0',
mediaType: 'images'
})
Object.defineProperty(resultItem, 'url', {
get() {
return url
},
configurable: true
})
items.value = [resultItem]
activeIndex.value = 0
}
return {
activeIndex,
items,
close,
openSingle
openSingle,
openUrl
}
}
)

View File

@@ -1,6 +1,6 @@
import _ from 'es-toolkit/compat'
import { downloadFile, openFileInNewTab } from '@/base/common/downloadUtil'
import { downloadFile } from '@/base/common/downloadUtil'
import { useSelectedLiteGraphItems } from '@/composables/canvas/useSelectedLiteGraphItems'
import { useSubgraphOperations } from '@/composables/graph/useSubgraphOperations'
import { useNodeAnimatedImage } from '@/composables/node/useNodeAnimatedImage'
@@ -35,6 +35,7 @@ import type {
ISerialisedNode
} from '@/lib/litegraph/src/types/serialisation'
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
import { useMediaAssetGalleryStore } from '@/platform/assets/composables/useMediaAssetGalleryStore'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useToastStore } from '@/platform/updates/common/toastStore'
import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'
@@ -687,7 +688,7 @@ export const useLitegraphService = () => {
callback: () => {
const url = new URL(img.src)
url.searchParams.delete('preview')
void openFileInNewTab(url.toString())
useMediaAssetGalleryStore().openUrl(url.toString())
}
},
...getCopyImageOption(img),

View File

@@ -20,6 +20,11 @@
</template>
</div>
<ResultGallery
v-model:active-index="mediaAssetGalleryStore.activeIndex"
:all-gallery-items="mediaAssetGalleryStore.items"
/>
<GlobalToast />
<InviteAcceptedToast />
<RerouteMigrationToast />
@@ -50,6 +55,7 @@ import { runWhenGlobalIdle } from '@/base/common/async'
import MenuHamburger from '@/components/MenuHamburger.vue'
import UnloadWindowConfirmDialog from '@/components/dialog/UnloadWindowConfirmDialog.vue'
import GraphCanvas from '@/components/graph/GraphCanvas.vue'
import ResultGallery from '@/components/sidebar/tabs/queue/ResultGallery.vue'
import GlobalToast from '@/components/toast/GlobalToast.vue'
import InviteAcceptedToast from '@/platform/workspace/components/toasts/InviteAcceptedToast.vue'
import RerouteMigrationToast from '@/components/toast/RerouteMigrationToast.vue'
@@ -57,6 +63,7 @@ import { useBrowserTabTitle } from '@/composables/useBrowserTabTitle'
import { useCoreCommands } from '@/composables/useCoreCommands'
import { useQueuePolling } from '@/platform/remote/comfyui/useQueuePolling'
import { useErrorHandling } from '@/composables/useErrorHandling'
import { useMediaAssetGalleryStore } from '@/platform/assets/composables/useMediaAssetGalleryStore'
import { useProgressFavicon } from '@/composables/useProgressFavicon'
import { SERVER_CONFIG_ITEMS } from '@/constants/serverConfig'
import type { ServerConfig, ServerConfigValue } from '@/constants/serverConfig'
@@ -109,6 +116,7 @@ const colorPaletteStore = useColorPaletteStore()
const queueStore = useQueueStore()
const assetsStore = useAssetsStore()
const versionCompatibilityStore = useVersionCompatibilityStore()
const mediaAssetGalleryStore = useMediaAssetGalleryStore()
const graphCanvasContainerRef = ref<HTMLDivElement | null>(null)
const { isBuilderMode } = useAppMode()
const { linearMode } = storeToRefs(useCanvasStore())