mirror of
https://github.com/simstudioai/sim.git
synced 2026-08-30 17:05:18 +08:00
49a3399dd2
* fix(ui): unify branded error pages * fix(desktop): match canonical chip chrome * test(ui): update error chip mock * fix(desktop): package offline font reliably
237 lines
8.8 KiB
HTML
237 lines
8.8 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta
|
||
http-equiv="Content-Security-Policy"
|
||
content="default-src 'none'; font-src 'self'; style-src 'unsafe-inline'; script-src 'unsafe-inline'"
|
||
/>
|
||
<title>Sim - Can’t connect</title>
|
||
<style>
|
||
@font-face {
|
||
font-family: 'Season Sans';
|
||
src:
|
||
url('../../sim/public/brand/fonts/SeasonSansUprightsVF.woff2') format('woff2'),
|
||
url('./SeasonSansUprightsVF.woff2') format('woff2');
|
||
font-style: normal;
|
||
font-weight: 300 800;
|
||
font-display: block;
|
||
}
|
||
:root {
|
||
color-scheme: light;
|
||
--bg: #fefefe;
|
||
--text-primary: #1a1a1a;
|
||
--text-body: #434343;
|
||
--text-muted: #7a7a7a;
|
||
--text-inverse: #ffffff;
|
||
--surface-hover: #f2f2f2;
|
||
}
|
||
* {
|
||
box-sizing: border-box;
|
||
}
|
||
html,
|
||
body {
|
||
height: 100%;
|
||
margin: 0;
|
||
}
|
||
body {
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-width: 320px;
|
||
padding-top: max(env(titlebar-area-height, 38px), 38px);
|
||
background: var(--bg);
|
||
color: var(--text-primary);
|
||
font-family: 'Season Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||
-webkit-font-smoothing: antialiased;
|
||
user-select: none;
|
||
}
|
||
header {
|
||
flex: none;
|
||
width: 100%;
|
||
max-width: 1460px;
|
||
margin: 0 auto;
|
||
padding: 16px 80px;
|
||
-webkit-app-region: drag;
|
||
}
|
||
.wordmark {
|
||
display: block;
|
||
width: 37px;
|
||
height: 18px;
|
||
margin: 6px 0;
|
||
color: var(--text-body);
|
||
}
|
||
main {
|
||
display: flex;
|
||
flex: 1;
|
||
width: 100%;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0 16px 64px;
|
||
}
|
||
.content {
|
||
display: flex;
|
||
width: 100%;
|
||
max-width: 410px;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 12px;
|
||
text-align: center;
|
||
}
|
||
h1 {
|
||
max-width: 100%;
|
||
margin: 0;
|
||
font-size: 40px;
|
||
font-weight: 400;
|
||
letter-spacing: -0.02em;
|
||
line-height: 1.1;
|
||
text-wrap: balance;
|
||
}
|
||
p {
|
||
max-width: 100%;
|
||
margin: 0;
|
||
color: var(--text-muted);
|
||
font-size: 18px;
|
||
line-height: 28px;
|
||
}
|
||
.actions {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
justify-content: center;
|
||
margin-top: 12px;
|
||
}
|
||
button {
|
||
display: inline-flex;
|
||
height: 30px;
|
||
align-items: center;
|
||
gap: 6px;
|
||
appearance: none;
|
||
border: 0;
|
||
background: transparent;
|
||
color: var(--text-body);
|
||
border-radius: 8px;
|
||
padding: 0 8px;
|
||
font: inherit;
|
||
font-size: 14px;
|
||
line-height: 20px;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
outline: none;
|
||
transition:
|
||
color 150ms cubic-bezier(0.4, 0, 0.2, 1),
|
||
background-color 150ms cubic-bezier(0.4, 0, 0.2, 1),
|
||
border-color 150ms cubic-bezier(0.4, 0, 0.2, 1),
|
||
text-decoration-color 150ms cubic-bezier(0.4, 0, 0.2, 1),
|
||
fill 150ms cubic-bezier(0.4, 0, 0.2, 1),
|
||
stroke 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
||
-webkit-app-region: no-drag;
|
||
}
|
||
button .label {
|
||
min-width: 0;
|
||
flex: 1;
|
||
overflow: hidden;
|
||
color: currentColor;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
button.primary {
|
||
background: var(--text-primary);
|
||
color: var(--text-inverse);
|
||
}
|
||
@media (hover: hover) and (pointer: fine) {
|
||
button.primary:hover {
|
||
background: var(--text-body);
|
||
}
|
||
button.secondary:hover {
|
||
background: var(--surface-hover);
|
||
}
|
||
}
|
||
#detail {
|
||
min-height: 17px;
|
||
margin-top: 4px;
|
||
color: var(--text-muted);
|
||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||
font-size: 11px;
|
||
line-height: 1.5;
|
||
}
|
||
@media (max-width: 720px) {
|
||
header {
|
||
padding-right: 32px;
|
||
padding-left: 32px;
|
||
}
|
||
}
|
||
@media (max-width: 480px) {
|
||
header {
|
||
padding-right: 20px;
|
||
padding-left: 20px;
|
||
}
|
||
h1 {
|
||
font-size: 34px;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<header aria-label="Sim">
|
||
<svg class="wordmark" viewBox="0 0 441 212" role="img" aria-label="Sim">
|
||
<g fill="currentColor">
|
||
<path d="M0 160.9H29.51C29.51 169.08 32.46 175.61 38.37 180.48C44.27 185.12 52.25 187.44 62.31 187.44C73.24 187.44 81.65 185.34 87.56 181.14C93.46 176.71 96.41 170.85 96.41 163.55C96.41 158.24 94.77 153.82 91.49 150.28C88.43 146.74 82.75 143.86 74.44 141.65L46.24 135.01C32.03 131.47 21.42 126.05 14.43 118.75C7.65 111.45 4.26 101.83 4.26 89.88C4.26 79.93 6.78 71.3 11.81 64C17.05 56.7 24.16 51.06 33.12 47.08C42.3 43.09 52.8 41.1 64.6 41.1C76.41 41.1 86.57 43.2 95.1 47.41C103.84 51.61 110.62 57.47 115.43 64.99C120.46 72.52 123.08 81.48 123.3 91.87H93.79C93.57 83.47 90.84 76.94 85.59 72.3C80.34 67.65 73.02 65.33 63.62 65.33C54 65.33 46.57 67.43 41.32 71.63C36.07 75.83 33.45 81.59 33.45 88.89C33.45 99.73 41.32 107.14 57.06 111.12L85.26 118.09C98.81 121.19 108.98 126.28 115.76 133.35C122.53 140.21 125.92 149.61 125.92 161.56C125.92 171.74 123.19 180.7 117.73 188.44C112.26 195.96 104.72 201.82 95.1 206.03C85.7 210.01 74.55 212 61.65 212C42.85 212 27.87 207.35 16.72 198.06C5.57 188.77 0 176.38 0 160.9Z" />
|
||
<path d="M232.8 212H202.13L202.13 49.76H229.54V77.39C232.8 68.34 239.11 60.66 247.81 54.7C256.73 48.52 267.5 45.43 280.12 45.43C294.26 45.43 306.01 49.29 315.36 57.02C324.72 64.75 330.81 75.01 333.64 87.82H328.09C330.27 75.01 336.25 64.75 346.04 57.02C355.83 49.29 367.9 45.43 382.26 45.43C400.54 45.43 414.89 50.84 425.34 61.66C435.78 72.47 441 87.26 441 106.03V212H410.98V113.65C410.98 100.84 407.71 91.02 401.19 84.17C394.88 77.11 386.29 73.58 375.41 73.58C367.79 73.58 361.05 75.34 355.17 78.88C349.52 82.19 345.06 87.04 341.8 93.45C338.53 99.85 336.9 107.36 336.9 115.97V212H306.55V113.32C306.55 100.51 303.4 90.8 297.09 84.17C290.78 77.33 282.19 73.91 271.31 73.91C263.69 73.91 256.95 75.67 251.08 79.21C245.42 82.52 240.96 87.38 237.7 93.78C234.43 99.96 232.8 107.36 232.8 115.97V212Z" />
|
||
<path d="M184.83 20.55C184.83 31.9 175.64 41.1 164.29 41.1C152.95 41.1 143.76 31.9 143.76 20.55C143.76 9.2 152.95 0 164.29 0C175.64 0 184.83 9.2 184.83 20.55Z" />
|
||
<path d="M179.43 212H149.16V49.76C153.76 51.91 158.88 53.12 164.29 53.12C169.7 53.12 174.83 51.91 179.43 49.76V212Z" />
|
||
</g>
|
||
</svg>
|
||
</header>
|
||
<main>
|
||
<div class="content">
|
||
<h1 id="title">Can’t connect to Sim</h1>
|
||
<p id="message">
|
||
Sim couldn’t reach the server. Check your internet connection, then try again.
|
||
</p>
|
||
<div class="actions">
|
||
<button class="primary" id="retry"><span class="label">Retry</span></button>
|
||
<button class="secondary" id="status"><span class="label">Check status</span></button>
|
||
</div>
|
||
<div id="detail" role="status"></div>
|
||
</div>
|
||
</main>
|
||
<script>
|
||
const params = new URLSearchParams(location.search)
|
||
const copy = {
|
||
offline: {
|
||
title: 'You’re offline',
|
||
message: 'Sim needs an internet connection. Reconnect, then try again. We’ll also retry automatically.',
|
||
},
|
||
dns: {
|
||
title: 'Can’t find the server',
|
||
message: 'The server address couldn’t be resolved. Check your connection or the configured server.',
|
||
},
|
||
tls: {
|
||
title: 'Connection isn’t secure',
|
||
message: 'The server’s TLS certificate couldn’t be verified, so the connection was refused.',
|
||
},
|
||
timeout: {
|
||
title: 'The server isn’t responding',
|
||
message: 'The connection timed out. The server may be down or your network may be blocking it.',
|
||
},
|
||
unreachable: {
|
||
title: 'Can’t connect to Sim',
|
||
message: 'Sim couldn’t reach the server. Check your internet connection, then try again.',
|
||
},
|
||
}
|
||
const kind = params.get('kind') || 'unreachable'
|
||
const chosen = copy[kind] || copy.unreachable
|
||
document.getElementById('title').textContent = chosen.title
|
||
document.getElementById('message').textContent = chosen.message
|
||
const detail = params.get('detail')
|
||
if (detail) document.getElementById('detail').textContent = detail
|
||
|
||
const bridge = window.simDesktop
|
||
document.getElementById('retry').addEventListener('click', () => bridge?.offlineRetry())
|
||
document
|
||
.getElementById('status')
|
||
.addEventListener('click', () => bridge?.openExternal('https://status.sim.ai'))
|
||
</script>
|
||
</body>
|
||
</html>
|