[A] hide controls, animate.css, loadData interval

This commit is contained in:
Jan 2020-07-20 23:34:44 +02:00
parent 772279751f
commit 2a938fb248
5 changed files with 165 additions and 47 deletions

View file

@ -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

File diff suppressed because one or more lines are too long

View file

@ -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);
});
} }
}) })

View file

@ -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 {

View file

@ -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>