updates
This commit is contained in:
@@ -1405,6 +1405,14 @@ h1 {
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
}
|
||||
|
||||
.tray-menu-copy {
|
||||
margin: 0;
|
||||
padding: 6px 4px 2px;
|
||||
color: #cbd5e1;
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.window-content p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ if (payloadNode) {
|
||||
const startMenuUserAvatar = document.getElementById('start-menu-user-avatar');
|
||||
const startMenuSessionAction = document.getElementById('start-menu-session-action');
|
||||
const accountMenu = document.getElementById('tray-account-menu');
|
||||
const fxTrayMenu = document.getElementById('tray-fx-menu');
|
||||
const fxTrayStatusNode = document.getElementById('tray-fx-status');
|
||||
const clockNode = document.getElementById('clock');
|
||||
const clockTopNode = document.getElementById('clock-top');
|
||||
const debugToggleNode = document.getElementById('debug-toggle');
|
||||
@@ -389,6 +391,88 @@ if (payloadNode) {
|
||||
accountButton.setAttribute('aria-expanded', String(isOpen));
|
||||
};
|
||||
|
||||
const setFxTrayMenuOpen = (isOpen) => {
|
||||
const fxButton = document.querySelector('.tray-pill[data-tray-app-id="fx-rates"]');
|
||||
|
||||
if (!(fxTrayMenu instanceof HTMLElement) || !(fxButton instanceof HTMLElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fxTrayMenu.hidden = !isOpen;
|
||||
fxButton.setAttribute('aria-expanded', String(isOpen));
|
||||
};
|
||||
|
||||
const loadFxTrayStatus = async () => {
|
||||
const fxButton = document.querySelector('.tray-pill[data-tray-app-id="fx-rates"]');
|
||||
|
||||
if (!(fxTrayStatusNode instanceof HTMLElement) || !(fxButton instanceof HTMLElement)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
fxTrayStatusNode.textContent = 'Kursstatus wird geladen ...';
|
||||
fxButton.setAttribute('title', 'Kursstatus wird geladen ...');
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/fx-rates/index.php?path=v1/status', {
|
||||
credentials: 'same-origin',
|
||||
headers: { Accept: 'application/json' },
|
||||
});
|
||||
const payload = await response.json().catch(() => ({}));
|
||||
const rows = Array.isArray(payload?.data) ? payload.data : [];
|
||||
const latest = rows.slice().sort((left, right) => {
|
||||
const leftTs = new Date(left?.fetched_at || 0).getTime();
|
||||
const rightTs = new Date(right?.fetched_at || 0).getTime();
|
||||
return rightTs - leftTs;
|
||||
})[0] || null;
|
||||
const statusText = latest
|
||||
? `Letzter Abruf: ${latest.fetched_at_display || latest.fetched_at} · ${latest.base_currency} · ${latest.provider}`
|
||||
: 'Noch keine gespeicherten Kurse vorhanden.';
|
||||
|
||||
fxTrayStatusNode.textContent = statusText;
|
||||
fxButton.setAttribute('title', statusText);
|
||||
return latest;
|
||||
} catch (_error) {
|
||||
const errorText = 'Kursstatus konnte nicht geladen werden.';
|
||||
fxTrayStatusNode.textContent = errorText;
|
||||
fxButton.setAttribute('title', errorText);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const runFxTrayRefresh = async (force) => {
|
||||
if (!(fxTrayStatusNode instanceof HTMLElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fxTrayStatusNode.textContent = 'Aktualisierung laeuft ...';
|
||||
try {
|
||||
const response = await fetch('/api/fx-rates/index.php?path=v1/refresh', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
force: force === true,
|
||||
trigger_source: 'tray',
|
||||
}),
|
||||
});
|
||||
const payload = await response.json().catch(() => ({}));
|
||||
if (!response.ok) {
|
||||
throw new Error(payload?.context?.message || payload?.error || `HTTP ${response.status}`);
|
||||
}
|
||||
|
||||
const result = payload?.data || {};
|
||||
fxTrayStatusNode.textContent = result.reused
|
||||
? 'Kein neuer API-Abruf. Snapshot ist noch jung genug.'
|
||||
: `Kurse aktualisiert. ${result.updated_count || 0} Werte gespeichert.`;
|
||||
await loadFxTrayStatus();
|
||||
} catch (error) {
|
||||
fxTrayStatusNode.textContent = error instanceof Error ? error.message : 'Aktualisierung fehlgeschlagen.';
|
||||
}
|
||||
};
|
||||
|
||||
const findAppById = (appId) => payload.apps.find((app) => app.app_id === appId) || null;
|
||||
|
||||
const dispatchUserSettingsUpdate = (detail) => {
|
||||
@@ -1711,12 +1795,17 @@ if (payloadNode) {
|
||||
if (!(event.target instanceof Element) || !event.target.closest('.tray-pill[data-tray-id="account"], #tray-account-menu')) {
|
||||
setAccountMenuOpen(false);
|
||||
}
|
||||
|
||||
if (!(event.target instanceof Element) || !event.target.closest('.tray-pill[data-tray-app-id="fx-rates"], #tray-fx-menu')) {
|
||||
setFxTrayMenuOpen(false);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Escape') {
|
||||
closeDesktopContextMenu();
|
||||
setAccountMenuOpen(false);
|
||||
setFxTrayMenuOpen(false);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1729,6 +1818,7 @@ if (payloadNode) {
|
||||
const isClosed = startMenu.hasAttribute('hidden');
|
||||
setStartMenuOpen(isClosed);
|
||||
setAccountMenuOpen(false);
|
||||
setFxTrayMenuOpen(false);
|
||||
});
|
||||
|
||||
document.querySelector('.tray-pill[data-tray-id="account"]')?.addEventListener('click', () => {
|
||||
@@ -1738,20 +1828,50 @@ if (payloadNode) {
|
||||
|
||||
setStartMenuOpen(false);
|
||||
setAccountMenuOpen(accountMenu.hidden);
|
||||
setFxTrayMenuOpen(false);
|
||||
});
|
||||
|
||||
document.querySelectorAll('.tray-pill[data-tray-app-id]').forEach((button) => {
|
||||
button.addEventListener('click', () => {
|
||||
const appId = button.getAttribute('data-tray-app-id') || '';
|
||||
if (appId === 'fx-rates') {
|
||||
setStartMenuOpen(false);
|
||||
setAccountMenuOpen(false);
|
||||
setFxTrayMenuOpen(fxTrayMenu instanceof HTMLElement ? fxTrayMenu.hidden : false);
|
||||
void loadFxTrayStatus();
|
||||
return;
|
||||
}
|
||||
const app = findAppById(appId);
|
||||
if (app) {
|
||||
openApp(app);
|
||||
setStartMenuOpen(false);
|
||||
setAccountMenuOpen(false);
|
||||
setFxTrayMenuOpen(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
fxTrayMenu?.addEventListener('click', (event) => {
|
||||
const target = event.target instanceof Element ? event.target.closest('[data-fx-action]') : null;
|
||||
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
|
||||
const action = target.getAttribute('data-fx-action');
|
||||
|
||||
if (action === 'refresh') {
|
||||
void runFxTrayRefresh(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (action === 'force-refresh') {
|
||||
void runFxTrayRefresh(true);
|
||||
}
|
||||
});
|
||||
|
||||
void loadFxTrayStatus();
|
||||
|
||||
debugToggleNode?.addEventListener('click', () => {
|
||||
toggleDebugWindow();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user