mirror of
https://github.com/alangrainger/immich-public-proxy.git
synced 2024-12-28 03:41:58 +00: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 {
|
||||
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 {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
width: 400px;
|
||||
max-width: calc(50% - 6px);
|
||||
margin: 3px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#lightgallery img {
|
||||
max-height: 250px;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
@media screen and (min-width: 600px) {
|
||||
#lightgallery a {
|
||||
width: calc(100vw / 3 - 10px);
|
||||
height: calc(100vw / 3 - 10px);
|
||||
overflow: hidden;
|
||||
max-width: calc(33.33333% - 10px);
|
||||
margin: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
#lightgallery img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
@media screen and (min-width: 900px) {
|
||||
#lightgallery a {
|
||||
max-width: calc(20% - 10px);
|
||||
}
|
||||
}
|
||||
|
||||
#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 {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
|
@ -68,3 +103,41 @@ html {
|
|||
#download-all {
|
||||
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 = {}) {
|
||||
lightGallery(document.getElementById('lightgallery'), Object.assign({
|
||||
plugins: [lgZoom, lgThumbnail, lgVideo, lgFullscreen],
|
||||
/*
|
||||
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.
|
||||
/* Preloader */
|
||||
const preloader = document.getElementById('page-loader');
|
||||
if (preloader) {
|
||||
const fadeEffect = () => {
|
||||
setInterval(() => {
|
||||
if (!preloader.style.opacity) { preloader.style.opacity = 1; }
|
||||
if (preloader.style.opacity > 0) { preloader.style.opacity -= 0.1;}
|
||||
else {
|
||||
clearInterval(fadeEffect);
|
||||
preloader.remove();
|
||||
}
|
||||
}, 20)
|
||||
}
|
||||
window.addEventListener('load', fadeEffect);
|
||||
}
|
||||
|
||||
For your own projects you can use the default license key of
|
||||
0000-0000-000-0000 as per their docs:
|
||||
/* Init Gallery */
|
||||
masonryElMixed = document.getElementById('lightgallery'),
|
||||
masonryElMixed && imagesLoaded( document.getElementById('lightgallery'), function() {
|
||||
|
||||
https://www.lightgalleryjs.com/docs/settings/#licenseKey
|
||||
*/
|
||||
}, config))
|
||||
masonry = new Masonry(masonryElMixed,{
|
||||
itemSelector: '.grid-item',
|
||||
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"/>
|
||||
</head>
|
||||
<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">
|
||||
<% if (showTitle) { %>
|
||||
<h1><%- title || 'Gallery' %></h1>
|
||||
|
@ -27,7 +67,7 @@
|
|||
<div id="lightgallery">
|
||||
<% items.forEach(item => {
|
||||
if (item.video) { %>
|
||||
<a data-video='<%- item.video %>'
|
||||
<a data-video='<%- item.video %>' class="lg-item grid-item"
|
||||
<% if (item.downloadUrl) { %>
|
||||
data-download-url="<%- item.downloadUrl %>"
|
||||
<% } %>
|
||||
|
@ -36,7 +76,7 @@
|
|||
<div class="play-icon"></div>
|
||||
</a>
|
||||
<% } else { %>
|
||||
<a href="<%- item.previewUrl %>"
|
||||
<a href="<%- item.previewUrl %>" class="lg-item grid-item"
|
||||
<% if (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-video.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">
|
||||
initLightGallery(<%- JSON.stringify(lgConfig) %>) // initLightGallery imported from web.js
|
||||
<% if (openItem) { %>
|
||||
|
|
Loading…
Reference in a new issue