Add image comparison feature similar to imgsli
parent
6c20435904
commit
7cf69bd790
|
|
@ -15,8 +15,8 @@
|
|||
<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-5716a5d2.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-8961c2b3.css">
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-837602c1.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-ae43cab2.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ declare module '@vue/runtime-core' {
|
|||
AButton: typeof import('ant-design-vue/es')['Button']
|
||||
ACollapse: typeof import('ant-design-vue/es')['Collapse']
|
||||
ACollapsePanel: typeof import('ant-design-vue/es')['CollapsePanel']
|
||||
ADrawer: typeof import('ant-design-vue/es')['Drawer']
|
||||
ADropdown: typeof import('ant-design-vue/es')['Dropdown']
|
||||
AForm: typeof import('ant-design-vue/es')['Form']
|
||||
AFormItem: typeof import('ant-design-vue/es')['FormItem']
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
import{d as R,l as U,o as r,y as _,c as l,n as a,r as e,s as y,p as b,t as E,v as h,x as q,m as M,H as u,K as S,N as L,O as H,V as K}from"./index-5716a5d2.js";import{a as Q,f as j,L as J,R as W,b as X,S as Y}from"./fullScreenContextMenu-792aa198.js";import{t as Z}from"./hook-735191b8.js";import{g as ee}from"./db-1ccd7546.js";import{u as te}from"./hook-9ffbde00.js";const se={class:"hint"},ie={key:1,class:"preview-switch"},le=R({__name:"MatchedImageGrid",props:{tabIdx:{},paneIdx:{},selectedTagIds:{},id:{}},setup(V){const m=V,{queue:p,images:s,onContextMenuClickU:f,stackViewEl:T,previewIdx:n,previewing:v,onPreviewVisibleChange:z,previewImgMove:g,canPreview:I,itemSize:k,gridItems:$,showGenInfo:o,imageGenInfo:w,q:B,multiSelectedIdxs:D,onFileItemClick:F,scroller:C,showMenuIdx:d,onFileDragStart:G}=te();return U(()=>m.selectedTagIds,async()=>{var t;const{res:c}=p.pushAction(()=>ee(m.selectedTagIds));s.value=await c,(t=C.value)==null||t.scrollToItem(0)},{immediate:!0}),(c,t)=>{const N=L,A=H,O=Y;return r(),_("div",{class:"container",ref_key:"stackViewEl",ref:T},[l(O,{size:"large",spinning:!e(p).isIdle},{default:a(()=>[l(A,{visible:e(o),"onUpdate:visible":t[1]||(t[1]=i=>y(o)?o.value=i:null),width:"70vw","mask-closable":"",onOk:t[2]||(t[2]=i=>o.value=!1)},{cancelText:a(()=>[]),default:a(()=>[l(N,{active:"",loading:!e(B).isIdle},{default:a(()=>[b("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:t[0]||(t[0]=i=>e(E)(e(w)))},[b("div",se,h(c.$t("doubleClickToCopy")),1),q(" "+h(e(w)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),e(s)?(r(),M(e(Q),{key:0,ref_key:"scroller",ref:C,class:"file-list",items:e(s),"item-size":e(k).first,"key-field":"fullpath","item-secondary-size":e(k).second,gridItems:e($)},{default:a(({item:i,index:x})=>[l(j,{idx:x,file:i,"show-menu-idx":e(d),"onUpdate:showMenuIdx":t[3]||(t[3]=P=>y(d)?d.value=P:null),onDragstart:e(G),onFileItemClick:e(F),"full-screen-preview-image-url":e(s)[e(n)]?e(Z)(e(s)[e(n)]):"",selected:e(D).includes(x),onContextMenuClick:e(f),onPreviewVisibleChange:e(z)},null,8,["idx","file","show-menu-idx","onDragstart","onFileItemClick","full-screen-preview-image-url","selected","onContextMenuClick","onPreviewVisibleChange"])]),_:1},8,["items","item-size","item-secondary-size","gridItems"])):u("",!0),e(v)?(r(),_("div",ie,[l(e(J),{onClick:t[4]||(t[4]=i=>e(g)("prev")),class:S({disable:!e(I)("prev")})},null,8,["class"]),l(e(W),{onClick:t[5]||(t[5]=i=>e(g)("next")),class:S({disable:!e(I)("next")})},null,8,["class"])])):u("",!0)]),_:1},8,["spinning"]),e(v)&&e(s)&&e(s)[e(n)]?(r(),M(X,{key:0,file:e(s)[e(n)],idx:e(n),onContextMenuClick:e(f)},null,8,["file","idx","onContextMenuClick"])):u("",!0)],512)}}});const ce=K(le,[["__scopeId","data-v-448d483e"]]);export{ce as default};
|
||||
|
|
@ -0,0 +1 @@
|
|||
.preview-switch[data-v-2cae0a95]{position:fixed;top:0;bottom:0;left:0;right:0;display:flex;align-items:center;justify-content:space-between;z-index:11111;pointer-events:none}.preview-switch>*[data-v-2cae0a95]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-2cae0a95]{opacity:0;pointer-events:none;cursor:none}.container[data-v-2cae0a95]{background:var(--zp-secondary-background)}.container .file-list[data-v-2cae0a95]{list-style:none;padding:8px;height:100%;overflow:auto;height:var(--pane-max-height);width:100%}
|
||||
|
|
@ -1 +0,0 @@
|
|||
.preview-switch[data-v-448d483e]{position:fixed;top:0;bottom:0;left:0;right:0;display:flex;align-items:center;justify-content:space-between;z-index:11111;pointer-events:none}.preview-switch>*[data-v-448d483e]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-448d483e]{opacity:0;pointer-events:none;cursor:none}.container[data-v-448d483e]{background:var(--zp-secondary-background)}.container .file-list[data-v-448d483e]{list-style:none;padding:8px;height:100%;overflow:auto;height:var(--pane-max-height);width:100%}
|
||||
|
|
@ -0,0 +1 @@
|
|||
import{d as R,l as U,o as r,y as _,c as n,n as a,r as e,s as y,p as b,t as L,v as h,x as q,m as M,K as Q,H as u,L as S,O as H,Q as K,W}from"./index-837602c1.js";import{a as j,f as J,L as X,R as Y,b as Z,S as ee}from"./fullScreenContextMenu-f56d0b68.js";import"./hook-594118df.js";import{g as se}from"./db-90ebe1a2.js";import{u as te}from"./hook-0b66e22e.js";const ie={class:"hint"},ne={key:1,class:"preview-switch"},le=R({__name:"MatchedImageGrid",props:{tabIdx:{},paneIdx:{},selectedTagIds:{},id:{}},setup(V){const m=V,{queue:p,images:t,onContextMenuClickU:g,stackViewEl:D,previewIdx:l,previewing:v,onPreviewVisibleChange:T,previewImgMove:f,canPreview:I,itemSize:k,gridItems:z,showGenInfo:o,imageGenInfo:w,q:F,multiSelectedIdxs:$,onFileItemClick:B,scroller:C,showMenuIdx:d,onFileDragStart:G,onFileDragEnd:A}=te();return U(()=>m.selectedTagIds,async()=>{var s;const{res:c}=p.pushAction(()=>se(m.selectedTagIds));t.value=await c,(s=C.value)==null||s.scrollToItem(0)},{immediate:!0}),(c,s)=>{const E=H,N=K,O=ee;return r(),_("div",{class:"container",ref_key:"stackViewEl",ref:D},[n(O,{size:"large",spinning:!e(p).isIdle},{default:a(()=>[n(N,{visible:e(o),"onUpdate:visible":s[1]||(s[1]=i=>y(o)?o.value=i:null),width:"70vw","mask-closable":"",onOk:s[2]||(s[2]=i=>o.value=!1)},{cancelText:a(()=>[]),default:a(()=>[n(E,{active:"",loading:!e(F).isIdle},{default:a(()=>[b("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:s[0]||(s[0]=i=>e(L)(e(w)))},[b("div",ie,h(c.$t("doubleClickToCopy")),1),q(" "+h(e(w)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),e(t)?(r(),M(e(j),{key:0,ref_key:"scroller",ref:C,class:"file-list",items:e(t),"item-size":e(k).first,"key-field":"fullpath","item-secondary-size":e(k).second,gridItems:e(z)},{default:a(({item:i,index:x})=>[n(J,{idx:x,file:i,"show-menu-idx":e(d),"onUpdate:showMenuIdx":s[3]||(s[3]=P=>y(d)?d.value=P:null),onDragstart:e(G),onDragend:e(A),onFileItemClick:e(B),"full-screen-preview-image-url":e(t)[e(l)]?e(Q)(e(t)[e(l)]):"",selected:e($).includes(x),onContextMenuClick:e(g),onPreviewVisibleChange:e(T)},null,8,["idx","file","show-menu-idx","onDragstart","onDragend","onFileItemClick","full-screen-preview-image-url","selected","onContextMenuClick","onPreviewVisibleChange"])]),_:1},8,["items","item-size","item-secondary-size","gridItems"])):u("",!0),e(v)?(r(),_("div",ne,[n(e(X),{onClick:s[4]||(s[4]=i=>e(f)("prev")),class:S({disable:!e(I)("prev")})},null,8,["class"]),n(e(Y),{onClick:s[5]||(s[5]=i=>e(f)("next")),class:S({disable:!e(I)("next")})},null,8,["class"])])):u("",!0)]),_:1},8,["spinning"]),e(v)&&e(t)&&e(t)[e(l)]?(r(),M(Z,{key:0,file:e(t)[e(l)],idx:e(l),onContextMenuClick:e(g)},null,8,["file","idx","onContextMenuClick"])):u("",!0)],512)}}});const ue=W(le,[["__scopeId","data-v-2cae0a95"]]);export{ue as default};
|
||||
|
|
@ -0,0 +1 @@
|
|||
import{d as W,Z as $,ay as Z,br as j,bs as J,o,y as k,c as r,r as e,bx as X,m,n as d,x as b,v,H as f,s as B,p as V,t as Y,K as ee,L as A,bv as ne,ag as se,T as te,U as ae,O as ie,Q as le,W as oe}from"./index-837602c1.js";import{a as re,f as de,L as ue,R as ce,b as pe,S as me}from"./fullScreenContextMenu-f56d0b68.js";/* empty css */import"./hook-594118df.js";import{a as U,c as ve,e as fe,u as ge}from"./db-90ebe1a2.js";import{u as ke}from"./hook-0b66e22e.js";const be={key:0,class:"search-bar"},ye={class:"hint"},we={key:1,class:"preview-switch"},Ce=W({__name:"SubstrSearch",setup(Ie){const{queue:l,images:a,onContextMenuClickU:y,stackViewEl:F,previewIdx:u,previewing:w,onPreviewVisibleChange:E,previewImgMove:C,canPreview:I,itemSize:_,gridItems:R,showGenInfo:c,imageGenInfo:x,q:T,multiSelectedIdxs:K,onFileItemClick:L,scroller:h,showMenuIdx:g,onFileDragStart:N,onFileDragEnd:O}=ke(),p=$(""),s=$();Z(async()=>{s.value=await U(),s.value.img_count&&s.value.expired&&S()});const S=j(()=>l.pushAction(async()=>(await ge(),s.value=await U(),s.value)).res),M=async()=>{var t;a.value=await l.pushAction(()=>fe(p.value)).res,(t=h.value)==null||t.scrollToItem(0),a.value.length||ne.info(se("fuzzy-search-noResults"))};return J("return-to-iib",async()=>{const t=await l.pushAction(ve).res;s.value.expired=t.expired}),(t,n)=>{const P=te,z=ae,q=ie,G=le,H=me;return o(),k("div",{class:"container",ref_key:"stackViewEl",ref:F},[s.value?(o(),k("div",be,[r(P,{value:p.value,"onUpdate:value":n[0]||(n[0]=i=>p.value=i),placeholder:t.$t("fuzzy-search-placeholder"),disabled:!e(l).isIdle,onKeydown:X(M,["enter"])},null,8,["value","placeholder","disabled","onKeydown"]),s.value.expired||!s.value.img_count?(o(),m(z,{key:0,onClick:e(S),loading:!e(l).isIdle,type:"primary"},{default:d(()=>[b(v(s.value.img_count===0?t.$t("generateIndexHint"):t.$t("UpdateIndex")),1)]),_:1},8,["onClick","loading"])):(o(),m(z,{key:1,type:"primary",onClick:M,loading:!e(l).isIdle,disabled:!p.value},{default:d(()=>[b(v(t.$t("search")),1)]),_:1},8,["loading","disabled"]))])):f("",!0),r(H,{size:"large",spinning:!e(l).isIdle},{default:d(()=>[r(G,{visible:e(c),"onUpdate:visible":n[2]||(n[2]=i=>B(c)?c.value=i:null),width:"70vw","mask-closable":"",onOk:n[3]||(n[3]=i=>c.value=!1)},{cancelText:d(()=>[]),default:d(()=>[r(q,{active:"",loading:!e(T).isIdle},{default:d(()=>[V("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:n[1]||(n[1]=i=>e(Y)(e(x)))},[V("div",ye,v(t.$t("doubleClickToCopy")),1),b(" "+v(e(x)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),e(a)?(o(),m(e(re),{key:0,ref_key:"scroller",ref:h,class:"file-list",items:e(a),"item-size":e(_).first,"key-field":"fullpath","item-secondary-size":e(_).second,gridItems:e(R)},{default:d(({item:i,index:D})=>[r(de,{idx:D,file:i,"show-menu-idx":e(g),"onUpdate:showMenuIdx":n[4]||(n[4]=Q=>B(g)?g.value=Q:null),onFileItemClick:e(L),"full-screen-preview-image-url":e(a)[e(u)]?e(ee)(e(a)[e(u)]):"",selected:e(K).includes(D),onContextMenuClick:e(y),onDragstart:e(N),onDragend:e(O),onPreviewVisibleChange:e(E)},null,8,["idx","file","show-menu-idx","onFileItemClick","full-screen-preview-image-url","selected","onContextMenuClick","onDragstart","onDragend","onPreviewVisibleChange"])]),_:1},8,["items","item-size","item-secondary-size","gridItems"])):f("",!0),e(w)?(o(),k("div",we,[r(e(ue),{onClick:n[5]||(n[5]=i=>e(C)("prev")),class:A({disable:!e(I)("prev")})},null,8,["class"]),r(e(ce),{onClick:n[6]||(n[6]=i=>e(C)("next")),class:A({disable:!e(I)("next")})},null,8,["class"])])):f("",!0)]),_:1},8,["spinning"]),e(w)&&e(a)&&e(a)[e(u)]?(o(),m(pe,{key:1,file:e(a)[e(u)],idx:e(u),onContextMenuClick:e(y)},null,8,["file","idx","onContextMenuClick"])):f("",!0)],512)}}});const De=oe(Ce,[["__scopeId","data-v-bf9bdccd"]]);export{De as default};
|
||||
|
|
@ -0,0 +1 @@
|
|||
.search-bar[data-v-bf9bdccd]{padding:8px;display:flex}.preview-switch[data-v-bf9bdccd]{position:fixed;top:0;bottom:0;left:0;right:0;display:flex;align-items:center;justify-content:space-between;z-index:11111;pointer-events:none}.preview-switch>*[data-v-bf9bdccd]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-bf9bdccd]{opacity:0;pointer-events:none;cursor:none}.container[data-v-bf9bdccd]{background:var(--zp-secondary-background)}.container .file-list[data-v-bf9bdccd]{list-style:none;padding:8px;height:100%;overflow:auto;height:var(--pane-max-height);width:100%}
|
||||
|
|
@ -1 +0,0 @@
|
|||
import{d as Q,Y as $,ax as Y,bq as j,br as J,o,y as k,c as r,r as e,bw as W,m,n as u,x as w,v,H as f,s as B,p as A,t as X,K as D,bu as Z,af as ee,R as te,T as se,N as ae,O as ne,V as ie}from"./index-5716a5d2.js";import{a as le,f as oe,L as re,R as ue,b as de,S as ce}from"./fullScreenContextMenu-792aa198.js";/* empty css */import{t as pe}from"./hook-735191b8.js";import{a as U,c as me,e as ve,u as fe}from"./db-1ccd7546.js";import{u as ge}from"./hook-9ffbde00.js";const ke={key:0,class:"search-bar"},we={class:"hint"},ye={key:1,class:"preview-switch"},be=Q({__name:"SubstrSearch",setup(Ce){const{queue:l,images:n,onContextMenuClickU:y,stackViewEl:F,previewIdx:d,previewing:b,onPreviewVisibleChange:R,previewImgMove:C,canPreview:I,itemSize:_,gridItems:E,showGenInfo:c,imageGenInfo:x,q:N,multiSelectedIdxs:T,onFileItemClick:q,scroller:h,showMenuIdx:g,onFileDragStart:K}=ge(),p=$(""),s=$();Y(async()=>{s.value=await U(),s.value.img_count&&s.value.expired&&S()});const S=j(()=>l.pushAction(async()=>(await fe(),s.value=await U(),s.value)).res),M=async()=>{var a;n.value=await l.pushAction(()=>ve(p.value)).res,(a=h.value)==null||a.scrollToItem(0),n.value.length||Z.info(ee("fuzzy-search-noResults"))};return J("return-to-iib",async()=>{const a=await l.pushAction(me).res;s.value.expired=a.expired}),(a,t)=>{const O=te,z=se,P=ae,G=ne,L=ce;return o(),k("div",{class:"container",ref_key:"stackViewEl",ref:F},[s.value?(o(),k("div",ke,[r(O,{value:p.value,"onUpdate:value":t[0]||(t[0]=i=>p.value=i),placeholder:a.$t("fuzzy-search-placeholder"),disabled:!e(l).isIdle,onKeydown:W(M,["enter"])},null,8,["value","placeholder","disabled","onKeydown"]),s.value.expired||!s.value.img_count?(o(),m(z,{key:0,onClick:e(S),loading:!e(l).isIdle,type:"primary"},{default:u(()=>[w(v(s.value.img_count===0?a.$t("generateIndexHint"):a.$t("UpdateIndex")),1)]),_:1},8,["onClick","loading"])):(o(),m(z,{key:1,type:"primary",onClick:M,loading:!e(l).isIdle,disabled:!p.value},{default:u(()=>[w(v(a.$t("search")),1)]),_:1},8,["loading","disabled"]))])):f("",!0),r(L,{size:"large",spinning:!e(l).isIdle},{default:u(()=>[r(G,{visible:e(c),"onUpdate:visible":t[2]||(t[2]=i=>B(c)?c.value=i:null),width:"70vw","mask-closable":"",onOk:t[3]||(t[3]=i=>c.value=!1)},{cancelText:u(()=>[]),default:u(()=>[r(P,{active:"",loading:!e(N).isIdle},{default:u(()=>[A("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:t[1]||(t[1]=i=>e(X)(e(x)))},[A("div",we,v(a.$t("doubleClickToCopy")),1),w(" "+v(e(x)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),e(n)?(o(),m(e(le),{key:0,ref_key:"scroller",ref:h,class:"file-list",items:e(n),"item-size":e(_).first,"key-field":"fullpath","item-secondary-size":e(_).second,gridItems:e(E)},{default:u(({item:i,index:V})=>[r(oe,{idx:V,file:i,"show-menu-idx":e(g),"onUpdate:showMenuIdx":t[4]||(t[4]=H=>B(g)?g.value=H:null),onFileItemClick:e(q),"full-screen-preview-image-url":e(n)[e(d)]?e(pe)(e(n)[e(d)]):"",selected:e(T).includes(V),onContextMenuClick:e(y),onDragstart:e(K),onPreviewVisibleChange:e(R)},null,8,["idx","file","show-menu-idx","onFileItemClick","full-screen-preview-image-url","selected","onContextMenuClick","onDragstart","onPreviewVisibleChange"])]),_:1},8,["items","item-size","item-secondary-size","gridItems"])):f("",!0),e(b)?(o(),k("div",ye,[r(e(re),{onClick:t[5]||(t[5]=i=>e(C)("prev")),class:D({disable:!e(I)("prev")})},null,8,["class"]),r(e(ue),{onClick:t[6]||(t[6]=i=>e(C)("next")),class:D({disable:!e(I)("next")})},null,8,["class"])])):f("",!0)]),_:1},8,["spinning"]),e(b)&&e(n)&&e(n)[e(d)]?(o(),m(de,{key:1,file:e(n)[e(d)],idx:e(d),onContextMenuClick:e(y)},null,8,["file","idx","onContextMenuClick"])):f("",!0)],512)}}});const ze=ie(be,[["__scopeId","data-v-a2e6e698"]]);export{ze as default};
|
||||
|
|
@ -1 +0,0 @@
|
|||
.search-bar[data-v-a2e6e698]{padding:8px;display:flex}.preview-switch[data-v-a2e6e698]{position:fixed;top:0;bottom:0;left:0;right:0;display:flex;align-items:center;justify-content:space-between;z-index:11111;pointer-events:none}.preview-switch>*[data-v-a2e6e698]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-a2e6e698]{opacity:0;pointer-events:none;cursor:none}.container[data-v-a2e6e698]{background:var(--zp-secondary-background)}.container .file-list[data-v-a2e6e698]{list-style:none;padding:8px;height:100%;overflow:auto;height:var(--pane-max-height);width:100%}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +0,0 @@
|
|||
import{cs as I,ct as _,c2 as A,aL as P,b5 as m,cu as y,b7 as b,cv as C,b3 as E,bn as R,c8 as a}from"./index-5716a5d2.js";function O(t){return function(n){return n==null?void 0:n[t]}}var D=1,M=2;function T(t,n,e,s){var r=e.length,c=r,d=!s;if(t==null)return!c;for(t=Object(t);r--;){var i=e[r];if(d&&i[2]?i[1]!==t[i[0]]:!(i[0]in t))return!1}for(;++r<c;){i=e[r];var u=i[0],o=t[u],f=i[1];if(d&&i[2]){if(o===void 0&&!(u in t))return!1}else{var g=new I;if(s)var p=s(o,f,u,t,n,g);if(!(p===void 0?_(f,o,D|M,s,g):p))return!1}}return!0}function h(t){return t===t&&!A(t)}function L(t){for(var n=P(t),e=n.length;e--;){var s=n[e],r=t[s];n[e]=[s,r,h(r)]}return n}function l(t,n){return function(e){return e==null?!1:e[t]===n&&(n!==void 0||t in Object(e))}}function S(t){var n=L(t);return n.length==1&&n[0][2]?l(n[0][0],n[0][1]):function(e){return e===t||T(e,t,n)}}function v(t,n,e){var s=t==null?void 0:m(t,n);return s===void 0?e:s}var x=1,G=2;function F(t,n){return y(t)&&h(n)?l(b(t),n):function(e){var s=v(e,t);return s===void 0&&s===n?C(e,t):_(n,s,x|G)}}function B(t){return function(n){return m(n,t)}}function K(t){return y(t)?O(b(t)):B(t)}function U(t){return typeof t=="function"?t:t==null?E:typeof t=="object"?R(t)?F(t[0],t[1]):S(t):K(t)}const $=async()=>(await a.get("/db/basic_info")).data,q=async()=>(await a.get("/db/expired_dirs")).data,H=async()=>{await a.post("/db/update_image_data",{},{timeout:1/0})},J=async t=>(await a.post("/db/match_images_by_tags",t)).data,Q=async t=>(await a.post("/db/add_custom_tag",t)).data,W=async t=>(await a.post("/db/toggle_custom_tag_to_img",t)).data,X=async t=>{await a.post("/db/remove_custom_tag",t)},Y=async t=>(await a.get("/db/img_selected_custom_tag",{params:{path:t}})).data,Z=async t=>(await a.get("/db/search_by_substr",{params:{substr:t}})).data,w="/db/scanned_paths",z=async t=>{await a.post(w,{path:t})},k=async t=>{await a.delete(w,{data:{path:t}})};export{$ as a,U as b,q as c,Q as d,Z as e,Y as f,J as g,k as h,z as i,X as r,W as t,H as u};
|
||||
|
|
@ -0,0 +1 @@
|
|||
import{cn as I,co as _,bX as A,aM as P,b6 as m,cp as y,b8 as b,cq as C,b4 as E,bo as R,c1 as a}from"./index-837602c1.js";function M(t){return function(n){return n==null?void 0:n[t]}}var O=1,D=2;function T(t,n,e,s){var r=e.length,c=r,d=!s;if(t==null)return!c;for(t=Object(t);r--;){var i=e[r];if(d&&i[2]?i[1]!==t[i[0]]:!(i[0]in t))return!1}for(;++r<c;){i=e[r];var o=i[0],u=t[o],f=i[1];if(d&&i[2]){if(u===void 0&&!(o in t))return!1}else{var g=new I;if(s)var p=s(u,f,o,t,n,g);if(!(p===void 0?_(f,u,O|D,s,g):p))return!1}}return!0}function h(t){return t===t&&!A(t)}function S(t){for(var n=P(t),e=n.length;e--;){var s=n[e],r=t[s];n[e]=[s,r,h(r)]}return n}function l(t,n){return function(e){return e==null?!1:e[t]===n&&(n!==void 0||t in Object(e))}}function L(t){var n=S(t);return n.length==1&&n[0][2]?l(n[0][0],n[0][1]):function(e){return e===t||T(e,t,n)}}function x(t,n,e){var s=t==null?void 0:m(t,n);return s===void 0?e:s}var G=1,v=2;function F(t,n){return y(t)&&h(n)?l(b(t),n):function(e){var s=x(e,t);return s===void 0&&s===n?C(e,t):_(n,s,G|v)}}function B(t){return function(n){return m(n,t)}}function q(t){return y(t)?M(b(t)):B(t)}function N(t){return typeof t=="function"?t:t==null?E:typeof t=="object"?R(t)?F(t[0],t[1]):L(t):q(t)}const U=async()=>(await a.get("/db/basic_info")).data,$=async()=>(await a.get("/db/expired_dirs")).data,X=async()=>{await a.post("/db/update_image_data",{},{timeout:1/0})},H=async t=>(await a.post("/db/match_images_by_tags",t)).data,J=async t=>(await a.post("/db/add_custom_tag",t)).data,Q=async t=>(await a.post("/db/toggle_custom_tag_to_img",t)).data,W=async t=>{await a.post("/db/remove_custom_tag",t)},Y=async t=>(await a.get("/db/img_selected_custom_tag",{params:{path:t}})).data,Z=async t=>(await a.get("/db/search_by_substr",{params:{substr:t}})).data,w="/db/scanned_paths",z=async t=>{await a.post(w,{path:t})},k=async t=>{await a.delete(w,{data:{path:t}})};export{U as a,N as b,$ as c,J as d,Z as e,Y as f,H as g,k as h,z as i,W as r,Q as t,X as u};
|
||||
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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
|||
import{Z as l,bq as q,b4 as y}from"./index-837602c1.js";import{u as D,b as E,f as P,c as z,d as G,e as Q,g as R}from"./hook-594118df.js";const H=()=>{const e=l(),c=q(),o=l(),t={tabIdx:-1,target:"local",paneIdx:-1,walkMode:!1},{stackViewEl:r,multiSelectedIdxs:u,stack:m}=D({images:e}).toRefs(),{itemSize:f,gridItems:v}=E(t),{showMenuIdx:p}=P(),{onFileDragStart:I,onFileDragEnd:d}=z(),{showGenInfo:g,imageGenInfo:w,q:x,onContextMenuClick:i,onFileItemClick:k}=G(t,{openNext:y}),{previewIdx:F,previewing:M,onPreviewVisibleChange:b,previewImgMove:h,canPreview:C}=Q(t,{scroller:o,files:e}),S=async(n,s,a)=>{m.value=[{curr:"",files:e.value}],await i(n,s,a)};return R("removeFiles",async({paths:n})=>{var s;e.value=(s=e.value)==null?void 0:s.filter(a=>!n.includes(a.fullpath))}),{scroller:o,queue:c,images:e,onContextMenuClickU:S,stackViewEl:r,previewIdx:F,previewing:M,onPreviewVisibleChange:b,previewImgMove:h,canPreview:C,itemSize:f,gridItems:v,showGenInfo:g,imageGenInfo:w,q:x,onContextMenuClick:i,onFileItemClick:k,showMenuIdx:p,multiSelectedIdxs:u,onFileDragStart:I,onFileDragEnd:d}};export{H as u};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +0,0 @@
|
|||
import{Y as c,bp as S,b3 as y}from"./index-5716a5d2.js";import{u as q,b as P,f as z,c as D,d as E,e as G,h as Q}from"./hook-735191b8.js";const A=()=>{const e=c(),l=S(),o=c(),t={tabIdx:-1,target:"local",paneIdx:-1,walkMode:!1},{stackViewEl:r,multiSelectedIdxs:u,stack:m}=q({images:e}).toRefs(),{itemSize:f,gridItems:p}=P(t),{showMenuIdx:v}=z(),{onFileDragStart:I}=D(),{showGenInfo:d,imageGenInfo:w,q:g,onContextMenuClick:i,onFileItemClick:x}=E(t,{openNext:y}),{previewIdx:k,previewing:h,onPreviewVisibleChange:M,previewImgMove:b,canPreview:C}=G(t,{scroller:o,files:e}),F=async(a,s,n)=>{m.value=[{curr:"",files:e.value}],await i(a,s,n)};return Q("removeFiles",async({paths:a})=>{var s;e.value=(s=e.value)==null?void 0:s.filter(n=>!a.includes(n.fullpath))}),{scroller:o,queue:l,images:e,onContextMenuClickU:F,stackViewEl:r,previewIdx:k,previewing:h,onPreviewVisibleChange:M,previewImgMove:b,canPreview:C,itemSize:f,gridItems:p,showGenInfo:d,imageGenInfo:w,q:g,onContextMenuClick:i,onFileItemClick:x,showMenuIdx:v,multiSelectedIdxs:u,onFileDragStart:I}};export{A as u};
|
||||
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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
.ant-breadcrumb{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";color:#00000073;font-size:14px}.ant-breadcrumb .anticon{font-size:14px}.ant-breadcrumb a{color:#00000073;transition:color .3s}.ant-breadcrumb a:hover{color:#de632f}.ant-breadcrumb>span:last-child{color:#000000d9}.ant-breadcrumb>span:last-child a{color:#000000d9}.ant-breadcrumb>span:last-child .ant-breadcrumb-separator{display:none}.ant-breadcrumb-separator{margin:0 8px;color:#00000073}.ant-breadcrumb-link>.anticon+span,.ant-breadcrumb-link>.anticon+a{margin-left:4px}.ant-breadcrumb-overlay-link>.anticon{margin-left:4px}.ant-breadcrumb-rtl{direction:rtl}.ant-breadcrumb-rtl:before{display:table;content:""}.ant-breadcrumb-rtl:after{display:table;clear:both;content:""}.ant-breadcrumb-rtl>span{float:right}.ant-breadcrumb-rtl .ant-breadcrumb-link>.anticon+span,.ant-breadcrumb-rtl .ant-breadcrumb-link>.anticon+a{margin-right:4px;margin-left:0}.ant-breadcrumb-rtl .ant-breadcrumb-overlay-link>.anticon{margin-right:4px;margin-left:0}.nprogress{pointer-events:none}.nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}.nprogress .peg{display:block;position:absolute;right:0px;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translate(0px,-4px);-ms-transform:rotate(3deg) translate(0px,-4px);transform:rotate(3deg) translateY(-4px)}.nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}.nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:solid 2px transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent .nprogress .spinner,.nprogress-custom-parent .nprogress .bar{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.preview-switch[data-v-0ec31c23]{position:fixed;top:0;bottom:0;left:0;right:0;display:flex;align-items:center;justify-content:space-between;z-index:11111;pointer-events:none}.preview-switch>*[data-v-0ec31c23]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-0ec31c23]{opacity:0;pointer-events:none;cursor:none}.breadcrumb[data-v-0ec31c23]{display:flex;align-items:center}.breadcrumb>*[data-v-0ec31c23]{margin-right:4px}.container[data-v-0ec31c23]{background:var(--zp-secondary-background);height:var(--pane-max-height)}.location-bar[data-v-0ec31c23]{padding:4px 16px;background:var(--zp-primary-background);border-bottom:1px solid var(--zp-border);display:flex;align-items:center;justify-content:space-between}.location-bar .actions[data-v-0ec31c23]{display:flex;align-items:center;flex-shrink:0}.location-bar a.opt[data-v-0ec31c23]{margin-left:8px}.view[data-v-0ec31c23]{padding:8px;height:calc(100vh - 48px)}.view .file-list[data-v-0ec31c23]{list-style:none;padding:8px;height:100%;overflow:auto}.hint[data-v-0ec31c23]{padding:4px;border:4px;background:var(--zp-secondary-background);border:1px solid var(--zp-border)}
|
||||
.ant-breadcrumb{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";color:#00000073;font-size:14px}.ant-breadcrumb .anticon{font-size:14px}.ant-breadcrumb a{color:#00000073;transition:color .3s}.ant-breadcrumb a:hover{color:#de632f}.ant-breadcrumb>span:last-child{color:#000000d9}.ant-breadcrumb>span:last-child a{color:#000000d9}.ant-breadcrumb>span:last-child .ant-breadcrumb-separator{display:none}.ant-breadcrumb-separator{margin:0 8px;color:#00000073}.ant-breadcrumb-link>.anticon+span,.ant-breadcrumb-link>.anticon+a{margin-left:4px}.ant-breadcrumb-overlay-link>.anticon{margin-left:4px}.ant-breadcrumb-rtl{direction:rtl}.ant-breadcrumb-rtl:before{display:table;content:""}.ant-breadcrumb-rtl:after{display:table;clear:both;content:""}.ant-breadcrumb-rtl>span{float:right}.ant-breadcrumb-rtl .ant-breadcrumb-link>.anticon+span,.ant-breadcrumb-rtl .ant-breadcrumb-link>.anticon+a{margin-right:4px;margin-left:0}.ant-breadcrumb-rtl .ant-breadcrumb-overlay-link>.anticon{margin-right:4px;margin-left:0}.nprogress{pointer-events:none}.nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}.nprogress .peg{display:block;position:absolute;right:0px;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translate(0px,-4px);-ms-transform:rotate(3deg) translate(0px,-4px);transform:rotate(3deg) translateY(-4px)}.nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}.nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:solid 2px transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent .nprogress .spinner,.nprogress-custom-parent .nprogress .bar{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.preview-switch[data-v-e4015e72]{position:fixed;top:0;bottom:0;left:0;right:0;display:flex;align-items:center;justify-content:space-between;z-index:11111;pointer-events:none}.preview-switch>*[data-v-e4015e72]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-e4015e72]{opacity:0;pointer-events:none;cursor:none}.breadcrumb[data-v-e4015e72]{display:flex;align-items:center}.breadcrumb>*[data-v-e4015e72]{margin-right:4px}.container[data-v-e4015e72]{background:var(--zp-secondary-background);height:var(--pane-max-height)}.location-bar[data-v-e4015e72]{padding:4px 16px;background:var(--zp-primary-background);border-bottom:1px solid var(--zp-border);display:flex;align-items:center;justify-content:space-between}.location-bar .actions[data-v-e4015e72]{display:flex;align-items:center;flex-shrink:0}.location-bar a.opt[data-v-e4015e72]{margin-left:8px}.view[data-v-e4015e72]{padding:8px;height:calc(100vh - 48px)}.view .file-list[data-v-e4015e72]{list-style:none;padding:8px;height:100%;overflow:auto}.hint[data-v-e4015e72]{padding:4px;border:4px;background:var(--zp-secondary-background);border:1px solid var(--zp-border)}
|
||||
|
|
@ -7,8 +7,8 @@
|
|||
<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-5716a5d2.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-8961c2b3.css">
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-837602c1.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-ae43cab2.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -145,15 +145,21 @@ const zh = {
|
|||
edit: '编辑',
|
||||
document: '文档',
|
||||
multiSelectTips: '您可以按住 Shift、Ctrl 或 Cmd 键,然后单击文件来进行多选删除/移动操作',
|
||||
copyLocationUrlSuccessMsg: "复制完成,你可以通过复制的链接直接打开当前文件夹",
|
||||
share: '分享'
|
||||
copyLocationUrlSuccessMsg: '复制完成,你可以通过复制的链接直接打开当前文件夹',
|
||||
share: '分享',
|
||||
dragImageHere: '拖拽图像到这里',
|
||||
imgCompare: '图像对比'
|
||||
}
|
||||
const en: Record<keyof typeof zh, string> = {
|
||||
//! MissingTranslations: "Mark missing translations like this""shortcutKey": "Keyboard Shortcuts",
|
||||
//! MissingTranslations
|
||||
imgCompare: 'Image Comparison',
|
||||
share: 'Share',
|
||||
copyLocationUrlSuccessMsg: 'Copy completed, you can directly open the current folder through the copied link',
|
||||
multiSelectTips: 'You can hold down the Shift, Ctrl, or Cmd key and then click on files to perform batch delete/move operations',
|
||||
dragImageHere: 'Drag image here',
|
||||
copyLocationUrlSuccessMsg:
|
||||
'Copy completed, you can directly open the current folder through the copied link',
|
||||
multiSelectTips:
|
||||
'You can hold down the Shift, Ctrl, or Cmd key and then click on files to perform batch delete/move operations',
|
||||
document: 'Document',
|
||||
copy: 'Copy',
|
||||
edit: 'Edit',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,124 @@
|
|||
<script setup lang="ts">
|
||||
import { useImgSliStore } from '@/store/useImgSli'
|
||||
import { isFileTransferData, toRawFileUrl } from '@/page/fileTransfer/util'
|
||||
import { CloseCircleOutlined } from '@/icon'
|
||||
import { isImageFile } from '@/util'
|
||||
import { storeToRefs } from 'pinia'
|
||||
const sliStore = useImgSliStore()
|
||||
const { left, right } = storeToRefs(sliStore)
|
||||
|
||||
const onImageDrop = async (e: DragEvent, side: 'left' | 'right') => {
|
||||
const data = JSON.parse(e.dataTransfer?.getData('text') ?? '{}')
|
||||
if (isFileTransferData(data)) {
|
||||
const img = data.nodes[0]
|
||||
if (!isImageFile(img.name)) {
|
||||
return
|
||||
}
|
||||
sliStore[side] = img
|
||||
}
|
||||
}
|
||||
|
||||
const onCancel = () => {
|
||||
sliStore.left = undefined
|
||||
sliStore.right = undefined
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<Transition>
|
||||
<div class="dragging-port-wrap" v-if="sliStore.fileDragging || left || right">
|
||||
<h2>{{ $t('imgCompare') }}</h2>
|
||||
<div class="content">
|
||||
<div class="left port" @dragover.prevent @drop.prevent="onImageDrop($event, 'left')">
|
||||
<div v-if="left" class="img-wrap">
|
||||
<AImage :src="toRawFileUrl(left)" />
|
||||
<CloseCircleOutlined class="close" @click="left = undefined" />
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ $t('dragImageHere') }}
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 16px" />
|
||||
<div class="right port" @dragover.prevent @drop.prevent="onImageDrop($event, 'right')">
|
||||
<div v-if="right" class="img-wrap">
|
||||
<AImage :src="toRawFileUrl(right)" />
|
||||
<CloseCircleOutlined class="close" @click="right = undefined" />
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ $t('dragImageHere') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<AButton type="primary" @click="sliStore.drawerVisible = true">Confirm</AButton>
|
||||
<AButton style="margin-left: 16px;" @click="onCancel">Cancel</AButton>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
.dragging-port-wrap {
|
||||
position: fixed;
|
||||
bottom: 15%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background: var(--zp-primary-background);
|
||||
box-shadow: 0 0 4px var(--zp-secondary);
|
||||
border-radius: 8px;
|
||||
padding: 16px 32px;
|
||||
|
||||
.content {
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 8px 0;
|
||||
|
||||
.port {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--zp-tertiary);
|
||||
|
||||
.img-wrap {
|
||||
position: relative;
|
||||
|
||||
:deep() {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
transform: translate(50%, -50%);
|
||||
font-size: 1.5em;
|
||||
background: white;
|
||||
border-radius: 100%;
|
||||
color: black;
|
||||
z-index: 999;
|
||||
cursor: pointer;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.v-enter-active,
|
||||
.v-leave-active {
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
.v-enter-from,
|
||||
.v-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<script setup lang="ts">
|
||||
// @ts-ignore
|
||||
import { Splitpanes, Pane } from 'splitpanes'
|
||||
import DraggingPort from './DraggingPort.vue'
|
||||
import { useImgSliStore } from '@/store/useImgSli'
|
||||
import ImgSliSide from './ImgSliSide.vue'
|
||||
|
||||
const sli = useImgSliStore()
|
||||
|
||||
|
||||
const onResize = ([{ size }]: { size: number }[]) => {
|
||||
sli.splitPercent = size
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<ADrawer width="100vw" v-model:visible="sli.drawerVisible" destroy-on-close class="img-sli">
|
||||
<splitpanes class="default-theme" @resize="onResize">
|
||||
<pane>
|
||||
<ImgSliSide side="left" />
|
||||
</pane>
|
||||
<pane>
|
||||
<ImgSliSide side="right" />
|
||||
</pane>
|
||||
</splitpanes>
|
||||
</ADrawer>
|
||||
<DraggingPort />
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.img-sli .default-theme {
|
||||
.splitpanes {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.splitpanes__splitter {
|
||||
background-color: #ccc;
|
||||
position: relative;
|
||||
width: 2px;
|
||||
}
|
||||
|
||||
.splitpanes__splitter:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
transition: opacity 0.4s;
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.splitpanes__splitter:hover:before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.splitpanes--vertical>.splitpanes__splitter:before {
|
||||
left: -30px;
|
||||
right: -30px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.splitpanes--horizontal>.splitpanes__splitter:before {
|
||||
top: -30px;
|
||||
bottom: -30px;
|
||||
width: 100%;
|
||||
}
|
||||
}</style>
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<script setup lang="ts">
|
||||
import { useImgSliStore } from '@/store/useImgSli'
|
||||
import { toRawFileUrl } from '../fileTransfer/util'
|
||||
import { computed } from 'vue'
|
||||
const props = defineProps<{ side: 'left' | 'right' }>()
|
||||
const sli = useImgSliStore()
|
||||
const style = computed(() => {
|
||||
let x = ''
|
||||
const width = document.body.getBoundingClientRect().width - 48 - 7
|
||||
const per = sli.splitPercent
|
||||
|
||||
if (props.side === 'left') {
|
||||
x = `calc(50% - ${(per - 50) / 100 * width}px)`
|
||||
} else {
|
||||
x = `calc(-50% - ${(per - 50) / 100 * width}px)`
|
||||
}
|
||||
return `${sli.maxEdge === 'width' ? 'width:100%' : 'height:100%'};transform: translate(${x}, -50%)`
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container" v-if="sli?.[side]">
|
||||
<img class="img" :class="[side]" :style="style" :src="toRawFileUrl(sli[side]!)" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
user-select: none;
|
||||
height: 100%;
|
||||
|
||||
.img {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
.left {
|
||||
transform: translate(50%, -50%);
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.right {
|
||||
transform: translate(-50%, -50%);
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -9,6 +9,8 @@ import { debounce, uniqueId } from 'lodash-es'
|
|||
import edgeTrigger from './edgeTrigger.vue'
|
||||
import { t } from '@/i18n'
|
||||
import { tryOnMounted, useDocumentVisibility, type Fn } from '@vueuse/core'
|
||||
import ImgSliDrawer from '../ImgSli/ImgSliDrawer.vue'
|
||||
|
||||
|
||||
|
||||
const global = useGlobalStore()
|
||||
|
|
@ -79,8 +81,8 @@ 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
|
||||
console.log('watch tab change failed')
|
||||
return
|
||||
}
|
||||
par.onUiTabChange(() => {
|
||||
const el = par.get_uiCurrentTabContent()
|
||||
|
|
@ -104,6 +106,7 @@ watch(useDocumentVisibility(), v => v && emitReturnToIIB())
|
|||
</edge-trigger>
|
||||
</pane>
|
||||
</splitpanes>
|
||||
<img-sli-drawer />
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ const {
|
|||
onFileItemClick,
|
||||
scroller,
|
||||
showMenuIdx,
|
||||
onFileDragStart
|
||||
onFileDragStart,
|
||||
onFileDragEnd
|
||||
} = useImageSearch()
|
||||
|
||||
const props = defineProps<{
|
||||
|
|
@ -86,6 +87,7 @@ watch(
|
|||
:file="file"
|
||||
v-model:show-menu-idx="showMenuIdx"
|
||||
@dragstart="onFileDragStart"
|
||||
@dragend="onFileDragEnd"
|
||||
@file-item-click="onFileItemClick"
|
||||
:full-screen-preview-image-url="
|
||||
images[previewIdx] ? toRawFileUrl(images[previewIdx]) : ''
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ const {
|
|||
onFileItemClick,
|
||||
scroller,
|
||||
showMenuIdx,
|
||||
onFileDragStart
|
||||
onFileDragStart,
|
||||
onFileDragEnd
|
||||
} = useImageSearch()
|
||||
const substr = ref('')
|
||||
|
||||
|
|
@ -99,7 +100,7 @@ useGlobalEventListen('return-to-iib', async () => {
|
|||
<file-item-cell :idx="idx" :file="file" v-model:show-menu-idx="showMenuIdx" @file-item-click="onFileItemClick"
|
||||
:full-screen-preview-image-url="images[previewIdx] ? toRawFileUrl(images[previewIdx]) : ''"
|
||||
:selected="multiSelectedIdxs.includes(idx)" @context-menu-click="onContextMenuClickU"
|
||||
@dragstart="onFileDragStart"
|
||||
@dragstart="onFileDragStart" @dragend="onFileDragEnd"
|
||||
@preview-visible-change="onPreviewVisibleChange" />
|
||||
</template>
|
||||
</RecycleScroller>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export const useImageSearch = () => {
|
|||
const { stackViewEl, multiSelectedIdxs, stack } = useHookShareState({ images }).toRefs()
|
||||
const { itemSize, gridItems } = useFilesDisplay(propsMock)
|
||||
const { showMenuIdx } = useMobileOptimization()
|
||||
const { onFileDragStart } = useFileTransfer() // for reset selected
|
||||
const { onFileDragStart, onFileDragEnd } = useFileTransfer()
|
||||
const {
|
||||
showGenInfo,
|
||||
imageGenInfo,
|
||||
|
|
@ -63,6 +63,7 @@ export const useImageSearch = () => {
|
|||
onFileItemClick,
|
||||
showMenuIdx,
|
||||
multiSelectedIdxs,
|
||||
onFileDragStart
|
||||
onFileDragStart,
|
||||
onFileDragEnd
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ const emit = defineEmits<{
|
|||
(type: 'update:showMenuIdx', v: number): void
|
||||
(type: 'fileItemClick', event: MouseEvent, file: FileNodeInfo, idx: number): void
|
||||
(type: 'dragstart', event: DragEvent, idx: number): void
|
||||
(type: 'dragend', event: DragEvent, idx: number): void
|
||||
(type: 'previewVisibleChange', value: boolean, last: boolean): void
|
||||
(type: 'contextMenuClick', e: MenuInfo, file: FileNodeInfo, idx: number): void
|
||||
}>()
|
||||
|
|
@ -71,6 +72,7 @@ const imageSrc = computed(() => {
|
|||
:key="file.name"
|
||||
draggable="true"
|
||||
@dragstart="emit('dragstart', $event, idx)"
|
||||
@dragend="emit('dragend', $event, idx)"
|
||||
@contextmenu="onRightClick"
|
||||
@click.capture="emit('fileItemClick', $event, file, idx)"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { useGlobalStore, type FileTransferTabPane, type Shortcut } from '@/store/useGlobalStore'
|
||||
import { useImgSliStore } from '@/store/useImgSli'
|
||||
import { onLongPress, useElementSize } from '@vueuse/core'
|
||||
import { ref, computed, watch, onMounted, h, type Ref } from 'vue'
|
||||
import { gradioApp, parentWindow } from '@/util'
|
||||
|
|
@ -30,21 +31,14 @@ import type { MenuInfo } from 'ant-design-vue/lib/menu/src/interface'
|
|||
import { t } from '@/i18n'
|
||||
import { DatabaseOutlined } from '@/icon'
|
||||
import { addScannedPath, removeScannedPath, toggleCustomTagToImg } from '@/api/db'
|
||||
import { FileTransferData, isFileTransferData, toRawFileUrl } from './util'
|
||||
export * from './util'
|
||||
|
||||
export const stackCache = new Map<string, Page[]>()
|
||||
|
||||
const global = useGlobalStore()
|
||||
const sli = useImgSliStore()
|
||||
const imgTransferBus = new BroadcastChannel('iib-image-transfer-bus')
|
||||
const encode = encodeURIComponent
|
||||
export const toRawFileUrl = (file: FileNodeInfo, download = false) =>
|
||||
`/infinite_image_browsing/file?path=${encode(file.fullpath)}&t=${encode(file.date)}${
|
||||
download ? `&disposition=${encode(file.name)}` : ''
|
||||
}`
|
||||
export const toImageThumbnailUrl = (file: FileNodeInfo, size: string) =>
|
||||
`/infinite_image_browsing/image-thumbnail?path=${encode(file.fullpath)}&size=${size}&t=${encode(
|
||||
file.date
|
||||
)}`
|
||||
|
||||
export const { eventEmitter: events, useEventListen } = typedEventEmitter<{
|
||||
removeFiles(_: { paths: string[]; loc: string }): void
|
||||
addFiles(_: { files: FileNodeInfo[]; loc: string }): void
|
||||
|
|
@ -646,6 +640,7 @@ export function useFilesDisplay(props: Props) {
|
|||
itemSize
|
||||
}
|
||||
}
|
||||
|
||||
const multiSelectTips = () =>
|
||||
h(
|
||||
'p',
|
||||
|
|
@ -653,11 +648,12 @@ const multiSelectTips = () =>
|
|||
style: {
|
||||
background: 'var(--zp-secondary-background)',
|
||||
padding: '8px',
|
||||
borderLeft: '4px solid var(--primary-color)',
|
||||
borderLeft: '4px solid var(--primary-color)'
|
||||
}
|
||||
},
|
||||
`Tips: ${t('multiSelectTips')}`
|
||||
)
|
||||
|
||||
export function useFileTransfer() {
|
||||
const { currLocation, sortedFiles, currPage, multiSelectedIdxs, eventEmitter } =
|
||||
useHookShareState().toRefs()
|
||||
|
|
@ -670,6 +666,7 @@ export function useFileTransfer() {
|
|||
|
||||
const onFileDragStart = (e: DragEvent, idx: number) => {
|
||||
const file = cloneDeep(sortedFiles.value[idx])
|
||||
sli.fileDragging = true
|
||||
console.log('onFileDragStart set drag file ', e, idx, file)
|
||||
const files = [file]
|
||||
let includeDir = file.type === 'dir'
|
||||
|
|
@ -678,25 +675,26 @@ export function useFileTransfer() {
|
|||
files.push(...selectedFiles)
|
||||
includeDir = selectedFiles.some((v) => v.type === 'dir')
|
||||
}
|
||||
const data: FileTransferData = {
|
||||
includeDir,
|
||||
loc: currLocation.value || 'search-result',
|
||||
path: uniqBy(files, 'fullpath').map((f) => f.fullpath),
|
||||
nodes: uniqBy(files, 'fullpath'),
|
||||
__id: 'FileTransferData'
|
||||
}
|
||||
e.dataTransfer!.setData(
|
||||
'text/plain',
|
||||
JSON.stringify({
|
||||
includeDir,
|
||||
loc: currLocation.value || 'search-result',
|
||||
path: uniqBy(files, 'fullpath').map((f) => f.fullpath)
|
||||
})
|
||||
JSON.stringify(data)
|
||||
)
|
||||
}
|
||||
|
||||
const onFileDragEnd = () => {
|
||||
sli.fileDragging = false
|
||||
}
|
||||
|
||||
const onDrop = async (e: DragEvent) => {
|
||||
type Data = {
|
||||
path: string[]
|
||||
loc: string
|
||||
includeDir: boolean
|
||||
}
|
||||
const data = JSON.parse(e.dataTransfer?.getData('text') || '{}') as Data
|
||||
console.log(data)
|
||||
if (data.path && typeof data.includeDir !== 'undefined' && data.loc) {
|
||||
const data = JSON.parse(e.dataTransfer?.getData('text') ?? '{}')
|
||||
if (isFileTransferData(data)) {
|
||||
const toPath = currLocation.value
|
||||
if (data.loc === toPath) {
|
||||
return
|
||||
|
|
@ -724,7 +722,8 @@ export function useFileTransfer() {
|
|||
return {
|
||||
onFileDragStart,
|
||||
onDrop,
|
||||
multiSelectedIdxs
|
||||
multiSelectedIdxs,
|
||||
onFileDragEnd
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ const {
|
|||
onScroll,
|
||||
|
||||
} = useFilesDisplay(props)
|
||||
const { onDrop, onFileDragStart } = useFileTransfer()
|
||||
const { onDrop, onFileDragStart, onFileDragEnd } = useFileTransfer()
|
||||
const { onFileItemClick, onContextMenuClick, showGenInfo, imageGenInfo, q } = useFileItemActions(
|
||||
props,
|
||||
{ openNext }
|
||||
|
|
@ -199,7 +199,7 @@ watch(
|
|||
<file-item :idx="idx" :file="file"
|
||||
:full-screen-preview-image-url="sortedFiles[previewIdx] ? toRawFileUrl(sortedFiles[previewIdx]) : ''"
|
||||
v-model:show-menu-idx="showMenuIdx" :selected="multiSelectedIdxs.includes(idx)" :view-mode="viewMode"
|
||||
@file-item-click="onFileItemClick" @dragstart="onFileDragStart"
|
||||
@file-item-click="onFileItemClick" @dragstart="onFileDragStart" @dragend=" onFileDragEnd"
|
||||
@preview-visible-change="onPreviewVisibleChange" @context-menu-click="onContextMenuClick" />
|
||||
</template>
|
||||
<template v-if="props.walkModePath" #after>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
import type { FileNodeInfo } from '@/api/files'
|
||||
|
||||
const encode = encodeURIComponent
|
||||
export const toRawFileUrl = (file: FileNodeInfo, download = false) =>
|
||||
`/infinite_image_browsing/file?path=${encode(file.fullpath)}&t=${encode(file.date)}${
|
||||
download ? `&disposition=${encode(file.name)}` : ''
|
||||
}`
|
||||
export const toImageThumbnailUrl = (file: FileNodeInfo, size: string) =>
|
||||
`/infinite_image_browsing/image-thumbnail?path=${encode(file.fullpath)}&size=${size}&t=${encode(
|
||||
file.date
|
||||
)}`
|
||||
|
||||
export type FileTransferData = {
|
||||
path: string[]
|
||||
loc: string
|
||||
includeDir: boolean
|
||||
nodes: FileNodeInfo[]
|
||||
__id: 'FileTransferData'
|
||||
}
|
||||
|
||||
export const isFileTransferData = (v: any): v is FileTransferData =>
|
||||
typeof v === 'object' && v.__id === 'FileTransferData'
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import { FileNodeInfo } from '@/api/files'
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import { asyncComputed } from '@vueuse/core'
|
||||
import { createImage } from '@/util'
|
||||
import { toRawFileUrl } from '@/page/fileTransfer/util'
|
||||
|
||||
export const useImgSliStore = defineStore('useImgSliStore', () => {
|
||||
const splitPercent = ref(50)
|
||||
const fileDragging = ref(false)
|
||||
const drawerVisible = ref(false)
|
||||
const left = ref<FileNodeInfo>()
|
||||
const right = ref<FileNodeInfo>()
|
||||
|
||||
const maxEdge = asyncComputed(async () => {
|
||||
if (!left.value) {
|
||||
return 'width'
|
||||
}
|
||||
const l = await createImage(toRawFileUrl(left.value))
|
||||
const aspectRatio = l.width / l.height
|
||||
const clientAR = document.body.clientWidth / document.body.clientHeight
|
||||
return aspectRatio > clientAR ? 'width' : 'height'
|
||||
})
|
||||
return {
|
||||
drawerVisible,
|
||||
splitPercent,
|
||||
fileDragging,
|
||||
left,
|
||||
right,
|
||||
maxEdge
|
||||
}
|
||||
})
|
||||
|
|
@ -31,7 +31,11 @@ export const getTabIdxInSDWebui = () => {
|
|||
}
|
||||
|
||||
export const switch2IBB = () => {
|
||||
gradioApp().querySelector('#tabs')!.querySelectorAll('button')[getTabIdxInSDWebui()].click()
|
||||
try {
|
||||
gradioApp().querySelector('#tabs')!.querySelectorAll('button')[getTabIdxInSDWebui()].click()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
export const asyncCheck = async <T>(getter: () => T, checkSize = 100, timeout = 1000) => {
|
||||
|
|
@ -154,3 +158,13 @@ export function removeQueryParams(keys: string[]): string {
|
|||
// 返回新的 URL
|
||||
return newUrl
|
||||
}
|
||||
|
||||
|
||||
export const createImage = (src: string) => {
|
||||
return new Promise<HTMLImageElement>((resolve, reject) => {
|
||||
const img = new Image()
|
||||
img.onload = () => resolve(img)
|
||||
img.onerror = err => reject(err)
|
||||
img.src = src
|
||||
})
|
||||
}
|
||||
Loading…
Reference in New Issue