feat: Added support for Fooocus

pull/562/head
zanllp 2024-03-27 20:40:58 +08:00
parent 4595b71fe5
commit 6646af77ef
36 changed files with 139 additions and 45 deletions

View File

@ -12,7 +12,7 @@ Promise.resolve().then(async () => {
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Infinite Image Browsing</title>
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-cc113025.js"></script>
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-423bec18.js"></script>
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-4ed4b1ce.css">
</head>

View File

@ -4,4 +4,5 @@ piexif
python-dotenv
Pillow
imageio
av
av
lxml

View File

@ -93,6 +93,7 @@ def update_image_data(search_dirs: List[str], is_rebuild = False):
for k in [
"Model",
"Sampler",
"Source Identifier",
"Postprocess upscale by",
"Postprocess upscaler",
]:

View File

@ -20,11 +20,12 @@ class ComfyUIParser:
def parse(clz, img, file_path):
info = ""
params = None
if not clz.test(img):
if not clz.test(img, file_path):
raise Exception("The input image does not match the current parser.")
try:
if is_img_created_by_comfyui_with_webui_gen_info(img):
info = read_sd_webui_gen_info_from_image(img, file_path)
info += ", Source Identifier: ComfyUI"
params = parse_generation_parameters(info)
else:
params = get_comfyui_exif_data(img)
@ -41,7 +42,7 @@ class ComfyUIParser:
)
@classmethod
def test(clz, img: Image) -> bool:
def test(clz, img: Image, file_path: str) -> bool:
try:
return is_img_created_by_comfyui(
img

View File

@ -0,0 +1,69 @@
import os
import re
from PIL import Image
from scripts.iib.parsers.model import ImageGenerationInfo, ImageGenerationParams
from scripts.iib.tool import omit, parse_generation_parameters
def remove_extra_spaces(text):
return re.sub(r"\s+", " ", text)
def get_log_file(file_path: str):
dir = os.path.dirname(file_path)
with open(os.path.join(dir, "log.html")) as f:
return f.read()
class FooocusParser:
def __init__(self):
pass
@classmethod
def parse(clz, img: Image, file_path):
if not clz.test(img, file_path):
raise Exception("The input image does not match the current parser.")
from lxml import etree
log = get_log_file(file_path)
root = etree.HTML(log)
id = str(os.path.basename(file_path)).replace(".", "_")
metadata = root.xpath(f'//div[@id="{id}"]/descendant::table[@class="metadata"]')
tr_elements = metadata[0].xpath(".//tr")
# As a workaround to bypass parsing errors in the parser.
# https://github.com/jiw0220/stable-diffusion-image-metadata/blob/00b8d42d4d1a536862bba0b07c332bdebb2a0ce5/src/index.ts#L130
metadata_list_str = "Steps: Unknown , Source Identifier: Fooocus ,"
params = {"meta": {"Source Identifier": "Fooocus"}}
for tr in tr_elements:
label = tr.xpath('.//td[@class="label"]/text()')
value = tr.xpath('.//td[@class="value"]/text()')
if label:
k = label[0]
v = value[0] if value else "None"
if k == "Fooocus V2 Expansion":
continue
if k == "Prompt" or k == "Negative Prompt":
params[k] = remove_extra_spaces(v.replace("\n", "").strip())
else:
v = v.replace(",", "")
params["meta"][k] = v
metadata_list_str += f" {k}: {v},"
metadata_list_str = metadata_list_str.strip()
info = f"""{params['Prompt']}\nNegative prompt: {params['Negative Prompt']}\n{metadata_list_str}""".strip()
return ImageGenerationInfo(
info,
ImageGenerationParams(
meta=params["meta"],
pos_prompt=parse_generation_parameters(info)["pos_prompt"]
),
)
@classmethod
def test(clz, img: Image, file_path: str):
filename = os.path.basename(file_path)
try:
return get_log_file(file_path).find(filename) != -1
except Exception as e:
return False

View File

@ -1,13 +1,14 @@
from scripts.iib.parsers.comfyui import ComfyUIParser
from scripts.iib.parsers.sd_webui import SdWebUIParser
from scripts.iib.parsers.fooocus import FooocusParser
from scripts.iib.parsers.model import ImageGenerationInfo
from PIL import Image
def parse_image_info(image_path: str) -> ImageGenerationInfo:
parsers = [ComfyUIParser, SdWebUIParser]
parsers = [ComfyUIParser, FooocusParser, SdWebUIParser]
with Image.open(image_path) as img:
for parser in parsers:
if parser.test(img):
if parser.test(img, image_path):
return parser.parse(img, image_path)
raise Exception("matched parser is not found")

View File

@ -5,7 +5,7 @@ class ImageGenerationParams:
def __init__(self, meta: dict = {}, pos_prompt: list = [], extra: dict = {}) -> None:
self.meta = meta
self.pos_prompt = pos_prompt
self.extra = omit(extra, ["meta", "por_prompt"])
self.extra = omit(extra, ["meta", "pos_prompt"])
class ImageGenerationInfo:

View File

@ -13,9 +13,12 @@ class SdWebUIParser:
@classmethod
def parse(clz, img: Image, file_path):
if not clz.test(img):
if not clz.test(img, file_path):
raise Exception("The input image does not match the current parser.")
info = read_sd_webui_gen_info_from_image(img, file_path)
if not info:
return ImageGenerationInfo()
info += ", Source Identifier: Stable Diffusion web UI"
params = parse_generation_parameters(info)
return ImageGenerationInfo(
info,
@ -25,7 +28,7 @@ class SdWebUIParser:
)
@classmethod
def test(clz, img: Image):
def test(clz, img: Image, file_path: str):
try:
return True
except Exception as e:

View File

@ -364,8 +364,12 @@ def get_comfyui_exif_data(img: Image):
pass
meta = {}
KSampler_entry = data[meta_key]["inputs"]
# As a workaround to bypass parsing errors in the parser.
# https://github.com/jiw0220/stable-diffusion-image-metadata/blob/00b8d42d4d1a536862bba0b07c332bdebb2a0ce5/src/index.ts#L130
meta["Steps"] = "Unknown"
meta["Sampler"] = KSampler_entry["sampler_name"]
meta["Model"] = data[KSampler_entry["model"][0]]["inputs"]["ckpt_name"]
meta["Source Identifier"] = "ComfyUI"
def get_text_from_clip(idx: str) :
text = data[idx]["inputs"]["text"]
if isinstance(text, list): # type:CLIPTextEncode (NSP) mode:Wildcards

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{d as a,o as t,k as s,c as n,cc as _,q as o}from"./index-cc113025.js";const c={class:"img-sli-container"},i=a({__name:"ImgSliPagePane",props:{paneIdx:{},tabIdx:{},left:{},right:{}},setup(l){return(e,r)=>(t(),s("div",c,[n(_,{left:e.left,right:e.right},null,8,["left","right"])]))}});const d=o(i,[["__scopeId","data-v-ae3fb9a8"]]);export{d as default};
import{d as a,o as t,k as s,c as n,cc as _,q as o}from"./index-423bec18.js";const c={class:"img-sli-container"},i=a({__name:"ImgSliPagePane",props:{paneIdx:{},tabIdx:{},left:{},right:{}},setup(l){return(e,r)=>(t(),s("div",c,[n(_,{left:e.left,right:e.right},null,8,["left","right"])]))}});const d=o(i,[["__scopeId","data-v-ae3fb9a8"]]);export{d as default};

View File

@ -1 +1 @@
import{d as X,s as Z,a4 as ee,o as r,k as v,c as l,A as n,C as e,E as F,l as c,G as se,t as a,m as u,z as V,Q as te,p as f,R as z,U as le,V as ie,Y as D,bC as ne,q as oe}from"./index-cc113025.js";import{L as ae,R as de,f as re,S as ce}from"./fullScreenContextMenu-eb4947b3.js";import{g as me,F as ue}from"./FileItem-1cca3267.js";import{c as pe,u as ge}from"./hook-140ddf16.js";import{o as ve}from"./functionalCallableComp-92481a70.js";import"./index-fc060e0a.js";import"./index-f82c77d8.js";const fe={class:"hint"},Ie={class:"action-bar"},ke={key:1},Ce={class:"no-res-hint"},_e={class:"hint"},we={key:2,class:"preview-switch"},he=X({__name:"MatchedImageGrid",props:{tabIdx:{},paneIdx:{},selectedTagIds:{},id:{}},setup(B){const I=B,p=pe(t=>ne(I.selectedTagIds,t)),{queue:R,images:o,onContextMenuClickU:k,stackViewEl:G,previewIdx:d,previewing:C,onPreviewVisibleChange:E,previewImgMove:_,canPreview:w,itemSize:h,gridItems:N,showGenInfo:m,imageGenInfo:b,q:U,multiSelectedIdxs:x,onFileItemClick:J,scroller:y,showMenuIdx:g,onFileDragStart:L,onFileDragEnd:P,cellWidth:q,onScroll:M,saveAllFileAsJson:O,saveLoadedFileAsJson:Q}=ge(p);return Z(()=>I.selectedTagIds,async()=>{var t;await p.reset(),await ee(),(t=y.value)==null||t.scrollToItem(0),M()},{immediate:!0}),(t,s)=>{const W=le,Y=ie,S=D,j=D,H=ce;return r(),v("div",{class:"container",ref_key:"stackViewEl",ref:G},[l(H,{size:"large",spinning:!e(R).isIdle},{default:n(()=>{var A,T;return[l(Y,{visible:e(m),"onUpdate:visible":s[1]||(s[1]=i=>F(m)?m.value=i:null),width:"70vw","mask-closable":"",onOk:s[2]||(s[2]=i=>m.value=!1)},{cancelText:n(()=>[]),default:n(()=>[l(W,{active:"",loading:!e(U).isIdle},{default:n(()=>[c("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:s[0]||(s[0]=i=>e(se)(e(b)))},[c("div",fe,a(t.$t("doubleClickToCopy")),1),u(" "+a(e(b)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),c("div",Ie,[l(S,{onClick:e(Q)},{default:n(()=>[u(a(t.$t("saveLoadedImageAsJson")),1)]),_:1},8,["onClick"]),l(S,{onClick:e(O)},{default:n(()=>[u(a(t.$t("saveAllAsJson")),1)]),_:1},8,["onClick"])]),(A=e(o))!=null&&A.length?(r(),V(e(me),{key:0,ref_key:"scroller",ref:y,class:"file-list",items:e(o),"item-size":e(h).first,"key-field":"fullpath","item-secondary-size":e(h).second,gridItems:e(N),onScroll:e(M)},{default:n(({item:i,index:$})=>[l(ue,{idx:$,file:i,"cell-width":e(q),"show-menu-idx":e(g),"onUpdate:showMenuIdx":s[3]||(s[3]=K=>F(g)?g.value=K:null),onDragstart:e(L),onDragend:e(P),onFileItemClick:e(J),"full-screen-preview-image-url":e(o)[e(d)]?e(te)(e(o)[e(d)]):"",selected:e(x).includes($),onContextMenuClick:e(k),onPreviewVisibleChange:e(E),"is-selected-mutil-files":e(x).length>1},null,8,["idx","file","cell-width","show-menu-idx","onDragstart","onDragend","onFileItemClick","full-screen-preview-image-url","selected","onContextMenuClick","onPreviewVisibleChange","is-selected-mutil-files"])]),_:1},8,["items","item-size","item-secondary-size","gridItems","onScroll"])):e(p).load&&t.selectedTagIds.and_tags.length===1&&!((T=t.selectedTagIds.folder_paths_str)!=null&&T.trim())?(r(),v("div",ke,[c("div",Ce,[c("p",_e,a(t.$t("tagSearchNoResultsMessage")),1),l(j,{onClick:s[4]||(s[4]=i=>e(ve)()),type:"primary"},{default:n(()=>[u(a(t.$t("rebuildImageIndex")),1)]),_:1})])])):f("",!0),e(C)?(r(),v("div",we,[l(e(ae),{onClick:s[5]||(s[5]=i=>e(_)("prev")),class:z({disable:!e(w)("prev")})},null,8,["class"]),l(e(de),{onClick:s[6]||(s[6]=i=>e(_)("next")),class:z({disable:!e(w)("next")})},null,8,["class"])])):f("",!0)]}),_:1},8,["spinning"]),e(C)&&e(o)&&e(o)[e(d)]?(r(),V(re,{key:0,file:e(o)[e(d)],idx:e(d),onContextMenuClick:e(k)},null,8,["file","idx","onContextMenuClick"])):f("",!0)],512)}}});const $e=oe(he,[["__scopeId","data-v-d36b6e6b"]]);export{$e as default};
import{d as X,s as Z,a4 as ee,o as r,k as v,c as l,A as n,C as e,E as F,l as c,G as se,t as a,m as u,z as V,Q as te,p as f,R as z,U as le,V as ie,Y as D,bC as ne,q as oe}from"./index-423bec18.js";import{L as ae,R as de,f as re,S as ce}from"./fullScreenContextMenu-b87ca1f9.js";import{g as me,F as ue}from"./FileItem-08fb0ce5.js";import{c as pe,u as ge}from"./hook-edaa5e66.js";import{o as ve}from"./functionalCallableComp-81426c02.js";import"./index-8ac7462b.js";import"./index-fc855220.js";const fe={class:"hint"},Ie={class:"action-bar"},ke={key:1},Ce={class:"no-res-hint"},_e={class:"hint"},we={key:2,class:"preview-switch"},he=X({__name:"MatchedImageGrid",props:{tabIdx:{},paneIdx:{},selectedTagIds:{},id:{}},setup(B){const I=B,p=pe(t=>ne(I.selectedTagIds,t)),{queue:R,images:o,onContextMenuClickU:k,stackViewEl:G,previewIdx:d,previewing:C,onPreviewVisibleChange:E,previewImgMove:_,canPreview:w,itemSize:h,gridItems:N,showGenInfo:m,imageGenInfo:b,q:U,multiSelectedIdxs:x,onFileItemClick:J,scroller:y,showMenuIdx:g,onFileDragStart:L,onFileDragEnd:P,cellWidth:q,onScroll:M,saveAllFileAsJson:O,saveLoadedFileAsJson:Q}=ge(p);return Z(()=>I.selectedTagIds,async()=>{var t;await p.reset(),await ee(),(t=y.value)==null||t.scrollToItem(0),M()},{immediate:!0}),(t,s)=>{const W=le,Y=ie,S=D,j=D,H=ce;return r(),v("div",{class:"container",ref_key:"stackViewEl",ref:G},[l(H,{size:"large",spinning:!e(R).isIdle},{default:n(()=>{var A,T;return[l(Y,{visible:e(m),"onUpdate:visible":s[1]||(s[1]=i=>F(m)?m.value=i:null),width:"70vw","mask-closable":"",onOk:s[2]||(s[2]=i=>m.value=!1)},{cancelText:n(()=>[]),default:n(()=>[l(W,{active:"",loading:!e(U).isIdle},{default:n(()=>[c("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:s[0]||(s[0]=i=>e(se)(e(b)))},[c("div",fe,a(t.$t("doubleClickToCopy")),1),u(" "+a(e(b)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),c("div",Ie,[l(S,{onClick:e(Q)},{default:n(()=>[u(a(t.$t("saveLoadedImageAsJson")),1)]),_:1},8,["onClick"]),l(S,{onClick:e(O)},{default:n(()=>[u(a(t.$t("saveAllAsJson")),1)]),_:1},8,["onClick"])]),(A=e(o))!=null&&A.length?(r(),V(e(me),{key:0,ref_key:"scroller",ref:y,class:"file-list",items:e(o),"item-size":e(h).first,"key-field":"fullpath","item-secondary-size":e(h).second,gridItems:e(N),onScroll:e(M)},{default:n(({item:i,index:$})=>[l(ue,{idx:$,file:i,"cell-width":e(q),"show-menu-idx":e(g),"onUpdate:showMenuIdx":s[3]||(s[3]=K=>F(g)?g.value=K:null),onDragstart:e(L),onDragend:e(P),onFileItemClick:e(J),"full-screen-preview-image-url":e(o)[e(d)]?e(te)(e(o)[e(d)]):"",selected:e(x).includes($),onContextMenuClick:e(k),onPreviewVisibleChange:e(E),"is-selected-mutil-files":e(x).length>1},null,8,["idx","file","cell-width","show-menu-idx","onDragstart","onDragend","onFileItemClick","full-screen-preview-image-url","selected","onContextMenuClick","onPreviewVisibleChange","is-selected-mutil-files"])]),_:1},8,["items","item-size","item-secondary-size","gridItems","onScroll"])):e(p).load&&t.selectedTagIds.and_tags.length===1&&!((T=t.selectedTagIds.folder_paths_str)!=null&&T.trim())?(r(),v("div",ke,[c("div",Ce,[c("p",_e,a(t.$t("tagSearchNoResultsMessage")),1),l(j,{onClick:s[4]||(s[4]=i=>e(ve)()),type:"primary"},{default:n(()=>[u(a(t.$t("rebuildImageIndex")),1)]),_:1})])])):f("",!0),e(C)?(r(),v("div",we,[l(e(ae),{onClick:s[5]||(s[5]=i=>e(_)("prev")),class:z({disable:!e(w)("prev")})},null,8,["class"]),l(e(de),{onClick:s[6]||(s[6]=i=>e(_)("next")),class:z({disable:!e(w)("next")})},null,8,["class"])])):f("",!0)]}),_:1},8,["spinning"]),e(C)&&e(o)&&e(o)[e(d)]?(r(),V(re,{key:0,file:e(o)[e(d)],idx:e(d),onContextMenuClick:e(k)},null,8,["file","idx","onContextMenuClick"])):f("",!0)],512)}}});const $e=oe(he,[["__scopeId","data-v-d36b6e6b"]]);export{$e as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
vue/dist/assets/TagSearch-5e46b304.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{d as v,cd as C,bN as I,o as i,k as _,l as f,c,A as r,m as h,t as d,C as e,z,Q as F,ce as B,cf as x,Y as $,q as R}from"./index-cc113025.js";import{u as S,b as A,j as E,F as V,g as N}from"./FileItem-1cca3267.js";import"./functionalCallableComp-92481a70.js";import"./index-f82c77d8.js";import"./index-fc060e0a.js";const T={class:"actions-panel actions"},L={key:0,class:"file-list"},U={class:"hint"},j=v({__name:"batchDownload",props:{tabIdx:{},paneIdx:{},id:{}},setup(q){const{stackViewEl:w}=S().toRefs(),{itemSize:p,gridItems:k,cellWidth:b}=A(),n=E(),{selectdFiles:l}=C(n),m=I(),y=async t=>{const s=B(t);s&&n.addFiles(s.nodes)},D=async()=>{m.pushAction(async()=>{const t=await x.value.post("/zip",{paths:l.value.map(o=>o.fullpath)},{responseType:"blob"}),s=window.URL.createObjectURL(new Blob([t.data])),a=document.createElement("a");a.href=s,a.setAttribute("download",`iib_${new Date().toLocaleString()}.zip`),document.body.appendChild(a),a.click()})},g=t=>{l.value.splice(t,1)};return(t,s)=>{const a=$;return i(),_("div",{class:"container",ref_key:"stackViewEl",ref:w,onDrop:y},[f("div",T,[c(a,{onClick:s[0]||(s[0]=o=>e(n).selectdFiles=[])},{default:r(()=>[h(d(t.$t("clear")),1)]),_:1}),c(a,{onClick:D,type:"primary",loading:!e(m).isIdle},{default:r(()=>[h(d(t.$t("zipDownload")),1)]),_:1},8,["loading"])]),e(l).length?(i(),z(e(N),{key:1,ref:"scroller",class:"file-list",items:e(l).slice(),"item-size":e(p).first,"key-field":"fullpath","item-secondary-size":e(p).second,gridItems:e(k)},{default:r(({item:o,index:u})=>[c(V,{idx:u,file:o,"cell-width":e(b),"enable-close-icon":"",onCloseIconClick:H=>g(u),"full-screen-preview-image-url":e(F)(o),"enable-right-click-menu":!1},null,8,["idx","file","cell-width","onCloseIconClick","full-screen-preview-image-url"])]),_:1},8,["items","item-size","item-secondary-size","gridItems"])):(i(),_("div",L,[f("p",U,d(t.$t("batchDownloaDDragAndDropHint")),1)]))],544)}}});const J=R(j,[["__scopeId","data-v-aab31da2"]]);export{J as default};
import{d as v,cd as C,bN as I,o as i,k as _,l as f,c,A as r,m as h,t as d,C as e,z,Q as F,ce as B,cf as x,Y as $,q as R}from"./index-423bec18.js";import{u as S,b as A,j as E,F as V,g as N}from"./FileItem-08fb0ce5.js";import"./functionalCallableComp-81426c02.js";import"./index-fc855220.js";import"./index-8ac7462b.js";const T={class:"actions-panel actions"},L={key:0,class:"file-list"},U={class:"hint"},j=v({__name:"batchDownload",props:{tabIdx:{},paneIdx:{},id:{}},setup(q){const{stackViewEl:w}=S().toRefs(),{itemSize:p,gridItems:k,cellWidth:b}=A(),n=E(),{selectdFiles:l}=C(n),m=I(),y=async t=>{const s=B(t);s&&n.addFiles(s.nodes)},D=async()=>{m.pushAction(async()=>{const t=await x.value.post("/zip",{paths:l.value.map(o=>o.fullpath)},{responseType:"blob"}),s=window.URL.createObjectURL(new Blob([t.data])),a=document.createElement("a");a.href=s,a.setAttribute("download",`iib_${new Date().toLocaleString()}.zip`),document.body.appendChild(a),a.click()})},g=t=>{l.value.splice(t,1)};return(t,s)=>{const a=$;return i(),_("div",{class:"container",ref_key:"stackViewEl",ref:w,onDrop:y},[f("div",T,[c(a,{onClick:s[0]||(s[0]=o=>e(n).selectdFiles=[])},{default:r(()=>[h(d(t.$t("clear")),1)]),_:1}),c(a,{onClick:D,type:"primary",loading:!e(m).isIdle},{default:r(()=>[h(d(t.$t("zipDownload")),1)]),_:1},8,["loading"])]),e(l).length?(i(),z(e(N),{key:1,ref:"scroller",class:"file-list",items:e(l).slice(),"item-size":e(p).first,"key-field":"fullpath","item-secondary-size":e(p).second,gridItems:e(k)},{default:r(({item:o,index:u})=>[c(V,{idx:u,file:o,"cell-width":e(b),"enable-close-icon":"",onCloseIconClick:H=>g(u),"full-screen-preview-image-url":e(F)(o),"enable-right-click-menu":!1},null,8,["idx","file","cell-width","onCloseIconClick","full-screen-preview-image-url"])]),_:1},8,["items","item-size","item-secondary-size","gridItems"])):(i(),_("div",L,[f("p",U,d(t.$t("batchDownloaDDragAndDropHint")),1)]))],544)}}});const J=R(j,[["__scopeId","data-v-aab31da2"]]);export{J as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{u as w,b as k,F as y,g as x}from"./FileItem-1cca3267.js";import{d as F,r as h,c5 as C,v as D,aS as I,aW as b,o as E,k as S,c,A as V,C as e,Q as z,ce as B,cg as A,q as R}from"./index-cc113025.js";import"./functionalCallableComp-92481a70.js";import"./index-f82c77d8.js";import"./index-fc060e0a.js";const q=F({__name:"gridView",props:{tabIdx:{},paneIdx:{},id:{},removable:{type:Boolean},allowDragAndDrop:{type:Boolean},files:{},paneKey:{}},setup(p){const o=p,d=h(),{stackViewEl:m}=w().toRefs(),{itemSize:i,gridItems:u,cellWidth:f}=k(),g=C(),s=D(o.files??[]),_=async a=>{const l=B(a);o.allowDragAndDrop&&l&&(s.value=A([...s.value,...l.nodes]))},v=a=>{s.value.splice(a,1)};return I(()=>{d.pageFuncExportMap.set(o.paneKey,{getFiles:()=>b(s.value),setFiles:a=>s.value=a})}),(a,l)=>(E(),S("div",{class:"container",ref_key:"stackViewEl",ref:m,onDrop:_},[c(e(x),{ref:"scroller",class:"file-list",items:s.value.slice(),"item-size":e(i).first,"key-field":"fullpath","item-secondary-size":e(i).second,gridItems:e(u)},{default:V(({item:t,index:r})=>{var n;return[c(y,{idx:r,file:t,"cell-width":e(f),"enable-close-icon":o.removable,onCloseIconClick:K=>v(r),"full-screen-preview-image-url":e(z)(t),"extra-tags":(n=t==null?void 0:t.tags)==null?void 0:n.map(e(g).tagConvert),"enable-right-click-menu":!1},null,8,["idx","file","cell-width","enable-close-icon","onCloseIconClick","full-screen-preview-image-url","extra-tags"])]}),_:1},8,["items","item-size","item-secondary-size","gridItems"])],544))}});const M=R(q,[["__scopeId","data-v-f35f4802"]]);export{M as default};
import{u as w,b as k,F as y,g as x}from"./FileItem-08fb0ce5.js";import{d as F,r as h,c5 as C,v as D,aS as I,aW as b,o as E,k as S,c,A as V,C as e,Q as z,ce as B,cg as A,q as R}from"./index-423bec18.js";import"./functionalCallableComp-81426c02.js";import"./index-fc855220.js";import"./index-8ac7462b.js";const q=F({__name:"gridView",props:{tabIdx:{},paneIdx:{},id:{},removable:{type:Boolean},allowDragAndDrop:{type:Boolean},files:{},paneKey:{}},setup(p){const o=p,d=h(),{stackViewEl:m}=w().toRefs(),{itemSize:i,gridItems:u,cellWidth:f}=k(),g=C(),s=D(o.files??[]),_=async a=>{const l=B(a);o.allowDragAndDrop&&l&&(s.value=A([...s.value,...l.nodes]))},v=a=>{s.value.splice(a,1)};return I(()=>{d.pageFuncExportMap.set(o.paneKey,{getFiles:()=>b(s.value),setFiles:a=>s.value=a})}),(a,l)=>(E(),S("div",{class:"container",ref_key:"stackViewEl",ref:m,onDrop:_},[c(e(x),{ref:"scroller",class:"file-list",items:s.value.slice(),"item-size":e(i).first,"key-field":"fullpath","item-secondary-size":e(i).second,gridItems:e(u)},{default:V(({item:t,index:r})=>{var n;return[c(y,{idx:r,file:t,"cell-width":e(f),"enable-close-icon":o.removable,onCloseIconClick:K=>v(r),"full-screen-preview-image-url":e(z)(t),"extra-tags":(n=t==null?void 0:t.tags)==null?void 0:n.map(e(g).tagConvert),"enable-right-click-menu":!1},null,8,["idx","file","cell-width","enable-close-icon","onCloseIconClick","full-screen-preview-image-url","extra-tags"])]}),_:1},8,["items","item-size","item-secondary-size","gridItems"])],544))}});const M=R(q,[["__scopeId","data-v-f35f4802"]]);export{M as default};

View File

@ -1 +1 @@
import{bd as F,v as g,b$ as R,c0 as x,aj as A,ag as q,bN as D,b3 as j,c1 as z}from"./index-cc113025.js";import{u as G,b as L,f as O,c as Q,d as H,e as T,h as U}from"./FileItem-1cca3267.js";let W=0;const $=()=>++W,B=(o,c,{dataUpdateStrategy:l="replace"}={})=>{const n=F([""]),u=g(!1),t=g(),a=g(!1);let f=g(-1);const v=new Set,w=e=>{var s;l==="replace"?t.value=e:l==="merge"&&(A((Array.isArray(t.value)||typeof t.value>"u")&&Array.isArray(e),"数据更新策略为合并时仅可用于值为数组的情况"),t.value=[...(s=t==null?void 0:t.value)!==null&&s!==void 0?s:[],...e])},d=e=>x(void 0,void 0,void 0,function*(){if(a.value||u.value&&typeof e>"u")return!1;a.value=!0;const s=$();f.value=s;try{let r;if(typeof e=="number"){if(r=n[e],typeof r!="string")return!1}else r=n[n.length-1];const m=yield o(r);if(v.has(s))return v.delete(s),!1;w(c(m));const i=m.cursor;if((e===n.length-1||typeof e!="number")&&(u.value=!i.has_next,i.has_next)){const p=i.next_cursor||i.next;A(typeof p=="string"),n.push(p)}}finally{f.value===s&&(a.value=!1)}return!0}),h=()=>{v.add(f.value),a.value=!1},S=(e=!1)=>x(void 0,void 0,void 0,function*(){const{refetch:s,force:r}=typeof e=="object"?e:{refetch:e};r&&h(),A(!a.value),n.splice(0,n.length,""),a.value=!1,t.value=void 0,u.value=!1,s&&(yield d())}),I=()=>({next:()=>x(void 0,void 0,void 0,function*(){if(a.value)throw new Error("不允许同时迭代");return{done:!(yield d()),value:t.value}})});return R({abort:h,load:u,next:d,res:t,loading:a,cursorStack:n,reset:S,[Symbol.asyncIterator]:I,iter:{[Symbol.asyncIterator]:I}})},Y=o=>F(B(o,c=>c.files,{dataUpdateStrategy:"merge"})),Z=o=>{const c=F(new Set),l=q(()=>(o.res??[]).filter(y=>!c.has(y.fullpath))),n=D(),{stackViewEl:u,multiSelectedIdxs:t,stack:a,scroller:f}=G({images:l}).toRefs(),{itemSize:v,gridItems:w,cellWidth:d,onScroll:h}=L({fetchNext:()=>o.next()}),{showMenuIdx:S}=O(),{onFileDragStart:I,onFileDragEnd:e}=Q(),{showGenInfo:s,imageGenInfo:r,q:m,onContextMenuClick:i,onFileItemClick:p}=H({openNext:j}),{previewIdx:C,previewing:_,onPreviewVisibleChange:E,previewImgMove:M,canPreview:J}=T(),N=async(y,b,P)=>{a.value=[{curr:"",files:l.value}],await i(y,b,P)};U("removeFiles",async({paths:y})=>{y.forEach(b=>c.add(b))});const k=()=>{z(l.value)};return{images:l,scroller:f,queue:n,iter:o,onContextMenuClickU:N,stackViewEl:u,previewIdx:C,previewing:_,onPreviewVisibleChange:E,previewImgMove:M,canPreview:J,itemSize:v,gridItems:w,showGenInfo:s,imageGenInfo:r,q:m,onContextMenuClick:i,onFileItemClick:p,showMenuIdx:S,multiSelectedIdxs:t,onFileDragStart:I,onFileDragEnd:e,cellWidth:d,onScroll:h,saveLoadedFileAsJson:k,saveAllFileAsJson:async()=>{for(;!o.load;)await o.next();k()}}};export{Y as c,Z as u};
import{bd as F,v as g,b$ as R,c0 as x,aj as A,ag as q,bN as D,b3 as j,c1 as z}from"./index-423bec18.js";import{u as G,b as L,f as O,c as Q,d as H,e as T,h as U}from"./FileItem-08fb0ce5.js";let W=0;const $=()=>++W,B=(o,c,{dataUpdateStrategy:l="replace"}={})=>{const n=F([""]),u=g(!1),t=g(),a=g(!1);let f=g(-1);const v=new Set,w=e=>{var s;l==="replace"?t.value=e:l==="merge"&&(A((Array.isArray(t.value)||typeof t.value>"u")&&Array.isArray(e),"数据更新策略为合并时仅可用于值为数组的情况"),t.value=[...(s=t==null?void 0:t.value)!==null&&s!==void 0?s:[],...e])},d=e=>x(void 0,void 0,void 0,function*(){if(a.value||u.value&&typeof e>"u")return!1;a.value=!0;const s=$();f.value=s;try{let r;if(typeof e=="number"){if(r=n[e],typeof r!="string")return!1}else r=n[n.length-1];const m=yield o(r);if(v.has(s))return v.delete(s),!1;w(c(m));const i=m.cursor;if((e===n.length-1||typeof e!="number")&&(u.value=!i.has_next,i.has_next)){const p=i.next_cursor||i.next;A(typeof p=="string"),n.push(p)}}finally{f.value===s&&(a.value=!1)}return!0}),h=()=>{v.add(f.value),a.value=!1},S=(e=!1)=>x(void 0,void 0,void 0,function*(){const{refetch:s,force:r}=typeof e=="object"?e:{refetch:e};r&&h(),A(!a.value),n.splice(0,n.length,""),a.value=!1,t.value=void 0,u.value=!1,s&&(yield d())}),I=()=>({next:()=>x(void 0,void 0,void 0,function*(){if(a.value)throw new Error("不允许同时迭代");return{done:!(yield d()),value:t.value}})});return R({abort:h,load:u,next:d,res:t,loading:a,cursorStack:n,reset:S,[Symbol.asyncIterator]:I,iter:{[Symbol.asyncIterator]:I}})},Y=o=>F(B(o,c=>c.files,{dataUpdateStrategy:"merge"})),Z=o=>{const c=F(new Set),l=q(()=>(o.res??[]).filter(y=>!c.has(y.fullpath))),n=D(),{stackViewEl:u,multiSelectedIdxs:t,stack:a,scroller:f}=G({images:l}).toRefs(),{itemSize:v,gridItems:w,cellWidth:d,onScroll:h}=L({fetchNext:()=>o.next()}),{showMenuIdx:S}=O(),{onFileDragStart:I,onFileDragEnd:e}=Q(),{showGenInfo:s,imageGenInfo:r,q:m,onContextMenuClick:i,onFileItemClick:p}=H({openNext:j}),{previewIdx:C,previewing:_,onPreviewVisibleChange:E,previewImgMove:M,canPreview:J}=T(),N=async(y,b,P)=>{a.value=[{curr:"",files:l.value}],await i(y,b,P)};U("removeFiles",async({paths:y})=>{y.forEach(b=>c.add(b))});const k=()=>{z(l.value)};return{images:l,scroller:f,queue:n,iter:o,onContextMenuClickU:N,stackViewEl:u,previewIdx:C,previewing:_,onPreviewVisibleChange:E,previewImgMove:M,canPreview:J,itemSize:v,gridItems:w,showGenInfo:s,imageGenInfo:r,q:m,onContextMenuClick:i,onFileItemClick:p,showMenuIdx:S,multiSelectedIdxs:t,onFileDragStart:I,onFileDragEnd:e,cellWidth:d,onScroll:h,saveLoadedFileAsJson:k,saveAllFileAsJson:async()=>{for(;!o.load;)await o.next();k()}}};export{Y as c,Z as u};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{d as E,bg as $,v as f,s as M,_ as T,a as c,a1 as W,h as g,c as v,P as z}from"./index-cc113025.js";var G=["prefixCls","name","id","type","disabled","readonly","tabindex","autofocus","value","required"],H={prefixCls:String,name:String,id:String,type:String,defaultChecked:{type:[Boolean,Number],default:void 0},checked:{type:[Boolean,Number],default:void 0},disabled:Boolean,tabindex:{type:[Number,String]},readonly:Boolean,autofocus:Boolean,value:z.any,required:Boolean};const L=E({compatConfig:{MODE:3},name:"Checkbox",inheritAttrs:!1,props:$(H,{prefixCls:"rc-checkbox",type:"checkbox",defaultChecked:!1}),emits:["click","change"],setup:function(a,d){var t=d.attrs,h=d.emit,x=d.expose,o=f(a.checked===void 0?a.defaultChecked:a.checked),i=f();M(function(){return a.checked},function(){o.value=a.checked}),x({focus:function(){var e;(e=i.value)===null||e===void 0||e.focus()},blur:function(){var e;(e=i.value)===null||e===void 0||e.blur()}});var l=f(),m=function(e){if(!a.disabled){a.checked===void 0&&(o.value=e.target.checked),e.shiftKey=l.value;var r={target:c(c({},a),{},{checked:e.target.checked}),stopPropagation:function(){e.stopPropagation()},preventDefault:function(){e.preventDefault()},nativeEvent:e};a.checked!==void 0&&(i.value.checked=!!a.checked),h("change",r),l.value=!1}},C=function(e){h("click",e),l.value=e.shiftKey};return function(){var n,e=a.prefixCls,r=a.name,s=a.id,p=a.type,b=a.disabled,K=a.readonly,P=a.tabindex,B=a.autofocus,S=a.value,N=a.required,_=T(a,G),q=t.class,D=t.onFocus,j=t.onBlur,w=t.onKeydown,A=t.onKeypress,F=t.onKeyup,y=c(c({},_),t),O=Object.keys(y).reduce(function(k,u){return(u.substr(0,5)==="aria-"||u.substr(0,5)==="data-"||u==="role")&&(k[u]=y[u]),k},{}),R=W(e,q,(n={},g(n,"".concat(e,"-checked"),o.value),g(n,"".concat(e,"-disabled"),b),n)),V=c(c({name:r,id:s,type:p,readonly:K,disabled:b,tabindex:P,class:"".concat(e,"-input"),checked:!!o.value,autofocus:B,value:S},O),{},{onChange:m,onClick:C,onFocus:D,onBlur:j,onKeydown:w,onKeypress:A,onKeyup:F,required:N});return v("span",{class:R},[v("input",c({ref:i},V),null),v("span",{class:"".concat(e,"-inner")},null)])}}});export{L as V};
import{d as E,bg as $,v as f,s as M,_ as T,a as c,a1 as W,h as g,c as v,P as z}from"./index-423bec18.js";var G=["prefixCls","name","id","type","disabled","readonly","tabindex","autofocus","value","required"],H={prefixCls:String,name:String,id:String,type:String,defaultChecked:{type:[Boolean,Number],default:void 0},checked:{type:[Boolean,Number],default:void 0},disabled:Boolean,tabindex:{type:[Number,String]},readonly:Boolean,autofocus:Boolean,value:z.any,required:Boolean};const L=E({compatConfig:{MODE:3},name:"Checkbox",inheritAttrs:!1,props:$(H,{prefixCls:"rc-checkbox",type:"checkbox",defaultChecked:!1}),emits:["click","change"],setup:function(a,d){var t=d.attrs,h=d.emit,x=d.expose,o=f(a.checked===void 0?a.defaultChecked:a.checked),i=f();M(function(){return a.checked},function(){o.value=a.checked}),x({focus:function(){var e;(e=i.value)===null||e===void 0||e.focus()},blur:function(){var e;(e=i.value)===null||e===void 0||e.blur()}});var l=f(),m=function(e){if(!a.disabled){a.checked===void 0&&(o.value=e.target.checked),e.shiftKey=l.value;var r={target:c(c({},a),{},{checked:e.target.checked}),stopPropagation:function(){e.stopPropagation()},preventDefault:function(){e.preventDefault()},nativeEvent:e};a.checked!==void 0&&(i.value.checked=!!a.checked),h("change",r),l.value=!1}},C=function(e){h("click",e),l.value=e.shiftKey};return function(){var n,e=a.prefixCls,r=a.name,s=a.id,p=a.type,b=a.disabled,K=a.readonly,P=a.tabindex,B=a.autofocus,S=a.value,N=a.required,_=T(a,G),q=t.class,D=t.onFocus,j=t.onBlur,w=t.onKeydown,A=t.onKeypress,F=t.onKeyup,y=c(c({},_),t),O=Object.keys(y).reduce(function(k,u){return(u.substr(0,5)==="aria-"||u.substr(0,5)==="data-"||u==="role")&&(k[u]=y[u]),k},{}),R=W(e,q,(n={},g(n,"".concat(e,"-checked"),o.value),g(n,"".concat(e,"-disabled"),b),n)),V=c(c({name:r,id:s,type:p,readonly:K,disabled:b,tabindex:P,class:"".concat(e,"-input"),checked:!!o.value,autofocus:B,value:S},O),{},{onChange:m,onClick:C,onFocus:D,onBlur:j,onKeydown:w,onKeypress:A,onKeyup:F,required:N});return v("span",{class:R},[v("input",c({ref:i},V),null),v("span",{class:"".concat(e,"-inner")},null)])}}});export{L as V};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
vue/dist/index.html vendored
View File

@ -7,7 +7,7 @@
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Infinite Image Browsing</title>
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-cc113025.js"></script>
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-423bec18.js"></script>
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-4ed4b1ce.css">
</head>

View File

@ -1,6 +1,7 @@
import type { IIBI18nMap } from '.'
export const en: IIBI18nMap = {
'Source Identifier': 'Source',
openWithDefaultApp: 'Open with default app',
saveSelectedAsJson: 'Save selected image info',
saveAllAsJson: 'Save all image info',

View File

@ -1,4 +1,5 @@
export const zhHans = {
'Source Identifier': '来源',
openWithDefaultApp: '使用默认应用打开',
saveSelectedAsJson: '保存选中图像信息',
saveAllAsJson: '保存所有图像信息',

View File

@ -1,6 +1,7 @@
import type { IIBI18nMap } from '.'
export const zhHant: Partial<IIBI18nMap> = {
'Source Identifier': '來源',
openWithDefaultApp: '使用預設應用程式開啟',
saveSelectedAsJson: '儲存選取的圖像資訊',
saveAllAsJson: '儲存所有圖像資訊',

View File

@ -31,6 +31,7 @@ const tags = computed(() =>
)
const classSort = [
'custom',
'Source Identifier',
'Model',
'lora',
'lyco',

View File

@ -50,6 +50,16 @@ const emit = defineEmits<{
(type: 'contextMenuClick', e: MenuInfo, file: FileNodeInfo, idx: number): void
}>()
function reverseEscapeHtml(string: string) {
return `${string}`
.replace(/&amp;/g, '&')
.replace(/&lt;/g,'<')
.replace( /&gt;/g,'>')
.replace( /&quot;/g,'"',)
.replace( /&#39;/g,'\'');
}
watch(
() => props?.file?.fullpath,
async (path) => {
@ -59,11 +69,11 @@ watch(
q.tasks.forEach((v) => v.cancel())
q.pushAction(() => getImageGenerationInfo(path)).res.then((v) => {
imageGenInfo.value = v
cleanImageGenInfo.value = v.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;");
cleanImageGenInfo.value = v.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
})
},
{ immediate: true }
@ -107,20 +117,20 @@ function getParNode (p: any) {
function spanWrap (text: string) {
if (!text) {
return ""
return ''
}
let result = ''
const values = text.split(/[\n,]+/)
let parenthesisActive = false
for (let i = 0; i < values.length; i++) {
const trimmedValue = values[i].trim()
if (!parenthesisActive) parenthesisActive = trimmedValue.includes("(")
const cssClass = parenthesisActive ? "has-parentheses" : ""
if (!parenthesisActive) parenthesisActive = trimmedValue.includes('(')
const cssClass = parenthesisActive ? 'has-parentheses' : ''
result += `<span class="${cssClass}">${trimmedValue}</span>`
if (i < values.length - 1) {
result += ","
result += ','
}
if (parenthesisActive) parenthesisActive = !trimmedValue.includes(")")
if (parenthesisActive) parenthesisActive = !trimmedValue.includes(')')
}
return result
}
@ -250,7 +260,7 @@ const copyPositivePrompt = () => {
<code>{{ txt }}</code>
</td>
<td v-else>
{{ txt }}
{{ reverseEscapeHtml(txt) }}
</td>
</tr>
</table>