Files
m8chat-app2/web/index.html
help4bis b95471b0b4 feat: Phase 3 — E2EE calls, Jitsi conferencing, help tab, web security model
- LiveKit call E2EE: CallE2EEManager exchanges encryption keys via Matrix
  to-device events (m.rtc.encryption_keys) for interop with Element X
- Olm bootstrapped in index.html before Flutter init; main.dart logs result
- Encrypted messages shown with lock icon and informative fallback text
- Profile screen: key restore dialog + security setup (cross-signing/backup)
- Jitsi feature: welcome screen (public, no login), conference tab, full-screen
  embed via JitsiMeetExternalAPI, JitsiLink parser for all common link formats
- Help tab: expandable cards for encryption, video calls, account management
- Web security model: no session persistence — device ID only across visits
- Media auth: MSC3916 authenticated endpoint for avatars (Synapse 1.120+)
- Router: welcome route as public landing page; jitsi route as public
- Manifest/index.html: M8Chat branding, dark theme colours

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 05:28:14 +10:00

92 lines
3.4 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<!--
If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from.
The path provided below has to start and end with a slash "/" in order for
it to work correctly.
For more details:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
This is a placeholder for base href that will be replaced by the value of
the `--base-href` argument provided to `flutter build`.
-->
<base href="$FLUTTER_BASE_HREF">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="M8Chat — secure chat and conferencing.">
<!-- iOS meta tags & icons -->
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="M8Chat">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>
<title>M8Chat</title>
<link rel="manifest" href="manifest.json">
</head>
<body>
<!--
Olm WASM must fully initialise before Flutter boots — the Matrix SDK calls
Olm.init() synchronously at startup and crashes if the global isn't ready.
Strategy: load olm.js synchronously, await Olm.init(), THEN inject
flutter_bootstrap.js dynamically so Flutter never starts before Olm.
-->
<script>
// Unregister any stale service worker from previous builds — cached old JS
// causes calls and features to use outdated code silently.
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistrations().then(function(registrations) {
for (var r of registrations) { r.unregister(); }
});
}
</script>
<!--
Olm (E2EE): load olm.js synchronously, await Olm.init() for WASM, THEN
inject flutter_bootstrap.js so the Matrix SDK finds global Olm ready.
If Olm fails to load (e.g. WASM blocked by browser), Flutter boots anyway
without encryption — unencrypted rooms still work.
-->
<script src="olm.js"></script>
<script>
(function() {
function bootFlutter() {
var s = document.createElement('script');
s.src = 'flutter_bootstrap.js';
s.async = true;
document.body.appendChild(s);
}
// Ensure Olm is accessible on both window and globalThis.
// dart2js may resolve bare 'Olm' via different global references.
if (typeof Olm !== 'undefined') {
window.Olm = Olm;
if (typeof globalThis !== 'undefined') globalThis.Olm = Olm;
if (typeof self !== 'undefined') self.Olm = Olm;
}
if (typeof Olm !== 'undefined' && Olm.init) {
console.log('[M8Chat] Olm.js loaded, calling Olm.init()...');
Olm.init().then(function() {
console.log('[M8Chat] Olm.init() SUCCESS — E2EE available');
console.log('[M8Chat] window.Olm =', window.Olm);
console.log('[M8Chat] typeof Olm.Account =', typeof Olm.Account);
bootFlutter();
}).catch(function(e) {
console.warn('[M8Chat] Olm init FAILED, booting without E2EE:', e);
bootFlutter();
});
} else {
console.warn('[M8Chat] olm.js did NOT load — typeof Olm =', typeof Olm);
bootFlutter();
}
})();
</script>
</body>
</html>