Release v1.0.0rc1
Some checks failed
CI / Checks (push) Has been cancelled

This commit is contained in:
2025-08-18 07:09:27 +02:00
commit d909391ee6
383 changed files with 22792 additions and 0 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,38 @@
/*!
* HotPocket by BTHLabs (https://hotpocket.app/)
* Copyright 2025-present by BTHLabs. All rights reserved.
* Licensed under BTHLabs Source Available License Agreement
*/
((HotPocket) => {
class HotPocketHTMXConfirmPlugin {
constructor (app) {
this.app = app;
}
onLoad = (event) => {
document.addEventListener('htmx:confirm', this.onHTMXConfirm);
};
onHTMXConfirm = (event) => {
if (!event.detail.question) {
return;
}
event.preventDefault();
const modal = this.app.plugin('UI.Modal')({
triggerElement: event.detail.elt,
confirm: true,
onHide: (action) => {
if (action === 'confirm') {
event.detail.issueRequest(true);
}
},
});
modal.show();
};
}
HotPocket.addPlugin('htmx.confirm', (app) => {
return new HotPocketHTMXConfirmPlugin(app);
});
})(window.HotPocket);

View File

@@ -0,0 +1,18 @@
/*!
* HotPocket by BTHLabs (https://hotpocket.app/)
* Copyright 2025-present by BTHLabs. All rights reserved.
* Licensed under BTHLabs Source Available License Agreement
*/
((HotPocket, htmx) => {
class HotPocketHTMXPlugin {
constructor (app) {
if (app.options.debug) {
htmx.logAll();
}
}
}
window.HotPocket.addPlugin('htmx', (app) => {
return new HotPocketHTMXPlugin(app);
});
})(window.HotPocket, window.htmx);

View File

@@ -0,0 +1,66 @@
/*!
* HotPocket by BTHLabs (https://hotpocket.app/)
* Copyright 2025-present by BTHLabs. All rights reserved. (https://bthlabs.pl/)
* Licensed under BTHLabs Source Available License Agreement
*
* Because I'm too stubborn to use React, LOL
*/
(() => {
const DEFAULT_OPTIONS = {
debug: false,
};
class HotPocketApp {
constructor (options) {
this.plugins = [];
this.options = {
...DEFAULT_OPTIONS,
...options,
}
}
initPlugins = (plugins) => {
for (let pluginSpec of plugins) {
const [name, pluginFactory] = pluginSpec;
this.plugins.push([name, pluginFactory(this)]);
}
}
plugin = (name) => {
const pluginSpec = this.plugins.find((pluginSpec) => {
return pluginSpec[0] === name;
});
if (pluginSpec !== undefined) {
return pluginSpec[1];
}
return null;
}
onLoad = (event) => {
console.log('HotPocketApp.onLoad()', event);
for (let pluginSpec of this.plugins) {
if (pluginSpec[1].onLoad) {
pluginSpec[1].onLoad(event);
}
}
}
}
const plugins = [];
window.HotPocket = {
app: null,
addPlugin: (name, pluginFactory) => {
plugins.push([name, pluginFactory]);
},
run: (options) => {
if (window.HotPocket.app === null) {
window.HotPocket.app = new HotPocketApp(options);
window.HotPocket.app.initPlugins(plugins);
document.addEventListener('DOMContentLoaded', (event) => {
window.HotPocket.app.onLoad(event);
});
}
}
};
})();

View File

@@ -0,0 +1,33 @@
/*!
* HotPocket by BTHLabs (https://hotpocket.app/)
* Copyright 2025-present by BTHLabs. All rights reserved.
* Licensed under BTHLabs Source Available License Agreement
*/
((HotPocket, htmx) => {
class BrowseSavesView {
constructor (app) {
this.app = app;
}
onLoad = (event) => {
document.addEventListener('HotPocket:BrowseSavesView:updateLoadMoreButton', (event) => {
const button = document.querySelector('#BrowseSavesView .ui-load-more-button');
if (button) {
if (event.detail.next_url) {
button.setAttribute('hx-get', event.detail.next_url);
button.classList.remove('disable');
button.removeAttribute('disabled', true);
} else {
button.classList.add('disable');
button.setAttribute('disabled', true);
}
htmx.process('#BrowseSavesView .ui-load-more-button');
}
});
};
}
HotPocket.addPlugin('UI.BrowseSavesView', (app) => {
return new BrowseSavesView(app);
});
})(window.HotPocket, window.htmx);

View File

@@ -0,0 +1,28 @@
/*!
* HotPocket by BTHLabs (https://hotpocket.app/)
* Copyright 2025-present by BTHLabs. All rights reserved.
* Licensed under BTHLabs Source Available License Agreement
*/
((HotPocket) => {
class HotPocketUIFormPlugin {
constructor (app) {
}
onLoad (event) {
for (let cancelButton of document.querySelectorAll('.ui-form-cancel-button')) {
cancelButton.addEventListener('click', this.onCancelButtonClick);
}
}
onCancelButtonClick = (event) => {
event.stopPropagation();
event.preventDefault();
window.history.back();
return false;
};
}
HotPocket.addPlugin('UI.Form', (app) => {
return new HotPocketUIFormPlugin(app);
});
})(window.HotPocket);

View File

@@ -0,0 +1,52 @@
/*!
* HotPocket by BTHLabs (https://hotpocket.app/)
* Copyright 2025-present by BTHLabs. All rights reserved.
* Licensed under BTHLabs Source Available License Agreement
*/
((HotPocket, bootstrap) => {
const LEVEL_TO_BOOTSTRAP_CLASS = {
'debug': 'alert-secondary',
'info': 'alert-info',
'success': 'alert-success',
'warning': 'alert-warning',
'error': 'alert-danger',
};
class HotPocketUIMessagesPlugin {
constructor (app) {
this.containerElement = null;
this.templateElement = null;
}
onLoad = (event) => {
this.containerElement = document.querySelector('.ui-messages');
this.templateElement = document.querySelector('#Messages-Alert');
for (let element of this.containerElement.querySelectorAll('.alert')) {
element.classList.add('alert-dismissible');
element.classList.add('fade');
element.classList.add('show');
new bootstrap.Alert(element);
}
document.addEventListener('HotPocket:UI:Messages:addMessage', this.onAddMessage);
};
onAddMessage = (event) => {
const alertContentElement = this.templateElement.content.cloneNode(true);
const alertElement = alertContentElement.querySelector('.alert');
alertElement.classList.add(LEVEL_TO_BOOTSTRAP_CLASS[event.detail.level] || 'alert-secondary');
if (event.detail.extra_tags) {
alertElement.classList.add(event.detail.extra_tags);
}
alertElement.querySelector('.ui-alert-message').innerHTML = event.detail.message;
new bootstrap.Alert(alertElement);
this.containerElement.appendChild(alertContentElement);
};
}
HotPocket.addPlugin('UI.Messages', (app) => {
return new HotPocketUIMessagesPlugin(app);
});
})(window.HotPocket, window.bootstrap);

View File

@@ -0,0 +1,78 @@
/*!
* HotPocket by BTHLabs (https://hotpocket.app/)
* Copyright 2025-present by BTHLabs. All rights reserved.
* Licensed under BTHLabs Source Available License Agreement
*/
((HotPocket, bootstrap) => {
const DEFAULT_OPTIONS = {
triggerElement: null,
confirm: false,
onHide: () => {},
};
class HotPocketModal {
constructor (app, options) {
this.app = app;
this.options = {
...DEFAULT_OPTIONS,
...options,
};
this.action = 'dismiss';
this.triggerElement = this.options.triggerElement;
if (options.confirm === false) {
this.triggerElement.addEventListener('click', this.onTriggerElementClick);
}
this.templateElement = document.querySelector(
this.triggerElement.dataset.uiModal,
);
this.modalElement = null;
this.modal = null;
this.triggerElement.HotPocketModal = this;
}
show = () => {
this.modalElement = this.templateElement.content.cloneNode(true).querySelector('.modal');
this.modalElement.querySelector('[data-ui-modal-action]').addEventListener(
'click', this.onActionClick,
);
this.modalElement.addEventListener('hidden.bs.modal', this.onModalHidden);
this.modal = new bootstrap.Modal(this.modalElement);
document.body.appendChild(this.modalElement);
this.modal.show();
};
onTriggerElementClick = (event) => {
event.preventDefault();
this.show();
return false;
};
onActionClick = (event) => {
this.action = event.target.dataset['uiModalAction'];
this.modal.hide();
};
onModalHidden = (event) => {
document.body.removeChild(this.modalElement);
this.modal = null;
this.modalElement = null;
this.options.onHide(this.action);
};
};
HotPocket.addPlugin('UI.Modal', (app) => {
return (options) => {
return new HotPocketModal(app, options);
};
});
})(window.HotPocket, window.bootstrap);

View File

@@ -0,0 +1,66 @@
/*!
* HotPocket by BTHLabs (https://hotpocket.app/)
* Copyright 2025-present by BTHLabs. All rights reserved.
* Licensed under BTHLabs Source Available License Agreement
*/
((HotPocket) => {
class ViewAssociationView {
constructor (app) {
this.app = app;
this.onWindowResizeTimeout = null;
}
clearOnWindowResizeTimeout () {
if (this.onWindowResizeTimeout) {
window.clearTimeout(this.onWindowResizeTimeout);
this.onWindowResizeTimeout = null;
}
}
onLoad = (event) => {
document.addEventListener('HotPocket:ViewAssociationView:loadEmbed', this.onWindowResize);
window.addEventListener('resize', (event) => {
this.clearOnWindowResizeTimeout();
this.onWindowResizeTimeout = window.setTimeout(
this.onWindowResize, 300,
);
});
this.onWindowResize();
for (let shareButton of document.querySelectorAll('#ViewAssociationView .ui-share-button')) {
if (navigator.share) {
shareButton.addEventListener('click', this.onShareButtonClick);
} else {
shareButton.addClass('d-none');
}
}
};
onWindowResize = (event) => {
const widthReference = document.querySelector('#ViewAssociationView .ui-width-reference');
const youtubeIFrame = document.querySelector('#ViewAssociationView .ui-youtube-iframe');
if (youtubeIFrame) {
const width = widthReference.offsetWidth - 8;
const height = Math.ceil(width / 1.6);
youtubeIFrame.setAttribute('width', width);
youtubeIFrame.setAttribute('height', height);
}
};
onShareButtonClick = (event) => {
event.preventDefault();
const shareUrl = new URL(window.location.href);
shareUrl.searchParams.set('share', 'true');
navigator.share({
title: document.title,
url: shareUrl.toString(),
});
return false;
};
}
HotPocket.addPlugin('UI.ViewAssociationView', (app) => {
return new ViewAssociationView(app);
});
})(window.HotPocket);

View File

@@ -0,0 +1,22 @@
/*!
* HotPocket by BTHLabs (https://hotpocket.app/)
* Copyright 2025-present by BTHLabs. All rights reserved.
* Licensed under BTHLabs Source Available License Agreement
*/
((HotPocket) => {
class HotPocketUIPlugin {
constructor (app) {
document.body.classList.add('ui-js-enabled');
if (window.navigator.standalone === true) {
document.querySelector('body').classList.add('ui-mode-standalone');
} else {
document.querySelector('body').classList.remove('ui-mode-standalone');
}
}
}
HotPocket.addPlugin('UI', (app) => {
return new HotPocketUIPlugin(app);
});
})(window.HotPocket);

File diff suppressed because one or more lines are too long