docs(changelog): add inline video playback and recent updates
Add changelog entries for: - Inline video playback feature (2026-02-23) - Parse extra JSON metadata (2026-02-22) - Tips carousel component (2026-02-22) - Optimize database backup (2026-02-22) - Docs improvements (2026-02-22) Include screenshot for inline video playback feature.docs/update-changelog-inline-video
parent
f8015e6631
commit
41471e4349
|
|
@ -1,6 +1,42 @@
|
|||
[跳到中文](#中文)
|
||||
# English
|
||||
|
||||
## 2026-02-23
|
||||
### 🎬 Inline Video Playback
|
||||
Added inline video playback feature for video items wider than 400px.
|
||||
|
||||
**Features:**
|
||||
- **Play Here Button**: Hover over a video to see the "Play Here" button in the bottom-left corner
|
||||
- **Inline Playback**: Click to play the video directly in the grid item without opening a modal
|
||||
- **Auto-Stop Others**: Automatically stops any other playing videos when starting a new one
|
||||
- **Multi-language Support**: Button text is fully internationalized (English, Chinese, German)
|
||||
- **Smart Reset**: Automatically stops playback when the list is reordered or refreshed
|
||||
|
||||
**How to use:**
|
||||
1. Make sure your grid cell width is greater than 400px (adjustable in settings)
|
||||
2. Hover over any video thumbnail
|
||||
3. Click the "Play Here" button in the bottom-left corner
|
||||
4. The video plays inline with full controls
|
||||
5. Click elsewhere or play another video to stop
|
||||
|
||||
**Note:** The center play icon still opens the modal player for full-screen viewing.
|
||||
|
||||
<img width="400" alt="Inline video playback" src="docs/imgs/file-item-play-here.png" />
|
||||
|
||||
## 2026-02-22
|
||||
### 📝 Parse extra JSON metadata
|
||||
Parse and mixin `extraJsonMetaInfo` field from image metadata.
|
||||
|
||||
### 🎡 Tips carousel
|
||||
Added tips carousel component with 10 multilingual tips to help users discover features.
|
||||
|
||||
### 🗄️ Optimize database backup
|
||||
Optimized database backup to run once per day and reduced max backups to 4.
|
||||
|
||||
### 📚 Docs improvements
|
||||
Fixed URL encoding example with correct keywords and reorganized skill documentation.
|
||||
|
||||
|
||||
## 2026-02-17
|
||||
### 🗂️ Smart Organize - AI-Powered File Organization \
|
||||
|
||||
|
|
@ -691,6 +727,41 @@ Triggered under the same circumstances as above, there will be a button to updat
|
|||
|
||||
# 中文
|
||||
|
||||
## 2026-02-23
|
||||
### 🎬 视频原地播放功能
|
||||
为宽度超过 400px 的视频 item 添加了原地播放功能。
|
||||
|
||||
**功能特性:**
|
||||
- **"在此播放"按钮**:鼠标悬停在视频上时,左下角会显示播放按钮
|
||||
- **原地播放**:点击按钮直接在网格 item 内播放视频,无需打开弹窗
|
||||
- **自动停止其他视频**:播放新视频时,会自动停止其他正在播放的视频
|
||||
- **多语言支持**:按钮文字支持多语言(英文、简体中文、繁体中文、德语)
|
||||
- **智能重置**:列表重新排序或刷新时,自动停止播放
|
||||
|
||||
**使用方法:**
|
||||
1. 确保网格单元格宽度大于 400px(可在设置中调整)
|
||||
2. 将鼠标悬停在任意视频缩略图上
|
||||
3. 点击左下角的"在此播放"按钮
|
||||
4. 视频将在 item 内播放,带有完整的控制条
|
||||
5. 点击其他位置或播放其他视频即可停止
|
||||
|
||||
**注意:** 中心的播放图标仍然可以打开模态框播放器进行全屏查看。
|
||||
|
||||
<img width="400" alt="视频原地播放" src="docs/imgs/file-item-play-here.png" />
|
||||
## 2026-02-22
|
||||
### 📝 解析额外 JSON 元数据
|
||||
解析并混入图片元数据中的 `extraJsonMetaInfo` 字段。
|
||||
|
||||
### 🎡 提示轮播
|
||||
新增提示轮播组件,包含 10 条多语言提示,帮助用户发现功能。
|
||||
|
||||
### 🗄️ 优化数据库备份
|
||||
优化数据库备份为每天一次,并减少最大备份数为 4 个。
|
||||
|
||||
### 📚 文档改进
|
||||
修复 URL 编码示例中的关键词,并重组技能文档。
|
||||
|
||||
|
||||
## 2026-02-17
|
||||
### 🗂️ 智能整理 - AI 驱动的文件整理
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 693 KiB |
|
|
@ -13,7 +13,7 @@ Promise.resolve().then(async () => {
|
|||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Infinite Image Browsing</title>
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-32743103.js"></script>
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-f2db319b.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-dd273d5b.css">
|
||||
</head>
|
||||
|
||||
|
|
|
|||
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 @@
|
|||
import{d as a,o as t,j as n,c as s,c1 as _,n as o}from"./index-32743103.js";const c={class:"img-sli-container"},i=a({__name:"ImgSliPagePane",props:{paneIdx:{},tabIdx:{},left:{},right:{}},setup(l){return(e,r)=>(t(),n("div",c,[s(_,{left:e.left,right:e.right},null,8,["left","right"])]))}});const d=o(i,[["__scopeId","data-v-ae3fb9a8"]]);export{d as default};
|
||||
import{d as a,o as t,j as n,c as s,c1 as _,n as o}from"./index-f2db319b.js";const c={class:"img-sli-container"},i=a({__name:"ImgSliPagePane",props:{paneIdx:{},tabIdx:{},left:{},right:{}},setup(l){return(e,r)=>(t(),n("div",c,[s(_,{left:e.left,right:e.right},null,8,["left","right"])]))}});const d=o(i,[["__scopeId","data-v-ae3fb9a8"]]);export{d 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
File diff suppressed because one or more lines are too long
|
|
@ -1,3 +1,3 @@
|
|||
import{bJ as N,bK as E,bL as q,c as u,A as U,d as R,o as d,j as p,k as _,F as X,K as G,ah as K,C as f,l as g,t as h,E as L,a3 as H,n as z,aq as Q,aC as C,aD as F,r as W,aj as I,X as V,v as Y,bM as Z,m as T,bN as ee,bO as te}from"./index-32743103.js";const ge=N(E),me=N(q);var ne={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M878.3 392.1L631.9 145.7c-6.5-6.5-15-9.7-23.5-9.7s-17 3.2-23.5 9.7L423.8 306.9c-12.2-1.4-24.5-2-36.8-2-73.2 0-146.4 24.1-206.5 72.3-15.4 12.3-16.6 35.4-2.7 49.4l181.7 181.7-215.4 215.2a15.8 15.8 0 00-4.6 9.8l-3.4 37.2c-.9 9.4 6.6 17.4 15.9 17.4.5 0 1 0 1.5-.1l37.2-3.4c3.7-.3 7.2-2 9.8-4.6l215.4-215.4 181.7 181.7c6.5 6.5 15 9.7 23.5 9.7 9.7 0 19.3-4.2 25.9-12.4 56.3-70.3 79.7-158.3 70.2-243.4l161.1-161.1c12.9-12.8 12.9-33.8 0-46.8z"}}]},name:"pushpin",theme:"filled"};const se=ne;function k(i){for(var e=1;e<arguments.length;e++){var t=arguments[e]!=null?Object(arguments[e]):{},n=Object.keys(t);typeof Object.getOwnPropertySymbols=="function"&&(n=n.concat(Object.getOwnPropertySymbols(t).filter(function(s){return Object.getOwnPropertyDescriptor(t,s).enumerable}))),n.forEach(function(s){ie(i,s,t[s])})}return i}function ie(i,e,t){return e in i?Object.defineProperty(i,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):i[e]=t,i}var P=function(e,t){var n=k({},e,t.attrs);return u(U,k({},n,{icon:se}),null)};P.displayName="PushpinFilled";P.inheritAttrs=!1;const re=P,ae={class:"record-container"},oe={style:{flex:"1"}},ce={class:"rec-actions"},le=["onClick"],ue=R({__name:"HistoryRecord",props:{records:{}},emits:["reuseRecord"],setup(i){return(e,t)=>{const n=H;return d(),p("div",null,[_("ul",ae,[(d(!0),p(X,null,G(e.records.getRecords(),s=>(d(),p("li",{key:s.id,class:"record"},[_("div",oe,[K(e.$slots,"default",{record:s},void 0,!0)]),_("div",ce,[u(n,{onClick:o=>e.$emit("reuseRecord",s),type:"primary"},{default:f(()=>[g(h(e.$t("restore")),1)]),_:2},1032,["onClick"]),_("div",{class:"pin",onClick:o=>e.records.switchPin(s)},[u(L(re)),g(" "+h(e.records.isPinned(s)?e.$t("unpin"):e.$t("pin")),1)],8,le)])]))),128))])])}}});const ve=z(ue,[["__scopeId","data-v-834a248f"]]);class m{constructor(e=128,t=[],n=[]){this.maxLength=e,this.records=t,this.pinnedValues=n}isPinned(e){return this.pinnedValues.some(t=>t.id===e.id)}add(e){this.records.length>=this.maxLength&&this.records.pop(),this.records.unshift({...e,id:Q()+Date.now(),time:new Date().toLocaleString()})}pin(e){const t=this.records.findIndex(n=>n.id===e.id);t!==-1&&this.records.splice(t,1),this.pinnedValues.push(e)}unpin(e){const t=this.pinnedValues.findIndex(n=>n.id===e.id);t!==-1&&this.pinnedValues.splice(t,1),this.records.unshift(e)}switchPin(e){this.isPinned(e)?this.unpin(e):this.pin(e)}getRecords(){return[...this.pinnedValues,...this.records]}getPinnedValues(){return this.pinnedValues}}const ye=C(`${F}fuzzy-search-HistoryRecord`,new m,{serializer:{read:i=>{const e=JSON.parse(i);return new m(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}}),be=C(`${F}tag-search-HistoryRecord`,new m,{serializer:{read:i=>{const e=JSON.parse(i);return new m(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}}),de={key:0,class:"tips-carousel"},pe={class:"tip-text"},_e={key:0,class:"tip-actions"},he=R({__name:"TipsCarousel",props:{interval:{type:Number,default:1e4}},setup(i){const e=i,t=C("iib-dismissed-tips-v2",{}),n=W(0);let s=null;const o=I(()=>{var v;const r=[];for(let a=1;a<=10;a++){const l=`loadingTip${a}`,y=V(l);if(!y||typeof y!="string")continue;const $=y.split("|"),b=$[0],M=((v=$[1])==null?void 0:v.trim())||"info",S=`
|
||||
import{bJ as N,bK as E,bL as q,c as u,A as U,d as R,o as d,j as p,k as _,F as X,K as G,ah as K,C as f,l as g,t as h,E as L,a3 as H,n as z,aq as Q,aC as C,aD as F,r as W,aj as I,X as V,v as Y,bM as Z,m as T,bN as ee,bO as te}from"./index-f2db319b.js";const ge=N(E),me=N(q);var ne={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M878.3 392.1L631.9 145.7c-6.5-6.5-15-9.7-23.5-9.7s-17 3.2-23.5 9.7L423.8 306.9c-12.2-1.4-24.5-2-36.8-2-73.2 0-146.4 24.1-206.5 72.3-15.4 12.3-16.6 35.4-2.7 49.4l181.7 181.7-215.4 215.2a15.8 15.8 0 00-4.6 9.8l-3.4 37.2c-.9 9.4 6.6 17.4 15.9 17.4.5 0 1 0 1.5-.1l37.2-3.4c3.7-.3 7.2-2 9.8-4.6l215.4-215.4 181.7 181.7c6.5 6.5 15 9.7 23.5 9.7 9.7 0 19.3-4.2 25.9-12.4 56.3-70.3 79.7-158.3 70.2-243.4l161.1-161.1c12.9-12.8 12.9-33.8 0-46.8z"}}]},name:"pushpin",theme:"filled"};const se=ne;function k(i){for(var e=1;e<arguments.length;e++){var t=arguments[e]!=null?Object(arguments[e]):{},n=Object.keys(t);typeof Object.getOwnPropertySymbols=="function"&&(n=n.concat(Object.getOwnPropertySymbols(t).filter(function(s){return Object.getOwnPropertyDescriptor(t,s).enumerable}))),n.forEach(function(s){ie(i,s,t[s])})}return i}function ie(i,e,t){return e in i?Object.defineProperty(i,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):i[e]=t,i}var P=function(e,t){var n=k({},e,t.attrs);return u(U,k({},n,{icon:se}),null)};P.displayName="PushpinFilled";P.inheritAttrs=!1;const re=P,ae={class:"record-container"},oe={style:{flex:"1"}},ce={class:"rec-actions"},le=["onClick"],ue=R({__name:"HistoryRecord",props:{records:{}},emits:["reuseRecord"],setup(i){return(e,t)=>{const n=H;return d(),p("div",null,[_("ul",ae,[(d(!0),p(X,null,G(e.records.getRecords(),s=>(d(),p("li",{key:s.id,class:"record"},[_("div",oe,[K(e.$slots,"default",{record:s},void 0,!0)]),_("div",ce,[u(n,{onClick:o=>e.$emit("reuseRecord",s),type:"primary"},{default:f(()=>[g(h(e.$t("restore")),1)]),_:2},1032,["onClick"]),_("div",{class:"pin",onClick:o=>e.records.switchPin(s)},[u(L(re)),g(" "+h(e.records.isPinned(s)?e.$t("unpin"):e.$t("pin")),1)],8,le)])]))),128))])])}}});const ve=z(ue,[["__scopeId","data-v-834a248f"]]);class m{constructor(e=128,t=[],n=[]){this.maxLength=e,this.records=t,this.pinnedValues=n}isPinned(e){return this.pinnedValues.some(t=>t.id===e.id)}add(e){this.records.length>=this.maxLength&&this.records.pop(),this.records.unshift({...e,id:Q()+Date.now(),time:new Date().toLocaleString()})}pin(e){const t=this.records.findIndex(n=>n.id===e.id);t!==-1&&this.records.splice(t,1),this.pinnedValues.push(e)}unpin(e){const t=this.pinnedValues.findIndex(n=>n.id===e.id);t!==-1&&this.pinnedValues.splice(t,1),this.records.unshift(e)}switchPin(e){this.isPinned(e)?this.unpin(e):this.pin(e)}getRecords(){return[...this.pinnedValues,...this.records]}getPinnedValues(){return this.pinnedValues}}const ye=C(`${F}fuzzy-search-HistoryRecord`,new m,{serializer:{read:i=>{const e=JSON.parse(i);return new m(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}}),be=C(`${F}tag-search-HistoryRecord`,new m,{serializer:{read:i=>{const e=JSON.parse(i);return new m(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}}),de={key:0,class:"tips-carousel"},pe={class:"tip-text"},_e={key:0,class:"tip-actions"},he=R({__name:"TipsCarousel",props:{interval:{type:Number,default:1e4}},setup(i){const e=i,t=C("iib-dismissed-tips-v2",{}),n=W(0);let s=null;const o=I(()=>{var v;const r=[];for(let a=1;a<=10;a++){const l=`loadingTip${a}`,y=V(l);if(!y||typeof y!="string")continue;const $=y.split("|"),b=$[0],M=((v=$[1])==null?void 0:v.trim())||"info",S=`
|
||||
|
||||
`,w=b.indexOf(S);if(w===-1)continue;const x=b.substring(0,w).trim(),A=b.substring(w+S.length).trim(),O={title:x,content:A,type:M};O.type==="warning"&&t.value[x]||r.push(O)}for(let a=r.length-1;a>0;a--){const l=Math.floor(Math.random()*(a+1));[r[a],r[l]]=[r[l],r[a]]}return r}),c=I(()=>{const r=o.value;return r.length===0?{title:"",content:"",type:"info"}:r[n.value%r.length]}),j=r=>{switch(r){case"warning":return"warning";case"info":return"blue";case"tip":return"green";default:return"default"}},B=()=>{c.value.type==="warning"&&(t.value={...t.value,[c.value.title]:!0})},D=()=>{s&&clearInterval(s),s=setInterval(()=>{o.value.length>1&&(n.value=(n.value+1)%o.value.length)},e.interval)},J=()=>{s&&(clearInterval(s),s=null)};return Y(()=>{D()}),Z(()=>{J()}),(r,v)=>{const a=te,l=H;return o.value.length>0?(d(),p("div",de,[u(ee,{name:"tip-fade",mode:"out-in"},{default:f(()=>[(d(),p("div",{key:n.value,class:"tip-content"},[u(a,{color:j(c.value.type),class:"tip-tag"},{default:f(()=>[g(h(c.value.title),1)]),_:1},8,["color"]),_("span",pe,h(c.value.content),1),c.value.type==="warning"?(d(),p("div",_e,[u(l,{size:"small",type:"link",onClick:B},{default:f(()=>[g(h(L(V)("dontShowAgain")),1)]),_:1})])):T("",!0)]))]),_:1})])):T("",!0)}}});const we=z(he,[["__scopeId","data-v-3b5692ee"]]);export{ve as H,we as T,me as _,ge as a,ye as f,be as t};
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import{d as LA,r as Kt,aj as Rr,X as Ut,s as gs,x as Dh,v as IA,bM as zk,o as te,j as Ce,c as Ht,k as Mt,t as Vt,E as ve,C as le,l as ze,bC as PA,B as Ka,bP as Vk,bQ as Gk,m as fr,W as Jr,bR as Fk,a8 as RA,av as kA,bO as EA,bS as Hk,a0 as OA,a2 as NA,bT as BA,a3 as zA,aw as VA,ax as GA,bU as Wk,n as FA,p as $k,aC as H_,bV as Uk,T as Yk,F as W_,K as Zk,bW as Xk,bX as qk,bY as Kk,bt as jk,bZ as Jk,b_ as Qk,aq as Ro,b$ as tE,a6 as eE,Z as rE,c0 as aE}from"./index-32743103.js";/* empty css *//* empty css *//*! *****************************************************************************
|
||||
import{d as LA,r as Kt,aj as Rr,X as Ut,s as gs,x as Dh,v as IA,bM as zk,o as te,j as Ce,c as Ht,k as Mt,t as Vt,E as ve,C as le,l as ze,bC as PA,B as Ka,bP as Vk,bQ as Gk,m as fr,W as Jr,bR as Fk,a8 as RA,av as kA,bO as EA,bS as Hk,a0 as OA,a2 as NA,bT as BA,a3 as zA,aw as VA,ax as GA,bU as Wk,n as FA,p as $k,aC as H_,bV as Uk,T as Yk,F as W_,K as Zk,bW as Xk,bX as qk,bY as Kk,bt as jk,bZ as Jk,b_ as Qk,aq as Ro,b$ as tE,a6 as eE,Z as rE,c0 as aE}from"./index-f2db319b.js";/* empty css *//* empty css *//*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
|
|
@ -1 +1 @@
|
|||
import{b2 as i,aO as t,dJ as f,aS as n}from"./index-32743103.js";function u(e,a,r){if(!i(r))return!1;var s=typeof a;return(s=="number"?t(r)&&f(a,r.length):s=="string"&&a in r)?n(r[a],e):!1}export{u as i};
|
||||
import{b2 as i,aO as t,dK as f,aS as n}from"./index-f2db319b.js";function u(e,a,r){if(!i(r))return!1;var s=typeof a;return(s=="number"?t(r)&&f(a,r.length):s=="string"&&a in r)?n(r[a],e):!1}export{u as i};
|
||||
|
|
@ -1 +1 @@
|
|||
import{d as z,p as B,c2 as $,bp as S,o as _,j as w,k as f,c as l,C as d,l as p,t as c,E as s,B as A,U as E,c3 as R,c4 as y,W as x,X as T,a3 as U,a6 as V,n as N}from"./index-32743103.js";import{F as j,s as L}from"./FileItem-aa47825a.js";import{u as H,b as O,j as W}from"./index-c80754a2.js";import"./index-e1a70e12.js";import"./shortcut-3129f75b.js";import"./_isIterateeCall-16c5cf9c.js";const q={class:"actions-panel actions"},G={class:"item"},P={key:0,class:"file-list"},Q={class:"hint"},X=z({__name:"batchDownload",props:{tabIdx:{},paneIdx:{},id:{}},setup(J){const{stackViewEl:b}=H().toRefs(),{itemSize:h,gridItems:D,cellWidth:g}=O(),i=B(),m=W(),{selectdFiles:a}=$(m),r=S(),v=async e=>{const t=R(e);t&&m.addFiles(t.nodes)},C=async()=>{r.pushAction(async()=>{const e=await y.value.post("/zip",{paths:a.value.map(u=>u.fullpath),compress:i.batchDownloadCompress,pack_only:!1},{responseType:"blob"}),t=window.URL.createObjectURL(new Blob([e.data])),o=document.createElement("a");o.href=t,o.setAttribute("download",`iib_${new Date().toLocaleString()}.zip`),document.body.appendChild(o),o.click()})},I=async()=>{r.pushAction(async()=>{await y.value.post("/zip",{paths:a.value.map(e=>e.fullpath),compress:i.batchDownloadCompress,pack_only:!0},{responseType:"blob"}),x.success(T("success"))})},F=e=>{a.value.splice(e,1)};return(e,t)=>{const o=U,u=V;return _(),w("div",{class:"container",ref_key:"stackViewEl",ref:b,onDrop:v},[f("div",q,[l(o,{onClick:t[0]||(t[0]=n=>s(m).selectdFiles=[])},{default:d(()=>[p(c(e.$t("clear")),1)]),_:1}),f("div",G,[p(c(e.$t("compressFile"))+": ",1),l(u,{checked:s(i).batchDownloadCompress,"onUpdate:checked":t[1]||(t[1]=n=>s(i).batchDownloadCompress=n)},null,8,["checked"])]),l(o,{onClick:I,type:"primary",loading:!s(r).isIdle},{default:d(()=>[p(c(e.$t("packOnlyNotDownload")),1)]),_:1},8,["loading"]),l(o,{onClick:C,type:"primary",loading:!s(r).isIdle},{default:d(()=>[p(c(e.$t("zipDownload")),1)]),_:1},8,["loading"])]),s(a).length?(_(),A(s(L),{key:1,ref:"scroller",class:"file-list",items:s(a).slice(),"item-size":s(h).first,"key-field":"fullpath","item-secondary-size":s(h).second,gridItems:s(D)},{default:d(({item:n,index:k})=>[l(j,{idx:k,file:n,"cell-width":s(g),"enable-close-icon":"",onCloseIconClick:K=>F(k),"full-screen-preview-image-url":s(E)(n),"enable-right-click-menu":!1},null,8,["idx","file","cell-width","onCloseIconClick","full-screen-preview-image-url"])]),_:1},8,["items","item-size","item-secondary-size","gridItems"])):(_(),w("div",P,[f("p",Q,c(e.$t("batchDownloaDDragAndDropHint")),1)]))],544)}}});const oe=N(X,[["__scopeId","data-v-a2642a17"]]);export{oe as default};
|
||||
import{d as z,p as B,c2 as $,bp as S,o as _,j as w,k as f,c as l,C as d,l as p,t as c,E as s,B as A,U as E,c3 as R,c4 as y,W as x,X as T,a3 as U,a6 as V,n as N}from"./index-f2db319b.js";import{F as j,s as L}from"./FileItem-72718f68.js";import{u as H,b as O,j as W}from"./index-0d856f16.js";import"./index-29e38a15.js";import"./shortcut-869fab50.js";import"./_isIterateeCall-dd643bcf.js";const q={class:"actions-panel actions"},G={class:"item"},P={key:0,class:"file-list"},Q={class:"hint"},X=z({__name:"batchDownload",props:{tabIdx:{},paneIdx:{},id:{}},setup(J){const{stackViewEl:b}=H().toRefs(),{itemSize:h,gridItems:D,cellWidth:g}=O(),i=B(),m=W(),{selectdFiles:a}=$(m),r=S(),v=async e=>{const t=R(e);t&&m.addFiles(t.nodes)},C=async()=>{r.pushAction(async()=>{const e=await y.value.post("/zip",{paths:a.value.map(u=>u.fullpath),compress:i.batchDownloadCompress,pack_only:!1},{responseType:"blob"}),t=window.URL.createObjectURL(new Blob([e.data])),o=document.createElement("a");o.href=t,o.setAttribute("download",`iib_${new Date().toLocaleString()}.zip`),document.body.appendChild(o),o.click()})},I=async()=>{r.pushAction(async()=>{await y.value.post("/zip",{paths:a.value.map(e=>e.fullpath),compress:i.batchDownloadCompress,pack_only:!0},{responseType:"blob"}),x.success(T("success"))})},F=e=>{a.value.splice(e,1)};return(e,t)=>{const o=U,u=V;return _(),w("div",{class:"container",ref_key:"stackViewEl",ref:b,onDrop:v},[f("div",q,[l(o,{onClick:t[0]||(t[0]=n=>s(m).selectdFiles=[])},{default:d(()=>[p(c(e.$t("clear")),1)]),_:1}),f("div",G,[p(c(e.$t("compressFile"))+": ",1),l(u,{checked:s(i).batchDownloadCompress,"onUpdate:checked":t[1]||(t[1]=n=>s(i).batchDownloadCompress=n)},null,8,["checked"])]),l(o,{onClick:I,type:"primary",loading:!s(r).isIdle},{default:d(()=>[p(c(e.$t("packOnlyNotDownload")),1)]),_:1},8,["loading"]),l(o,{onClick:C,type:"primary",loading:!s(r).isIdle},{default:d(()=>[p(c(e.$t("zipDownload")),1)]),_:1},8,["loading"])]),s(a).length?(_(),A(s(L),{key:1,ref:"scroller",class:"file-list",items:s(a).slice(),"item-size":s(h).first,"key-field":"fullpath","item-secondary-size":s(h).second,gridItems:s(D)},{default:d(({item:n,index:k})=>[l(j,{idx:k,file:n,"cell-width":s(g),"enable-close-icon":"",onCloseIconClick:K=>F(k),"full-screen-preview-image-url":s(E)(n),"enable-right-click-menu":!1},null,8,["idx","file","cell-width","onCloseIconClick","full-screen-preview-image-url"])]),_:1},8,["items","item-size","item-secondary-size","gridItems"])):(_(),w("div",P,[f("p",Q,c(e.$t("batchDownloaDDragAndDropHint")),1)]))],544)}}});const oe=N(X,[["__scopeId","data-v-a2642a17"]]);export{oe as default};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
import{F as w,s as y}from"./FileItem-aa47825a.js";import{u as k,b as x}from"./index-c80754a2.js";import{d as F,p as b,bm as h,r as C,c5 as D,c6 as I,o as E,j as V,c,C as z,E as e,U as S,c3 as B,c7 as R,n as A}from"./index-32743103.js";import"./index-e1a70e12.js";import"./shortcut-3129f75b.js";import"./_isIterateeCall-16c5cf9c.js";const K=F({__name:"gridView",props:{tabIdx:{},paneIdx:{},id:{},removable:{type:Boolean},allowDragAndDrop:{type:Boolean},files:{},paneKey:{}},setup(p){const o=p,m=b(),{stackViewEl:d}=k().toRefs(),{itemSize:i,gridItems:u,cellWidth:f}=x(),g=h(),s=C(o.files??[]),_=async t=>{const l=B(t);o.allowDragAndDrop&&l&&(s.value=R([...s.value,...l.nodes]))},v=t=>{s.value.splice(t,1)};return D(()=>{m.pageFuncExportMap.set(o.paneKey,{getFiles:()=>I(s.value),setFiles:t=>s.value=t})}),(t,l)=>(E(),V("div",{class:"container",ref_key:"stackViewEl",ref:d,onDrop:_},[c(e(y),{ref:"scroller",class:"file-list",items:s.value.slice(),"item-size":e(i).first,"key-field":"fullpath","item-secondary-size":e(i).second,gridItems:e(u)},{default:z(({item:a,index:r})=>{var n;return[c(w,{idx:r,file:a,"cell-width":e(f),"enable-close-icon":o.removable,onCloseIconClick:T=>v(r),"full-screen-preview-image-url":e(S)(a),"extra-tags":(n=a==null?void 0:a.tags)==null?void 0:n.map(e(g).tagConvert),"enable-right-click-menu":!1},null,8,["idx","file","cell-width","enable-close-icon","onCloseIconClick","full-screen-preview-image-url","extra-tags"])]}),_:1},8,["items","item-size","item-secondary-size","gridItems"])],544))}});const M=A(K,[["__scopeId","data-v-f35f4802"]]);export{M as default};
|
||||
import{F as w,s as y}from"./FileItem-72718f68.js";import{u as k,b as x}from"./index-0d856f16.js";import{d as F,p as b,bm as h,r as C,c5 as D,c6 as I,o as E,j as V,c,C as z,E as e,U as S,c3 as B,c7 as R,n as A}from"./index-f2db319b.js";import"./index-29e38a15.js";import"./shortcut-869fab50.js";import"./_isIterateeCall-dd643bcf.js";const K=F({__name:"gridView",props:{tabIdx:{},paneIdx:{},id:{},removable:{type:Boolean},allowDragAndDrop:{type:Boolean},files:{},paneKey:{}},setup(p){const o=p,m=b(),{stackViewEl:d}=k().toRefs(),{itemSize:i,gridItems:u,cellWidth:f}=x(),g=h(),s=C(o.files??[]),_=async t=>{const l=B(t);o.allowDragAndDrop&&l&&(s.value=R([...s.value,...l.nodes]))},v=t=>{s.value.splice(t,1)};return D(()=>{m.pageFuncExportMap.set(o.paneKey,{getFiles:()=>I(s.value),setFiles:t=>s.value=t})}),(t,l)=>(E(),V("div",{class:"container",ref_key:"stackViewEl",ref:d,onDrop:_},[c(e(y),{ref:"scroller",class:"file-list",items:s.value.slice(),"item-size":e(i).first,"key-field":"fullpath","item-secondary-size":e(i).second,gridItems:e(u)},{default:z(({item:a,index:r})=>{var n;return[c(w,{idx:r,file:a,"cell-width":e(f),"enable-close-icon":o.removable,onCloseIconClick:T=>v(r),"full-screen-preview-image-url":e(S)(a),"extra-tags":(n=a==null?void 0:a.tags)==null?void 0:n.map(e(g).tagConvert),"enable-right-click-menu":!1},null,8,["idx","file","cell-width","enable-close-icon","onCloseIconClick","full-screen-preview-image-url","extra-tags"])]}),_:1},8,["items","item-size","item-secondary-size","gridItems"])],544))}});const M=A(K,[["__scopeId","data-v-f35f4802"]]);export{M as default};
|
||||
|
|
@ -1 +1 @@
|
|||
import{aL as F,r as g,bF as P,bG as S,ar as A,aj as R,bp as q,bH as L,bI as j}from"./index-32743103.js";import{u as z,b as H,f as O,c as Q,d as T,e as U,i as W,h as B}from"./index-c80754a2.js";let K=0;const V=()=>++K,X=(n,i,{dataUpdateStrategy:l="replace"}={})=>{const a=F([""]),c=g(!1),t=g(),o=g(!1);let f=g(-1);const v=new Set,w=e=>{var s;l==="replace"?t.value=e:l==="merge"&&(A((Array.isArray(t.value)||typeof t.value>"u")&&Array.isArray(e),"数据更新策略为合并时仅可用于值为数组的情况"),t.value=[...(s=t==null?void 0:t.value)!==null&&s!==void 0?s:[],...e])},d=e=>S(void 0,void 0,void 0,function*(){if(o.value||c.value&&typeof e>"u")return!1;o.value=!0;const s=V();f.value=s;try{let r;if(typeof e=="number"){if(r=a[e],typeof r!="string")return!1}else r=a[a.length-1];const m=yield n(r);if(v.has(s))return v.delete(s),!1;w(i(m));const u=m.cursor;if((e===a.length-1||typeof e!="number")&&(c.value=!u.has_next,u.has_next)){const y=u.next_cursor||u.next;A(typeof y=="string"),a.push(y)}}finally{f.value===s&&(o.value=!1)}return!0}),I=()=>{v.add(f.value),o.value=!1},x=(e=!1)=>S(void 0,void 0,void 0,function*(){const{refetch:s,force:r}=typeof e=="object"?e:{refetch:e};r&&I(),A(!o.value),a.splice(0,a.length,""),o.value=!1,t.value=void 0,c.value=!1,s&&(yield d())}),h=()=>({next:()=>S(void 0,void 0,void 0,function*(){if(o.value)throw new Error("不允许同时迭代");return{done:!(yield d()),value:t.value}})});return P({abort:I,load:c,next:d,res:t,loading:o,cursorStack:a,reset:x,[Symbol.asyncIterator]:h,iter:{[Symbol.asyncIterator]:h}})},ee=n=>F(X(n,i=>i.files,{dataUpdateStrategy:"merge"})),te=n=>{const i=F(new Set),l=R(()=>(n.res??[]).filter(p=>!i.has(p.fullpath))),a=q(),{stackViewEl:c,multiSelectedIdxs:t,stack:o,scroller:f,props:v}=z({images:l}).toRefs(),{itemSize:w,gridItems:d,cellWidth:I,onScroll:x}=H({fetchNext:()=>n.next()}),{showMenuIdx:h}=O(),{onFileDragStart:e,onFileDragEnd:s}=Q(),{showGenInfo:r,imageGenInfo:m,q:u,onContextMenuClick:y,onFileItemClick:C}=T({openNext:L}),{previewIdx:_,previewing:E,onPreviewVisibleChange:M,previewImgMove:D,canPreview:G}=U({loadNext:()=>n.next()}),J=async(p,b,N)=>{o.value=[{curr:"",files:l.value}],await y(p,b,N)};W("removeFiles",async({paths:p})=>{p.forEach(b=>i.add(b))});const k=()=>{j(l.value)};return{images:l,scroller:f,queue:a,iter:n,onContextMenuClickU:J,stackViewEl:c,previewIdx:_,previewing:E,onPreviewVisibleChange:M,previewImgMove:D,canPreview:G,itemSize:w,gridItems:d,showGenInfo:r,imageGenInfo:m,q:u,onContextMenuClick:y,onFileItemClick:C,showMenuIdx:h,multiSelectedIdxs:t,onFileDragStart:e,onFileDragEnd:s,cellWidth:I,onScroll:x,saveLoadedFileAsJson:k,saveAllFileAsJson:async()=>{for(;!n.load;)await n.next();k()},props:v,...B()}};export{ee as c,te as u};
|
||||
import{aL as F,r as g,bF as P,bG as S,ar as A,aj as R,bp as q,bH as L,bI as j}from"./index-f2db319b.js";import{u as z,b as H,f as O,c as Q,d as T,e as U,i as W,h as B}from"./index-0d856f16.js";let K=0;const V=()=>++K,X=(n,i,{dataUpdateStrategy:l="replace"}={})=>{const a=F([""]),c=g(!1),t=g(),o=g(!1);let f=g(-1);const v=new Set,w=e=>{var s;l==="replace"?t.value=e:l==="merge"&&(A((Array.isArray(t.value)||typeof t.value>"u")&&Array.isArray(e),"数据更新策略为合并时仅可用于值为数组的情况"),t.value=[...(s=t==null?void 0:t.value)!==null&&s!==void 0?s:[],...e])},d=e=>S(void 0,void 0,void 0,function*(){if(o.value||c.value&&typeof e>"u")return!1;o.value=!0;const s=V();f.value=s;try{let r;if(typeof e=="number"){if(r=a[e],typeof r!="string")return!1}else r=a[a.length-1];const m=yield n(r);if(v.has(s))return v.delete(s),!1;w(i(m));const u=m.cursor;if((e===a.length-1||typeof e!="number")&&(c.value=!u.has_next,u.has_next)){const y=u.next_cursor||u.next;A(typeof y=="string"),a.push(y)}}finally{f.value===s&&(o.value=!1)}return!0}),I=()=>{v.add(f.value),o.value=!1},x=(e=!1)=>S(void 0,void 0,void 0,function*(){const{refetch:s,force:r}=typeof e=="object"?e:{refetch:e};r&&I(),A(!o.value),a.splice(0,a.length,""),o.value=!1,t.value=void 0,c.value=!1,s&&(yield d())}),h=()=>({next:()=>S(void 0,void 0,void 0,function*(){if(o.value)throw new Error("不允许同时迭代");return{done:!(yield d()),value:t.value}})});return P({abort:I,load:c,next:d,res:t,loading:o,cursorStack:a,reset:x,[Symbol.asyncIterator]:h,iter:{[Symbol.asyncIterator]:h}})},ee=n=>F(X(n,i=>i.files,{dataUpdateStrategy:"merge"})),te=n=>{const i=F(new Set),l=R(()=>(n.res??[]).filter(p=>!i.has(p.fullpath))),a=q(),{stackViewEl:c,multiSelectedIdxs:t,stack:o,scroller:f,props:v}=z({images:l}).toRefs(),{itemSize:w,gridItems:d,cellWidth:I,onScroll:x}=H({fetchNext:()=>n.next()}),{showMenuIdx:h}=O(),{onFileDragStart:e,onFileDragEnd:s}=Q(),{showGenInfo:r,imageGenInfo:m,q:u,onContextMenuClick:y,onFileItemClick:C}=T({openNext:L}),{previewIdx:_,previewing:E,onPreviewVisibleChange:M,previewImgMove:D,canPreview:G}=U({loadNext:()=>n.next()}),J=async(p,b,N)=>{o.value=[{curr:"",files:l.value}],await y(p,b,N)};W("removeFiles",async({paths:p})=>{p.forEach(b=>i.add(b))});const k=()=>{j(l.value)};return{images:l,scroller:f,queue:a,iter:n,onContextMenuClickU:J,stackViewEl:c,previewIdx:_,previewing:E,onPreviewVisibleChange:M,previewImgMove:D,canPreview:G,itemSize:w,gridItems:d,showGenInfo:r,imageGenInfo:m,q:u,onContextMenuClick:y,onFileItemClick:C,showMenuIdx:h,multiSelectedIdxs:t,onFileDragStart:e,onFileDragEnd:s,cellWidth:I,onScroll:x,saveLoadedFileAsJson:k,saveAllFileAsJson:async()=>{for(;!n.load;)await n.next();k()},props:v,...B()}};export{ee as c,te 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 +1 @@
|
|||
import{d as x,p as $,an as g,c8 as b,r as w,o as p,j as d,k as a,c as l,C as i,l as u,t as n,F as B,K as I,E as m,as as W,W as _,X as v,a2 as D,a3 as F,c9 as N,n as R}from"./index-32743103.js";const V={class:"container"},E={class:"actions"},K={class:"uni-desc"},L={class:"snapshot"},j=x({__name:"index",props:{tabIdx:{},paneIdx:{},id:{},paneKey:{}},setup(q){const h=$(),t=g(),f=e=>{h.tabList=W(e.tabs)},k=b(async e=>{await N(`workspace_snapshot_${e.id}`),t.snapshots=t.snapshots.filter(c=>c.id!==e.id),_.success(v("deleteSuccess"))}),o=w(""),C=async()=>{if(!o.value){_.error(v("nameRequired"));return}const e=t.createSnapshot(o.value);await t.addSnapshot(e),_.success(v("saveCompleted"))};return(e,c)=>{const y=D,r=F;return p(),d("div",V,[a("div",E,[l(y,{value:o.value,"onUpdate:value":c[0]||(c[0]=s=>o.value=s),placeholder:e.$t("name"),style:{"max-width":"300px"}},null,8,["value","placeholder"]),l(r,{type:"primary",onClick:C},{default:i(()=>[u(n(e.$t("saveWorkspaceSnapshot")),1)]),_:1})]),a("p",K,n(e.$t("WorkspaceSnapshotDesc")),1),a("ul",L,[(p(!0),d(B,null,I(m(t).snapshots,s=>(p(),d("li",{key:s.id},[a("div",null,[a("span",null,n(s.name),1)]),a("div",null,[l(r,{onClick:S=>f(s)},{default:i(()=>[u(n(e.$t("restore")),1)]),_:2},1032,["onClick"]),l(r,{onClick:S=>m(k)(s)},{default:i(()=>[u(n(e.$t("remove")),1)]),_:2},1032,["onClick"])])]))),128))])])}}});const G=R(j,[["__scopeId","data-v-2c44013c"]]);export{G as default};
|
||||
import{d as x,p as $,an as g,c8 as b,r as w,o as p,j as d,k as a,c as l,C as i,l as u,t as n,F as B,K as I,E as m,as as W,W as _,X as v,a2 as D,a3 as F,c9 as N,n as R}from"./index-f2db319b.js";const V={class:"container"},E={class:"actions"},K={class:"uni-desc"},L={class:"snapshot"},j=x({__name:"index",props:{tabIdx:{},paneIdx:{},id:{},paneKey:{}},setup(q){const h=$(),t=g(),f=e=>{h.tabList=W(e.tabs)},k=b(async e=>{await N(`workspace_snapshot_${e.id}`),t.snapshots=t.snapshots.filter(c=>c.id!==e.id),_.success(v("deleteSuccess"))}),o=w(""),C=async()=>{if(!o.value){_.error(v("nameRequired"));return}const e=t.createSnapshot(o.value);await t.addSnapshot(e),_.success(v("saveCompleted"))};return(e,c)=>{const y=D,r=F;return p(),d("div",V,[a("div",E,[l(y,{value:o.value,"onUpdate:value":c[0]||(c[0]=s=>o.value=s),placeholder:e.$t("name"),style:{"max-width":"300px"}},null,8,["value","placeholder"]),l(r,{type:"primary",onClick:C},{default:i(()=>[u(n(e.$t("saveWorkspaceSnapshot")),1)]),_:1})]),a("p",K,n(e.$t("WorkspaceSnapshotDesc")),1),a("ul",L,[(p(!0),d(B,null,I(m(t).snapshots,s=>(p(),d("li",{key:s.id},[a("div",null,[a("span",null,n(s.name),1)]),a("div",null,[l(r,{onClick:S=>f(s)},{default:i(()=>[u(n(e.$t("restore")),1)]),_:2},1032,["onClick"]),l(r,{onClick:S=>m(k)(s)},{default:i(()=>[u(n(e.$t("remove")),1)]),_:2},1032,["onClick"])])]))),128))])])}}});const G=R(j,[["__scopeId","data-v-2c44013c"]]);export{G as default};
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
import{d as Y,p as ee,r as F,aC as te,aD as le,v as se,ca as ie,o as v,j as N,c as s,E as e,k as g,C as n,l as k,t as u,G as R,I as oe,H as ae,U as ne,V as A,m as $,B as re,W as w,X as ce,cb as de,a3 as ue,a1 as me,Z as fe,n as pe}from"./index-32743103.js";import{F as ve,s as ge}from"./FileItem-aa47825a.js";import{u as ke,g as we,c as he,b as Ce,d as Se,e as _e,o as z}from"./index-c80754a2.js";import{M as Ie,L as ye,R as be,f as xe}from"./MultiSelectKeep-56b94e1f.js";import"./index-e1a70e12.js";import"./shortcut-3129f75b.js";import"./_isIterateeCall-16c5cf9c.js";/* empty css */const Ve={class:"refresh-button"},Me={class:"hint"},Te={key:0,class:"preview-switch"},Fe=Y({__name:"randomImage",props:{tabIdx:{},paneIdx:{},id:{},paneKey:{}},setup(Ne){const B=ee(),m=F(!1),l=F([]),r=l,h=te(`${le}randomImageSettingNotificationShown`,!1),P=()=>{h.value||(w.info({content:ce("randomImageSettingNotification"),duration:6,key:"randomImageSetting"}),h.value=!0)},f=async()=>{try{m.value=!0;const i=await de();i.length===0&&w.warn("No data, please generate index in image search page first"),l.value=i}finally{m.value=!1,_()}},C=()=>{if(l.value.length===0){w.warn("没有图片可以浏览");return}z(l.value,a.value||0)};se(()=>{f(),setTimeout(()=>{P()},2e3)});const{stackViewEl:D,multiSelectedIdxs:p,stack:E,scroller:G}=ke({images:l}).toRefs(),{onClearAllSelected:U,onSelectAll:K,onReverseSelect:L}=we();he();const{itemSize:S,gridItems:O,cellWidth:W,onScroll:_}=Ce(),{showGenInfo:c,imageGenInfo:I,q:H,onContextMenuClick:j,onFileItemClick:q}=Se({openNext:ie}),{previewIdx:a,previewing:y,onPreviewVisibleChange:Q,previewImgMove:b,canPreview:x}=_e(),V=async(i,t,d)=>{E.value=[{curr:"",files:l.value}],await j(i,t,d)};return(i,t)=>{var M;const d=ue,X=me,Z=fe;return v(),N("div",{class:"container",ref_key:"stackViewEl",ref:D},[s(Ie,{show:!!e(p).length||e(B).keepMultiSelect,onClearAllSelected:e(U),onSelectAll:e(K),onReverseSelect:e(L)},null,8,["show","onClearAllSelected","onSelectAll","onReverseSelect"]),g("div",Ve,[s(d,{onClick:f,onTouchstart:R(f,["prevent"]),type:"primary",loading:m.value,shape:"round"},{default:n(()=>[k(u(i.$t("shuffle")),1)]),_:1},8,["onTouchstart","loading"]),s(d,{onClick:C,onTouchstart:R(C,["prevent"]),type:"default",disabled:!((M=l.value)!=null&&M.length),shape:"round"},{default:n(()=>[k(u(i.$t("tiktokView")),1)]),_:1},8,["onTouchstart","disabled"])]),s(Z,{visible:e(c),"onUpdate:visible":t[1]||(t[1]=o=>ae(c)?c.value=o:null),width:"70vw","mask-closable":"",onOk:t[2]||(t[2]=o=>c.value=!1)},{cancelText:n(()=>[]),default:n(()=>[s(X,{active:"",loading:!e(H).isIdle},{default:n(()=>[g("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:t[0]||(t[0]=o=>e(oe)(e(I)))},[g("div",Me,u(i.$t("doubleClickToCopy")),1),k(" "+u(e(I)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),s(e(ge),{ref_key:"scroller",ref:G,class:"file-list",items:l.value.slice(),"item-size":e(S).first,"key-field":"fullpath","item-secondary-size":e(S).second,gridItems:e(O),onScroll:e(_)},{default:n(({item:o,index:T})=>[s(ve,{idx:T,file:o,"cell-width":e(W),"full-screen-preview-image-url":e(r)[e(a)]?e(ne)(e(r)[e(a)]):"",onContextMenuClick:V,onPreviewVisibleChange:e(Q),"is-selected-mutil-files":e(p).length>1,selected:e(p).includes(T),onFileItemClick:e(q),onTiktokView:(Re,J)=>e(z)(l.value,J)},null,8,["idx","file","cell-width","full-screen-preview-image-url","onPreviewVisibleChange","is-selected-mutil-files","selected","onFileItemClick","onTiktokView"])]),_:1},8,["items","item-size","item-secondary-size","gridItems","onScroll"]),e(y)?(v(),N("div",Te,[s(e(ye),{onClick:t[3]||(t[3]=o=>e(b)("prev")),class:A({disable:!e(x)("prev")})},null,8,["class"]),s(e(be),{onClick:t[4]||(t[4]=o=>e(b)("next")),class:A({disable:!e(x)("next")})},null,8,["class"])])):$("",!0),e(y)&&e(r)&&e(r)[e(a)]?(v(),re(xe,{key:1,file:e(r)[e(a)],idx:e(a),onContextMenuClick:V},null,8,["file","idx"])):$("",!0)],512)}}});const Ue=pe(Fe,[["__scopeId","data-v-49082269"]]);export{Ue as default};
|
||||
import{d as Y,p as ee,r as F,aC as te,aD as le,v as se,ca as ie,o as v,j as N,c as s,E as e,k as g,C as n,l as k,t as u,G as R,I as oe,H as ae,U as ne,V as A,m as $,B as re,W as w,X as ce,cb as de,a3 as ue,a1 as me,Z as fe,n as pe}from"./index-f2db319b.js";import{F as ve,s as ge}from"./FileItem-72718f68.js";import{u as ke,g as we,c as he,b as Ce,d as Se,e as _e,o as z}from"./index-0d856f16.js";import{M as Ie,L as ye,R as be,f as xe}from"./MultiSelectKeep-a11efe88.js";import"./index-29e38a15.js";import"./shortcut-869fab50.js";import"./_isIterateeCall-dd643bcf.js";/* empty css */const Ve={class:"refresh-button"},Me={class:"hint"},Te={key:0,class:"preview-switch"},Fe=Y({__name:"randomImage",props:{tabIdx:{},paneIdx:{},id:{},paneKey:{}},setup(Ne){const B=ee(),m=F(!1),l=F([]),r=l,h=te(`${le}randomImageSettingNotificationShown`,!1),P=()=>{h.value||(w.info({content:ce("randomImageSettingNotification"),duration:6,key:"randomImageSetting"}),h.value=!0)},f=async()=>{try{m.value=!0;const i=await de();i.length===0&&w.warn("No data, please generate index in image search page first"),l.value=i}finally{m.value=!1,_()}},C=()=>{if(l.value.length===0){w.warn("没有图片可以浏览");return}z(l.value,a.value||0)};se(()=>{f(),setTimeout(()=>{P()},2e3)});const{stackViewEl:D,multiSelectedIdxs:p,stack:E,scroller:G}=ke({images:l}).toRefs(),{onClearAllSelected:U,onSelectAll:K,onReverseSelect:L}=we();he();const{itemSize:S,gridItems:O,cellWidth:W,onScroll:_}=Ce(),{showGenInfo:c,imageGenInfo:I,q:H,onContextMenuClick:j,onFileItemClick:q}=Se({openNext:ie}),{previewIdx:a,previewing:y,onPreviewVisibleChange:Q,previewImgMove:b,canPreview:x}=_e(),V=async(i,t,d)=>{E.value=[{curr:"",files:l.value}],await j(i,t,d)};return(i,t)=>{var M;const d=ue,X=me,Z=fe;return v(),N("div",{class:"container",ref_key:"stackViewEl",ref:D},[s(Ie,{show:!!e(p).length||e(B).keepMultiSelect,onClearAllSelected:e(U),onSelectAll:e(K),onReverseSelect:e(L)},null,8,["show","onClearAllSelected","onSelectAll","onReverseSelect"]),g("div",Ve,[s(d,{onClick:f,onTouchstart:R(f,["prevent"]),type:"primary",loading:m.value,shape:"round"},{default:n(()=>[k(u(i.$t("shuffle")),1)]),_:1},8,["onTouchstart","loading"]),s(d,{onClick:C,onTouchstart:R(C,["prevent"]),type:"default",disabled:!((M=l.value)!=null&&M.length),shape:"round"},{default:n(()=>[k(u(i.$t("tiktokView")),1)]),_:1},8,["onTouchstart","disabled"])]),s(Z,{visible:e(c),"onUpdate:visible":t[1]||(t[1]=o=>ae(c)?c.value=o:null),width:"70vw","mask-closable":"",onOk:t[2]||(t[2]=o=>c.value=!1)},{cancelText:n(()=>[]),default:n(()=>[s(X,{active:"",loading:!e(H).isIdle},{default:n(()=>[g("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:t[0]||(t[0]=o=>e(oe)(e(I)))},[g("div",Me,u(i.$t("doubleClickToCopy")),1),k(" "+u(e(I)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),s(e(ge),{ref_key:"scroller",ref:G,class:"file-list",items:l.value.slice(),"item-size":e(S).first,"key-field":"fullpath","item-secondary-size":e(S).second,gridItems:e(O),onScroll:e(_)},{default:n(({item:o,index:T})=>[s(ve,{idx:T,file:o,"cell-width":e(W),"full-screen-preview-image-url":e(r)[e(a)]?e(ne)(e(r)[e(a)]):"",onContextMenuClick:V,onPreviewVisibleChange:e(Q),"is-selected-mutil-files":e(p).length>1,selected:e(p).includes(T),onFileItemClick:e(q),onTiktokView:(Re,J)=>e(z)(l.value,J)},null,8,["idx","file","cell-width","full-screen-preview-image-url","onPreviewVisibleChange","is-selected-mutil-files","selected","onFileItemClick","onTiktokView"])]),_:1},8,["items","item-size","item-secondary-size","gridItems","onScroll"]),e(y)?(v(),N("div",Te,[s(e(ye),{onClick:t[3]||(t[3]=o=>e(b)("prev")),class:A({disable:!e(x)("prev")})},null,8,["class"]),s(e(be),{onClick:t[4]||(t[4]=o=>e(b)("next")),class:A({disable:!e(x)("next")})},null,8,["class"])])):$("",!0),e(y)&&e(r)&&e(r)[e(a)]?(v(),re(xe,{key:1,file:e(r)[e(a)],idx:e(a),onContextMenuClick:V},null,8,["file","idx"])):$("",!0)],512)}}});const Ue=pe(Fe,[["__scopeId","data-v-49082269"]]);export{Ue as default};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -7,7 +7,7 @@
|
|||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Infinite Image Browsing</title>
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-32743103.js"></script>
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-f2db319b.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-dd273d5b.css">
|
||||
</head>
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import type { FileNodeInfo } from '@/api/files'
|
|||
import { isImageFile, isVideoFile, isAudioFile } from '@/util'
|
||||
import { toImageThumbnailUrl, toVideoCoverUrl, toRawFileUrl } from '@/util/file'
|
||||
import type { MenuInfo } from 'ant-design-vue/lib/menu/src/interface'
|
||||
import { computed, ref } from 'vue'
|
||||
import { computed, ref, nextTick, watch } from 'vue'
|
||||
import ContextMenu from './ContextMenu.vue'
|
||||
import ChangeIndicator from './ChangeIndicator.vue'
|
||||
import { useTagStore } from '@/store/useTagStore'
|
||||
|
|
@ -16,10 +16,12 @@ import { openVideoModal, openAudioModal } from './functionalCallableComp'
|
|||
import type { GenDiffInfo } from '@/api/files'
|
||||
import { play } from '@/icon'
|
||||
import { Top4MediaInfo } from '@/api'
|
||||
import { watch } from 'vue'
|
||||
import { debounce } from 'lodash-es'
|
||||
|
||||
import { closeImageFullscreenPreview } from '@/util/imagePreviewOperation'
|
||||
import { eventEmitter as videoEventEmitter, useEventListen } from './videoEventEmitter'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const global = useGlobalStore()
|
||||
const tagStore = useTagStore()
|
||||
|
|
@ -97,6 +99,75 @@ const taggleLikeTag = () => {
|
|||
|
||||
const minShowDetailWidth = 160
|
||||
|
||||
// 视频原地播放相关
|
||||
const isPlayingInline = ref(false)
|
||||
const videoElementRef = ref<HTMLVideoElement | null>(null)
|
||||
|
||||
// 切换原地播放
|
||||
const toggleInlinePlay = (event: MouseEvent) => {
|
||||
console.log('toggleInlinePlay', { event, isPlayingInline: isPlayingInline.value, videoRef: videoElementRef.value })
|
||||
event.stopPropagation()
|
||||
|
||||
// 如果要开始播放,先通知其他视频停止
|
||||
if (!isPlayingInline.value) {
|
||||
videoEventEmitter.emit('stopInlinePlay')
|
||||
}
|
||||
|
||||
// 先切换状态,让video元素渲染出来
|
||||
isPlayingInline.value = !isPlayingInline.value
|
||||
|
||||
// 使用 nextTick 确保 video 元素已经渲染
|
||||
if (!isPlayingInline.value) {
|
||||
// 如果是暂停,直接暂停
|
||||
if (videoElementRef.value) {
|
||||
videoElementRef.value.pause()
|
||||
}
|
||||
} else {
|
||||
// 如果是播放,等待DOM更新后再播放
|
||||
nextTick(() => {
|
||||
if (videoElementRef.value) {
|
||||
console.log('Playing video', videoElementRef.value)
|
||||
videoElementRef.value.play().catch(err => {
|
||||
console.error('Play failed:', err)
|
||||
isPlayingInline.value = false
|
||||
})
|
||||
} else {
|
||||
console.error('Video ref is null after nextTick')
|
||||
isPlayingInline.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 处理其他视频播放的通知
|
||||
const handleStopInlinePlay = () => {
|
||||
if (isPlayingInline.value && videoElementRef.value) {
|
||||
videoElementRef.value.pause()
|
||||
isPlayingInline.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 监听停止事件
|
||||
useEventListen('stopInlinePlay', handleStopInlinePlay)
|
||||
|
||||
// 视频播放结束处理
|
||||
const handleVideoEnded = () => {
|
||||
isPlayingInline.value = false
|
||||
}
|
||||
|
||||
// 判断是否显示原地播放按钮(宽度大于400且未在播放)
|
||||
const shouldShowInlinePlayBtn = computed(() => {
|
||||
return props.cellWidth > 400 && !isPlayingInline.value
|
||||
})
|
||||
|
||||
// 监听 idx 变化,如果正在播放则停止
|
||||
watch(() => props.idx, () => {
|
||||
if (isPlayingInline.value && videoElementRef.value) {
|
||||
videoElementRef.value.pause()
|
||||
isPlayingInline.value = false
|
||||
}
|
||||
})
|
||||
|
||||
const handleDragOver = (event: DragEvent) => {
|
||||
if (props.file.type !== 'dir') {
|
||||
return
|
||||
|
|
@ -136,6 +207,15 @@ const handleFileClick = (event: MouseEvent) => {
|
|||
|
||||
// 处理视频点击事件
|
||||
const handleVideoClick = () => {
|
||||
// 如果正在原地播放,先停止播放
|
||||
if (isPlayingInline.value) {
|
||||
isPlayingInline.value = false
|
||||
if (videoElementRef.value) {
|
||||
videoElementRef.value.pause()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (global.magicSwitchTiktokView) {
|
||||
// 直接触发TikTok视图
|
||||
emit('tiktokView', props.file, props.idx)
|
||||
|
|
@ -222,11 +302,31 @@ const handleAudioClick = () => {
|
|||
</a-tag>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`idx-${idx} item-content video`" :url="toVideoCoverUrl(file)"
|
||||
:style="{ 'background-image': `url('${file.cover_url ?? toVideoCoverUrl(file)}')` }" v-else-if="isVideoFile(file.name)"
|
||||
<div :class="[`idx-${idx} item-content video`, { 'playing-inline': isPlayingInline }]" :url="toVideoCoverUrl(file)"
|
||||
:style="{ 'background-image': isPlayingInline ? 'none' : `url('${file.cover_url ?? toVideoCoverUrl(file)}')` }" v-else-if="isVideoFile(file.name)"
|
||||
@click="handleVideoClick">
|
||||
|
||||
<div class="play-icon">
|
||||
<!-- 原地播放视频元素 -->
|
||||
<video
|
||||
v-if="cellWidth > 400 && isPlayingInline"
|
||||
:ref="(el) => videoElementRef = el as HTMLVideoElement"
|
||||
:src="toRawFileUrl(file)"
|
||||
class="inline-video-player"
|
||||
@ended="handleVideoEnded"
|
||||
@click.stop
|
||||
controls
|
||||
/>
|
||||
|
||||
<!-- 遮罩层和原地播放按钮 -->
|
||||
<div v-if="shouldShowInlinePlayBtn" class="inline-play-overlay" @click="toggleInlinePlay">
|
||||
<div class="inline-play-btn">
|
||||
<img :src="play" class="play-icon-img">
|
||||
<span class="play-text">{{ t('playInline') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 原有的中心播放图标(用于打开modal) -->
|
||||
<div class="play-icon" v-show="!isPlayingInline">
|
||||
<img :src="play" style="width: 40px;height: 40px;">
|
||||
</div>
|
||||
<div class="tags-container" v-if="customTags && cellWidth > minShowDetailWidth">
|
||||
|
|
@ -295,6 +395,81 @@ const handleAudioClick = () => {
|
|||
background-size: cover;
|
||||
background-position: center;
|
||||
cursor: pointer;
|
||||
|
||||
&.playing-inline {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.inline-video-player {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.inline-play-overlay {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
left: 8px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-start;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.inline-play-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 10px 16px;
|
||||
border-radius: 8px;
|
||||
background: linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(20, 20, 20, 0.9) 100%);
|
||||
backdrop-filter: blur(8px);
|
||||
cursor: pointer;
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||
box-shadow:
|
||||
0 2px 8px rgba(0, 0, 0, 0.3),
|
||||
0 0 0 1px rgba(0, 0, 0, 0.1) inset,
|
||||
0 1px 0 rgba(255, 255, 255, 0.1) inset;
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(30, 30, 30, 0.95) 100%);
|
||||
border-color: rgba(255, 255, 255, 0.25);
|
||||
transform: translateY(-1px);
|
||||
box-shadow:
|
||||
0 4px 12px rgba(0, 0, 0, 0.4),
|
||||
0 0 0 1px rgba(0, 0, 0, 0.1) inset,
|
||||
0 1px 0 rgba(255, 255, 255, 0.15) inset;
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translateY(0);
|
||||
background: rgba(0, 0, 0, 0.95);
|
||||
}
|
||||
|
||||
.play-icon-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
filter: brightness(0) invert(1);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.play-text {
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.2px;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .inline-play-overlay {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.audio {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
import { typedEventEmitter } from 'vue3-ts-util'
|
||||
|
||||
// 创建视频原地播放的事件发射器(模块级别,所有组件共享)
|
||||
export const { eventEmitter, useEventListen } = typedEventEmitter<{
|
||||
stopInlinePlay: () => void
|
||||
}>()
|
||||
|
|
@ -316,5 +316,8 @@ export const de: Partial<IIBI18nMap> = {
|
|||
loadingTip7: '📸 Workspace-Snapshots\n\nSie können Ihren aktuellen Workspace-Status (offene Ordner, Sortierung, etc.) speichern, um ihn beim nächsten Öffnen von IIB schnell wiederherzustellen. In den globalen Einstellungen kann automatische Wiederherstellung beim Start eingestellt werden.|info',
|
||||
loadingTip8: '🏷️ Auto-Tagging-Funktion\n\nKonfigurieren Sie Auto-Tagging-Regeln in den globalen Einstellungen. Tags werden automatisch angewendet, wenn Bilder indexiert werden, unterstützt Bedingungen wie Prompt, Modell, Sampler, etc.|info',
|
||||
loadingTip9: '⚡ Leistungstipp\n\nWenn Sie beim schnellen Scrollen durch viele Bilder Verzögerungen bemerken, können Sie "Change Indicators" in den globalen Einstellungen deaktivieren für deutlich bessere Leistung.|info',
|
||||
loadingTip10: '🤖 KI-Agenten-Integration\n\nSie können jetzt KI-Agenten IIB nutzen lassen, um bei Bildverwaltung, Tag-Organisation und intelligenter Suche zu helfen. Über die API-Schnittstelle kann die KI auf alle IIB-Funktionen zugreifen und automatisierte Workflows erstellen.|info'
|
||||
loadingTip10: '🤖 KI-Agenten-Integration\n\nSie können jetzt KI-Agenten IIB nutzen lassen, um bei Bildverwaltung, Tag-Organisation und intelligenter Suche zu helfen. Über die API-Schnittstelle kann die KI auf alle IIB-Funktionen zugreifen und automatisierte Workflows erstellen.|info',
|
||||
|
||||
// ===== Video Inline Play =====
|
||||
playInline: 'Hier abspielen'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -576,5 +576,8 @@ You can specify which snapshot to restore to when starting IIB in the global set
|
|||
loadingTip7: '📸 Workspace Snapshots\n\nSave your current workspace state (open folders, sorting, etc.) for quick restoration later. In global settings, set it to auto-restore on startup.|info',
|
||||
loadingTip8: '🏷️ Auto Tagging Feature\n\nConfigure auto-tagging rules in global settings. Tags are automatically applied when images are indexed, supporting conditions like prompt, model, sampler, etc.|info',
|
||||
loadingTip9: '⚡ Performance Tip\n\nIf you experience lag when scrolling through a large number of images quickly, you can disable "Change Indicators" in global settings for significantly better performance.|info',
|
||||
loadingTip10: '🤖 AI Agent Integration\n\nYou can now let AI agents use IIB to help with image management, tag organization, and smart search. Through the API interface, AI can access all IIB features for automated workflows.|info'
|
||||
loadingTip10: '🤖 AI Agent Integration\n\nYou can now let AI agents use IIB to help with image management, tag organization, and smart search. Through the API interface, AI can access all IIB features for automated workflows.|info',
|
||||
|
||||
// ===== Video Inline Play =====
|
||||
playInline: 'Play Here'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -554,5 +554,8 @@ export const zhHans = {
|
|||
loadingTip7: '📸 工作区快照\n\n你可以保存当前的工作区状态(打开的文件夹、排序方式等),下次打开 IIB 时快速恢复。在全局设置中可以设为启动时自动恢复。|info',
|
||||
loadingTip8: '🏷️ 自动标签功能\n\n在全局设置中配置自动标签规则,当图片被索引时会自动添加标签。支持根据 prompt、模型、采样器等条件自动分类。|info',
|
||||
loadingTip9: '⚡ 性能优化提示\n\n如果在快速滚动大量图片时感到卡顿,可以在全局设置中关闭"变更指示器"功能,这可以显著提升浏览性能。|info',
|
||||
loadingTip10: '🤖 AI Agent 集成\n\n现在你可以让 AI agent 来使用 IIB 帮助进行图像管理、标签整理和智能搜索。通过 API 接口,AI 可以访问所有 IIB 功能,实现自动化工作流程。|info'
|
||||
loadingTip10: '🤖 AI Agent 集成\n\n现在你可以让 AI agent 来使用 IIB 帮助进行图像管理、标签整理和智能搜索。通过 API 接口,AI 可以访问所有 IIB 功能,实现自动化工作流程。|info',
|
||||
|
||||
// ===== 视频原地播放 =====
|
||||
playInline: '在此播放'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -556,5 +556,8 @@ export const zhHant: Partial<IIBI18nMap> = {
|
|||
loadingTip7: '📸 工作區快照\n\n你可以儲存目前的工作區狀態(打開的資料夾、排序方式等),下次打開 IIB 時快速還原。在全域設定中可以設為啟動時自動還原。|info',
|
||||
loadingTip8: '🏷️ 自動標籤功能\n\n在全域設定中配置自動標籤規則,當圖片被索引時會自動添加標籤。支援根據 prompt、模型、採樣器等條件自動分類。|info',
|
||||
loadingTip9: '⚡ 效能優化提示\n\n如果在快速滾動大量圖片時感到卡頓,可以在全域設定中關閉「變更指示器」功能,這可以顯著提升瀏覽效能。|info',
|
||||
loadingTip10: '🤖 AI Agent 整合\n\n現在您可以讓 AI agent 使用 IIB 來協助進行圖片管理、標籤整理和智慧搜尋。透過 API 介面,AI 可以存取所有 IIB 功能,實現自動化工作流程。|info'
|
||||
loadingTip10: '🤖 AI Agent 整合\n\n現在您可以讓 AI agent 使用 IIB 來協助進行圖片管理、標籤整理和智慧搜尋。透過 API 介面,AI 可以存取所有 IIB 功能,實現自動化工作流程。|info',
|
||||
|
||||
// ===== 視頻原地播放 =====
|
||||
playInline: '在此播放'
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue