Merge pull request #126 from zanllp/feature/auto-refresh-with-tree-view-and-index-check

Add auto-refresh with tree view and index check when returning to ext…
pull/132/head
zanllp 2023-05-12 02:16:40 +08:00 committed by GitHub
commit d67fcf9394
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 324 additions and 284 deletions

View File

@ -8,8 +8,8 @@
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title> <title>Vite App</title>
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-e10b03a9.js"></script> <script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-edca4075.js"></script>
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-55967755.css"> <link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-99766f9b.css">
</head> </head>
<body> <body>

View File

@ -303,6 +303,15 @@ def infinite_image_browsing_api(_: Any, app: FastAPI, **kwargs):
"expired_dirs": expired_dirs, "expired_dirs": expired_dirs,
} }
@app.get(db_pre+"/expired_dirs")
async def get_db_expired():
conn = DataBase.get_conn()
expired_dirs = Floder.get_expired_dirs(conn)
return {
"expired": len(expired_dirs) != 0,
"expired_dirs": expired_dirs,
}
@app.post(db_pre + "/update_image_data") @app.post(db_pre + "/update_image_data")
async def update_image_db_data(): async def update_image_db_data():
try: try:

View File

@ -1 +1 @@
import{d as E,r as S,aX as L,x as Q,o as d,l as T,c as a,m as r,n as e,p as V,q as z,A as j,t as F,B as H,y as A,J as k,I as B,aM as J,L as X,Q as K}from"./index-e10b03a9.js";import{u as W,b as Y,f as Z,c as ee,d as se,e as le,i as te,j as ie,t as ae,L as ne,R as oe,k as re,S as ce}from"./fullScreenContextMenu-8784c740.js";import{g as de,M as ue}from"./db-20204a02.js";import"./index-85f87e21.js";import"./_baseIteratee-0f4d51fc.js";import"./button-955acb02.js";const me={class:"hint"},pe={key:1,class:"preview-switch"},ve=E({__name:"MatchedImageGrid",props:{tabIdx:null,paneIdx:null,selectedTagIds:null,id:null},setup(R){const u=R,l=S(),g=L();Q(()=>u.selectedTagIds,async()=>{var s;const{res:i}=g.pushAction(()=>de(u.selectedTagIds));l.value=await i,(s=m.value)==null||s.scrollToItem(0)},{immediate:!0});const m=S(),I={tabIdx:-1,target:"local",paneIdx:-1,walkMode:!1},{stackViewEl:$,multiSelectedIdxs:p,stack:G}=W().toRefs(),{itemSize:w,gridItems:N}=Y(I),{showMenuIdx:v}=Z();ee();const{showGenInfo:c,imageGenInfo:x,q:P,onContextMenuClick:O,onFileItemClick:U}=se(I,{openNext:J}),{previewIdx:n,previewing:C,onPreviewVisibleChange:q,previewImgMove:_,canPreview:y}=le(u,{scroller:m,files:l}),b=async(i,s,o)=>{G.value=[{curr:"",files:l.value}];const f=p.value.includes(o)?p.value:[o];await O(i,s,o),i.key==="deleteFiles"&&(l.value=l.value.filter((M,t)=>!f.includes(t)))};return(i,s)=>{const o=X,f=ue,M=ce;return d(),T("div",{class:"container",ref_key:"stackViewEl",ref:$},[a(M,{size:"large",spinning:!e(g).isIdle},{default:r(()=>[a(f,{visible:e(c),"onUpdate:visible":s[1]||(s[1]=t=>V(c)?c.value=t:null),width:"70vw","mask-closable":"",onOk:s[2]||(s[2]=t=>c.value=!1)},{cancelText:r(()=>[]),default:r(()=>[a(o,{active:"",loading:!e(P).isIdle},{default:r(()=>[z("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:s[0]||(s[0]=t=>e(j)(e(x)))},[z("div",me,F(i.$t("doubleClickToCopy")),1),H(" "+F(e(x)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),l.value?(d(),A(e(te),{key:0,ref_key:"scroller",ref:m,class:"file-list",items:l.value,"item-size":e(w).first,"key-field":"fullpath","item-secondary-size":e(w).second,gridItems:e(N)},{default:r(({item:t,index:h})=>[a(ie,{idx:h,file:t,"show-menu-idx":e(v),"onUpdate:showMenuIdx":s[3]||(s[3]=D=>V(v)?v.value=D:null),onFileItemClick:e(U),"full-screen-preview-image-url":l.value[e(n)]?e(ae)(l.value[e(n)]):"",selected:e(p).includes(h),onContextMenuClick:b,onPreviewVisibleChange:e(q)},null,8,["idx","file","show-menu-idx","onFileItemClick","full-screen-preview-image-url","selected","onPreviewVisibleChange"])]),_:1},8,["items","item-size","item-secondary-size","gridItems"])):k("",!0),e(C)?(d(),T("div",pe,[a(e(ne),{onClick:s[4]||(s[4]=t=>e(_)("prev")),class:B({disable:!e(y)("prev")})},null,8,["class"]),a(e(oe),{onClick:s[5]||(s[5]=t=>e(_)("next")),class:B({disable:!e(y)("next")})},null,8,["class"])])):k("",!0)]),_:1},8,["spinning"]),e(C)&&l.value&&l.value[e(n)]?(d(),A(re,{key:0,file:l.value[e(n)],idx:e(n),onContextMenuClick:b},null,8,["file","idx"])):k("",!0)],512)}}});const Ce=K(ve,[["__scopeId","data-v-a04a415f"]]);export{Ce as default}; import{d as E,r as S,aX as L,x as Q,o as d,l as T,c as a,m as r,n as e,p as V,q as z,A as j,t as F,B as H,y as A,J as k,I as B,aM as J,L as X,Q as K}from"./index-edca4075.js";import{u as W,b as Y,f as Z,c as ee,d as se,e as le,i as te,j as ie,t as ae,L as ne,R as oe,k as re,S as ce}from"./fullScreenContextMenu-f4394da9.js";import{g as de,M as ue}from"./db-0ad5acd9.js";import"./index-011a6447.js";import"./_baseIteratee-8e08e621.js";import"./button-8244f7e4.js";const me={class:"hint"},pe={key:1,class:"preview-switch"},ve=E({__name:"MatchedImageGrid",props:{tabIdx:null,paneIdx:null,selectedTagIds:null,id:null},setup(R){const u=R,l=S(),g=L();Q(()=>u.selectedTagIds,async()=>{var s;const{res:i}=g.pushAction(()=>de(u.selectedTagIds));l.value=await i,(s=m.value)==null||s.scrollToItem(0)},{immediate:!0});const m=S(),I={tabIdx:-1,target:"local",paneIdx:-1,walkMode:!1},{stackViewEl:$,multiSelectedIdxs:p,stack:G}=W().toRefs(),{itemSize:w,gridItems:N}=Y(I),{showMenuIdx:v}=Z();ee();const{showGenInfo:c,imageGenInfo:x,q:P,onContextMenuClick:O,onFileItemClick:U}=se(I,{openNext:J}),{previewIdx:n,previewing:C,onPreviewVisibleChange:q,previewImgMove:_,canPreview:y}=le(u,{scroller:m,files:l}),b=async(i,s,o)=>{G.value=[{curr:"",files:l.value}];const f=p.value.includes(o)?p.value:[o];await O(i,s,o),i.key==="deleteFiles"&&(l.value=l.value.filter((M,t)=>!f.includes(t)))};return(i,s)=>{const o=X,f=ue,M=ce;return d(),T("div",{class:"container",ref_key:"stackViewEl",ref:$},[a(M,{size:"large",spinning:!e(g).isIdle},{default:r(()=>[a(f,{visible:e(c),"onUpdate:visible":s[1]||(s[1]=t=>V(c)?c.value=t:null),width:"70vw","mask-closable":"",onOk:s[2]||(s[2]=t=>c.value=!1)},{cancelText:r(()=>[]),default:r(()=>[a(o,{active:"",loading:!e(P).isIdle},{default:r(()=>[z("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:s[0]||(s[0]=t=>e(j)(e(x)))},[z("div",me,F(i.$t("doubleClickToCopy")),1),H(" "+F(e(x)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),l.value?(d(),A(e(te),{key:0,ref_key:"scroller",ref:m,class:"file-list",items:l.value,"item-size":e(w).first,"key-field":"fullpath","item-secondary-size":e(w).second,gridItems:e(N)},{default:r(({item:t,index:h})=>[a(ie,{idx:h,file:t,"show-menu-idx":e(v),"onUpdate:showMenuIdx":s[3]||(s[3]=D=>V(v)?v.value=D:null),onFileItemClick:e(U),"full-screen-preview-image-url":l.value[e(n)]?e(ae)(l.value[e(n)]):"",selected:e(p).includes(h),onContextMenuClick:b,onPreviewVisibleChange:e(q)},null,8,["idx","file","show-menu-idx","onFileItemClick","full-screen-preview-image-url","selected","onPreviewVisibleChange"])]),_:1},8,["items","item-size","item-secondary-size","gridItems"])):k("",!0),e(C)?(d(),T("div",pe,[a(e(ne),{onClick:s[4]||(s[4]=t=>e(_)("prev")),class:B({disable:!e(y)("prev")})},null,8,["class"]),a(e(oe),{onClick:s[5]||(s[5]=t=>e(_)("next")),class:B({disable:!e(y)("next")})},null,8,["class"])])):k("",!0)]),_:1},8,["spinning"]),e(C)&&l.value&&l.value[e(n)]?(d(),A(re,{key:0,file:l.value[e(n)],idx:e(n),onContextMenuClick:b},null,8,["file","idx"])):k("",!0)],512)}}});const Ce=K(ve,[["__scopeId","data-v-a04a415f"]]);export{Ce as default};

1
vue/dist/assets/TagSearch-001cc62a.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.container[data-v-2a184aeb]{height:var(--pane-max-height);overflow:auto;display:flex;flex-direction:column;align-items:stretch}.container .generate-idx-hint[data-v-2a184aeb]{margin:64px;padding:64px;font-size:2em;text-align:center;background-color:var(--zp-secondary-background);white-space:pre-line;line-height:2.5em;border-radius:16px}.container .remove[data-v-2a184aeb]{padding:4px;position:cursor;border-radius:2px}.container .remove[data-v-2a184aeb]:hover{background-color:var(--zp-secondary-background)}.container .select[data-v-2a184aeb]{padding:8px}.container .search-bar[data-v-2a184aeb]{padding:8px;display:flex}.container .list-container[data-v-2a184aeb]{background-color:var(--zp-secondary-background);overflow:scroll}.container .tag-list[data-v-2a184aeb]{list-style:none;margin:16px;border-radius:16px;background:var(--zp-primary-background);padding:8px}.container .tag-list .cat-name[data-v-2a184aeb]{position:sticky;top:0;padding:4px 16px;background:var(--zp-primary-background);border-left:4px solid var(--primary-color);margin:4px}.container .tag-list .tag[data-v-2a184aeb]{border:2px solid var(--zp-secondary);color:var(--zp-primary);border-radius:999px;padding:4px 16px;margin:4px;display:inline-block;cursor:pointer;max-width:256px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.container .tag-list .tag.selected[data-v-2a184aeb]{color:var(--primary-color);border:2px solid var(--primary-color)}

View File

@ -1 +0,0 @@
.container[data-v-c4b1e490]{height:var(--pane-max-height);overflow:auto;display:flex;flex-direction:column;align-items:stretch}.container .generate-idx-hint[data-v-c4b1e490]{margin:64px;padding:64px;font-size:2em;text-align:center;background-color:var(--zp-secondary-background);white-space:pre-line;line-height:2.5em;border-radius:16px}.container .remove[data-v-c4b1e490]{padding:4px;position:cursor;border-radius:2px}.container .remove[data-v-c4b1e490]:hover{background-color:var(--zp-secondary-background)}.container .select[data-v-c4b1e490]{padding:8px}.container .search-bar[data-v-c4b1e490]{padding:8px;display:flex}.container .list-container[data-v-c4b1e490]{background-color:var(--zp-secondary-background);overflow:scroll}.container .tag-list[data-v-c4b1e490]{list-style:none;margin:16px;border-radius:16px;background:var(--zp-primary-background);padding:8px}.container .tag-list .cat-name[data-v-c4b1e490]{position:sticky;top:0;padding:4px 16px;background:var(--zp-primary-background);border-left:4px solid var(--primary-color);margin:4px}.container .tag-list .tag[data-v-c4b1e490]{border:2px solid var(--zp-secondary);color:var(--zp-primary);border-radius:999px;padding:4px 16px;margin:4px;display:inline-block;cursor:pointer;max-width:256px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.container .tag-list .tag.selected[data-v-c4b1e490]{color:var(--primary-color);border:2px solid var(--primary-color)}

View File

@ -1 +0,0 @@
import{ap as J,ao as X,c2 as K,bR as W,d as Y,v as Z,aX as ee,U as M,r as $,V as ae,ac as te,o as c,l as g,J as b,s as B,q as S,c as C,n as d,S as se,y as T,m as A,B as I,t as _,C as V,I as ne,c6 as oe,z,b5 as re,c7 as le,bs as D,T as N,Q as ie}from"./index-e10b03a9.js";import{I as ue,_ as ce}from"./index-8eb4bcf4.js";import"./index-9ce39af0.js";import{c as E,u as de,e as pe,M as me,r as ge}from"./db-20204a02.js";import{b as ve}from"./_baseIteratee-0f4d51fc.js";import{B as F}from"./button-955acb02.js";function fe(s,n,t,l){for(var u=-1,a=s==null?0:s.length;++u<a;){var o=s[u];n(l,o,t(o),s)}return l}function _e(s){return function(n,t,l){for(var u=-1,a=Object(n),o=l(n),v=o.length;v--;){var k=o[s?v:++u];if(t(a[k],k,a)===!1)break}return n}}var ye=_e();const he=ye;function be(s,n){return s&&he(s,n,J)}function ke(s,n){return function(t,l){if(t==null)return t;if(!X(t))return s(t,l);for(var u=t.length,a=n?u:-1,o=Object(t);(n?a--:++a<u)&&l(o[a],a,o)!==!1;);return t}}var Ce=ke(be);const Ie=Ce;function we(s,n,t,l){return Ie(s,function(u,a,o){n(l,u,t(u),o)}),l}function xe(s,n){return function(t,l){var u=K(t)?fe:we,a=n?n():{};return u(t,s,ve(l),a)}}var $e=Object.prototype,Be=$e.hasOwnProperty,Se=xe(function(s,n,t){Be.call(s,t)?s[t].push(n):W(s,t,[n])});const Te=Se,Ae={class:"container"},Oe={class:"search-bar"},Me={key:0,class:"generate-idx-hint"},Ne={class:"list-container"},Pe={class:"cat-name"},Ve=["onClick"],ze=["onClickCapture"],De=Y({__name:"TagSearch",props:{tabIdx:null,paneIdx:null},setup(s){const n=s,t=Z(),l=ee(),u=M(()=>!l.isIdle),a=$(),o=$(new Set),v=M(()=>a.value?a.value.tags.slice().sort((e,r)=>r.count-e.count):[]),k=["custom","Model","lora","pos","size","Postprocess upscaler","Postprocess upscale by","Sampler"].reduce((e,r,m)=>(e[r]=m,e),{}),U=M(()=>Object.entries(Te(v.value,e=>e.type)).sort((e,r)=>k[e[0]]-k[r[0]])),q=ae();te(async()=>{a.value=await E(),a.value.img_count&&a.value.expired&&P()});const P=async()=>{l.pushAction(async()=>{await de(),a.value=await E()})},G=()=>{t.openTagSearchMatchedImageGridInRight(n.tabIdx,q,Array.from(o.value))},O=(e,r=!1)=>(r?`[${e.type}] `:"")+(e.display_name?`${e.display_name} : ${e.name}`:e.name),w=$(!1),y=$(""),R=async()=>{var r,m,f;if(!y.value){w.value=!1;return}const e=await l.pushAction(()=>pe({tag_name:y.value})).res;e.type!=="custom"&&D.error(N("existInOtherType")),(r=a.value)!=null&&r.tags.find(h=>h.id===e.id)?D.error(N("alreadyExists")):((m=a.value)==null||m.tags.push(e),(f=t.conf)==null||f.all_custom_tags.push(e)),y.value="",w.value=!1},j=e=>{me.confirm({title:N("confirmDelete"),async onOk(){var m,f,h,x;await ge({tag_id:e});const r=((m=a.value)==null?void 0:m.tags.findIndex(i=>i.id===e))??-1;(f=a.value)==null||f.tags.splice(r,1),(x=t.conf)==null||x.all_custom_tags.splice((h=t.conf)==null?void 0:h.all_custom_tags.findIndex(i=>i.id===e),1)}})};return(e,r)=>{const m=F,f=ue,h=F,x=ce;return c(),g("div",Ae,[b("",!0),a.value?(c(),g(B,{key:1},[S("div",null,[S("div",Oe,[C(d(se),{conv:{value:i=>i.id,text:O,optionText:i=>O(i,!0)},mode:"multiple",style:{width:"100%"},options:d(v),value:Array.from(o.value),disabled:!d(v).length,placeholder:"Select tags to match images","onUpdate:value":r[0]||(r[0]=i=>o.value=new Set(i))},null,8,["conv","options","value","disabled"]),a.value.expired||!a.value.img_count?(c(),T(m,{key:0,onClick:P,loading:!d(l).isIdle,type:"primary"},{default:A(()=>[I(_(a.value.img_count===0?e.$t("generateIndexHint"):e.$t("UpdateIndex")),1)]),_:1},8,["loading"])):(c(),T(m,{key:1,type:"primary",onClick:G,loading:!d(l).isIdle,disabled:!o.value.size},{default:A(()=>[I(_(e.$t("search")),1)]),_:1},8,["loading","disabled"]))])]),d(v).filter(i=>i.type!=="custom").length?b("",!0):(c(),g("p",Me,_(e.$t("needGenerateIdx")),1)),S("div",Ne,[(c(!0),g(B,null,V(d(U),([i,L])=>(c(),g("ul",{class:"tag-list",key:i},[S("h3",Pe,_(e.$t(i)),1),(c(!0),g(B,null,V(L,(p,Q)=>(c(),g("li",{key:p.id,class:ne(["tag",{selected:o.value.has(p.id)}]),onClick:H=>o.value.has(p.id)?o.value.delete(p.id):o.value.add(p.id)},[o.value.has(p.id)?(c(),T(d(oe),{key:0})):b("",!0),I(" "+_(O(p))+" ",1),i==="custom"&&Q!==0?(c(),g("span",{key:1,class:"remove",onClickCapture:z(H=>j(p.id),["stop"])},[C(d(re))],40,ze)):b("",!0)],10,Ve))),128)),i==="custom"?(c(),g("li",{key:0,class:"tag",onClick:r[2]||(r[2]=p=>w.value=!0)},[w.value?(c(),T(x,{key:0,compact:""},{default:A(()=>[C(f,{value:y.value,"onUpdate:value":r[1]||(r[1]=p=>y.value=p),style:{width:"128px"},loading:d(u),"allow-clear":"",size:"small"},null,8,["value","loading"]),C(h,{size:"small",type:"primary",onClickCapture:z(R,["stop"]),loading:d(u)},{default:A(()=>[I(_(y.value?e.$t("submit"):e.$t("cancel")),1)]),_:1},8,["onClickCapture","loading"])]),_:1})):(c(),g(B,{key:1},[C(d(le)),I(" "+_(e.$t("add")),1)],64))])):b("",!0)]))),128))])],64)):b("",!0)])}}});const je=ie(De,[["__scopeId","data-v-c4b1e490"]]);export{je as default};

View File

@ -1 +1 @@
import{cl as A,cm as P,ce as _,c4 as b,cn as m,bj as C,ap as w,aO as h,co as E,aQ as g,cp as R,aM as x,c2 as D}from"./index-e10b03a9.js";var G=A(Object.getPrototypeOf,Object);const J=G;function y(e,n){for(var r=0;r<n.length;r++){var t=n[r];t.enumerable=t.enumerable||!1,t.configurable=!0,"value"in t&&(t.writable=!0),Object.defineProperty(e,P(t.key),t)}}function W(e,n,r){return n&&y(e.prototype,n),r&&y(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e}function X(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}function M(e){return function(n){return n==null?void 0:n[e]}}var F=function(){return _()&&window.document.documentElement},a,Y=function(){if(!F())return!1;if(a!==void 0)return a;var n=document.createElement("div");return n.style.display="flex",n.style.flexDirection="column",n.style.rowGap="1px",n.appendChild(document.createElement("div")),n.appendChild(document.createElement("div")),document.body.appendChild(n),a=n.scrollHeight===1,document.body.removeChild(n),a},I=1,L=2;function S(e,n,r,t){var i=r.length,o=i,s=!t;if(e==null)return!o;for(e=Object(e);i--;){var f=r[i];if(s&&f[2]?f[1]!==e[f[0]]:!(f[0]in e))return!1}for(;++i<o;){f=r[i];var u=f[0],l=e[u],c=f[1];if(s&&f[2]){if(l===void 0&&!(u in e))return!1}else{var d=new b;if(t)var p=t(l,c,u,e,n,d);if(!(p===void 0?m(c,l,I|L,t,d):p))return!1}}return!0}function O(e){return e===e&&!C(e)}function U(e){for(var n=w(e),r=n.length;r--;){var t=n[r],i=e[t];n[r]=[t,i,O(i)]}return n}function v(e,n){return function(r){return r==null?!1:r[e]===n&&(n!==void 0||e in Object(r))}}function K(e){var n=U(e);return n.length==1&&n[0][2]?v(n[0][0],n[0][1]):function(r){return r===e||S(r,e,n)}}function T(e,n,r){var t=e==null?void 0:h(e,n);return t===void 0?r:t}var $=1,N=2;function q(e,n){return E(e)&&O(n)?v(g(e),n):function(r){var t=T(r,e);return t===void 0&&t===n?R(r,e):m(n,t,$|N)}}function H(e){return function(n){return h(n,e)}}function Q(e){return E(e)?M(g(e)):H(e)}function Z(e){return typeof e=="function"?e:e==null?x:typeof e=="object"?D(e)?q(e[0],e[1]):K(e):Q(e)}export{W as _,X as a,Z as b,F as c,Y as d,J as g}; import{cn as A,co as P,cg as _,c6 as b,cp as m,bj as C,ap as w,aO as g,cq as h,aQ as E,cr as R,aM as x,c4 as D}from"./index-edca4075.js";var G=A(Object.getPrototypeOf,Object);const J=G;function y(e,n){for(var r=0;r<n.length;r++){var t=n[r];t.enumerable=t.enumerable||!1,t.configurable=!0,"value"in t&&(t.writable=!0),Object.defineProperty(e,P(t.key),t)}}function W(e,n,r){return n&&y(e.prototype,n),r&&y(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e}function X(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}function M(e){return function(n){return n==null?void 0:n[e]}}var F=function(){return _()&&window.document.documentElement},a,Y=function(){if(!F())return!1;if(a!==void 0)return a;var n=document.createElement("div");return n.style.display="flex",n.style.flexDirection="column",n.style.rowGap="1px",n.appendChild(document.createElement("div")),n.appendChild(document.createElement("div")),document.body.appendChild(n),a=n.scrollHeight===1,document.body.removeChild(n),a},I=1,L=2;function S(e,n,r,t){var i=r.length,o=i,s=!t;if(e==null)return!o;for(e=Object(e);i--;){var f=r[i];if(s&&f[2]?f[1]!==e[f[0]]:!(f[0]in e))return!1}for(;++i<o;){f=r[i];var u=f[0],l=e[u],c=f[1];if(s&&f[2]){if(l===void 0&&!(u in e))return!1}else{var d=new b;if(t)var p=t(l,c,u,e,n,d);if(!(p===void 0?m(c,l,I|L,t,d):p))return!1}}return!0}function O(e){return e===e&&!C(e)}function U(e){for(var n=w(e),r=n.length;r--;){var t=n[r],i=e[t];n[r]=[t,i,O(i)]}return n}function v(e,n){return function(r){return r==null?!1:r[e]===n&&(n!==void 0||e in Object(r))}}function K(e){var n=U(e);return n.length==1&&n[0][2]?v(n[0][0],n[0][1]):function(r){return r===e||S(r,e,n)}}function T(e,n,r){var t=e==null?void 0:g(e,n);return t===void 0?r:t}var $=1,q=2;function N(e,n){return h(e)&&O(n)?v(E(e),n):function(r){var t=T(r,e);return t===void 0&&t===n?R(r,e):m(n,t,$|q)}}function H(e){return function(n){return g(n,e)}}function Q(e){return h(e)?M(E(e)):H(e)}function Z(e){return typeof e=="function"?e:e==null?x:typeof e=="object"?D(e)?N(e[0],e[1]):K(e):Q(e)}export{W as _,X as a,Z as b,F as c,Y as d,J as g};

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{c as y,R as F,d as L,v as B,T as w,U as D,o,l,q as s,t as r,J as h,n as d,z as k,s as v,C as g,m as M,B as N,V as I,W as V,X as j,Y as H,Z as P,Q as R}from"./index-e10b03a9.js";import{B as A}from"./button-955acb02.js";var E={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M688 312v-48c0-4.4-3.6-8-8-8H296c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h384c4.4 0 8-3.6 8-8zm-392 88c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h184c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H296zm376 116c-119.3 0-216 96.7-216 216s96.7 216 216 216 216-96.7 216-216-96.7-216-216-216zm107.5 323.5C750.8 868.2 712.6 884 672 884s-78.8-15.8-107.5-44.5C535.8 810.8 520 772.6 520 732s15.8-78.8 44.5-107.5C593.2 595.8 631.4 580 672 580s78.8 15.8 107.5 44.5C808.2 653.2 824 691.4 824 732s-15.8 78.8-44.5 107.5zM761 656h-44.3c-2.6 0-5 1.2-6.5 3.3l-63.5 87.8-23.1-31.9a7.92 7.92 0 00-6.5-3.3H573c-6.5 0-10.3 7.4-6.5 12.7l73.8 102.1c3.2 4.4 9.7 4.4 12.9 0l114.2-158c3.9-5.3.1-12.7-6.4-12.7zM440 852H208V148h560v344c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V108c0-17.7-14.3-32-32-32H168c-17.7 0-32 14.3-32 32v784c0 17.7 14.3 32 32 32h272c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z"}}]},name:"file-done",theme:"outlined"};const T=E;function S(a){for(var c=1;c<arguments.length;c++){var t=arguments[c]!=null?Object(arguments[c]):{},i=Object.keys(t);typeof Object.getOwnPropertySymbols=="function"&&(i=i.concat(Object.getOwnPropertySymbols(t).filter(function(u){return Object.getOwnPropertyDescriptor(t,u).enumerable}))),i.forEach(function(u){W(a,u,t[u])})}return a}function W(a,c,t){return c in a?Object.defineProperty(a,c,{value:t,enumerable:!0,configurable:!0,writable:!0}):a[c]=t,a}var C=function(c,t){var i=S({},c,t.attrs);return y(F,S({},i,{icon:T}),null)};C.displayName="FileDoneOutlined";C.inheritAttrs=!1;const Q=C,q=a=>(H("data-v-fd61e9cd"),a=a(),P(),a),G={class:"container"},J={class:"header"},U=q(()=>s("div",{"flex-placeholder":""},null,-1)),X={class:"last-record"},Y=["onClick"],Z=q(()=>s("a",{href:"https://github.com/zanllp/sd-webui-infinite-image-browsing/issues/90",target:"_blank",class:"last-record",style:{color:"unset"}},"FAQ / 常见问题",-1)),K={class:"content"},ee={key:0,class:"quick-start"},te={key:1,class:"quick-start"},se=["onClick"],ne={class:"quick-start__text line-clamp-1"},ae={class:"quick-start"},oe=["onClick"],le={class:"quick-start__text line-clamp-1"},ce={key:2,class:"quick-start"},re=["onClick"],ie={class:"quick-start__text line-clamp-1"},ue=L({__name:"emptyStartup",props:{tabIdx:null,paneIdx:null},setup(a){const c=a,t=B(),i={local:w("local"),"tag-search":w("imgSearch"),"global-setting":w("globalSettings")},u=(e,_,f=!1)=>{let p;switch(e){case"tag-search-matched-image-grid":return;case"global-setting":case"tag-search":case"empty":p={type:e,name:i[e],key:Date.now()+I()};break;case"local":p={type:e,name:i[e],key:Date.now()+I(),path:_,walkMode:f}}const n=t.tabList[c.tabIdx];n.panes.splice(c.paneIdx,1,p),n.key=p.key},m=D(()=>{var e;return(e=t.lastTabListRecord)==null?void 0:e[1]});console.log(m.value);const O=D(()=>t.autoCompletedDirList.filter(({key:e})=>e==="outdir_txt2img_samples"||e==="outdir_img2img_samples")),$=window.parent!==window,z=()=>window.parent.open("/infinite_image_browsing"),x=()=>{V(m.value),t.tabList=m.value.tabs.map(e=>j(e,!0)),t.tabList.forEach(e=>{e.panes.forEach(_=>{typeof _.name!="string"&&(_.name="")})})};return(e,_)=>{var p;const f=A;return o(),l("div",G,[s("div",J,[s("h1",null,r(e.$t("welcome")),1),U,$?(o(),l("div",{key:0,class:"last-record",onClick:z},[s("a",null,r(e.$t("openInNewWindow")),1)])):h("",!0),s("div",X,[(p=d(m))!=null&&p.tabs.length?(o(),l("a",{key:0,onClick:k(x,["prevent"])},r(e.$t("restoreLastRecord")),9,Y)):h("",!0)]),Z]),s("div",K,[d(O).length?(o(),l("div",ee,[s("h2",null,r(e.$t("walkMode")),1),s("ul",null,[(o(!0),l(v,null,g(d(O),n=>(o(),l("li",{key:n.dir,class:"quick-start__item"},[y(f,{onClick:b=>u("local",n.dir,!0),ghost:"",type:"primary",block:""},{default:M(()=>[N(r(n.zh),1)]),_:2},1032,["onClick"])]))),128))])])):h("",!0),d(t).autoCompletedDirList.length?(o(),l("div",te,[s("h2",null,r(e.$t("launchFromQuickMove")),1),s("ul",null,[(o(!0),l(v,null,g(d(t).autoCompletedDirList,n=>(o(),l("li",{key:n.key,class:"quick-start__item",onClick:k(b=>u("local",n.dir),["prevent"])},[s("span",ne,r(n.zh),1)],8,se))),128))])])):h("",!0),s("div",ae,[s("h2",null,r(e.$t("launch")),1),s("ul",null,[(o(!0),l(v,null,g(Object.keys(i),n=>(o(),l("li",{key:n,class:"quick-start__item",onClick:k(b=>u(n),["prevent"])},[s("span",le,r(i[n]),1)],8,oe))),128))])]),d(t).recent.length?(o(),l("div",ce,[s("h2",null,r(e.$t("recent")),1),s("ul",null,[(o(!0),l(v,null,g(d(t).recent,n=>(o(),l("li",{key:n.key,class:"quick-start__item",onClick:k(b=>u("local",n.path),["prevent"])},[y(d(Q),{class:"quick-start__icon"}),s("span",ie,r(n.path),1)],8,re))),128))])])):h("",!0)])])}}});const _e=R(ue,[["__scopeId","data-v-fd61e9cd"]]);export{_e as default}; import{c as y,R as F,d as L,v as B,T as w,U as D,o,l,q as s,t as r,J as h,n as d,z as k,s as v,C as g,m as M,B as N,V as I,W as V,X as j,Y as H,Z as P,Q as R}from"./index-edca4075.js";import{B as A}from"./button-8244f7e4.js";var E={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M688 312v-48c0-4.4-3.6-8-8-8H296c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h384c4.4 0 8-3.6 8-8zm-392 88c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h184c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8H296zm376 116c-119.3 0-216 96.7-216 216s96.7 216 216 216 216-96.7 216-216-96.7-216-216-216zm107.5 323.5C750.8 868.2 712.6 884 672 884s-78.8-15.8-107.5-44.5C535.8 810.8 520 772.6 520 732s15.8-78.8 44.5-107.5C593.2 595.8 631.4 580 672 580s78.8 15.8 107.5 44.5C808.2 653.2 824 691.4 824 732s-15.8 78.8-44.5 107.5zM761 656h-44.3c-2.6 0-5 1.2-6.5 3.3l-63.5 87.8-23.1-31.9a7.92 7.92 0 00-6.5-3.3H573c-6.5 0-10.3 7.4-6.5 12.7l73.8 102.1c3.2 4.4 9.7 4.4 12.9 0l114.2-158c3.9-5.3.1-12.7-6.4-12.7zM440 852H208V148h560v344c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V108c0-17.7-14.3-32-32-32H168c-17.7 0-32 14.3-32 32v784c0 17.7 14.3 32 32 32h272c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z"}}]},name:"file-done",theme:"outlined"};const T=E;function S(a){for(var c=1;c<arguments.length;c++){var t=arguments[c]!=null?Object(arguments[c]):{},i=Object.keys(t);typeof Object.getOwnPropertySymbols=="function"&&(i=i.concat(Object.getOwnPropertySymbols(t).filter(function(u){return Object.getOwnPropertyDescriptor(t,u).enumerable}))),i.forEach(function(u){W(a,u,t[u])})}return a}function W(a,c,t){return c in a?Object.defineProperty(a,c,{value:t,enumerable:!0,configurable:!0,writable:!0}):a[c]=t,a}var C=function(c,t){var i=S({},c,t.attrs);return y(F,S({},i,{icon:T}),null)};C.displayName="FileDoneOutlined";C.inheritAttrs=!1;const Q=C,q=a=>(H("data-v-fd61e9cd"),a=a(),P(),a),G={class:"container"},J={class:"header"},U=q(()=>s("div",{"flex-placeholder":""},null,-1)),X={class:"last-record"},Y=["onClick"],Z=q(()=>s("a",{href:"https://github.com/zanllp/sd-webui-infinite-image-browsing/issues/90",target:"_blank",class:"last-record",style:{color:"unset"}},"FAQ / 常见问题",-1)),K={class:"content"},ee={key:0,class:"quick-start"},te={key:1,class:"quick-start"},se=["onClick"],ne={class:"quick-start__text line-clamp-1"},ae={class:"quick-start"},oe=["onClick"],le={class:"quick-start__text line-clamp-1"},ce={key:2,class:"quick-start"},re=["onClick"],ie={class:"quick-start__text line-clamp-1"},ue=L({__name:"emptyStartup",props:{tabIdx:null,paneIdx:null},setup(a){const c=a,t=B(),i={local:w("local"),"tag-search":w("imgSearch"),"global-setting":w("globalSettings")},u=(e,_,f=!1)=>{let p;switch(e){case"tag-search-matched-image-grid":return;case"global-setting":case"tag-search":case"empty":p={type:e,name:i[e],key:Date.now()+I()};break;case"local":p={type:e,name:i[e],key:Date.now()+I(),path:_,walkMode:f}}const n=t.tabList[c.tabIdx];n.panes.splice(c.paneIdx,1,p),n.key=p.key},m=D(()=>{var e;return(e=t.lastTabListRecord)==null?void 0:e[1]});console.log(m.value);const O=D(()=>t.autoCompletedDirList.filter(({key:e})=>e==="outdir_txt2img_samples"||e==="outdir_img2img_samples")),$=window.parent!==window,z=()=>window.parent.open("/infinite_image_browsing"),x=()=>{V(m.value),t.tabList=m.value.tabs.map(e=>j(e,!0)),t.tabList.forEach(e=>{e.panes.forEach(_=>{typeof _.name!="string"&&(_.name="")})})};return(e,_)=>{var p;const f=A;return o(),l("div",G,[s("div",J,[s("h1",null,r(e.$t("welcome")),1),U,$?(o(),l("div",{key:0,class:"last-record",onClick:z},[s("a",null,r(e.$t("openInNewWindow")),1)])):h("",!0),s("div",X,[(p=d(m))!=null&&p.tabs.length?(o(),l("a",{key:0,onClick:k(x,["prevent"])},r(e.$t("restoreLastRecord")),9,Y)):h("",!0)]),Z]),s("div",K,[d(O).length?(o(),l("div",ee,[s("h2",null,r(e.$t("walkMode")),1),s("ul",null,[(o(!0),l(v,null,g(d(O),n=>(o(),l("li",{key:n.dir,class:"quick-start__item"},[y(f,{onClick:b=>u("local",n.dir,!0),ghost:"",type:"primary",block:""},{default:M(()=>[N(r(n.zh),1)]),_:2},1032,["onClick"])]))),128))])])):h("",!0),d(t).autoCompletedDirList.length?(o(),l("div",te,[s("h2",null,r(e.$t("launchFromQuickMove")),1),s("ul",null,[(o(!0),l(v,null,g(d(t).autoCompletedDirList,n=>(o(),l("li",{key:n.key,class:"quick-start__item",onClick:k(b=>u("local",n.dir),["prevent"])},[s("span",ne,r(n.zh),1)],8,se))),128))])])):h("",!0),s("div",ae,[s("h2",null,r(e.$t("launch")),1),s("ul",null,[(o(!0),l(v,null,g(Object.keys(i),n=>(o(),l("li",{key:n,class:"quick-start__item",onClick:k(b=>u(n),["prevent"])},[s("span",le,r(i[n]),1)],8,oe))),128))])]),d(t).recent.length?(o(),l("div",ce,[s("h2",null,r(e.$t("recent")),1),s("ul",null,[(o(!0),l(v,null,g(d(t).recent,n=>(o(),l("li",{key:n.key,class:"quick-start__item",onClick:k(b=>u("local",n.path),["prevent"])},[y(d(Q),{class:"quick-start__icon"}),s("span",ie,r(n.path),1)],8,re))),128))])])):h("",!0)])])}}});const _e=R(ue,[["__scopeId","data-v-fd61e9cd"]]);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

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/index-4aeb0932.js vendored Normal file
View File

@ -0,0 +1 @@
import{aN as n,cd as c}from"./index-edca4075.js";import{g as a}from"./_baseIteratee-8e08e621.js";var i="[object Object]",s=Function.prototype,p=Object.prototype,e=s.toString,f=p.hasOwnProperty,b=e.call(Object);function l(o){if(!n(o)||c(o)!=i)return!1;var r=a(o);if(r===null)return!0;var t=f.call(r,"constructor")&&r.constructor;return typeof t=="function"&&t instanceof t&&e.call(t)==b}export{l as i};

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 +0,0 @@
import{aN as n,cb as c}from"./index-e10b03a9.js";import{g as a}from"./_baseIteratee-0f4d51fc.js";var i="[object Object]",s=Function.prototype,p=Object.prototype,e=s.toString,b=p.hasOwnProperty,f=e.call(Object);function l(o){if(!n(o)||c(o)!=i)return!1;var r=a(o);if(r===null)return!0;var t=b.call(r,"constructor")&&r.constructor;return typeof t=="function"&&t instanceof t&&e.call(t)==f}export{l as i};

File diff suppressed because one or more lines are too long

169
vue/dist/assets/index-edca4075.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

4
vue/dist/index.html vendored
View File

@ -7,8 +7,8 @@
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title> <title>Vite App</title>
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-e10b03a9.js"></script> <script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-edca4075.js"></script>
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-55967755.css"> <link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-99766f9b.css">
</head> </head>
<body> <body>

View File

@ -21,6 +21,12 @@ export const getDbBasicInfo = async () => {
return resp.data as DataBaseBasicInfo return resp.data as DataBaseBasicInfo
} }
export const getExpiredDirs = async () => {
const resp = await axiosInst.get('/db/expired_dirs')
return resp.data as Pick<DataBaseBasicInfo, 'expired' | 'expired_dirs'>
}
export const updateImageData = async () => { export const updateImageData = async () => {
await axiosInst.post('/db/update_image_data', {}, { timeout: Infinity }) await axiosInst.post('/db/update_image_data', {}, { timeout: Infinity })
} }

View File

@ -124,10 +124,14 @@ const zh = {
"walk-mode-move-message": "在walk模式下仅允许使用“快速移动”移动位置", "walk-mode-move-message": "在walk模式下仅允许使用“快速移动”移动位置",
"long_loading": "已经连续加载超过5秒如果你认为不是网络问题的话请尝试关掉VPN或者添加启动参数 --no-gradio-queue。如果还是不行请提Issue。", "long_loading": "已经连续加载超过5秒如果你认为不是网络问题的话请尝试关掉VPN或者添加启动参数 --no-gradio-queue。如果还是不行请提Issue。",
"manualExitFullScreen": "你删除了最后一张图片,也许需要你手动退出全屏预览", "manualExitFullScreen": "你删除了最后一张图片,也许需要你手动退出全屏预览",
"copied": "已复制!" "copied": "已复制!",
"index.expired": "索引过期,正在自动更新",
"auto.refreshed": "自动刷新完成!"
} }
const en: Record<keyof typeof zh, string> = { const en: Record<keyof typeof zh, string> = {
"auto.refreshed": "Auto refresh completed!",
copied: "Copied!", copied: "Copied!",
"index.expired": "Index expired, updating automatically",
"manualExitFullScreen": "You have deleted the last image and may need to manually exit full-screen preview", "manualExitFullScreen": "You have deleted the last image and may need to manually exit full-screen preview",
"long_loading": "Loading has been continuing for more than 5 seconds. If you don't think it's a network issue, please try turning off your VPN or adding the startup parameter --no-gradio-queue. If it still doesn't work, please submit an issue.", "long_loading": "Loading has been continuing for more than 5 seconds. If you don't think it's a network issue, please try turning off your VPN or adding the startup parameter --no-gradio-queue. If it still doesn't work, please submit an issue.",
"walk-mode-move-message": "Moving position is only allowed using 'Quick Move' in walk mode", "walk-mode-move-message": "Moving position is only allowed using 'Quick Move' in walk mode",

View File

@ -4,11 +4,14 @@ import { Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css' import 'splitpanes/dist/splitpanes.css'
import { useGlobalStore, type TabPane } from '@/store/useGlobalStore' import { useGlobalStore, type TabPane } from '@/store/useGlobalStore'
import { defineAsyncComponent, watch, ref, nextTick } from 'vue' import { defineAsyncComponent, watch, ref, nextTick } from 'vue'
import { key } from '@/util' import { gradioApp, key, globalEvents, asyncCheck } from '@/util'
import { uniqueId } from 'lodash-es' import { debounce, uniqueId } from 'lodash-es'
import edgeTrigger from './edgeTrigger.vue' import edgeTrigger from './edgeTrigger.vue'
import { t } from '@/i18n' import { t } from '@/i18n'
import { ID } from 'vue3-ts-util' import { ID } from 'vue3-ts-util'
import { tryOnMounted, useDocumentVisibility, type Fn } from '@vueuse/core'
const global = useGlobalStore() const global = useGlobalStore()
const compMap: Record<TabPane['type'], ReturnType<typeof defineAsyncComponent>> = { const compMap: Record<TabPane['type'], ReturnType<typeof defineAsyncComponent>> = {
local: defineAsyncComponent(() => import('@/page/fileTransfer/stackView.vue')), local: defineAsyncComponent(() => import('@/page/fileTransfer/stackView.vue')),
@ -70,29 +73,32 @@ watch(
}, },
{ immediate: true, deep: true } { immediate: true, deep: true }
) )
const emitReturnToIIB = debounce(() => globalEvents.emit('return-to-iib'), 100)
tryOnMounted(async () => {
const par = window.parent as Window & { get_uiCurrentTabContent (): undefined | HTMLButtonElement, onUiTabChange (cb: Fn): void }
if (!await asyncCheck(() => par?.onUiTabChange, 200, 30_000)) {
console.log('watch tab change failed');
return
}
par.onUiTabChange(() => {
const el = par.get_uiCurrentTabContent()
if (el?.id.includes("infinite-image-browsing")) {
emitReturnToIIB()
}
})
})
watch(useDocumentVisibility(), v => v && emitReturnToIIB())
</script> </script>
<template> <template>
<div ref="container"> <div ref="container">
<splitpanes class="default-theme"> <splitpanes class="default-theme">
<pane v-for="(tab, tabIdx) in global.tabList" :key="key(tab)"> <pane v-for="(tab, tabIdx) in global.tabList" :key="key(tab)">
<edge-trigger :tabIdx="tabIdx"> <edge-trigger :tabIdx="tabIdx">
<a-tabs <a-tabs type="editable-card" v-model:activeKey="tab.key" @edit="(key, act) => onEdit(tabIdx, key, act)">
type="editable-card" <a-tab-pane v-for="(pane, paneIdx) in tab.panes" :key="pane.key" :tab="pane.name" class="pane">
v-model:activeKey="tab.key" <component :is="compMap[pane.type]" :tabIdx="tabIdx" :paneIdx="paneIdx" v-bind="pane" />
@edit="(key, act) => onEdit(tabIdx, key, act)"
>
<a-tab-pane
v-for="(pane, paneIdx) in tab.panes"
:key="pane.key"
:tab="pane.name"
class="pane"
>
<component
:is="compMap[pane.type]"
:tabIdx="tabIdx"
:paneIdx="paneIdx"
v-bind="pane"
/>
</a-tab-pane> </a-tab-pane>
</a-tabs> </a-tabs>
</edge-trigger> </edge-trigger>

View File

@ -6,15 +6,17 @@ import {
type DataBaseBasicInfo, type DataBaseBasicInfo,
type Tag, type Tag,
addCustomTag, addCustomTag,
removeCustomTag removeCustomTag,
getExpiredDirs
} from '@/api/db' } from '@/api/db'
import { SearchSelect } from 'vue3-ts-util' import { SearchSelect } from 'vue3-ts-util'
import { CheckOutlined, PlusOutlined, CloseOutlined } from '@/icon' import { CheckOutlined, PlusOutlined, CloseOutlined } from '@/icon'
import { useGlobalStore } from '@/store/useGlobalStore' import { useGlobalStore } from '@/store/useGlobalStore'
import { groupBy, uniqueId } from 'lodash-es' import { groupBy, uniqueId } from 'lodash-es'
import { createReactiveQueue, type Dict } from '@/util' import { createReactiveQueue, type Dict, useGlobalEventListen } from '@/util'
import { Modal, message } from 'ant-design-vue' import { Modal, message } from 'ant-design-vue'
import { t } from '@/i18n' import { t } from '@/i18n'
import { makeAsyncFunctionSingle } from '@/util'
const props = defineProps<{ tabIdx: number; paneIdx: number }>() const props = defineProps<{ tabIdx: number; paneIdx: number }>()
const global = useGlobalStore() const global = useGlobalStore()
@ -51,17 +53,21 @@ onMounted(async () => {
} }
}) })
const onUpdateBtnClick = async () => { const onUpdateBtnClick = makeAsyncFunctionSingle(() => queue.pushAction(async () => {
queue.pushAction(async () => { await updateImageData()
await updateImageData() info.value = await getDbBasicInfo()
info.value = await getDbBasicInfo() return info.value
}) }).res)
}
const query = () => { const query = () => {
global.openTagSearchMatchedImageGridInRight(props.tabIdx, pairid, Array.from(selectedId.value)) global.openTagSearchMatchedImageGridInRight(props.tabIdx, pairid, Array.from(selectedId.value))
} }
useGlobalEventListen('return-to-iib', async () => {
const res = await queue.pushAction(getExpiredDirs).res
info.value!.expired = res.expired
})
const toTagDisplayName = (v: Tag, withType = false) => const toTagDisplayName = (v: Tag, withType = false) =>
(withType ? `[${v.type}] ` : '') + (v.display_name ? `${v.display_name} : ${v.name}` : v.name) (withType ? `[${v.type}] ` : '') + (v.display_name ? `${v.display_name} : ${v.name}` : v.name)
const addInputing = ref(false) const addInputing = ref(false)
@ -87,7 +93,7 @@ const onAddTagBtnSubmit = async () => {
const onTagRemoveClick = (tagId: number) => { const onTagRemoveClick = (tagId: number) => {
Modal.confirm({ Modal.confirm({
title: t('confirmDelete'), title: t('confirmDelete'),
async onOk() { async onOk () {
await removeCustomTag({ tag_id: tagId }) await removeCustomTag({ tag_id: tagId })
const idx = info.value?.tags.findIndex((v) => v.id === tagId) ?? -1 const idx = info.value?.tags.findIndex((v) => v.id === tagId) ?? -1
info.value?.tags.splice(idx, 1) info.value?.tags.splice(idx, 1)
@ -105,35 +111,18 @@ const onTagRemoveClick = (tagId: number) => {
<template v-if="info"> <template v-if="info">
<div> <div>
<div class="search-bar"> <div class="search-bar">
<SearchSelect <SearchSelect :conv="{
:conv="{ value: (v) => v.id,
value: (v) => v.id, text: toTagDisplayName,
text: toTagDisplayName, optionText: (v) => toTagDisplayName(v, true)
optionText: (v) => toTagDisplayName(v, true) }" mode="multiple" style="width: 100%" :options="tags" :value="Array.from(selectedId)"
}" :disabled="!tags.length" placeholder="Select tags to match images"
mode="multiple" @update:value="(v) => (selectedId = new Set(v))" />
style="width: 100%" <AButton @click="onUpdateBtnClick" :loading="!queue.isIdle" type="primary"
:options="tags" v-if="info.expired || !info.img_count">
:value="Array.from(selectedId)" {{ info.img_count === 0 ? $t('generateIndexHint') : $t('UpdateIndex') }}</AButton>
:disabled="!tags.length" <AButton v-else type="primary" @click="query" :loading="!queue.isIdle" :disabled="!selectedId.size">{{
placeholder="Select tags to match images" $t('search') }}
@update:value="(v) => (selectedId = new Set(v))"
/>
<AButton
@click="onUpdateBtnClick"
:loading="!queue.isIdle"
type="primary"
v-if="info.expired || !info.img_count"
>
{{ info.img_count === 0 ? $t('generateIndexHint') : $t('UpdateIndex') }}</AButton
>
<AButton
v-else
type="primary"
@click="query"
:loading="!queue.isIdle"
:disabled="!selectedId.size"
>{{ $t('search') }}
</AButton> </AButton>
</div> </div>
</div> </div>
@ -144,43 +133,25 @@ const onTagRemoveClick = (tagId: number) => {
<div class="list-container"> <div class="list-container">
<ul class="tag-list" v-for="[name, list] in classifyTags" :key="name"> <ul class="tag-list" v-for="[name, list] in classifyTags" :key="name">
<h3 class="cat-name">{{ $t(name) }}</h3> <h3 class="cat-name">{{ $t(name) }}</h3>
<li <li v-for="(tag, idx) in list" :key="tag.id" class="tag" :class="{ selected: selectedId.has(tag.id) }"
v-for="(tag, idx) in list" @click="selectedId.has(tag.id) ? selectedId.delete(tag.id) : selectedId.add(tag.id)">
:key="tag.id"
class="tag"
:class="{ selected: selectedId.has(tag.id) }"
@click="selectedId.has(tag.id) ? selectedId.delete(tag.id) : selectedId.add(tag.id)"
>
<CheckOutlined v-if="selectedId.has(tag.id)" /> <CheckOutlined v-if="selectedId.has(tag.id)" />
{{ toTagDisplayName(tag) }} {{ toTagDisplayName(tag) }}
<span <span v-if="name === 'custom' && idx !== 0" class="remove" @click.capture.stop="onTagRemoveClick(tag.id)">
v-if="name === 'custom' && idx !== 0"
class="remove"
@click.capture.stop="onTagRemoveClick(tag.id)"
>
<CloseOutlined /> <CloseOutlined />
</span> </span>
</li> </li>
<li v-if="name === 'custom'" class="tag" @click="addInputing = true"> <li v-if="name === 'custom'" class="tag" @click="addInputing = true">
<template v-if="addInputing"> <template v-if="addInputing">
<a-input-group compact> <a-input-group compact>
<a-input <a-input v-model:value="addTagName" style="width: 128px" :loading="loading" allow-clear size="small" />
v-model:value="addTagName" <a-button size="small" type="primary" @click.capture.stop="onAddTagBtnSubmit" :loading="loading">{{
style="width: 128px" addTagName ? $t('submit') : $t('cancel') }}</a-button>
:loading="loading"
allow-clear
size="small"
/>
<a-button
size="small"
type="primary"
@click.capture.stop="onAddTagBtnSubmit"
:loading="loading"
>{{ addTagName ? $t('submit') : $t('cancel') }}</a-button
>
</a-input-group> </a-input-group>
</template> </template>
<template v-else> <PlusOutlined /> {{ $t('add') }} </template> <template v-else>
<PlusOutlined /> {{ $t('add') }}
</template>
</li> </li>
</ul> </ul>
</div> </div>
@ -210,6 +181,7 @@ const onTagRemoveClick = (tagId: number) => {
padding: 4px; padding: 4px;
position: cursor; position: cursor;
border-radius: 2px; border-radius: 2px;
&:hover { &:hover {
background-color: var(--zp-secondary-background); background-color: var(--zp-secondary-background);
} }

View File

@ -12,7 +12,7 @@ import {
typedEventEmitter, typedEventEmitter,
ID ID
} from 'vue3-ts-util' } from 'vue3-ts-util'
import { createReactiveQueue, gradioApp, isImageFile, copy2clipboardI18n } from '@/util' import { createReactiveQueue, gradioApp, isImageFile, copy2clipboardI18n, useGlobalEventListen, makeAsyncFunctionSingle } from '@/util'
import { getTargetFolderFiles, type FileNodeInfo, deleteFiles, moveFiles } from '@/api/files' import { getTargetFolderFiles, type FileNodeInfo, deleteFiles, moveFiles } from '@/api/files'
import { sortFiles, sortMethodMap, SortMethod } from './fileSort' import { sortFiles, sortMethodMap, SortMethod } from './fileSort'
import { cloneDeep, debounce, last, range, uniqBy, uniqueId } from 'lodash-es' import { cloneDeep, debounce, last, range, uniqBy, uniqueId } from 'lodash-es'
@ -388,7 +388,7 @@ export function useLocation (props: Props) {
} }
} }
const refresh = async () => { const refresh = makeAsyncFunctionSingle(async () => {
try { try {
np.value?.start() np.value?.start()
if (walkModePath.value) { if (walkModePath.value) {
@ -406,9 +406,23 @@ export function useLocation (props: Props) {
} finally { } finally {
np.value?.done() np.value?.done()
} }
} })
useGlobalEventListen('return-to-iib',makeAsyncFunctionSingle(async () => {
if (!props.walkMode) {
try {
np.value?.start()
const { files } = await getTargetFolderFiles(
'local',
stack.value.length === 1 ? '/' : currLocation.value
)
last(stack.value)!.files = files
message.success(t('auto.refreshed'))
} finally {
np.value?.done()
}
}
}))
useEventListen.value('refresh', refresh) useEventListen.value('refresh', refresh)

View File

@ -1,9 +1,9 @@
import { t } from '@/i18n' import { t } from '@/i18n'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import { reactive } from 'vue' import { reactive } from 'vue'
import { FetchQueue, idKey, type UniqueId } from 'vue3-ts-util' import { FetchQueue, idKey, typedEventEmitter, type UniqueId } from 'vue3-ts-util'
export function gradioApp () { export function gradioApp (): Window & Document {
try { try {
return (parent.window as any).gradioApp() return (parent.window as any).gradioApp()
} catch (error) { } catch (error) {
@ -11,7 +11,7 @@ export function gradioApp () {
} }
const elems = parent.document.getElementsByTagName('gradio-app') const elems = parent.document.getElementsByTagName('gradio-app')
const gradioShadowRoot = elems.length == 0 ? null : elems[0].shadowRoot const gradioShadowRoot = elems.length == 0 ? null : elems[0].shadowRoot
return gradioShadowRoot ? gradioShadowRoot : document return (gradioShadowRoot ? gradioShadowRoot : document) as any
} }
export const asyncCheck = async <T> (getter: () => T, checkSize = 100, timeout = 1000) => { export const asyncCheck = async <T> (getter: () => T, checkSize = 100, timeout = 1000) => {
@ -71,3 +71,32 @@ export const copy2clipboardI18n = async (text: string) => {
message.error("copy failed. maybe it's non-secure environment") message.error("copy failed. maybe it's non-secure environment")
} }
} }
export const { useEventListen: useGlobalEventListen, eventEmitter: globalEvents } = typedEventEmitter<{
'return-to-iib'(): void
}>()
type AsyncFunction<T> = (...args: any[]) => Promise<T>;
export function makeAsyncFunctionSingle<T>(fn: AsyncFunction<T>): AsyncFunction<T> {
let promise: Promise<T> | null = null;
let isExecuting = false;
return async function (this: any, ...args: any[]): Promise<T> {
if (isExecuting) {
// 如果当前有其他调用正在执行,直接返回上一个 Promise 对象
return promise as Promise<T>;
}
isExecuting = true;
try {
// 执行异步函数并等待结果
promise = fn.apply(this, args);
const result = await promise;
return result;
} finally {
isExecuting = false;
}
};
}