183 lines
7.3 KiB
JavaScript
183 lines
7.3 KiB
JavaScript
window.App = window.App || {};
|
|
App.storage = App.storage || {};
|
|
App.session = App.session || {};
|
|
|
|
(function() {
|
|
const { FAVORITES_KEY, FAVORITES_VISIBILITY_KEY } = App.constants;
|
|
|
|
// Basic localStorage helpers.
|
|
App.storage.getConfig = function() {
|
|
return JSON.parse(localStorage.getItem('config')) || { servers: [] };
|
|
};
|
|
|
|
App.storage.setConfig = function(nextConfig) {
|
|
localStorage.setItem('config', JSON.stringify(nextConfig));
|
|
};
|
|
|
|
App.storage.getSession = function() {
|
|
return JSON.parse(localStorage.getItem('session')) || null;
|
|
};
|
|
|
|
App.storage.setSession = function(nextSession) {
|
|
localStorage.setItem('session', JSON.stringify(nextSession));
|
|
};
|
|
|
|
App.storage.getPreferences = function() {
|
|
return JSON.parse(localStorage.getItem('preferences')) || {};
|
|
};
|
|
|
|
App.storage.setPreferences = function(nextPreferences) {
|
|
localStorage.setItem('preferences', JSON.stringify(nextPreferences));
|
|
};
|
|
|
|
App.storage.getServerEntries = function() {
|
|
const config = App.storage.getConfig();
|
|
if (!config.servers || !Array.isArray(config.servers)) return [];
|
|
return config.servers.map((serverObj) => {
|
|
const server = Object.keys(serverObj)[0];
|
|
return {
|
|
url: server,
|
|
data: serverObj[server] || null
|
|
};
|
|
});
|
|
};
|
|
|
|
// Options/session helpers that power channel selection and filters.
|
|
App.session.serializeOptions = function(options) {
|
|
const serialized = {};
|
|
Object.entries(options || {}).forEach(([key, value]) => {
|
|
if (Array.isArray(value)) {
|
|
serialized[key] = value.map((entry) => entry.id);
|
|
} else if (value && value.id) {
|
|
serialized[key] = value.id;
|
|
}
|
|
});
|
|
return serialized;
|
|
};
|
|
|
|
App.session.hydrateOptions = function(channel, savedOptions) {
|
|
const hydrated = {};
|
|
if (!channel || !Array.isArray(channel.options)) return hydrated;
|
|
const saved = savedOptions || {};
|
|
channel.options.forEach((optionGroup) => {
|
|
const allOptions = optionGroup.options || [];
|
|
const savedValue = saved[optionGroup.id];
|
|
if (optionGroup.multiSelect) {
|
|
const selectedIds = Array.isArray(savedValue) ? savedValue : [];
|
|
const selected = allOptions.filter((opt) => selectedIds.includes(opt.id));
|
|
hydrated[optionGroup.id] = selected.length > 0 ? selected : allOptions.slice(0, 1);
|
|
} else {
|
|
const selected = allOptions.find((opt) => opt.id === savedValue) || allOptions[0];
|
|
if (selected) hydrated[optionGroup.id] = selected;
|
|
}
|
|
});
|
|
return hydrated;
|
|
};
|
|
|
|
App.session.savePreference = function(session) {
|
|
if (!session || !session.server || !session.channel) return;
|
|
const prefs = App.storage.getPreferences();
|
|
const serverPrefs = prefs[session.server] || {};
|
|
serverPrefs.channelId = session.channel.id;
|
|
serverPrefs.optionsByChannel = serverPrefs.optionsByChannel || {};
|
|
serverPrefs.optionsByChannel[session.channel.id] = App.session.serializeOptions(session.options);
|
|
prefs[session.server] = serverPrefs;
|
|
App.storage.setPreferences(prefs);
|
|
};
|
|
|
|
App.session.buildDefaultOptions = function(channel) {
|
|
const selected = {};
|
|
if (!channel || !Array.isArray(channel.options)) return selected;
|
|
channel.options.forEach((optionGroup) => {
|
|
if (!optionGroup.options || optionGroup.options.length === 0) return;
|
|
if (optionGroup.multiSelect) {
|
|
selected[optionGroup.id] = [optionGroup.options[0]];
|
|
} else {
|
|
selected[optionGroup.id] = optionGroup.options[0];
|
|
}
|
|
});
|
|
return selected;
|
|
};
|
|
|
|
// Ensures defaults exist and refreshes server status.
|
|
App.storage.ensureDefaults = async function() {
|
|
if (!localStorage.getItem('config')) {
|
|
localStorage.setItem('config', JSON.stringify({
|
|
servers: [
|
|
{ "https://getfigleaf.com": {} },
|
|
{ "https://hottubapp.io": {} },
|
|
{ "https://hottub.spacemoehre.de": {} }
|
|
]
|
|
}));
|
|
}
|
|
if (!localStorage.getItem('theme')) {
|
|
localStorage.setItem('theme', 'dark');
|
|
}
|
|
if (!localStorage.getItem(FAVORITES_KEY)) {
|
|
localStorage.setItem(FAVORITES_KEY, JSON.stringify([]));
|
|
}
|
|
if (!localStorage.getItem(FAVORITES_VISIBILITY_KEY)) {
|
|
localStorage.setItem(FAVORITES_VISIBILITY_KEY, 'true');
|
|
}
|
|
await App.storage.initializeServerStatus();
|
|
};
|
|
|
|
// Fetches server status and keeps the session pointing to a valid channel/options.
|
|
App.storage.initializeServerStatus = async function() {
|
|
const config = JSON.parse(localStorage.getItem('config'));
|
|
if (!config || !config.servers) return;
|
|
|
|
const statusPromises = config.servers.map(async (serverObj) => {
|
|
const server = Object.keys(serverObj)[0];
|
|
try {
|
|
const response = await fetch(`/api/status`, {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
server: server
|
|
}),
|
|
headers: {
|
|
"Content-Type": "application/json"
|
|
},
|
|
});
|
|
const status = await response.json();
|
|
serverObj[server] = status;
|
|
} catch (err) {
|
|
serverObj[server] = {
|
|
online: false,
|
|
channels: []
|
|
};
|
|
}
|
|
});
|
|
|
|
await Promise.all(statusPromises);
|
|
localStorage.setItem('config', JSON.stringify(config));
|
|
|
|
const existingSession = App.storage.getSession();
|
|
const serverKeys = config.servers.map((serverObj) => Object.keys(serverObj)[0]);
|
|
if (serverKeys.length === 0) return;
|
|
const selectedServerKey = existingSession && serverKeys.includes(existingSession.server)
|
|
? existingSession.server
|
|
: serverKeys[0];
|
|
const serverEntry = config.servers.find((serverObj) => Object.keys(serverObj)[0] === selectedServerKey);
|
|
const serverData = serverEntry ? serverEntry[selectedServerKey] : null;
|
|
|
|
if (serverData && serverData.channels && serverData.channels.length > 0) {
|
|
const prefs = App.storage.getPreferences();
|
|
const serverPrefs = prefs[selectedServerKey] || {};
|
|
const preferredChannelId = serverPrefs.channelId;
|
|
const channel = serverData.channels.find((ch) => ch.id === preferredChannelId) || serverData.channels[0];
|
|
const savedOptions = serverPrefs.optionsByChannel ? serverPrefs.optionsByChannel[channel.id] : null;
|
|
const options = savedOptions ? App.session.hydrateOptions(channel, savedOptions) : App.session.buildDefaultOptions(channel);
|
|
|
|
const sessionData = {
|
|
server: selectedServerKey,
|
|
channel: channel,
|
|
options: options,
|
|
};
|
|
|
|
App.storage.setSession(sessionData);
|
|
App.session.savePreference(sessionData);
|
|
}
|
|
};
|
|
})();
|