mirror of
https://github.com/alangrainger/immich-public-proxy.git
synced 2025-01-16 04:46:45 +01:00
Merge pull request #38 from tenekev/main
Improved layout with Isotope Masonry and the loading experience with the Immich loading stencil
This commit is contained in:
commit
48e1ef832d
6 changed files with 232 additions and 38 deletions
12
app/public/metafizzy/imagesloaded.min.js
vendored
Normal file
12
app/public/metafizzy/imagesloaded.min.js
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/*!
|
||||||
|
* imagesLoaded PACKAGED v5.0.0
|
||||||
|
* JavaScript is all like "You images are done yet or what?"
|
||||||
|
* MIT License
|
||||||
|
*/
|
||||||
|
!function(t,e){"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}("undefined"!=typeof window?window:this,(function(){function t(){}let e=t.prototype;return e.on=function(t,e){if(!t||!e)return this;let i=this._events=this._events||{},s=i[t]=i[t]||[];return s.includes(e)||s.push(e),this},e.once=function(t,e){if(!t||!e)return this;this.on(t,e);let i=this._onceEvents=this._onceEvents||{};return(i[t]=i[t]||{})[e]=!0,this},e.off=function(t,e){let i=this._events&&this._events[t];if(!i||!i.length)return this;let s=i.indexOf(e);return-1!=s&&i.splice(s,1),this},e.emitEvent=function(t,e){let i=this._events&&this._events[t];if(!i||!i.length)return this;i=i.slice(0),e=e||[];let s=this._onceEvents&&this._onceEvents[t];for(let n of i){s&&s[n]&&(this.off(t,n),delete s[n]),n.apply(this,e)}return this},e.allOff=function(){return delete this._events,delete this._onceEvents,this},t})),
|
||||||
|
/*!
|
||||||
|
* imagesLoaded v5.0.0
|
||||||
|
* JavaScript is all like "You images are done yet or what?"
|
||||||
|
* MIT License
|
||||||
|
*/
|
||||||
|
function(t,e){"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter")):t.imagesLoaded=e(t,t.EvEmitter)}("undefined"!=typeof window?window:this,(function(t,e){let i=t.jQuery,s=t.console;function n(t,e,o){if(!(this instanceof n))return new n(t,e,o);let r=t;var h;("string"==typeof t&&(r=document.querySelectorAll(t)),r)?(this.elements=(h=r,Array.isArray(h)?h:"object"==typeof h&&"number"==typeof h.length?[...h]:[h]),this.options={},"function"==typeof e?o=e:Object.assign(this.options,e),o&&this.on("always",o),this.getImages(),i&&(this.jqDeferred=new i.Deferred),setTimeout(this.check.bind(this))):s.error(`Bad element for imagesLoaded ${r||t}`)}n.prototype=Object.create(e.prototype),n.prototype.getImages=function(){this.images=[],this.elements.forEach(this.addElementImages,this)};const o=[1,9,11];n.prototype.addElementImages=function(t){"IMG"===t.nodeName&&this.addImage(t),!0===this.options.background&&this.addElementBackgroundImages(t);let{nodeType:e}=t;if(!e||!o.includes(e))return;let i=t.querySelectorAll("img");for(let t of i)this.addImage(t);if("string"==typeof this.options.background){let e=t.querySelectorAll(this.options.background);for(let t of e)this.addElementBackgroundImages(t)}};const r=/url\((['"])?(.*?)\1\)/gi;function h(t){this.img=t}function d(t,e){this.url=t,this.element=e,this.img=new Image}return n.prototype.addElementBackgroundImages=function(t){let e=getComputedStyle(t);if(!e)return;let i=r.exec(e.backgroundImage);for(;null!==i;){let s=i&&i[2];s&&this.addBackground(s,t),i=r.exec(e.backgroundImage)}},n.prototype.addImage=function(t){let e=new h(t);this.images.push(e)},n.prototype.addBackground=function(t,e){let i=new d(t,e);this.images.push(i)},n.prototype.check=function(){if(this.progressedCount=0,this.hasAnyBroken=!1,!this.images.length)return void this.complete();let t=(t,e,i)=>{setTimeout((()=>{this.progress(t,e,i)}))};this.images.forEach((function(e){e.once("progress",t),e.check()}))},n.prototype.progress=function(t,e,i){this.progressedCount++,this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded,this.emitEvent("progress",[this,t,e]),this.jqDeferred&&this.jqDeferred.notify&&this.jqDeferred.notify(this,t),this.progressedCount===this.images.length&&this.complete(),this.options.debug&&s&&s.log(`progress: ${i}`,t,e)},n.prototype.complete=function(){let t=this.hasAnyBroken?"fail":"done";if(this.isComplete=!0,this.emitEvent(t,[this]),this.emitEvent("always",[this]),this.jqDeferred){let t=this.hasAnyBroken?"reject":"resolve";this.jqDeferred[t](this)}},h.prototype=Object.create(e.prototype),h.prototype.check=function(){this.getIsImageComplete()?this.confirm(0!==this.img.naturalWidth,"naturalWidth"):(this.proxyImage=new Image,this.img.crossOrigin&&(this.proxyImage.crossOrigin=this.img.crossOrigin),this.proxyImage.addEventListener("load",this),this.proxyImage.addEventListener("error",this),this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.proxyImage.src=this.img.currentSrc||this.img.src)},h.prototype.getIsImageComplete=function(){return this.img.complete&&this.img.naturalWidth},h.prototype.confirm=function(t,e){this.isLoaded=t;let{parentNode:i}=this.img,s="PICTURE"===i.nodeName?i:this.img;this.emitEvent("progress",[this,s,e])},h.prototype.handleEvent=function(t){let e="on"+t.type;this[e]&&this[e](t)},h.prototype.onload=function(){this.confirm(!0,"onload"),this.unbindEvents()},h.prototype.onerror=function(){this.confirm(!1,"onerror"),this.unbindEvents()},h.prototype.unbindEvents=function(){this.proxyImage.removeEventListener("load",this),this.proxyImage.removeEventListener("error",this),this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype=Object.create(h.prototype),d.prototype.check=function(){this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.img.src=this.url,this.getIsImageComplete()&&(this.confirm(0!==this.img.naturalWidth,"naturalWidth"),this.unbindEvents())},d.prototype.unbindEvents=function(){this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.element,e])},n.makeJQueryPlugin=function(e){(e=e||t.jQuery)&&(i=e,i.fn.imagesLoaded=function(t,e){return new n(this,t,e).jqDeferred.promise(i(this))})},n.makeJQueryPlugin(),n}));
|
12
app/public/metafizzy/isotope.min.js
vendored
Normal file
12
app/public/metafizzy/isotope.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
9
app/public/metafizzy/masonry.min.js
vendored
Normal file
9
app/public/metafizzy/masonry.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,36 +1,71 @@
|
||||||
|
:root {
|
||||||
|
--gallery-width-ultrawide: 1900px;
|
||||||
|
--gallery-width-desktop: 90%;
|
||||||
|
--gallery-width-tablet: 90%;
|
||||||
|
--gallery-width-mobile: 98%;
|
||||||
|
--color-1: #191919;
|
||||||
|
--stencil-width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
background: #191919;
|
background: var(--color-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#lightgallery {
|
||||||
|
max-width: var(--gallery-width-mobile);
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 600px) {
|
||||||
|
#lightgallery {
|
||||||
|
max-width: var(--gallery-width-tablet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 900px) {
|
||||||
|
#lightgallery {
|
||||||
|
max-width: var(--gallery-width-desktop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 1950px) {
|
||||||
|
#lightgallery {
|
||||||
|
max-width: var(--gallery-width-ultrawide);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#lightgallery a {
|
#lightgallery a {
|
||||||
position: relative;
|
width: 400px;
|
||||||
display: inline-block;
|
max-width: calc(50% - 6px);
|
||||||
text-decoration: none;
|
margin: 3px;
|
||||||
margin: 0;
|
overflow: hidden;
|
||||||
padding: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#lightgallery img {
|
@media screen and (min-width: 600px) {
|
||||||
max-height: 250px;
|
|
||||||
margin: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 800px) {
|
|
||||||
#lightgallery a {
|
#lightgallery a {
|
||||||
width: calc(100vw / 3 - 10px);
|
max-width: calc(33.33333% - 10px);
|
||||||
height: calc(100vw / 3 - 10px);
|
margin: 5px;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#lightgallery img {
|
@media screen and (min-width: 900px) {
|
||||||
width: 100%;
|
#lightgallery a {
|
||||||
height: 100%;
|
max-width: calc(20% - 10px);
|
||||||
object-fit: cover;
|
|
||||||
object-position: center;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#lightgallery a img {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
transition: transform .15s ease-in, filter .15s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lightgallery a:hover img {
|
||||||
|
transform: scale(1.1);
|
||||||
|
filter: brightness(0.7);
|
||||||
|
}
|
||||||
|
|
||||||
.play-icon {
|
.play-icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
@ -68,3 +103,41 @@ html {
|
||||||
#download-all {
|
#download-all {
|
||||||
margin: auto 4px auto auto;
|
margin: auto 4px auto auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#page-loader {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: fixed;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
z-index: 999999;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: var(--color-1)
|
||||||
|
}
|
||||||
|
#stencil {
|
||||||
|
display: flex;
|
||||||
|
width: var(--stencil-width);
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-top: calc(50vh - var(--stencil-width) / 2);
|
||||||
|
margin-bottom: 100vh;
|
||||||
|
place-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
visibility: hidden;
|
||||||
|
animation: 0s linear 0.3s forwards delayedVisibility, loadspin 8s linear infinite;
|
||||||
|
}
|
||||||
|
@keyframes delayedVisibility {
|
||||||
|
to {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes loadspin {
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +1,64 @@
|
||||||
function initLightGallery (config = {}) {
|
function initLightGallery (config = {}) {
|
||||||
lightGallery(document.getElementById('lightgallery'), Object.assign({
|
/* Preloader */
|
||||||
plugins: [lgZoom, lgThumbnail, lgVideo, lgFullscreen],
|
const preloader = document.getElementById('page-loader');
|
||||||
/*
|
if (preloader) {
|
||||||
This license key was graciously provided by LightGallery under their
|
const fadeEffect = () => {
|
||||||
GPLv3 open-source project license:
|
setInterval(() => {
|
||||||
*/
|
if (!preloader.style.opacity) { preloader.style.opacity = 1; }
|
||||||
licenseKey: '8FFA6495-676C4D30-8BFC54B6-4D0A6CEC'
|
if (preloader.style.opacity > 0) { preloader.style.opacity -= 0.1;}
|
||||||
/*
|
else {
|
||||||
Please do not take it and use it for other projects, as it was provided
|
clearInterval(fadeEffect);
|
||||||
specifically for Immich Public Proxy.
|
preloader.remove();
|
||||||
|
}
|
||||||
|
}, 20)
|
||||||
|
}
|
||||||
|
window.addEventListener('load', fadeEffect);
|
||||||
|
}
|
||||||
|
|
||||||
For your own projects you can use the default license key of
|
/* Init Gallery */
|
||||||
0000-0000-000-0000 as per their docs:
|
masonryElMixed = document.getElementById('lightgallery'),
|
||||||
|
masonryElMixed && imagesLoaded( document.getElementById('lightgallery'), function() {
|
||||||
|
|
||||||
https://www.lightgalleryjs.com/docs/settings/#licenseKey
|
masonry = new Masonry(masonryElMixed,{
|
||||||
*/
|
itemSelector: '.grid-item',
|
||||||
}, config))
|
percentPosition: true,
|
||||||
|
gutter: 0,
|
||||||
|
columnWidth: '.lg-item:first-of-type' //Taken from first item. Can put .Class as selector
|
||||||
|
})
|
||||||
|
|
||||||
|
masonry.layout()
|
||||||
|
|
||||||
|
lgallery = window.lightGallery(masonryElMixed, Object.assign({
|
||||||
|
selector: '.lg-item',
|
||||||
|
animateThumb: true,
|
||||||
|
/*
|
||||||
|
This license key was graciously provided by LightGallery under their
|
||||||
|
GPLv3 open-source project license:
|
||||||
|
*/
|
||||||
|
licenseKey: '8FFA6495-676C4D30-8BFC54B6-4D0A6CEC',
|
||||||
|
/*
|
||||||
|
Please do not take it and use it for other projects, as it was provided
|
||||||
|
specifically for Immich Public Proxy.
|
||||||
|
|
||||||
|
For your own projects you can use the default license key of
|
||||||
|
0000-0000-000-0000 as per their docs:
|
||||||
|
|
||||||
|
https://www.lightgalleryjs.com/docs/settings/#licenseKey
|
||||||
|
*/
|
||||||
|
plugins: [
|
||||||
|
lgFullscreen,
|
||||||
|
lgThumbnail,
|
||||||
|
lgVideo,
|
||||||
|
lgZoom
|
||||||
|
],
|
||||||
|
hash: true,
|
||||||
|
toggleThumb: true,
|
||||||
|
allowMediaOverlap: true,
|
||||||
|
subHtmlSelectorRelative: true,
|
||||||
|
zoomFromOrigin: true,
|
||||||
|
}), config)
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,46 @@
|
||||||
<link type="text/css" rel="stylesheet" href="/share/static/lg/lightgallery-bundle.min.css"/>
|
<link type="text/css" rel="stylesheet" href="/share/static/lg/lightgallery-bundle.min.css"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div id="page-loader">
|
||||||
|
<div id="stencil">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 792 792">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0 {
|
||||||
|
fill: #fa2921;
|
||||||
|
}
|
||||||
|
.st1 {
|
||||||
|
fill: #ed79b5;
|
||||||
|
}
|
||||||
|
.st2 {
|
||||||
|
fill: #ffb400;
|
||||||
|
}
|
||||||
|
.st3 {
|
||||||
|
fill: #1e83f7;
|
||||||
|
}
|
||||||
|
.st4 {
|
||||||
|
fill: #18c249;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M375.48,267.63c38.64,34.21,69.78,70.87,89.82,105.42c34.42-61.56,57.42-134.71,57.71-181.3
|
||||||
|
c0-0.33,0-0.63,0-0.91c0-68.94-68.77-95.77-128.01-95.77s-128.01,26.83-128.01,95.77c0,0.94,0,2.2,0,3.72
|
||||||
|
C300.01,209.24,339.15,235.47,375.48,267.63z"></path>
|
||||||
|
<path class="st1" d="M164.7,455.63c24.15-26.87,61.2-55.99,103.01-80.61c44.48-26.18,88.97-44.47,128.02-52.84
|
||||||
|
c-47.91-51.76-110.37-96.24-154.6-110.91c-0.31-0.1-0.6-0.19-0.86-0.28c-65.57-21.3-112.34,35.81-130.64,92.15
|
||||||
|
c-18.3,56.34-14.04,130.04,51.53,151.34C162.05,454.77,163.25,455.16,164.7,455.63z"></path>
|
||||||
|
<path class="st2" d="M681.07,302.19c-18.3-56.34-65.07-113.45-130.64-92.15c-0.9,0.29-2.1,0.68-3.54,1.15
|
||||||
|
c-3.75,35.93-16.6,81.27-35.96,125.76c-20.59,47.32-45.84,88.27-72.51,118c69.18,13.72,145.86,12.98,190.26-1.14
|
||||||
|
c0.31-0.1,0.6-0.2,0.86-0.28C695.11,432.22,699.37,358.52,681.07,302.19z"></path>
|
||||||
|
<path class="st3" d="M336.54,510.71c-11.15-50.39-14.8-98.36-10.7-138.08c-64.03,29.57-125.63,75.23-153.26,112.76
|
||||||
|
c-0.19,0.26-0.37,0.51-0.53,0.73c-40.52,55.78-0.66,117.91,47.27,152.72c47.92,34.82,119.33,53.54,159.86-2.24
|
||||||
|
c0.56-0.76,1.3-1.78,2.19-3.01C363.28,602.32,347.02,558.08,336.54,510.71z"></path>
|
||||||
|
<path class="st4" d="M617.57,482.52c-35.33,7.54-82.42,9.33-130.72,4.66c-51.37-4.96-98.11-16.32-134.63-32.5
|
||||||
|
c8.33,70.03,32.73,142.73,59.88,180.6c0.19,0.26,0.37,0.51,0.53,0.73c40.52,55.78,111.93,37.06,159.86,2.24
|
||||||
|
c47.92-34.82,87.79-96.95,47.27-152.72C619.2,484.77,618.46,483.75,617.57,482.52z"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<% if (showTitle) { %>
|
<% if (showTitle) { %>
|
||||||
<h1><%- title || 'Gallery' %></h1>
|
<h1><%- title || 'Gallery' %></h1>
|
||||||
|
@ -27,7 +67,7 @@
|
||||||
<div id="lightgallery">
|
<div id="lightgallery">
|
||||||
<% items.forEach(item => {
|
<% items.forEach(item => {
|
||||||
if (item.video) { %>
|
if (item.video) { %>
|
||||||
<a data-video='<%- item.video %>'
|
<a data-video='<%- item.video %>' class="lg-item grid-item"
|
||||||
<% if (item.downloadUrl) { %>
|
<% if (item.downloadUrl) { %>
|
||||||
data-download-url="<%- item.downloadUrl %>"
|
data-download-url="<%- item.downloadUrl %>"
|
||||||
<% } %>
|
<% } %>
|
||||||
|
@ -36,7 +76,7 @@
|
||||||
<div class="play-icon"></div>
|
<div class="play-icon"></div>
|
||||||
</a>
|
</a>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<a href="<%- item.previewUrl %>"
|
<a href="<%- item.previewUrl %>" class="lg-item grid-item"
|
||||||
<% if (item.downloadUrl) { %>
|
<% if (item.downloadUrl) { %>
|
||||||
data-download-url="<%- item.downloadUrl %>"
|
data-download-url="<%- item.downloadUrl %>"
|
||||||
<% } %>
|
<% } %>
|
||||||
|
@ -52,6 +92,9 @@
|
||||||
<script src="/share/static/lg/lg-thumbnail.min.js"></script>
|
<script src="/share/static/lg/lg-thumbnail.min.js"></script>
|
||||||
<script src="/share/static/lg/lg-video.min.js"></script>
|
<script src="/share/static/lg/lg-video.min.js"></script>
|
||||||
<script src="/share/static/lg/lg-zoom.min.js"></script>
|
<script src="/share/static/lg/lg-zoom.min.js"></script>
|
||||||
|
<script src="/share/static/metafizzy/imagesloaded.min.js"></script>
|
||||||
|
<script src="/share/static/metafizzy/isotope.min.js"></script>
|
||||||
|
<script src="/share/static/metafizzy/masonry.min.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
initLightGallery(<%- JSON.stringify(lgConfig) %>) // initLightGallery imported from web.js
|
initLightGallery(<%- JSON.stringify(lgConfig) %>) // initLightGallery imported from web.js
|
||||||
<% if (openItem) { %>
|
<% if (openItem) { %>
|
||||||
|
|
Loading…
Reference in a new issue