Show previews on folders
parent
5144c64b19
commit
3999f7b9bd
|
@ -149,11 +149,12 @@ class ApiController extends Controller {
|
||||||
// Map sub to JSON array
|
// Map sub to JSON array
|
||||||
$subdirArray = [
|
$subdirArray = [
|
||||||
"day_id" => -0.1,
|
"day_id" => -0.1,
|
||||||
"detail" => array_map(function ($item) {
|
"detail" => array_map(function ($node) {
|
||||||
return [
|
return [
|
||||||
"file_id" => $item->getId(),
|
"file_id" => $node->getId(),
|
||||||
"name" => $item->getName(),
|
"name" => $node->getName(),
|
||||||
"is_folder" => 1,
|
"is_folder" => 1,
|
||||||
|
"path" => $node->getPath(),
|
||||||
];
|
];
|
||||||
}, $sub, []),
|
}, $sub, []),
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,16 +1,27 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="folder"
|
<div class="folder" v-bind:class="{
|
||||||
|
hasPreview: previewFileInfos.length > 0,
|
||||||
|
onePreview: previewFileInfos.length === 1,
|
||||||
|
}"
|
||||||
@click="openFolder(data.file_id)"
|
@click="openFolder(data.file_id)"
|
||||||
v-bind:style="{
|
v-bind:style="{
|
||||||
width: rowHeight + 'px',
|
width: rowHeight + 'px',
|
||||||
height: rowHeight + 'px',
|
height: rowHeight + 'px',
|
||||||
}">
|
}">
|
||||||
<div class="icon-folder icon-dark"></div>
|
<div class="big-icon">
|
||||||
|
<div class="icon-folder"></div>
|
||||||
<div class="name">{{ data.name }}</div>
|
<div class="name">{{ data.name }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="previews">
|
||||||
|
<img v-for="info of previewFileInfos"
|
||||||
|
:src="`/core/preview?fileId=${info.fileid}&c=${info.etag}&x=250&y=250&forceIcon=0&a=0`" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import * as dav from "../services/DavRequests";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Folder',
|
name: 'Folder',
|
||||||
|
@ -24,6 +35,29 @@ export default {
|
||||||
required: true,
|
required: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
previewFileInfos: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (!this.data.previewFileInfos) {
|
||||||
|
const folderPath = this.data.path.split('/').slice(3).join('/');
|
||||||
|
dav.getFolderPreviewFileIds(folderPath, 4).then(fileInfos => {
|
||||||
|
fileInfos = fileInfos.filter(f => f.hasPreview);
|
||||||
|
if (fileInfos.length > 0 && fileInfos.length < 4) {
|
||||||
|
fileInfos = [fileInfos[0]];
|
||||||
|
}
|
||||||
|
this.data.previewFileInfos = fileInfos;
|
||||||
|
this.previewFileInfos = fileInfos;
|
||||||
|
}).catch(() => {
|
||||||
|
this.data.previewFileInfos = [];
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.previewFileInfos = this.data.previewFileInfos;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
/** Open album folder */
|
/** Open album folder */
|
||||||
openFolder(id) {
|
openFolder(id) {
|
||||||
|
@ -40,13 +74,67 @@ export default {
|
||||||
.folder .name {
|
.folder .name {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
padding: 0 5%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
font-size: 1.08em;
|
||||||
|
word-wrap: break-word;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-height: 35%;
|
||||||
}
|
}
|
||||||
.icon-folder {
|
.icon-folder {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-size: 40%;
|
height: 65%; width: 100%;
|
||||||
height: 60%; width: 100%;
|
|
||||||
background-position: bottom;
|
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
|
background-size: 40%;
|
||||||
|
background-position: bottom;
|
||||||
|
background-image: var(--icon-folder-000);
|
||||||
|
}
|
||||||
|
.big-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 100;
|
||||||
|
position: absolute;
|
||||||
|
top: 0; left: 0;
|
||||||
|
width: 100%; height: 100%;
|
||||||
|
transition: opacity 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
.folder.hasPreview .big-icon .icon-folder {
|
||||||
|
opacity: 1;
|
||||||
|
background-image: var(--icon-folder-fff);
|
||||||
|
}
|
||||||
|
.folder.hasPreview .big-icon .name {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.folder.hasPreview:hover .big-icon {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.folder:hover .previews img {
|
||||||
|
filter: brightness(100%);
|
||||||
|
}
|
||||||
|
.previews {
|
||||||
|
z-index: 3;
|
||||||
|
line-height: 0;
|
||||||
|
position: absolute;
|
||||||
|
height: calc(100% - 4px);
|
||||||
|
width: calc(100% - 4px);
|
||||||
|
top: 2px; left: 2px;
|
||||||
|
}
|
||||||
|
.previews img {
|
||||||
|
padding: 0;
|
||||||
|
width: 50%;
|
||||||
|
height: 50%;
|
||||||
|
border-radius: 0;
|
||||||
|
display: inline-block;
|
||||||
|
filter: brightness(50%);
|
||||||
|
transition: filter 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
.previews img:nth-of-type(1) { border-top-left-radius: 3px; }
|
||||||
|
.previews img:nth-of-type(2) { border-top-right-radius: 3px; }
|
||||||
|
.previews img:nth-of-type(3) { border-bottom-left-radius: 3px; }
|
||||||
|
.previews img:nth-of-type(4) { border-bottom-right-radius: 3px; }
|
||||||
|
|
||||||
|
.folder.onePreview .previews img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -573,7 +573,7 @@ export default {
|
||||||
top: 2px; left: 2px;
|
top: 2px; left: 2px;
|
||||||
background: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.3) 95%);
|
background: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.3) 95%);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
border-radius: 3%;
|
border-radius: 3px;
|
||||||
transition: opacity .1s ease-in-out;
|
transition: opacity .1s ease-in-out;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
|
@ -12,6 +12,13 @@ const props = `
|
||||||
<oc:favorite />
|
<oc:favorite />
|
||||||
<d:resourcetype />`;
|
<d:resourcetype />`;
|
||||||
|
|
||||||
|
const IMAGE_MIME_TYPES = [
|
||||||
|
'image/jpeg',
|
||||||
|
'image/png',
|
||||||
|
'image/tiff',
|
||||||
|
'image/heic',
|
||||||
|
];
|
||||||
|
|
||||||
export async function getFiles(fileIds) {
|
export async function getFiles(fileIds) {
|
||||||
const prefixPath = `/files/${getCurrentUser().uid}`;
|
const prefixPath = `/files/${getCurrentUser().uid}`;
|
||||||
|
|
||||||
|
@ -64,3 +71,68 @@ export async function getFiles(fileIds) {
|
||||||
.map(data => genFileInfo(data))
|
.map(data => genFileInfo(data))
|
||||||
.map(data => Object.assign({}, data, { filename: data.filename.replace(prefixPath, '') }));
|
.map(data => Object.assign({}, data, { filename: data.filename.replace(prefixPath, '') }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getFolderPreviewFileIds(folderPath, limit) {
|
||||||
|
const prefixPath = `/files/${getCurrentUser().uid}`;
|
||||||
|
|
||||||
|
const filter = IMAGE_MIME_TYPES.map(mime => `
|
||||||
|
<d:like>
|
||||||
|
<d:prop>
|
||||||
|
<d:getcontenttype/>
|
||||||
|
</d:prop>
|
||||||
|
<d:literal>${mime}</d:literal>
|
||||||
|
</d:like>
|
||||||
|
`).join('');
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
method: 'SEARCH',
|
||||||
|
headers: {
|
||||||
|
'content-Type': 'text/xml',
|
||||||
|
},
|
||||||
|
data: `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<d:searchrequest xmlns:d="DAV:"
|
||||||
|
xmlns:oc="http://owncloud.org/ns"
|
||||||
|
xmlns:nc="http://nextcloud.org/ns"
|
||||||
|
xmlns:ns="https://github.com/icewind1991/SearchDAV/ns"
|
||||||
|
xmlns:ocs="http://open-collaboration-services.org/ns">
|
||||||
|
<d:basicsearch>
|
||||||
|
<d:select>
|
||||||
|
<d:prop>
|
||||||
|
${props}
|
||||||
|
</d:prop>
|
||||||
|
</d:select>
|
||||||
|
<d:from>
|
||||||
|
<d:scope>
|
||||||
|
<d:href>${prefixPath}/${folderPath}</d:href>
|
||||||
|
<d:depth>0</d:depth>
|
||||||
|
</d:scope>
|
||||||
|
</d:from>
|
||||||
|
<d:where>
|
||||||
|
<d:or>
|
||||||
|
${filter}
|
||||||
|
</d:or>
|
||||||
|
</d:where>
|
||||||
|
|
||||||
|
<d:orderby>
|
||||||
|
<d:order>
|
||||||
|
<d:prop>
|
||||||
|
<d:getlastmodified/>
|
||||||
|
</d:prop>
|
||||||
|
<d:ascending/>
|
||||||
|
</d:order>
|
||||||
|
</d:orderby>
|
||||||
|
<d:limit>
|
||||||
|
<d:nresults>${limit}</d:nresults>
|
||||||
|
</d:limit>
|
||||||
|
</d:basicsearch>
|
||||||
|
</d:searchrequest>`,
|
||||||
|
deep: true,
|
||||||
|
details: true,
|
||||||
|
responseType: 'text',
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = await client.getDirectoryContents('', options);
|
||||||
|
return response.data
|
||||||
|
.map(data => genFileInfo(data))
|
||||||
|
.map(data => Object.assign({}, data, { filename: data.filename.replace(prefixPath, '') }));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue