1<!doctype html> 2<html lang="en"> 3 <head> 4 <meta charset="UTF-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 <meta name="theme-color" content="#EBD3BC" /> 7 <meta name="description" content="MyChara is a service for publishing an AI Chara setup as a creative work and then talking with that Chara. This page explains who creates the public material, where AI is used, anâ¦" /> 8 <meta name="msvalidate.01" content="18CB8C6BC3D06889BA248A82DC9AF1F6" /> 9 <meta name="mobile-web-app-capable" content="yes" /> 10 <meta name="apple-mobile-web-app-capable" content="yes" /> 11 <meta name="apple-mobile-web-app-status-bar-style" content="default" /> 12 <meta name="apple-mobile-web-app-title" content="MyChara" /> 13 <title>AI Chara creation and conversation on MyChara â MyChara</title> 14 15
15<script> 16 (() => { 17 const devHosts = { 18 main: 'dev.mychara.ai', 19 plans: 'dev.plans.mychara.ai', 20 charge: 'dev.charge.mychara.ai', 21 planPayment: 'dev.plan-payment.mychara.ai', 22 chargePayment: 'dev.charge-payment.mychara.ai', 23 }; 24 const prodHosts = { 25 main: 'mychara.ai', 26 plans: 'plans.mychara.ai', 27 charge: 'charge.mychara.ai', 28 planPayment: 'plan-payment.mychara.ai', 29 chargePayment: 'charge-payment.mychara.ai', 30 }; 31 const billingOnlyDevHosts = [ 32 devHosts.plans, 33 devHosts.charge, 34 devHosts.planPayment, 35 devHosts.chargePayment, 36 ]; 37 const billingOnlyProdHosts = [ 38 prodHosts.plans, 39 prodHosts.charge, 40 prodHosts.planPayment, 41 prodHosts.chargePayment, 42 ]; 43 const hosts = billingOnlyDevHosts.includes(location.hostname) 44 ? devHosts 45 : billingOnlyProdHosts.includes(location.hostname) 46 ? prodHosts 47 : null; 48 49 if (hosts === null || location.pathname === '/') return; 50 51 const url = new URL(location.href); 52 url.port = ''; 53 54 if (location.pathname === '/plans') { 55 url.hostname = hosts.plans; 56 url.pathname = '/'; 57 } else if (location.pathname === '/charge') { 58 url.hostname = hosts.charge; 59 url.pathname = '/'; 60 } else if (location.pathname === '/billing/plan-payment') { 61 url.hostname = hosts.planPayment; 62 url.pathname = '/'; 63 } else if (location.pathname === '/billing/charge-payment') { 64 url.hostname = hosts.chargePayment; 65 url.pathname = '/'; 66 } else { 67 url.hostname = hosts.main; 68 } 69 70 location.replace(url); 71 })(); 72 </script>
72 73 74 <!-- 75 Warm up TLS to the API origin before the SPA bundle parses and 76 issues its first /api/charas fetch. Saves ~200-400 ms on 77 cold mobile networks where DNS + TLS is the long pole. `crossorigin` 78 is required because API calls send credentials (cookies). Failure 79 is silent â preconnect is a hint, not a load. 80 --> 81 <link rel="preconnect" href="https://api.mychara.ai" crossorigin /> 82 <link rel="dns-prefetch" href="https://api.mychara.ai" /> 83 84 <link rel="icon" href="/favicon.ico" sizes="any" /> 85 <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png" /> 86 <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" /> 87 <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" /> 88 <link rel="apple-touch-icon-precomposed" sizes="180x180" href="/apple-touch-icon.png" /> 89 <link rel="manifest" href="/manifest.webmanifest" /> 90 <link rel="canonical" href="https://mychara.ai/about" /> 91 <style> 92 html, 93 body, 94 #root { 95 margin: 0; 96 min-height: 100%; 97 } 98 99 body { 100 background: #0a0f12; 101 } 102 103 .app-startup-loading { 104 min-height: 100vh; 105 min-height: 100dvh; 106 display: grid; 107 place-items: start center; 108 padding: max(24px, env(safe-area-inset-top)) 24px max(24px, env(safe-area-inset-bottom)); 109 box-sizing: border-box; 110 color: #f8fafc; 111 background: #0a0f12; 112 font-family: 113 -apple-system, BlinkMacSystemFont, 'Hiragino Kaku Gothic ProN', 'Hiragino Sans', 114 'Noto Sans JP', 'Yu Gothic Medium', 'Segoe UI', system-ui, sans-serif; 115 } 116 117 .app-startup-loading *, 118 .app-startup-loading *::before, 119 .app-startup-loading *::after { 120 box-sizing: border-box; 121 } 122 123 .app-startup-loading__content { 124 display: flex; 125 flex-direction: column; 126 align-items: center; 127 gap: 16px; 128 width: min(100%, 760px); 129 padding-top: clamp(32px, 8vh, 64px); 130 } 131 132 .app-startup-loading__brand { 133 display: inline-flex; 134 align-items: center; 135 gap: 10px; 136 color: #f8fafc; 137 font-size: 20px; 138 font-weight: 700; 139 line-height: 1; 140 letter-spacing: 0; 141 } 142 143 .app-startup-loading__logo { 144 width: 36px; 145 height: 36px; 146 flex: 0 0 auto; 147 } 148 149 .app-startup-loading__wordmark { 150 transform: translateY(1px); 151 } 152 153 .app-startup-loading__spinner { 154 width: 40px; 155 height: 40px; 156 border: 3px solid rgba(255, 255, 255, 0.14); 157 border-top-color: #10b981; 158 border-radius: 50%; 159 animation: app-startup-spin 0.8s linear infinite; 160 } 161 162 .app-startup-loading__message { 163 margin: 0; 164 color: #a7b4bd; 165 font-size: 14px; 166 font-weight: 600; 167 line-height: 1.4; 168 letter-spacing: 0; 169 } 170 171 .app-startup-loading__recovery { 172 display: flex; 173 flex-direction: column; 174 align-items: center; 175 gap: 12px; 176 width: min(100%, 440px); 177 text-align: center; 178 } 179 180 .app-startup-loading__recovery[hidden], 181 .app-startup-loading__spinner[hidden] { 182 display: none; 183 } 184 185 .app-startup-loading__retry { 186 display: inline-flex; 187 min-height: 44px; 188 align-items: center; 189 justify-content: center; 190 border: 0; 191 border-radius: 8px; 192 padding: 10px 28px; 193 background: #10b981; 194 color: #07120e; 195 font-size: 14px; 196 font-weight: 800; 197 text-decoration: none; 198 } 199 200 .app-startup-loading__external-hint { 201 margin: 0; 202 color: #a7b4bd; 203 font-size: 13px; 204 line-height: 1.7; 205 } 206 207 .app-startup-loading__copy { 208 appearance: none; 209 border: 0; 210 padding: 8px 12px; 211 background: transparent; 212 color: #86efac; 213 font-size: 13px; 214 font-weight: 700; 215 text-decoration: underline; 216 text-underline-offset: 3px; 217 } 218 219 .app-crawlable-content { 220 width: 100%; 221 margin-top: 4px; 222 color: #d9e5ea; 223 text-align: left; 224 font-size: 14px; 225 line-height: 1.75; 226 } 227 228 .app-crawlable-content__article { 229 width: 100%; 230 } 231 232 .app-crawlable-content__eyebrow { 233 margin: 0 0 4px; 234 color: #86efac; 235 font-size: 12px; 236 font-weight: 800; 237 letter-spacing: 0; 238 } 239 240 .app-crawlable-content h1 { 241 margin: 0 0 10px; 242 color: #f8fafc; 243 font-size: 20px; 244 font-weight: 800; 245 line-height: 1.35; 246 letter-spacing: 0; 247 } 248 249 .app-crawlable-content p { 250 margin: 8px 0 0; 251 } 252 253 .app-crawlable-content ul { 254 margin: 12px 0 0; 255 padding-left: 1.25em; 256 } 257 258 .app-crawlable-content li + li { 259 margin-top: 4px; 260 } 261 262 .app-crawlable-content__links { 263 display: flex; 264 flex-wrap: wrap; 265 gap: 8px 12px; 266 padding-left: 0; 267 list-style: none; 268 } 269 270 .app-crawlable-content__links a { 271 color: #86efac; 272 font-weight: 700; 273 text-decoration-thickness: 1px; 274 text-underline-offset: 3px; 275 } 276 277 @keyframes app-startup-spin { 278 to { 279 transform: rotate(360deg); 280 } 281 } 282 283 @media (prefers-reduced-motion: reduce) { 284 .app-startup-loading__spinner { 285 animation: none; 286 border-color: rgba(255, 255, 255, 0.14); 287 border-top-color: #10b981; 288 } 289 } 290 </style> 291 292 <!-- 293 Default Open Graph / Twitter Card tags. Per-page tags for 294 /chara/:id and /users/:userId are rewritten at the edge by 295 the Cloudflare Pages Functions under `functions/` â those tags 296 override these defaults for crawlers that don't execute JS 297 (Facebook, X, LINE, Discord, Slack, etc.). 298 --> 299 <meta property="og:type" content="website" /> 300 <meta property="og:site_name" content="MyChara" /> 301 <meta property="og:locale" content="ja_JP" /> 302 <meta property="og:title" content="AI Chara creation and conversation on MyChara â MyChara" /> 303 <meta property="og:description" content="MyChara is a service for publishing an AI Chara setup as a creative work and then talking with that Chara. This page explains who creates the public material, where AI is used, anâ¦" /> 304 <meta property="og:url" content="https://mychara.ai/about" /> 305 <meta property="og:image" content="https://mychara.ai/ogp-default.png" />
306 <meta property="og:image:width" content="1200" /> 307 <meta property="og:image:height" content="630" /> 308 <meta property="og:image:alt" content="MyChara" /> 309 <meta name="twitter:card" content="summary_large_image" /> 310 <meta name="twitter:site" content="@MyCharaAI" /> 311 <meta name="twitter:title" content="AI Chara creation and conversation on MyChara â MyChara" /> 312 <meta name="twitter:description" content="MyChara is a service for publishing an AI Chara setup as a creative work and then talking with that Chara. This page explains who creates the public material, where AI is used, anâ¦" /> 313 <meta name="twitter:image" content="https://mychara.ai/ogp-default.png" /> 314 315 <!-- 316 JSON-LD: Organization + WebSite. Helps Google understand the 317 site identity and surface the sitelinks search box once the 318 domain has reputation. Per-page Person / ProfilePage records 319 are injected by the Pages Functions for /chara/:id and 320 /users/:userId. 321 --> 322
322<script type="application/ld+json"> 323 { 324 "@context": "https://schema.org", 325 "@graph": [ 326 { 327 "@type": "Organization", 328 "@id": "https://mychara.ai/#org", 329 "name": "MyChara", 330 "url": "https://mychara.ai", 331 "logo": "https://mychara.ai/logo-512.png", 332 "sameAs": ["https://x.com/MyCharaAI"] 333 }, 334 { 335 "@type": "WebSite", 336 "@id": "https://mychara.ai/#site", 337 "url": "https://mychara.ai", 338 "name": "MyChara", 339 "publisher": { "@id": "https://mychara.ai/#org" }, 340 "inLanguage": "ja", 341 "potentialAction": { 342 "@type": "SearchAction", 343 "target": { 344 "@type": "EntryPoint", 345 "urlTemplate": "https://mychara.ai/search?q={search_term_string}" 346 }, 347 "query-input": "required name=search_term_string" 348 } 349 } 350 ] 351 } 352 </script>
352 353 354 <!-- AdSense site verification / Auto ads loader. --> 355
355<script 356 async 357 src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8347367683271780" 358 crossorigin="anonymous" 359 ></script>
359 360
360<script id="app-main-module" onload="window.__MYCHARA_BOOT__ && window.__MYCHARA_BOOT__.mark('app_boot_module_loaded')" onerror="window.__MYCHARA_BOOT__ && window.__MYCHARA_BOOT__.fail('app_boot_module_error', { error_kind: 'main_module_resource_error' })" type="module" crossorigin src="/assets/index-B04v8a-s.js"></script>
360 361 </head> 362 <body> 363 <div id="root"> 364 <div 365 class="app-startup-loading" 366 role="status" 367 aria-live="polite" 368 aria-busy="true" 369 aria-label="Loading" 370 > 371 <div class="app-startup-loading__content"> 372 <span class="app-startup-loading__brand" aria-hidden="true"> 373 <svg 374 class="app-startup-loading__logo" 375 viewBox="0 0 32 32" 376 xmlns="http://www.w3.org/2000/svg" 377 focusable="false" 378 > 379 <circle cx="16" cy="16" r="14" fill="#10b981"></circle> 380 <path 381 d="M10 13 Q10 10 13 10 L19 10 Q22 10 22 13 L22 17 Q22 20 19 20 L14 20 L10 23 Z" 382 fill="#0a0f12" 383 ></path> 384 <circle cx="14" cy="15" r="1.3" fill="#ffffff"></circle> 385 <circle cx="18" cy="15" r="1.3" fill="#ffffff"></circle> 386 </svg> 387 <span class="app-startup-loading__wordmark">MyChara</span> 388 </span> 389 <span class="app-startup-loading__spinner" aria-hidden="true"></span> 390 <p class="app-startup-loading__message">Fetching dataâ¦</p> 391 <div class="app-startup-loading__recovery" hidden> 392 <a class="app-startup-loading__retry" href="">å試è¡</a> 393 <p class="app-startup-loading__external-hint"> 394 Xã¢ããªå ã§ç¹°ãè¿ã失æããå ´åã¯ãå³ä¸ã®ã¡ãã¥ã¼ããSafariã¾ãã¯Chromeã§éãã¦ãã ããã 395 </p> 396 <button class="app-startup-loading__copy" type="button">ç¾å¨ã®URLãã³ãã¼</button> 397 </div> 398 <section id="app-crawlable-content" class="app-crawlable-content" aria-label="About MyChara"><article class="app-crawlable-content__article"> 399 <p class="app-crawlable-content__eyebrow">About MyChara</p> 400 <h1>AI Chara creation and conversation on MyChara</h1> 401 <p>MyChara is a service for publishing an AI Chara setup as a creative work and then talking with that Chara. This page explains who creates the public material, where AI is used, and what the operator provides.</p> 402<p>What the service is for</p> 403<p>MyChara is built around reading a setup before choosing to talk. A public Chara page carries a name, introduction, basic setting, main Chara profile, opening message, and tags, so a reader can understand the scene and relationship before starting a conversation.</p> 404<p>Public pages can be read without signing in. An account adds saved conversations and creation tools for Charas, voices, replays, and world settings. Every post can be public, unlisted, invite-only, or private.</p> 405<p>Who creates public material</p> 406<p>The name, description, setup, opening message, images, and tags on a public Chara are created and published by its author. MyChara provides the publishing and reading system; the operator does not create every Chara. Except for anonymous posts, public pages link back to the author.</p> 407<p>Published material can be edited later, and its visibility can also be changed. Public pages are designed to show the information that a conversation depends on before the reader decides to begin.</p> 408<p>Where AI is used</p> 409<p>The setup and opening message shown on a public page are material saved and published by the author. After a conversation starts, AI generates replies from that setup, the opening message, and the userâs messages. The same Chara can respond differently as the conversation changes.</p> 410<p>AI replies are for creative conversation, not a replacement for fact-checking or professional judgement. MyChara treats reading a published setup and reading generated conversation as distinct activities.</p> 411<p>Operator and contact</p> 412<p>MyChara is operated by MyChara Inc. Service behaviour, pricing, and the handling of posted material are described on the public pages, in the terms of use, the privacy policy, and the legal information page.</p> 413<p>Questions about faults, rights, or public material can be sent to <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cbb8bebbbba4b9bf8ba6b2a8a3aab9aae5aaa2">[email protected]</a>.</p> 414 415 <nav aria-label="Links to public pages"> 416 <ul class="app-crawlable-content__links"> 417 <li><a href="/guides/create">
417AI Chara creation guide</a></li> 418 <li><a href="/">Home</a></li> 419 <li><a href="/terms">Terms of Service</a></li> 420 <li><a href="/privacy">Privacy Policy</a></li> 421 </ul> 422 </nav> 423 </article></section> 424 </div> 425 </div> 426 </div>
vendor: 113 bytes, lines 426-427
426 427 <script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>
427<script id="app-boot-monitor"> 428 (function () { 429 var API_URL = 'https://api.mychara.ai/api/product-analytics/events'; 430 var TIMEOUT_MS = 9000; 431 var ALLOWED_PARAMS = [ 432 'utm_source', 433 'utm_medium', 434 'utm_campaign', 435 'utm_term', 436 'utm_content', 437 'mc_test', 438 'mc_entry', 439 'mc_lang', 440 'mc_gender', 441 'mc_chara', 442 'from', 443 'type', 444 'kenzen', 445 ]; 446 var COPY = { 447 ja: { 448 failed: 'èªã¿è¾¼ã¿ã«å¤±æãã¾ãã', 449 retry: 'å試è¡', 450 retrying: 'å試è¡ãã¦ãã¾ãâ¦', 451 hint: 'Xã¢ããªå ã§ç¹°ãè¿ã失æããå ´åã¯ãå³ä¸ã®ã¡ãã¥ã¼ããSafariã¾ãã¯Chromeã§éãã¦ãã ããã', 452 copy: 'ç¾å¨ã®URLãã³ãã¼', 453 copied: 'URLãã³ãã¼ãã¾ãã', 454 }, 455 en: { 456 failed: 'Failed to load this page', 457 retry: 'Try again', 458 retrying: 'Trying againâ¦', 459 hint: 'If this keeps failing inside X, use the top-right menu to open the page in Safari or Chrome.', 460 copy: 'Copy current URL', 461 copied: 'URL copied', 462 }, 463 'zh-CN': { 464 failed: '页é¢å 载失败', 465 retry: 'éè¯', 466 retrying: 'æ£å¨éè¯â¦', 467 hint: 'å¦æå¨ X åºç¨å åå¤å¤±è´¥ï¼è¯·ä»å³ä¸è§èåä½¿ç¨ Safari æ Chrome æå¼ã', 468 copy: 'å¤å¶å½åç½å', 469 copied: 'ç½åå·²å¤å¶', 470 }, 471 'zh-TW': { 472 failed: 'é é¢è¼å ¥å¤±æ', 473 retry: 'é試', 474 retrying: 'æ£å¨é試â¦', 475 hint: 'å¦æå¨ X æç¨ç¨å¼å §åè¦å¤±æï¼è«å¾å³ä¸è§é¸å®ä½¿ç¨ Safari æ Chrome éåã', 476 copy: 'è¤è£½ç®åç¶²å', 477 copied: 'ç¶²åå·²è¤è£½', 478 }, 479 ko: { 480 failed: 'íì´ì§ë¥¼ ë¶ë¬ì¤ì§ 못íìµëë¤', 481 retry: 'ë¤ì ìë', 482 retrying: 'ë¤ì ìëíë ì¤â¦', 483 hint: 'X ì± ììì ê³ì ì¤í¨íë©´ ì¤ë¥¸ìª½ ì ë©ë´ìì Safari ëë Chromeì¼ë¡ ì´ì´ 주ì¸ì.', 484 copy: 'íì¬ URL ë³µì¬', 485 copied: 'URLì ë³µì¬íìµëë¤', 486 }, 487 }; 488 var startedAt = 489 window.performance && typeof window.performance.now === 'function' 490 ? window.performance.now() 491 : Date.now(); 492 var sent = Object.create(null); 493 var timeoutId = null; 494 var monitoring = true; 495 var mainAssetHash = ''; 496 var appAssetHash = ''; 497 498 function language() { 499 var raw = String(navigator.language || 'en').toLowerCase(); 500 if (raw.indexOf('ja') === 0) return 'ja'; 501 if (raw.indexOf('ko') === 0) return 'ko'; 502 if (raw.indexOf('zh') === 0) { 503 return raw.indexOf('tw') >= 0 || raw.indexOf('hk') >= 0 ? 'zh-TW' : 'zh-CN'; 504 } 505 return 'en'; 506 } 507 508 function browserFamily() { 509 var ua = String(navigator.userAgent || ''); 510 if (/CriOS|Chrome\//i.test(ua)) return 'chrome'; 511 if (/FxiOS|Firefox\//i.test(ua)) return 'firefox'; 512 if (/EdgiOS|EdgA|Edg\//i.test(ua)) return 'edge'; 513 if (/Safari\//i.test(ua) && /AppleWebKit\//i.test(ua)) return 'safari'; 514 if (/AppleWebKit\//i.test(ua) && /Mobile\//i.test(ua)) return 'ios_webview'; 515 return 'other'; 516 } 517 518 function isXInApp() { 519 return /Twitter(?:Android| for iPhone)?|XApp/i.test(String(navigator.userAgent || '')); 520 } 521 522 function elapsedMs() { 523 var now = 524 window.performance && typeof window.performance.now === 'function' 525 ? window.performance.now() 526 : Date.now(); 527 return Math.max(0, Math.round(now - startedAt)); 528 } 529 530 function assetHash(urlValue) { 531 try { 532 var pathname = new URL(String(urlValue), window.location.href).pathname; 533 var name = pathname.split('/').pop() || ''; 534 return name.slice(0, 96); 535 } catch (_error) { 536 return ''; 537 } 538 } 539 540 function anonymousId() { 541 try { 542 var existing = window.localStorage.getItem('mychara:anonymousId'); 543 if (existing) return existing.slice(0, 64); 544 var fresh = 545 window.crypto && typeof window.crypto.randomUUID === 'function' 546 ? window.crypto.randomUUID() 547 : 'boot-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2, 10); 548 window.localStorage.setItem('mychara:anonymousId', fresh); 549 return fresh.slice(0, 64); 550 } catch (_error) { 551 return ( 552 'boot-' + 553 Date.now().toString(36) +
554 '-' + 555 Math.random().toString(36).slice(2, 10) 556 ).slice(0, 64); 557 } 558 } 559 560 function attribution() { 561 var values = {}; 562 try { 563 var params = new URLSearchParams(window.location.search); 564 for (var index = 0; index < ALLOWED_PARAMS.length; index += 1) { 565 var key = ALLOWED_PARAMS[index]; 566 var value = params.get(key); 567 if (value) values[key] = value.slice(0, 200); 568 } 569 } catch (_error) { 570 // Malformed query parameters must not block startup. 571 } 572 return values; 573 } 574 575 function safePath() { 576 var query = new URLSearchParams(); 577 var values = attribution(); 578 for (var index = 0; index < ALLOWED_PARAMS.length; index += 1) { 579 var key = ALLOWED_PARAMS[index]; 580 if (values[key]) query.set(key, values[key]); 581 } 582 var suffix = query.toString(); 583 return (window.location.pathname + (suffix ? '?' + suffix : '')).slice(0, 300); 584 } 585 586 function send(eventName, extra) { 587 if (sent[eventName]) return; 588 sent[eventName] = true; 589 if (window.location.hostname !== 'mychara.ai') return; 590 var properties = Object.assign({}, attribution(), { 591 measurement_stage: eventName, 592 boot_duration_ms: elapsedMs(), 593 browser_family: browserFamily(), 594 x_in_app: isXInApp(), 595 main_asset_hash: mainAssetHash, 596 app_asset_hash: appAssetHash, 597 }); 598 if (extra) Object.assign(properties, extra); 599 var body = JSON.stringify({ 600 eventName: eventName, 601 anonymousId: anonymousId(), 602 path: safePath(), 603 properties: properties, 604 }); 605 try { 606 if (typeof navigator.sendBeacon === 'function') { 607 var accepted = navigator.sendBeacon( 608 API_URL, 609 new Blob([body], { type: 'application/json' }), 610 ); 611 if (accepted) return; 612 } 613 if (typeof window.fetch === 'function') { 614 window 615 .fetch(API_URL, { 616 method: 'POST', 617 headers: { 'Content-Type': 'application/json' }, 618 body: body, 619 keepalive: true, 620 credentials: 'omit', 621 }) 622 .catch(function () {}); 623 } 624 } catch (_error) { 625 // Telemetry is never allowed to affect startup. 626 } 627 } 628 629 function shellElements() { 630 var shell = document.querySelector('.app-startup-loading'); 631 return { 632 shell: shell, 633 spinner: document.querySelector('.app-startup-loading__spinner'), 634 message: document.querySelector('.app-startup-loading__message'), 635 recovery: document.querySelector('.app-startup-loading__recovery'), 636 retry: document.querySelector('.app-startup-loading__retry'), 637 hint: document.querySelector('.app-startup-loading__external-hint'), 638 copy: document.querySelector('.app-startup-loading__copy'), 639 }; 640 } 641 642 function showError() { 643 var elements = shellElements(); 644 var text = COPY[language()]; 645 if (elements.shell) { 646 elements.shell.setAttribute('role', 'alert'); 647 elements.shell.setAttribute('aria-live', 'assertive'); 648 elements.shell.setAttribute('aria-busy', 'false'); 649 } 650 if (elements.spinner) elements.spinner.hidden = true; 651 if (elements.message) elements.message.textContent = text.failed; 652 if (elements.retry) { 653 elements.retry.textContent = text.retry; 654 elements.retry.href = window.location.href; 655 } 656 if (elements.hint) elements.hint.textContent = text.hint; 657 if (elements.copy) elements.copy.textContent = text.copy; 658 if (elements.recovery) elements.recovery.hidden = false;
659 } 660 661 function cleanupMonitoring() { 662 monitoring = false; 663 if (timeoutId !== null) window.clearTimeout(timeoutId); 664 window.removeEventListener('error', onWindowError, true); 665 window.removeEventListener('unhandledrejection', onUnhandledRejection); 666 } 667 668 function mark(eventName, properties) { 669 var cleanProperties = Object.assign({}, properties || {}); 670 if (cleanProperties.main_asset_url) { 671 mainAssetHash = assetHash(cleanProperties.main_asset_url); 672 delete cleanProperties.main_asset_url; 673 } 674 if (cleanProperties.app_asset_url) { 675 appAssetHash = assetHash(cleanProperties.app_asset_url); 676 delete cleanProperties.app_asset_url; 677 } 678 send(eventName, cleanProperties); 679 } 680 681 function complete(properties) { 682 mark('app_boot_completed', properties); 683 cleanupMonitoring(); 684 } 685 686 function fail(eventName, properties) { 687 mark(eventName, properties); 688 cleanupMonitoring(); 689 showError(); 690 } 691 692 function retry(properties) { 693 mark('app_boot_retry', properties); 694 var elements = shellElements(); 695 if (elements.retry) elements.retry.textContent = COPY[language()].retrying; 696 } 697 698 function sameOriginScript(filename) { 699 try { 700 return ( 701 filename && new URL(filename, window.location.href).origin === window.location.origin 702 ); 703 } catch (_error) { 704 return false; 705 } 706 } 707 708 function onWindowError(event) { 709 if (!monitoring) return; 710 var target = event.target; 711 if (target && target.id === 'app-main-module') { 712 fail('app_boot_module_error', { error_kind: 'main_module_resource_error' }); 713 return; 714 } 715 if (sameOriginScript(event.filename)) { 716 fail('app_boot_app_module_error', { 717 error_kind: String(event.message || 'module evaluation error').slice(0, 160), 718 }); 719 } 720 } 721 722 function onUnhandledRejection(event) { 723 if (!monitoring) return; 724 var reason = event.reason; 725 var message = reason && reason.message ? reason.message : 'unhandled module rejection'; 726 fail('app_boot_app_module_error', { error_kind: String(message).slice(0, 160) }); 727 } 728 729 window.__MYCHARA_BOOT__ = { 730 mark: mark, 731 complete: complete, 732 fail: fail, 733 retry: retry, 734 }; 735 736 window.addEventListener('error', onWindowError, true); 737 window.addEventListener('unhandledrejection', onUnhandledRejection); 738 739 var initialElements = shellElements(); 740 if (initialElements.retry) { 741 initialElements.retry.href = window.location.href; 742 initialElements.retry.addEventListener('click', function () { 743 retry({ recovery_surface: 'static_startup' }); 744 }); 745 } 746 if (initialElements.copy) { 747 initialElements.copy.addEventListener('click', function () { 748 var finish = function () { 749 initialElements.copy.textContent = COPY[language()].copied; 750 }; 751 try { 752 if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') { 753 navigator.clipboard 754 .writeText(window.location.href) 755 .then(finish) 756 .catch(function () {}); 757 } 758 } catch (_error) { 759 // Clipboard access is optional recovery help. 760 } 761 }); 762 } 763 764 mark('app_boot_html_arrived'); 765 timeoutId = window.setTimeout(function () { 766 if (!monitoring) return; 767 fail('app_boot_timeout'); 768 }, TIMEOUT_MS); 769 })(); 770 </script>
770 771
771<script> 772 (function () { 773 var moduleScript = document.getElementById('app-main-module'); 774 if (moduleScript && window.__MYCHARA_BOOT__) { 775 window.__MYCHARA_BOOT__.mark('app_boot_module_detected', { 776 main_asset_url: moduleScript.src, 777 }); 778 } 779 })(); 780 </script>
780 781 </body> 782</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.