Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial photoswipe widget support #309

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
3 changes: 3 additions & 0 deletions src/static_src/css/photoswipe-widget.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.photoswipe-attribution-size {
max-width: 130px;
}
79 changes: 79 additions & 0 deletions src/widgets/templates/includes/base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// config (rendered serverside)
const uuid = "{{ uuid }}";
const host = "{{ host }}";
const count = "{{ count }}";

const templateFiles = "{{ files|escapejs }}";

// custom error class
class BmaNotFoundError extends Error {
constructor(message) {
super(message);
this.name = "BmaNotFoundError";
}
}
class BmaApiError extends Error {
constructor(message) {
super(message);
this.name = "BmaApiError";
}
}
class BmaPermissionError extends Error {
constructor(message) {
super(message);
this.name = "BmaPermissionError";
}
}

const main_loader = document.createElement('div');
main_loader.id = "photoswipe-" + count + "-loader"
main_loader.innerHTML = `<div class="spinner-grow" role="status"></div><span class="h3">Loading Gallery....</span>`;
// A reference to the currently running script
const bma_script = document.scripts[document.scripts.length - 1];
bma_script.parentElement.insertBefore(main_loader, bma_script);


async function getFileMetadata(file_uuid) {
const response = fetch("//" + host + "/api/v1/json/files/" + file_uuid + "/", {mode: 'cors'})
.then((x) => {
if (!x.ok) {
// handle non-2xx x code
if (x.status === 404) {
throw new BmaNotFoundError("File UUID " + file_uuid + " not found!");
} else if (x.status === 403) {
throw new BmaPermissionError("No permission for file UUID " + file_uuid + "!");
} else {
throw new BmaApiError("BMA API returned unexpected x code " + x.status);
}
}
return x.json()
})
.then((x) => ({[file_uuid]: x['bma_response']}))
.catch((response) => {
console.log(response);
});
return response
}

async function getAlbumMetadata(album_uuid) {
const response = fetch("//" + host + "/api/v1/json/albums/" + album_uuid + "/", {mode: 'cors'})
.then((response) => {
if (!response.ok) {
// handle non-2xx response code
if (response.status === 404) {
throw new BmaNotFoundError("Album UUID " + album_uuid + " not found!");
} else if (response.status === 403) {
throw new BmaPermissionError("No permission for album UUID " + album_uuid + "!");
} else {
throw new BmaApiError("BMA API returned unexpected response code " + response.status);
}
}
return response.json();
})
.then((data) => data["bma_response"])
.catch((response) => {
console.log(response);
});
return response;
}

160 changes: 160 additions & 0 deletions src/widgets/templates/photoswipe-module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
{% load static %}

const count = "{{ count }}";
const uuid = "{{ uuid }}";

// https://github.com/dimsemenov/PhotoSwipe
import PhotoSwipeLightbox from "{% static 'js/vendor/photoswipe-lightbox-v5.4.4.esm.min.js' %}";

// https://github.com/dimsemenov/photoswipe-video-plugin
import PhotoSwipeVideoPlugin from '{% static 'js/vendor/photoswipe-video-plugin-v1.0.2.esm.min.js' %}';

// https://github.com/dimsemenov/photoswipe-dynamic-caption-plugin
import PhotoSwipeDynamicCaption from '{% static 'js/vendor/photoswipe-dynamic-caption-plugin-v1.2.7.esm.js' %}';

// https://github.com/junkfix/photoswipe-slideshow
import PhotoSwipeSlideshow from '{% static 'js/vendor/photoswipe-slideshow.21b9b68e9ffa5bbd370d57888ebf001dd08e36e2.esm.js' %}';

// https://github.com/arnowelzel/photoswipe-auto-hide-ui
import PhotoSwipeAutoHideUI from '{% static 'js/vendor/photoswipe-auto-hide-ui.v1.0.1.esm.js' %}';

// https://github.com/arnowelzel/photoswipe-fullscreen
import PhotoSwipeFullscreen from '{% static 'js/vendor/photoswipe-fullscreen.v1.0.5.esm.js' %}';

///////////////////////////////////////////////////////////////////////////////
export const lightbox = new PhotoSwipeLightbox({
gallery: `#photoswipe-${count}-${uuid}-main`,
children: `a.gallery-${count}-${uuid}`,
pswpModule: () => import('/static/js/vendor/photoswipe-v5.4.4.esm.min.js')
});

// enable videoplugin
const videoPlugin = new PhotoSwipeVideoPlugin(lightbox, {
// no options for now
});

// enable captionplugin
const captionPlugin = new PhotoSwipeDynamicCaption(lightbox, {
// Plugins options
type: 'auto',
captionContent: (slide) => {
return slide.data.element.parentElement.querySelector("div.pswp-caption-content").innerHTML
},
});

// slideshow plugin
const slideshowPlugin = new PhotoSwipeSlideshow(lightbox, {
// Plugin options
defaultDelayMs: 5000,
progressBarPosition: 'bottom',
});

// autohideui plugin
const autoHideUI = new PhotoSwipeAutoHideUI(lightbox, {
// Plugin options
idleTime: 4000 // ms
});

// fullscreen plugin
const fullscreenPlugin = new PhotoSwipeFullscreen(lightbox);

///////////////////////////////////////////////////////////////////////////////
// bullets
lightbox.on('uiRegister', function() {
lightbox.pswp.ui.registerElement({
name: 'bulletsIndicator',
className: 'pswp__bullets-indicator d-none d-sm-flex',
appendTo: 'wrapper',
onInit: (el, pswp) => {
// skip bullets if there is only 1 file
if (pswp.getNumItems() == 1) {
return;
};
const bullets = [];
let bullet;
let prevIndex = -1;

for (let i = 0; i < pswp.getNumItems(); i++) {
bullet = document.createElement('div');
bullet.className = 'pswp__bullet';
bullet.onclick = (e) => {
pswp.goTo(bullets.indexOf(e.target));
};
el.appendChild(bullet);
bullets.push(bullet);
}

pswp.on('change', (a,) => {
if (prevIndex >= 0) {
bullets[prevIndex].classList.remove('pswp__bullet--active');
}
bullets[pswp.currIndex].classList.add('pswp__bullet--active');
prevIndex = pswp.currIndex;
});
}
});
});

///////////////////////////////////////////////////////////////////////////////
// add download button
lightbox.on('uiRegister', function() {
lightbox.pswp.ui.registerElement({
name: 'download-button',
order: 8,
isButton: true,
tagName: 'a',
html: {
isCustomSVG: true,
inner: '<path d="M20.5 14.3 17.1 18V10h-2.2v7.9l-3.4-3.6L10 16l6 6.1 6-6.1ZM23 23H9v2h14Z" id="pswp__icn-download"/>',
outlineID: 'pswp__icn-download'
},
onInit: (el, pswp) => {
el.setAttribute('download', '');
el.setAttribute('rel', 'noopener');
pswp.on('change', () => {
el.href = pswp.currSlide.data.element.dataset.bmaFileOrigUrl;
el.title = "Download original";
});
}
});
});


///////////////////////////////////////////////////////////////////////////////
// parse data-bma-file-orig-url attribute
lightbox.addFilter('itemData', (itemData, _index) => {
const bmaFileOrigUrl = itemData.element.dataset.bmaFileOrigUrl;
if (bmaFileOrigUrl) {
itemData.bmaFileOrigUrl = bmaFileOrigUrl;
}
return itemData;
});

// override slide content
lightbox.on('contentLoad', (e) => {
const { content } = e;
if (content.type === 'document') {
console.log("DOCUMENT");
// prevent the deafult behavior
e.preventDefault();

// Create a container for iframe
// and assign it to the `content.element` property
content.element = document.createElement('div');
content.element.className = 'pswp__document-container';

const iframe = document.createElement('iframe');
//iframe.setAttribute('allowfullscreen', '');
iframe.src = content.data.bmaFileOrigUrl;
content.element.appendChild(iframe);
}
});


// support autoplay
lightbox.on('openingAnimationEnd', () => {
if (location.hash.includes("autoplay")) {
slideshowPlugin.setSlideshowState();
autoHideUI.hideUI();
}
});
Loading
Loading