[A] hide controls, animate.css, loadData interval
This commit is contained in:
parent
772279751f
commit
2a938fb248
5 changed files with 165 additions and 47 deletions
29
index.js
29
index.js
|
|
@ -25,26 +25,39 @@ async function listDir(dir = process.env.WEBFRAME_PATH) {
|
||||||
return directoryItems;
|
return directoryItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dlFile(file, dir = process.env.WEBFRAME_PATH) {
|
async function dlFile(file, dir = process.env.WEBFRAME_PATH) {
|
||||||
return client.createReadStream(dir+'/'+file).pipe(fs.createWriteStream('./files/'+file));
|
const isDirExists = fs.existsSync(dir) && fs.lstatSync(dir).isDirectory();
|
||||||
|
if (!isDirExists) {
|
||||||
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
|
console.log('Created dir:', dir);
|
||||||
|
}
|
||||||
|
// return client.createReadStream(dir+'/'+file).pipe(fs.createWriteStream('./files/'+file));
|
||||||
|
return client.getFileContents(dir+'/'+file);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadImages() {
|
async function loadImages() {
|
||||||
client.exists(process.env.WEBFRAME_PATH).then(async data => {
|
try {
|
||||||
|
const data = await client.exists(process.env.WEBFRAME_PATH);
|
||||||
if (data) {
|
if (data) {
|
||||||
const list = await listDir(process.env.WEBFRAME_PATH);
|
const list = await listDir(process.env.WEBFRAME_PATH);
|
||||||
list.forEach(file => {
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
const file = list[i];
|
||||||
|
const path = './files/'
|
||||||
const inDb = db.get('files').find({ basename: file.basename }).value() !== undefined ? true : false;
|
const inDb = db.get('files').find({ basename: file.basename }).value() !== undefined ? true : false;
|
||||||
if (!inDb) {
|
if (!inDb) {
|
||||||
|
const blob = await dlFile(file.basename);
|
||||||
console.log('Downloaded new File:', file.basename);
|
console.log('Downloaded new File:', file.basename);
|
||||||
dlFile(file.basename);
|
fs.writeFile(path+file.basename, blob, () => {
|
||||||
db.get('files').push(file).write();
|
db.get('files').push(file).write();
|
||||||
db.update('count', n => n + 1).write();
|
db.update('count', n => n + 1).write();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).catch(e => console.error('Path', process.env.WEBFRAME_PATH, 'not found.'));
|
}
|
||||||
|
}
|
||||||
setTimeout(() => loadImages(), process.env.POLL_TIMEOUT);
|
setTimeout(() => loadImages(), process.env.POLL_TIMEOUT);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[loadImages]', e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadImages();
|
loadImages();
|
||||||
|
|
|
||||||
9
public/animate.min.css
vendored
Normal file
9
public/animate.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -7,6 +7,8 @@ new Vue({
|
||||||
carouselTimeout: 20000,
|
carouselTimeout: 20000,
|
||||||
carouselActive: true,
|
carouselActive: true,
|
||||||
videoSrc: null,
|
videoSrc: null,
|
||||||
|
isDownloading: false,
|
||||||
|
controlsTimeout: null,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
next: function () {
|
next: function () {
|
||||||
|
|
@ -15,13 +17,7 @@ new Vue({
|
||||||
} else {
|
} else {
|
||||||
this.index = 0;
|
this.index = 0;
|
||||||
}
|
}
|
||||||
// force video src reload
|
this.refreshVideoSrc();
|
||||||
this.videoSrc = null;
|
|
||||||
setTimeout(() => {
|
|
||||||
if (this.files[this.index].mime.includes('video')) {
|
|
||||||
this.videoSrc = '/files/'+this.files[this.index].basename;
|
|
||||||
}
|
|
||||||
}, 100)
|
|
||||||
},
|
},
|
||||||
nextClick: function () {
|
nextClick: function () {
|
||||||
this.next();
|
this.next();
|
||||||
|
|
@ -33,24 +29,34 @@ new Vue({
|
||||||
} else {
|
} else {
|
||||||
this.index = this.files.length - 1;
|
this.index = this.files.length - 1;
|
||||||
}
|
}
|
||||||
// force video src reload
|
this.refreshVideoSrc();
|
||||||
setTimeout(() => {
|
|
||||||
if (this.files[this.index].mime.includes('video')) {
|
|
||||||
this.videoSrc = '/files/'+this.files[this.index].basename;
|
|
||||||
}
|
|
||||||
}, 100)
|
|
||||||
},
|
},
|
||||||
prevClick: function () {
|
prevClick: function () {
|
||||||
this.next();
|
this.next();
|
||||||
this.startCarousel();
|
this.startCarousel();
|
||||||
},
|
},
|
||||||
loadData: function () {
|
loadData: function () {
|
||||||
fetch('api/files').then(response => response.json()).then(
|
this.isDownloading = true;
|
||||||
|
const prom = fetch('api/files').then(response => response.json());
|
||||||
|
prom.then(
|
||||||
data => {
|
data => {
|
||||||
this.files = data.resource;
|
this.files = data.resource || [];
|
||||||
this.startCarousel();
|
this.startCarousel();
|
||||||
|
this.refreshVideoSrc();
|
||||||
|
this.isDownloading = false;
|
||||||
|
setTimeout(() => this.loadData(), (this.files.length*this.carouselTimeout)+1000);
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
|
return prom;
|
||||||
|
},
|
||||||
|
refreshVideoSrc: function () {
|
||||||
|
// force video src reload
|
||||||
|
this.videoSrc = null;
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.files[this.index].mime.includes('video')) {
|
||||||
|
this.videoSrc = '/files/'+this.files[this.index].basename;
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
},
|
},
|
||||||
startCarousel: function (time = this.carouselTimeout) {
|
startCarousel: function (time = this.carouselTimeout) {
|
||||||
this.carouselActive = true;
|
this.carouselActive = true;
|
||||||
|
|
@ -67,9 +73,53 @@ new Vue({
|
||||||
} else {
|
} else {
|
||||||
this.startCarousel();
|
this.startCarousel();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
toggleControls: function () {
|
||||||
|
clearTimeout(this.controlsTimeout)
|
||||||
|
if (document.querySelector('.controls').style.display === "none") {
|
||||||
|
document.querySelector('.controls').style.display = "";
|
||||||
|
this.animateCSS('.floatBtn.left', 'fadeInLeft');
|
||||||
|
this.animateCSS('.floatBtn.right', 'fadeInRight');
|
||||||
|
this.animateCSS('.floatBtn.bottom', 'fadeInUp');
|
||||||
|
this.controlsTimeout = setTimeout(() => this.toggleControls(), 15000);
|
||||||
|
} else {
|
||||||
|
Promise.all([
|
||||||
|
this.animateCSS('.floatBtn.left', 'fadeOutLeft'),
|
||||||
|
this.animateCSS('.floatBtn.right', 'fadeOutRight'),
|
||||||
|
this.animateCSS('.floatBtn.bottom', 'fadeOutDown')
|
||||||
|
]).then(data => {
|
||||||
|
document.querySelector('.controls').style.display = "none"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
animateCSS: function (element, animation, prefix = 'animate__') {
|
||||||
|
// We create a Promise and return it
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const animationName = `${prefix}${animation}`;
|
||||||
|
const node = document.querySelector(element);
|
||||||
|
|
||||||
|
node.classList.add(`${prefix}animated`, animationName);
|
||||||
|
|
||||||
|
// When the animation ends, we clean the classes and resolve the Promise
|
||||||
|
function handleAnimationEnd() {
|
||||||
|
node.classList.remove(`${prefix}animated`, animationName);
|
||||||
|
node.removeEventListener('animationend', handleAnimationEnd);
|
||||||
|
|
||||||
|
resolve('Animation ended');
|
||||||
|
}
|
||||||
|
|
||||||
|
node.addEventListener('animationend', handleAnimationEnd);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.loadData();
|
this.loadData().then(data => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.animateCSS('.floatBtn.left', 'fadeInLeft');
|
||||||
|
this.animateCSS('.floatBtn.right', 'fadeInRight');
|
||||||
|
this.animateCSS('.floatBtn.bottom', 'fadeInUp');
|
||||||
|
this.controlsTimeout = setTimeout(() => this.toggleControls(), 2500);
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -4,13 +4,47 @@ body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app,
|
#app {
|
||||||
#app div {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#app .loading {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
text-align: center;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app .touchCanvas,
|
||||||
|
#app .content {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app .controls {
|
||||||
|
z-index: 10;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app .touchCanvas {
|
||||||
|
z-index: 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app .content {
|
||||||
|
z-index: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
#app img {
|
#app img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
|
@ -21,6 +55,7 @@ body {
|
||||||
|
|
||||||
#app video {
|
#app video {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
max-width: 100vw;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
@ -32,8 +67,7 @@ body {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: rgba(0, 0, 0, .3);
|
background-color: rgba(0, 0, 0, .3);
|
||||||
color: white;
|
color: white;
|
||||||
z-index: 10;
|
position: fixed;
|
||||||
position: absolute;
|
|
||||||
top: 50vh;
|
top: 50vh;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
|
|
@ -49,7 +83,8 @@ body {
|
||||||
|
|
||||||
#app .floatBtn.bottom {
|
#app .floatBtn.bottom {
|
||||||
left: 49%;
|
left: 49%;
|
||||||
top: 90%;
|
top: unset;
|
||||||
|
bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app .empty {
|
#app .empty {
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,14 @@
|
||||||
<link rel="manifest" href="/manifest.webmanifest">
|
<link rel="manifest" href="/manifest.webmanifest">
|
||||||
<link rel="stylesheet" type="text/css" href="index.css">
|
<link rel="stylesheet" type="text/css" href="index.css">
|
||||||
<script src="vue.js"></script>
|
<script src="vue.js"></script>
|
||||||
|
<link rel="stylesheet" href="animate.min.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<div v-if="files && files.length > 0">
|
<div v-if="files && files.length > 0">
|
||||||
|
<!-- controls -->
|
||||||
|
<div class="controls">
|
||||||
<div class="floatBtn left" v-on:click="prevClick()">
|
<div class="floatBtn left" v-on:click="prevClick()">
|
||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M4 12C4 11.4477 4.44772 11 5 11H19C19.5523 11 20 11.4477 20 12C20 12.5523 19.5523 13 19 13H5C4.44772 13 4 12.5523 4 12Z" fill="currentColor"/></svg>
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M4 12C4 11.4477 4.44772 11 5 11H19C19.5523 11 20 11.4477 20 12C20 12.5523 19.5523 13 19 13H5C4.44772 13 4 12.5523 4 12Z" fill="currentColor"/></svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -22,13 +25,21 @@
|
||||||
<svg v-if="!carouselActive" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M15 12.3301L9 16.6603L9 8L15 12.3301Z" fill="currentColor"/></svg>
|
<svg v-if="!carouselActive" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M15 12.3301L9 16.6603L9 8L15 12.3301Z" fill="currentColor"/></svg>
|
||||||
<svg v-if="carouselActive" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M11 7H8V17H11V7Z" fill="currentColor"/> <path d="M13 17H16V7H13V17Z" fill="currentColor"/></svg>
|
<svg v-if="carouselActive" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M11 7H8V17H11V7Z" fill="currentColor"/> <path d="M13 17H16V7H13V17Z" fill="currentColor"/></svg>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- touch canvas -->
|
||||||
|
<div class="touchCanvas" v-on:click="toggleControls()"></div>
|
||||||
|
<!-- content -->
|
||||||
|
<div class="content">
|
||||||
<img v-if="files[index].mime.includes('image')" v-bind:src="'/files/'+files[index].basename" alt="">
|
<img v-if="files[index].mime.includes('image')" v-bind:src="'/files/'+files[index].basename" alt="">
|
||||||
<video v-if="videoSrc" autoplay muted loop>
|
<video v-if="videoSrc" autoplay muted loop>
|
||||||
<source v-bind:src="videoSrc" v-bind:type="files[index].mime">
|
<source v-bind:src="videoSrc" v-bind:type="files[index].mime">
|
||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="empty">
|
</div>
|
||||||
No images
|
<div class="loading" v-else class="empty">
|
||||||
|
<span v-if="!isDownloading">No images.</span>
|
||||||
|
<span v-if="!isDownloading">Downloading images...</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="app.js"></script>
|
<script src="app.js"></script>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue