Version 5.0.13
This commit is contained in:
1 parent
b89858b2ff
commit
5efe744c5f
1407 files changed
+69690
-30177
No files matched your search
@@ -241,5 +241,15 @@
|
||||
"create albums",
|
||||
"create albums permission"
|
||||
]
|
||||
},
|
||||
"app=gallery&module=gallery&controller=settings&searchResult=form_gallery_metadata": {
|
||||
"lang_key": "gallery_metadata",
|
||||
"restriction": "settings_manage",
|
||||
"keywords": [
|
||||
"exif",
|
||||
"metadata",
|
||||
"location",
|
||||
"image data"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
<setting key="gallery_detailed_bandwidth"><![CDATA[{"key":"gallery_detailed_bandwidth","default":"1","report":"full"}]]></setting>
|
||||
<setting key="gallery_large_dims"><![CDATA[{"key":"gallery_large_dims","default":"1600x1200","report":"full"}]]></setting>
|
||||
<setting key="gallery_maps_default"><![CDATA[{"key":"gallery_maps_default","default":"0","report":"full"}]]></setting>
|
||||
<setting key="gallery_metadata"><![CDATA[{"key":"gallery_metadata","default":"1","report":"none"}]]></setting>
|
||||
<setting key="gallery_new_images_count"><![CDATA[{"key":"gallery_new_images_count","default":"16","report":"none"}]]></setting>
|
||||
<setting key="gallery_nsfw"><![CDATA[{"key":"gallery_nsfw","default":"0","report":"bool"}]]></setting>
|
||||
<setting key="gallery_overview_carousel_count"><![CDATA[{"key":"gallery_overview_carousel_count","default":"20","report":"full"}]]></setting>
|
||||
@@ -59,4 +60,5 @@
|
||||
<acpsearch key="app=core&module=members&controller=groups&searchResult=4_g_max_upload"><![CDATA[{"lang_key":"g_max_upload","restriction":"groups_manage","keywords":["gallery image size","gallery max image size","gallery maximum image size","max size of image","maximum image size"]}]]></acpsearch>
|
||||
<acpsearch key="app=core&module=members&controller=groups&searchResult=4_g_movies"><![CDATA[{"lang_key":"g_movies","restriction":"groups_manage","keywords":["ability to upload movies","movie upload ability","movies","upload movie permission","upload movies"]}]]></acpsearch>
|
||||
<acpsearch key="app=core&module=members&controller=groups&searchResult=4_g_create_albums"><![CDATA[{"lang_key":"g_create_albums","restriction":"groups_manage","keywords":["albums","albums permission","create albums","create albums permission"]}]]></acpsearch>
|
||||
<acpsearch key="app=gallery&module=gallery&controller=settings&searchResult=form_gallery_metadata"><![CDATA[{"lang_key":"gallery_metadata","restriction":"settings_manage","keywords":["exif","metadata","location","image data"]}]]></acpsearch>
|
||||
</build>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<javascript app="gallery">
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/global" javascript_name="ips.global.nsfw.js" javascript_type="controller" javascript_version="5000074" javascript_position="1000200">;( function($, _, undefined){
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/global" javascript_name="ips.global.nsfw.js" javascript_type="controller" javascript_version="5001302" javascript_position="1000200">;( function($, _, undefined){
|
||||
"use strict";
|
||||
|
||||
ips.controller.register('gallery.front.global.nsfw', {
|
||||
@@ -20,7 +20,7 @@
|
||||
});
|
||||
|
||||
}(jQuery, _));</file>
|
||||
<file javascript_app="gallery" javascript_location="admin" javascript_path="controllers/settings" javascript_name="ips.settings.settings.js" javascript_type="controller" javascript_version="5000074" javascript_position="1000050">/**
|
||||
<file javascript_app="gallery" javascript_location="admin" javascript_path="controllers/settings" javascript_name="ips.settings.settings.js" javascript_type="controller" javascript_version="5001302" javascript_position="1000050">/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -77,7 +77,7 @@
|
||||
|
||||
});
|
||||
}(jQuery, _));</file>
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.chooseCategory.js" javascript_type="controller" javascript_version="5000074" javascript_position="1000100"><![CDATA[/**
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.chooseCategory.js" javascript_type="controller" javascript_version="5001302" javascript_position="1000100"><![CDATA[/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -244,7 +244,7 @@
|
||||
});
|
||||
}(jQuery, _));
|
||||
]]></file>
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.existingAlbums.js" javascript_type="controller" javascript_version="5000074" javascript_position="1000100"><![CDATA[/**
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.existingAlbums.js" javascript_type="controller" javascript_version="5001302" javascript_position="1000100"><![CDATA[/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -280,7 +280,7 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));]]></file>
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.uploadImages.js" javascript_type="controller" javascript_version="5000074" javascript_position="1000100"><![CDATA[/**
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.uploadImages.js" javascript_type="controller" javascript_version="5001302" javascript_position="1000100"><![CDATA[/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -411,7 +411,7 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));]]></file>
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.wrapper.js" javascript_type="controller" javascript_version="5000074" javascript_position="1000100"><![CDATA[/**
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.wrapper.js" javascript_type="controller" javascript_version="5001302" javascript_position="1000100"><![CDATA[/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -450,7 +450,6 @@
|
||||
this.on( 'click', '[data-role="imageDescriptionUseTextarea"]', this.setUpImageDescriptionPlain );
|
||||
this.on( 'click', '[data-role="addCopyrightCredit"]', this.showCopyrightCredit );
|
||||
this.on( 'click', '[data-role="saveDetails"]', this.saveDetails );
|
||||
this.on( 'click', '[data-role="saveInfo"]', this.saveInfo );
|
||||
|
||||
// Handle events from uploader
|
||||
this.on( 'gallery.activateSubmitButton', this.activateSubmitButton );
|
||||
@@ -562,16 +561,6 @@
|
||||
link.hide().next().slideDown();
|
||||
},
|
||||
|
||||
/**
|
||||
* Closes the copyright/credit menu
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
saveInfo: function (e) {
|
||||
e.preventDefault();
|
||||
$(e.currentTarget).trigger('closeMenu');
|
||||
},
|
||||
|
||||
/**
|
||||
* Mobile-specific functionality for 'save' button
|
||||
*
|
||||
@@ -1166,7 +1155,7 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));]]></file>
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.image.js" javascript_type="controller" javascript_version="5000074" javascript_position="1000150">/**
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.image.js" javascript_type="controller" javascript_version="5001302" javascript_position="1000150"><![CDATA[/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -1175,7 +1164,22 @@
|
||||
* Author: Rikki Tissier
|
||||
*/
|
||||
;( function($, _, undefined){
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* @typedef {{id: number|string, content:string}[]} ImageNavLinks
|
||||
* @typedef {Object&{image: string, url: string, info: string, title: string, id: string|number, images_prev: ImageNavLinks, images_next: ImageNavLinks, image_link_current:string}} ImageFetchResponse
|
||||
*/
|
||||
|
||||
const selectorPropertyMap = {
|
||||
comments: '[data-role="imageComments"]',
|
||||
image: '[data-role="imageFrame"]',
|
||||
info: '[data-role="imageInfo"]',
|
||||
breadcrumb_top: 'nav.ipsBreadcrumb--top',
|
||||
breadcrumb_bottom: 'nav.ipsBreadcrumb--bottom',
|
||||
breadcrumb_mobile: 'nav.ipsBreadcrumb--mobile',
|
||||
breadcrumb_off_canvas: 'nav.ipsOffCanvas__breadcrumb'
|
||||
};
|
||||
|
||||
ips.controller.register('gallery.front.view.image', {
|
||||
|
||||
@@ -1183,9 +1187,17 @@
|
||||
this.on( 'menuOpened', this.menuOpened );
|
||||
this.on( 'menuClosed', this.menuClosed );
|
||||
this.on( document, 'keydown', this.keyDown );
|
||||
this.on( 'click', '[data-action="setAsCover"]', this.setAsCover );
|
||||
this.on( 'click', '[data-action="setAsProfile"]', this.setAsProfile );
|
||||
this.on( 'click', '[data-action="rotateImage"]', this.rotateImage );
|
||||
this.on( 'click', '[data-action="setAsCover"]', this.setAsCover );
|
||||
this.on( 'click', '[data-action="setAsProfile"]', this.setAsProfile );
|
||||
this.on( 'click', '[data-action="rotateImage"]', this.rotateImage );
|
||||
this.on( 'click', '[data-action="changeImage"]', this.changeImage );
|
||||
this._stateUpdate = e => this.stateUpdate(e);
|
||||
ips.utils.history.replaceState({id: this.getCurrentImageId()}, 'gallery.view.image', window.location.href);
|
||||
window.addEventListener('historychange', this._stateUpdate);
|
||||
},
|
||||
|
||||
destroy() {
|
||||
window.removeEventListener('historychange:gallery.view.image', this._stateUpdate);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1220,10 +1232,10 @@
|
||||
|
||||
switch( e.keyCode ){
|
||||
case ips.ui.key.LEFT:
|
||||
this.scope.find('[data-action="prevMedia"]')[0].click();
|
||||
this.scope.find('[data-action="changeImage"][data-direction="prev"]')[0].click();
|
||||
break;
|
||||
case ips.ui.key.RIGHT:
|
||||
this.scope.find('[data-action="nextMedia"]')[0].click();
|
||||
this.scope.find('[data-action="changeImage"][data-direction="next"]')[0].click();
|
||||
break;
|
||||
}
|
||||
},
|
||||
@@ -1297,18 +1309,359 @@
|
||||
showLoading: true
|
||||
} )
|
||||
.done( function (response) {
|
||||
self.scope.find('[data-role="theImage"]')[0].src = response.src;
|
||||
self.scope.find('[data-role="theImage"]').css( { 'width': response.width + 'px', 'height': response.height + 'px' } );
|
||||
self.scope.find('[data-role="theImage"]').closest('.cGalleryViewImage').css( { 'width': response.width + 'px', 'height': response.height + 'px' } );
|
||||
self.scope.find('[data-role="theImage"]')[0].src = response.src;
|
||||
self.scope.find('[data-role="theImage"]').css( { 'width': response.width + 'px', 'height': response.height + 'px' } );
|
||||
self.scope.find('[data-role="theImage"]').closest('.cGalleryViewImage').css( { 'width': response.width + 'px', 'height': response.height + 'px' } );
|
||||
ips.ui.flashMsg.show( response.message );
|
||||
})
|
||||
.fail( function () {
|
||||
window.location = url;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch new image and replace existing HTML so we don't need to refresh the page
|
||||
*
|
||||
* @param {Event} e Event object
|
||||
* @returns {void}
|
||||
*/
|
||||
changeImage: async function(e){
|
||||
e.preventDefault();
|
||||
|
||||
let commentTab;
|
||||
const tabsContainer = this.elem.querySelector(`${selectorPropertyMap.comments} i-tabs`);
|
||||
if (tabsContainer) {
|
||||
let tab = tabsContainer.querySelector(`[href][aria-selected="true"]`)?.href;
|
||||
if (tab && tab.endsWith('comments')) {
|
||||
commentTab = 'comments';
|
||||
} else if (tab) {
|
||||
commentTab = 'reviews';
|
||||
}
|
||||
}
|
||||
let url = $( e.currentTarget ).attr('href');
|
||||
const currentId = this.getCurrentImageId();
|
||||
const urlObj = new URL(url, window.location.href);
|
||||
urlObj.updateSearchParams({param: 'browse', value: '1'});
|
||||
|
||||
try {
|
||||
// Fetch new image data
|
||||
let selectedId;
|
||||
if (urlObj.searchParams.get('do') === 'previous' && currentId && currentId in this._prevIdCache) {
|
||||
selectedId = this._prevIdCache[currentId];
|
||||
} else if (urlObj.searchParams.get('do') === 'next' && currentId && currentId in this._nextIdCache) {
|
||||
selectedId = this._nextIdCache[currentId];
|
||||
} else if (e.currentTarget.closest(`#gallery-image-thumbs > [data-image-id]`)) {
|
||||
selectedId = e.currentTarget.closest(`#gallery-image-thumbs > [data-image-id]`).dataset.imageId;
|
||||
}
|
||||
|
||||
if (selectedId && selectedId === currentId) {
|
||||
Debug.log(`Not loading image ${selectedId} from ${urlObj} because it is the current image`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const selector of Object.values(selectorPropertyMap)) {
|
||||
this.elem.querySelectorAll(`${selector}:not(${selector} *)`).forEach(el => el.classList.add('ipsLoading'));
|
||||
}
|
||||
|
||||
const response = await this.fetchImageData(urlObj.toString(), commentTab, selectedId);
|
||||
|
||||
// Update browser URL
|
||||
url = new URL(response.url, window.location.href)
|
||||
if (commentTab) {
|
||||
url.updateSearchParams({param: "tab", value: commentTab});
|
||||
}
|
||||
ips.utils.history.pushState({url:url.toString(), response, commentTab, id: response.id.toString()}, `gallery.view.image`, url.toString(), e);
|
||||
if (this.historyPromise) {
|
||||
await this.historyPromise;
|
||||
}
|
||||
|
||||
const currentThumbIDs = new Set(
|
||||
[...this.elem.querySelectorAll("#gallery-image-thumbs [data-image-id]")]
|
||||
.map(elem => elem.dataset.imageId)
|
||||
);
|
||||
|
||||
let thumbsChanged = false;
|
||||
for (const thumb of this.elem.querySelectorAll("#gallery-image-thumbs [data-image-id]")) {
|
||||
if (!currentThumbIDs.has(thumb.dataset.imageId)) {
|
||||
thumbsChanged = true;
|
||||
break;
|
||||
}
|
||||
currentThumbIDs.delete(thumb.dataset.imageId);
|
||||
}
|
||||
|
||||
if (currentThumbIDs.size && !thumbsChanged) {
|
||||
thumbsChanged = true;
|
||||
}
|
||||
selectedId = this.getCurrentImageId();
|
||||
if (selectedId) {
|
||||
// We need to clear out the existing prev/next associations if an image was added or deleted, otherwise it will skip images and/or display the cached deleted image and content feed, creating issues
|
||||
if (thumbsChanged) {
|
||||
this._prevIdCache = {};
|
||||
this._nextIdCache = {};
|
||||
}
|
||||
|
||||
const urlObj = new URL(response.url, window.location.href);
|
||||
if (urlObj.searchParams.get('do') === 'previous' && currentId) {
|
||||
this._prevIdCache[currentId] = selectedId;
|
||||
this._nextIdCache[selectedId] = currentId;
|
||||
} else if (urlObj.searchParams.get('do') === 'next' && currentId) {
|
||||
this._nextIdCache[currentId] = selectedId;
|
||||
this._prevIdCache[selectedId] = currentId;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
Debug.warn(e);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the image data based on details
|
||||
* @param url
|
||||
* @param commentTab
|
||||
* @param id
|
||||
* @return {Promise<ImageFetchResponse>}
|
||||
*/
|
||||
async fetchImageData(url, commentTab, id) {
|
||||
url = new URL(url, window.location.href)
|
||||
.updateSearchParams({params: {
|
||||
tab: ['comments','reviews'].includes(commentTab) ? commentTab : null, // null removes this param if it's set
|
||||
browse: 1,
|
||||
}})
|
||||
.toString();
|
||||
commentTab = commentTab || 'reviews';
|
||||
const response = this._resultCache?.[commentTab]?.[id] || await ips.fetch(url, {bypassRedirect: 'none'});
|
||||
if (typeof response !== 'object' || ['image','url','info','title', 'id'].some(prop => !(prop in response))) {
|
||||
throw new RangeError(`The response from the endpoint ${urlObj} is not a JSON object containing image, url, info and title properties.`);
|
||||
}
|
||||
|
||||
if (id) {
|
||||
this._resultCache[commentTab] = this._resultCache[commentTab] || {};
|
||||
this._resultCache[commentTab][id] = response;
|
||||
}
|
||||
|
||||
return response;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle a state update
|
||||
* @param {CustomEvent<Object&{detail: 'replace'|'pop'|'push'|string,state: {"gallery.view.image": Object&{response: Object|undefined, commentTab: string|undefined, id:string|number}}}>}e
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async stateUpdate(e) {
|
||||
if (e.detail.type === 'replace') {
|
||||
return;
|
||||
}
|
||||
let _resolve, _reject;
|
||||
let {response, commentTab, id} = e.detail.state['gallery.view.image'];
|
||||
this.historyPromise = new Promise(((resolve, reject) => {
|
||||
_resolve = resolve;
|
||||
_reject = reject;
|
||||
}));
|
||||
if (!id || id === this.getCurrentImageId()) {
|
||||
Debug.log(`Not handling a state update for the gallery view because the id has not changed`);
|
||||
_reject(`The view wasn't actually changed`);
|
||||
return;
|
||||
}
|
||||
if (!response || !commentTab) {
|
||||
let tab = this.elem.querySelector(`${selectorPropertyMap.comments} i-tabs [href][aria-selected="true"]`)?.href;
|
||||
if (tab && tab.endsWith('comments')) {
|
||||
commentTab = 'comments';
|
||||
} else if (tab) {
|
||||
commentTab = 'reviews';
|
||||
}
|
||||
|
||||
response = await this.fetchImageData(window.location.href, commentTab, id);
|
||||
ips.utils.history.replaceState({...e.detail.state['gallery.view.image'], response, commentTab, id, url: response.url});
|
||||
}
|
||||
|
||||
for (const [property, selector] of Object.entries(selectorPropertyMap)) {
|
||||
const root = ['breadcrumb_top','breadcrumb_bottom','breadcrumb_mobile', 'breadcrumb_off_canvas'].includes(property) ? document.body : this.elem;
|
||||
root.querySelectorAll(`${selector}:not(${selector} *)`).forEach(el => {
|
||||
el.insertAdjacentHTML("afterend", response[property] || "");
|
||||
el.remove();
|
||||
});
|
||||
}
|
||||
this.updateActiveThumb(response);
|
||||
|
||||
document.title = response.title;
|
||||
|
||||
// Refresh content
|
||||
$( document ).trigger( 'contentChange', [ $(this.elem) ] );
|
||||
|
||||
if (response.dataLayer) {
|
||||
this.scope.trigger('ipsDataLayerProperties', {_properties: response.dataLayer});
|
||||
}
|
||||
_resolve();
|
||||
},
|
||||
|
||||
/**
|
||||
* @type {Promise<void>|undefined}
|
||||
*/
|
||||
historyPromise: undefined,
|
||||
|
||||
/**
|
||||
* Get the id of the currently visible image.
|
||||
* @return {string | undefined}
|
||||
*/
|
||||
getCurrentImageId() {
|
||||
const id = this.elem.querySelector("[data-role='imageFrame'][data-image-id]")?.dataset.imageId;
|
||||
if (id === undefined) {
|
||||
Debug.warn(new RangeError(`Could not determine the current image id from the image frame`));
|
||||
}
|
||||
return id;
|
||||
},
|
||||
|
||||
/**
|
||||
* Since the prev/next buttons use the current image, and do=next in the URL, we have to cache the image ID after the request is done
|
||||
* @type {Object<string, string>}
|
||||
*/
|
||||
_nextIdCache: {},
|
||||
|
||||
/**
|
||||
* Since the prev/next buttons use the current image, and do=next in the URL, we have to cache the image ID after the request is done
|
||||
* @type {Object<string, string>}
|
||||
*/
|
||||
_prevIdCache: {},
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
_resultCache: {},
|
||||
|
||||
/**
|
||||
* @param {ImageFetchResponse|undefined} response
|
||||
*/
|
||||
updateActiveThumb(response) {
|
||||
if (response) {
|
||||
// merge in images before this one
|
||||
const allImages = [...this.elem.querySelectorAll(`#gallery-image-thumbs > [data-image-id]`)];
|
||||
const remainingIds = new Set(allImages.map(img => parseInt(img.dataset.imageId)));
|
||||
|
||||
/**
|
||||
* @type {ImageNavLinks}
|
||||
*/
|
||||
const toInsert = [...response.images_prev, {id: response.id, content:response.image_link_current}, ...response.images_next];
|
||||
|
||||
// first is there any overlap?
|
||||
const overlap = toInsert.findIndex(val => remainingIds.has((parseInt(val.id))));
|
||||
if (overlap !== -1) {
|
||||
const id = parseInt(toInsert[overlap].id);
|
||||
const overlapDOMIdx = allImages.findIndex(img => parseInt(img.dataset.imageId) === id);
|
||||
|
||||
// merge in any ids that aren't currently in the page
|
||||
const prevInDOM = allImages.slice(0,overlapDOMIdx).reverse();
|
||||
const prevIdsRemaining = new Set(prevInDOM.map(img => parseInt(img.dataset.imageId)));
|
||||
const prevToInsert = toInsert.slice(0, overlap).reverse();
|
||||
for (let i = 0; i < prevToInsert.length; i++) {
|
||||
const id = parseInt(prevToInsert[i].id);
|
||||
|
||||
|
||||
// just insert if there's no images before this one in the DOM
|
||||
if (!prevInDOM.length && !remainingIds.has(id)) {
|
||||
requestAnimationFrame(() => {
|
||||
this.elem.querySelector(`#gallery-image-thumbs`).insertAdjacentHTML('afterbegin', prevToInsert[i].content);
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prevIdsRemaining.has(id)) {
|
||||
prevIdsRemaining.delete(id);
|
||||
while (prevInDOM.length > 1 && parseInt(prevInDOM[0].dataset.imageId) !== id) {
|
||||
const skipped = prevInDOM.shift();
|
||||
prevIdsRemaining.delete(parseInt(skipped.dataset.imageId));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// if there's already an element for this, skip it
|
||||
if (remainingIds.has(id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// insert this before the first image
|
||||
const chunk = [];
|
||||
while (i < prevToInsert.length && !remainingIds.has(parseInt(prevToInsert[i].id))) {
|
||||
chunk.unshift(prevToInsert[i].content);
|
||||
i++;
|
||||
}
|
||||
requestAnimationFrame(() => {
|
||||
prevInDOM[0].insertAdjacentHTML('beforebegin', chunk.join(''));
|
||||
});
|
||||
}
|
||||
|
||||
const nextToInsert = toInsert.slice(overlap + 1);
|
||||
const nextInDOM = allImages.slice(overlapDOMIdx);
|
||||
const nextIdsRemaining = new Set(nextInDOM.map(img => parseInt(img.dataset.imageId)));
|
||||
for (let i = 0; i < nextToInsert.length; i++) {
|
||||
const id = parseInt(nextToInsert[i].id);
|
||||
// just insert if there's no images before this one in the DOM
|
||||
if (!nextInDOM.length) {
|
||||
requestAnimationFrame(() => {
|
||||
this.elem.querySelector(`#gallery-image-thumbs`).insertAdjacentHTML('beforeend', nextToInsert[i].content);
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nextIdsRemaining.has(id)) {
|
||||
nextIdsRemaining.delete(id);
|
||||
while (nextInDOM.length > 1 && parseInt(nextInDOM[0].dataset.imageId) !== id) {
|
||||
const skipped = nextInDOM.shift();
|
||||
nextIdsRemaining.delete(parseInt(skipped.dataset.imageId));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (remainingIds.has(id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// insert this before the first image
|
||||
let chunk = [];
|
||||
while (i < nextToInsert.length && !remainingIds.has(parseInt(nextToInsert[i].id))) {
|
||||
chunk.push(nextToInsert[i].content);
|
||||
i++;
|
||||
}
|
||||
requestAnimationFrame(() => {
|
||||
nextInDOM[0].insertAdjacentHTML('afterend', chunk.join(''));
|
||||
});
|
||||
}
|
||||
} else if (toInsert.length) {
|
||||
requestAnimationFrame(() => {
|
||||
// no overlap? Well then we need to replace the links as we have no way to properly merge the lists
|
||||
this.elem.querySelector('#gallery-image-thumbs').innerHTML = toInsert.map(img => img.content).join('\n');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const currentlyActiveThumb = this.getCurrentImageId();
|
||||
requestAnimationFrame(() => {
|
||||
this.elem.querySelectorAll(`#gallery-image-thumbs > [data-active]`).forEach(el => delete el.dataset.active);
|
||||
});
|
||||
if (currentlyActiveThumb) {
|
||||
let img;
|
||||
requestAnimationFrame(() => {
|
||||
this.elem.querySelectorAll(`#gallery-image-thumbs > [data-image-id="${currentlyActiveThumb}"]`).forEach(el => {
|
||||
el.dataset.active = '';
|
||||
img = el;
|
||||
});
|
||||
if (img) {
|
||||
requestAnimationFrame(() => {
|
||||
const imgRect = img.getBoundingClientRect();
|
||||
const scroller = img.closest('#gallery-image-thumbs');
|
||||
const scrollerRect = scroller.getBoundingClientRect();
|
||||
if (imgRect.left < scrollerRect.left) {
|
||||
scroller.scrollBy({left: imgRect.left - scrollerRect.left});
|
||||
} else if (imgRect.right > scrollerRect.right) {
|
||||
scroller.scrollBy({left: imgRect.right - scrollerRect.right});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}(jQuery, _));</file>
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.note.js" javascript_type="controller" javascript_version="5000074" javascript_position="1000150"><![CDATA[/**
|
||||
}(jQuery, _));]]></file>
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.note.js" javascript_type="controller" javascript_version="5001302" javascript_position="1000150"><![CDATA[/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -1768,7 +2121,7 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));]]></file>
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.notes.js" javascript_type="controller" javascript_version="5000074" javascript_position="1000150"><![CDATA[/**
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.notes.js" javascript_type="controller" javascript_version="5001302" javascript_position="1000150"><![CDATA[/**
|
||||
* Invision Community
|
||||
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
|
||||
*
|
||||
@@ -1851,8 +2204,8 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));]]></file>
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.browse.js" javascript_type="template" javascript_version="5000074" javascript_position="1000050">// Empty</file>
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.submit.js" javascript_type="template" javascript_version="5000074" javascript_position="1000050"><![CDATA[ips.templates.set('gallery.submit.imageItem', " \
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.browse.js" javascript_type="template" javascript_version="5001302" javascript_position="1000050">// Empty</file>
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.submit.js" javascript_type="template" javascript_version="5001302" javascript_position="1000050"><![CDATA[ips.templates.set('gallery.submit.imageItem', " \
|
||||
<div class='ipsAttach ipsImageAttach {{#done}}ipsAttach_done{{/done}}' id='{{id}}' data-role='file' data-fileid='{{id}}' data-fullsizeurl='{{imagesrc}}' data-thumbnailurl='{{thumbnail}}' data-isImage='1'>\
|
||||
<ul class='ipsImageAttach_controls'>\
|
||||
<li data-role='insert' {{#insertable}}style='display: none'{{/insertable}}><a href='#' data-action='insertFile' class='ipsAttach_selection' data-ipsTooltip title='{{#lang}}insertIntoPost{{/lang}}'><i class='fa-solid fa-plus'></i></a></li>\
|
||||
@@ -1879,7 +2232,7 @@
|
||||
ips.templates.set('gallery.submit.imageItemWrapper', " \
|
||||
<div class='cGallerySubmit_fileList'>{{{content}}}</div>\
|
||||
");]]></file>
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.view.js" javascript_type="template" javascript_version="5000074" javascript_position="1000050"><![CDATA[ips.templates.set('gallery.notes.wrapper', " \
|
||||
<file javascript_app="gallery" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.view.js" javascript_type="template" javascript_version="5001302" javascript_position="1000050"><![CDATA[ips.templates.set('gallery.notes.wrapper', " \
|
||||
<div class='cGalleryNote' data-controller='gallery.front.view.note' data-noteID='{{id}}' data-note=\"{{note}}\" {{#editable}}data-editable{{/editable}} data-posLeft='{{left}}' data-posTop='{{top}}' data-dimWidth='{{width}}' data-dimHeight='{{height}}'>\
|
||||
<div class='cGalleryNote_border'></div>\
|
||||
<div class='cGalleryNote_note' style='display: none'>\
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<language>
|
||||
<app key="gallery" version="5000074">
|
||||
<app key="gallery" version="5001302">
|
||||
<word key="__app_gallery" js="0">Gallery</word>
|
||||
<word key="frontnavigation_gallery" js="0">Gallery</word>
|
||||
<word key="gallery_title" js="0">Gallery</word>
|
||||
@@ -261,6 +261,12 @@
|
||||
<word key="cleaning_up_gallery_images" js="0">Cleaning up Gallery images </word>
|
||||
<word key="gallery_maps_default" js="0">Enable maps by default</word>
|
||||
<word key="gallery_maps_default_desc" js="0">Users can choose whether or not to show a map next to images that have geolocation data embedded into the image. This option controls whether those maps are enabled by default or not, however users can override this preference while submitting their images.</word>
|
||||
<word key="gallery_metadata_none" js="0">Hide all image metadata</word>
|
||||
<word key="gallery_metadata_sensitive" js="0">Hide sensitive metadata</word>
|
||||
<word key="gallery_metadata_sensitive_desc" js="0">Hides sensitive details, such as GPS geolocation data from images taken with mobile phones</word>
|
||||
<word key="gallery_metadata_all" js="0">Show all image metadata</word>
|
||||
<word key="gallery_metadata_desc_gd" js="0"><![CDATA[<strong>Note:</strong> All EXIF data is stripped from the image file itself and stored separately. The above setting determines what metadata will be visible to other users.]]></word>
|
||||
<word key="gallery_metadata_desc_imagick" js="0"><![CDATA[<strong>Note:</strong> EXIF data is stripped from the image file based on <a href='{internal.admin.app=core&module=overview&controller=files&do=imagesettings&searchResult=imagick_strip_exif}'>your image settings</a>. The above setting determines what metadata will be visible to other users.]]></word>
|
||||
<word key="member__gallery_Images" js="0">Gallery</word>
|
||||
<word key="remove_gallery_access" js="0">Allowed to access gallery?</word>
|
||||
<word key="remove_gallery_upload" js="0">Allowed to upload images?</word>
|
||||
@@ -523,6 +529,7 @@
|
||||
<word key="block_albums" js="0">Album Feed</word>
|
||||
<word key="block_albums_desc" js="0">Create a listing of albums</word>
|
||||
<word key="widget_feed_container_gallery_album" js="0">Category</word>
|
||||
<word key="widget_feed_album_empty" js="0">Include empty albums</word>
|
||||
<word key="profile_gallery_album" js="0">Albums</word>
|
||||
<word key="gallery_category_id" js="0">Category</word>
|
||||
<word key="profile_gallery_gallery" js="0">Albums</word>
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
"default": "0",
|
||||
"report": "full"
|
||||
},
|
||||
{
|
||||
"key": "gallery_metadata",
|
||||
"default": "1",
|
||||
"report": "none"
|
||||
},
|
||||
{
|
||||
"key": "gallery_new_images_count",
|
||||
"default": "16",
|
||||
|
||||
+714
-614
File diff suppressed because it is too large.
Load diff
@@ -348,5 +348,54 @@
|
||||
"5000071": "5.0.6 Beta 2",
|
||||
"5000072": "5.0.6 Beta 3",
|
||||
"5000073": "5.0.6 Beta 4",
|
||||
"5000074": "5.0.6"
|
||||
"5000074": "5.0.6",
|
||||
"5000075": "5.0.7 Beta 1",
|
||||
"5000076": "5.0.7 Beta 2",
|
||||
"5000077": "5.0.7 Beta 2",
|
||||
"5000078": "5.0.7 Beta 3",
|
||||
"5000079": "5.0.7 Beta 4",
|
||||
"5000080": "5.0.7",
|
||||
"5000081": "5.0.7",
|
||||
"5000082": "5.0.7",
|
||||
"5000800": "5.0.8 Alpha 1",
|
||||
"5000801": "5.0.8 Alpha 2",
|
||||
"5000802": "5.0.8 Beta 1",
|
||||
"5000803": "5.0.8 Beta 2",
|
||||
"5000804": "5.0.8 Beta 3",
|
||||
"5000805": "5.0.8",
|
||||
"5000900": "5.0.9 Beta 1",
|
||||
"5000901": "5.0.9 Beta 1",
|
||||
"5000902": "5.0.9 Beta 1",
|
||||
"5000903": "5.0.9 Beta 2",
|
||||
"5000904": "5.0.9",
|
||||
"5000905": "5.0.9",
|
||||
"5000906": "5.0.10 Beta 1",
|
||||
"5000907": "5.0.10 Beta 1",
|
||||
"5000908": "5.0.10 Beta 1",
|
||||
"5000909": "5.0.10 Beta 1",
|
||||
"5000910": "5.0.10 Beta 2",
|
||||
"5000911": "5.0.10 Beta 3",
|
||||
"5000912": "5.0.10 Beta 4",
|
||||
"5000913": "5.0.10 Beta 4",
|
||||
"5000914": "5.0.10",
|
||||
"5000915": "5.0.10",
|
||||
"5000916": "5.0.10",
|
||||
"5000917": "5.0.10",
|
||||
"5000918": "5.0.10",
|
||||
"5000919": "5.0.10",
|
||||
"5000920": "5.0.10",
|
||||
"5001100": "5.0.11 Beta 1",
|
||||
"5001101": "5.0.11 Beta 1",
|
||||
"5001102": "5.0.11 Beta 2",
|
||||
"5001103": "5.0.11",
|
||||
"5001104": "5.0.11",
|
||||
"5001105": "5.0.11",
|
||||
"5001200": "5.0.12 Beta 1",
|
||||
"5001201": "5.0.12 Beta 2",
|
||||
"5001202": "5.0.12 Beta 3",
|
||||
"5001203": "5.0.12",
|
||||
"5001204": "5.0.12",
|
||||
"5001300": "5.0.13 Beta 1",
|
||||
"5001301": "5.0.13 Beta 2",
|
||||
"5001302": "5.0.13"
|
||||
}
|
||||
Reference in new issue
Block a user