if(!remote.getGlobal('darwin')) {
let dragger = document.getElementById('dragger')
if(dragger !== null) {
dragger.remove()
}
}
//:::: GLOBAL FUNCTIONS ::::\\
function signout() {
remote.getGlobal('disconnect')()
}
function openDonate() {
remote.getGlobal('openExternal')('https://buymeacoff.ee/CodingBobby')
}
// TODO: Reloading should only fetch latest changes without reloading the html
function reload() {
remote.getGlobal('loadDashboard')()
}
function debugLog(...args) {
remote.getGlobal('debugLog').apply(null, args)
}
//:::: HELPERS ::::\\
// inserts an element before another one
function insertBefore(element, reference) {
reference.parentNode.insertBefore(element, reference)
}
// adds multiple css styles to an element, example:
// styles: { display: 'block', backgroundColor: 'red' }
function css(element, styles) {
for(let property in styles) {
// just a security check
if({}.hasOwnProperty.call(styles, property)) {
element.style[property] = styles[property]
}
}
}
// returns a random item from a given array
function pick(array) {
return array[Math.floor(Math.random() * array.length)]
}
// works as Array.prototype.length
function getObjectLength(obj) {
let len = 0
for(let item in obj) {
if(obj.hasOwnProperty(item)) {
len++
}
}
return len
}
// returns array of object's key-value pairs
function objectToArray(obj) {
let arr = []
for(let item in obj) {
arr.push({
name: item,
content: obj[item]
})
}
return arr
}
// This handy function allows to delay recursive actions. The taken arguments are explained below
function delayFunction(
callback, // function that contains whatever you want, takes an index and an optional array
delay, // the time to wait between iterations in ms
itemCount, // the maximum count
arrayToPass=[], // optional array you want to process
terminateAtIndex=itemCount, // optional index after which the callback is not delayed anymore, can be used when having many out-of-view items where the delay would stack up otherwise
current=0 // current iteration index, only used by the function itself
) {
if(itemCount-current > 0) {
callback(current, arrayToPass)
if(current >= terminateAtIndex) {
debugLog('delay', 'terminated')
delay = 0
}
setTimeout(() => {
delayFunction(callback, delay, itemCount, arrayToPass, terminateAtIndex, current+1)
}, delay)
}
}
function loadImage(parent, src, loadingSrc) {
let loading_img = document.createElement('img')
loading_img.src = '../../assets/'+loadingSrc
parent.appendChild(loading_img)
let img = document.createElement('img')
img.src = src
img.onload = function() {
setTimeout(() => {
parent.removeChild(loading_img)
parent.appendChild(img)
}, 7*33.3) // some extra animation and framerate buffer
}
}
/**
* This function can be called whenever you want to place an image element into some HTML context. It first shows a loading animation but as soon as the requested image is ready, it will take the placeholder's place.
* @param {object} options
* @param {HTMLElement} options.parent dom element the image should be appended to
* @param {'poster'} options.use in what type of element the image will be used
* @param {'season'} options.type type the item belongs to
* @param {number} options.itemId tvdb id of the item
* @param {any} options.reference some reference we can use
* @param {object} options.attributes additional attributes, only the final image should get
* @param {string[]} options.classes CSS classes the final image should have
* @param {Function} onLoad callback to execute after loading is fully complete
*/
async function requestAndLoadImage(options, onLoad) {
// placeholder element
let loading_img = document.createElement('img')
// the actual image, the placeholder will be updated to
let img = document.createElement('img')
switch(options.use) {
case 'poster': {
loading_img.src = '../../assets/loading_placeholder.gif'
options.parent.appendChild(loading_img)
switch(options.type) {
case 'season': {
img.src = await getSeasonPoster(options.itemId, options.reference)
break
}
}
break
}
}
// adding properties to the final image
if(options.classes) img.classList = options.classes.join(' ')
for(let name in options.attributes) {
if(options.attributes.hasOwnProperty(name)) {
img.setAttribute(name, options.attributes[name])
}
}
// after desired image is preloaded whilst remaining invisible
img.onload = function() {
options.parent.appendChild(img)
options.parent.removeChild(loading_img)
setTimeout(() => {
// ensures that the callback is definitely fired after the images are visible
onLoad()
}, 250)
}
img.onerror = function(event) {
// event does not contain error codes wtf
debugLog('error', `loading image from ${img.src}`)
img.src = '../../assets/'+config.client.placeholder.poster
options.parent.appendChild(img)
options.parent.removeChild(loading_img)
setTimeout(() => {
onLoad()
}, 250)
}
}
/**
* Highlights the passed element.
* It does this by giving the element the 'selected' class and removing it from all siblings.
* @param {HTMLElement} child
*/
function show(child) {
let par = child.parentElement.parentElement;
[...par.children].forEach(element => {
if(element.children[0] === child) {
child.classList.add('selected')
} else {
element.children[0].classList.remove('selected')
}
})
}
/**
* Adds class to element if it doesn't have it already, otherwise removes it.
* @param {HTMLElement} child Target element
*/
function toggleClass(child, cssClass) {
if(child.classList.contains(cssClass)) {
child.classList.remove(cssClass)
} else {
child.classList.add(cssClass)
}
}