This commit is contained in:
2026-05-11 08:27:44 +02:00
parent ab5a0c7697
commit 8261a281c4
96 changed files with 271838 additions and 778 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 413 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -248,6 +248,8 @@ var TONE_PRESETS = [
{name:'Stille Post', notes:[{f:784,d:.4}], wave:'sine', vol:.08},
];
var empfangPracticeInfoCache = null;
function parseQs() {
var p = new URLSearchParams(window.location.search);
mode = (p.get('mode') || 'general').toLowerCase() === 'dm' ? 'dm' : 'general';
@@ -294,6 +296,7 @@ async function loadPracticeSubline() {
var r = await fetch(API_BASE + '/practice/info', { credentials: 'include' });
if (!r.ok) return;
var d = await r.json();
empfangPracticeInfoCache = d;
var el = document.getElementById('hdr-practice-sub');
if (!el) return;
var pname = String(d.practice_name || '').trim() || 'Praxis-Chat';
@@ -445,34 +448,135 @@ function conversationAudienceParam() {
return '';
}
var AZA_DEFAULT_PRACTICE_TZ = 'Europe/Zurich';
function empfangChatTimeZoneId() {
try {
var d = empfangPracticeInfoCache;
var tz = d && String(d.practice_timezone || d.timezone || '').trim();
if (tz) return tz;
} catch (e) {}
return AZA_DEFAULT_PRACTICE_TZ;
}
function parseEmpfangChatInstantMs(raw) {
var s = String(raw || '').trim();
if (!s) return NaN;
var norm = s.replace(' ', 'T');
var hasTz = norm.indexOf('Z') >= 0 || /[+\-]\d{2}:\d{2}$/.test(norm);
if (hasTz) {
var tzParsed = Date.parse(norm);
return isFinite(tzParsed) ? tzParsed : NaN;
}
var m = s.match(/^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}(?::\d{2})?)/);
if (m) {
var u = Date.parse(m[1] + 'T' + m[2] + 'Z');
if (isFinite(u)) return u;
}
var fb = Date.parse(norm);
return isFinite(fb) ? fb : NaN;
}
function formatEmpfangChatClockFromMs(ms) {
if (!isFinite(ms)) return '';
try {
return new Intl.DateTimeFormat('de-CH', {
timeZone: empfangChatTimeZoneId(),
hour: '2-digit',
minute: '2-digit',
hour12: false
}).format(new Date(ms));
} catch (e) {
var d = new Date(ms);
var h = d.getHours();
var mi = d.getMinutes();
return (h < 10 ? '0' : '') + h + ':' + (mi < 10 ? '0' : '') + mi;
}
}
function formatMessengerDayKeyFromMs(ms) {
if (!isFinite(ms)) return '';
try {
var parts = new Intl.DateTimeFormat('en-CA', {
timeZone: empfangChatTimeZoneId(),
year: 'numeric',
month: '2-digit',
day: '2-digit'
}).formatToParts(new Date(ms));
var y = '';
var mo = '';
var da = '';
for (var ip = 0; ip < parts.length; ip++) {
var p = parts[ip];
if (p.type === 'year') y = p.value;
if (p.type === 'month') mo = p.value;
if (p.type === 'day') da = p.value;
}
if (y && mo && da) return y + '-' + mo + '-' + da;
} catch (e) {}
return '';
}
function formatEmpfangChatDateTimeLong(raw) {
var ms = parseEmpfangChatInstantMs(raw);
if (!isFinite(ms)) return String(raw || '');
try {
return new Intl.DateTimeFormat('de-CH', {
timeZone: empfangChatTimeZoneId(),
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false
}).format(new Date(ms));
} catch (e) {
return String(raw || '');
}
}
function conversationSortChrono(msgs) {
return msgs.slice().sort(function(a, b) {
return (a.empfangen || a.zeitstempel || '').localeCompare(b.empfangen || b.zeitstempel || '');
var sa = a.empfangen || a.zeitstempel || '';
var sb = b.empfangen || b.zeitstempel || '';
var ta = parseEmpfangChatInstantMs(sa);
var tb = parseEmpfangChatInstantMs(sb);
if (isFinite(ta) && isFinite(tb) && ta !== tb) return ta - tb;
return sa.localeCompare(sb);
});
}
function conversationDayKey(iso) {
var raw = String(iso || '').replace(' ', 'T');
var d = Date.parse(raw);
if (!isFinite(d)) return '';
var dt = new Date(d);
var y = dt.getFullYear(), mo = dt.getMonth() + 1, da = dt.getDate();
return y + '-' + (mo < 10 ? '0' : '') + mo + '-' + (da < 10 ? '0' : '') + da;
return formatMessengerDayKeyFromMs(parseEmpfangChatInstantMs(iso));
}
function conversationDateLabel(iso) {
var raw = String(iso || '').replace(' ', 'T');
var d = Date.parse(raw);
if (!isFinite(d)) return '';
var msgDate = new Date(d);
var today = new Date();
today.setHours(0, 0, 0, 0);
var dd = new Date(msgDate);
dd.setHours(0, 0, 0, 0);
var diffDays = Math.round((today.getTime() - dd.getTime()) / 86400000);
if (diffDays === 0) return 'Heute';
if (diffDays === 1) return 'Gestern';
return msgDate.getDate() + '.' + (msgDate.getMonth() + 1) + '.' + msgDate.getFullYear();
var ms = parseEmpfangChatInstantMs(iso);
if (!isFinite(ms)) return '';
var msgKey = formatMessengerDayKeyFromMs(ms);
var todayKey = formatMessengerDayKeyFromMs(Date.now());
if (msgKey === todayKey) return 'Heute';
var yestKey = formatMessengerDayKeyFromMs(Date.now() - 86400000);
if (msgKey === yestKey) return 'Gestern';
try {
var parts = new Intl.DateTimeFormat('de-CH', {
timeZone: empfangChatTimeZoneId(),
day: 'numeric',
month: 'numeric',
year: 'numeric'
}).formatToParts(new Date(ms));
var da = '';
var mo = '';
var ye = '';
for (var ip = 0; ip < parts.length; ip++) {
var p = parts[ip];
if (p.type === 'day') da = p.value;
if (p.type === 'month') mo = p.value;
if (p.type === 'year') ye = p.value;
}
if (da && mo && ye) return da + '.' + mo + '.' + ye;
} catch (e) {}
return '';
}
function conversationAnchorLastId() {
@@ -518,7 +622,6 @@ async function doSend() {
kommentar: text || (pendingAttach.length ? '\u200b' : ''),
patient: mode === 'dm' && peerName ? ('Direkt: ' + peerName) : patientLine(),
absender: currentSession.display_name + ' (Empfang)',
zeitstempel: new Date().toISOString().slice(0, 19).replace('T', ' '),
extras: extras
};
@@ -567,7 +670,7 @@ function renderOne(m, isMe) {
var meta = document.createElement('div');
meta.className = 'meta';
var core = (m.absender || '').split('(')[0].trim();
meta.textContent = core + ' · ' + (m.zeitstempel || m.empfangen || '');
meta.textContent = core + ' · ' + formatEmpfangChatDateTimeLong(m.zeitstempel || m.empfangen || '');
div.appendChild(meta);
var body = messageBodyLines(m);
if (body) {