diff options
Diffstat (limited to 'packages/backend/src/server/web')
| -rw-r--r-- | packages/backend/src/server/web/boot.js | 181 | ||||
| -rw-r--r-- | packages/backend/src/server/web/index.ts | 44 | ||||
| -rw-r--r-- | packages/backend/src/server/web/views/bios.pug | 4 |
3 files changed, 210 insertions, 19 deletions
diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js index 94329e11c9..0a5cc0e0dc 100644 --- a/packages/backend/src/server/web/boot.js +++ b/packages/backend/src/server/web/boot.js @@ -14,10 +14,10 @@ // ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔なので (async () => { window.onerror = (e) => { - renderError('SOMETHING_HAPPENED', e.toString()); + renderError('SOMETHING_HAPPENED', e); }; window.onunhandledrejection = (e) => { - renderError('SOMETHING_HAPPENED_IN_PROMISE', e.toString()); + renderError('SOMETHING_HAPPENED_IN_PROMISE', e); }; const v = localStorage.getItem('v') || VERSION; @@ -57,7 +57,7 @@ import(`/assets/${CLIENT_ENTRY}`) .catch(async e => { await checkUpdate(); - renderError('APP_FETCH_FAILED', JSON.stringify(e)); + renderError('APP_FETCH_FAILED', e); }) //#endregion @@ -102,22 +102,169 @@ document.head.appendChild(style); } - // eslint-disable-next-line no-inner-declarations + async function addStyle(styleText) { + let css = document.createElement('style'); + css.appendChild(document.createTextNode(styleText)); + document.head.appendChild(css); + } + function renderError(code, details) { - document.documentElement.innerHTML = ` - <h1>⚠エラーが発生しました</h1> - <p>問題が解決しない場合は管理者までお問い合わせください。以下のオプションを試すこともできます:</p> - <ul> - <li><a href="/cli">簡易クライアント</a>を起動</li> - <li><a href="/bios">BIOS</a>で修復を試みる</li> - <li><a href="/flush">キャッシュをクリア</a>する</li> - </ul> - <hr> + let errorsElement = document.getElementById('errors'); + + if (!errorsElement) { + document.documentElement.innerHTML = ` + <svg class="icon-warning" xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-alert-triangle" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> + <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> + <path d="M12 9v2m0 4v.01"></path> + <path d="M5 19h14a2 2 0 0 0 1.84 -2.75l-7.1 -12.25a2 2 0 0 0 -3.5 0l-7.1 12.25a2 2 0 0 0 1.75 2.75"></path> + </svg> + <h1>An error has occurred!</h1> + <button class="button-big" onclick="location.reload(true);"> + <span class="button-label-big">Refresh</span> + </button> + <p class="dont-worry">Don't worry, it's (probably) not your fault.</p> + <p>If the problem persists after refreshing, please contact your instance's administrator.<br>You may also try the following options:</p> + <a href="/flush"> + <button class="button-small"> + <span class="button-label-small">Clear preferences and cache</span> + </button> + </a> + <br> + <a href="/cli"> + <button class="button-small"> + <span class="button-label-small">Start the simple client</span> + </button> + </a> + <br> + <a href="/bios"> + <button class="button-small"> + <span class="button-label-small">Start the repair tool</span> + </button> + </a> + <br> + <div id="errors"></div> + `; + errorsElement = document.getElementById('errors'); + } + const detailsElement = document.createElement('details'); + detailsElement.innerHTML = ` + <br> + <summary> <code>ERROR CODE: ${code}</code> - <details> - ${details} - </details> - `; + </summary> + <code>${JSON.stringify(details)}</code>`; + errorsElement.appendChild(detailsElement); + addStyle(` + * { + font-family: BIZ UDGothic, Roboto, HelveticaNeue, Arial, sans-serif; + } + + #misskey_app, + #splash { + display: none !important; + } + + body, + html { + background-color: #222; + color: #dfddcc; + justify-content: center; + margin: auto; + padding: 10px; + text-align: center; + } + + button { + border-radius: 999px; + padding: 0px 12px 0px 12px; + border: none; + cursor: pointer; + margin-bottom: 12px; + } + + .button-big { + background: linear-gradient(90deg, rgb(134, 179, 0), rgb(74, 179, 0)); + line-height: 50px; + } + + .button-big:hover { + background: rgb(153, 204, 0); + } + + .button-small { + background: #444; + line-height: 40px; + } + + .button-small:hover { + background: #555; + } + + .button-label-big { + color: #222; + font-weight: bold; + font-size: 20px; + padding: 12px; + } + + .button-label-small { + color: rgb(153, 204, 0); + font-size: 16px; + padding: 12px; + } + + a { + color: rgb(134, 179, 0); + text-decoration: none; + } + + p, + li { + font-size: 16px; + } + + .dont-worry, + #msg { + font-size: 18px; + } + + .icon-warning { + color: #dec340; + height: 4rem; + padding-top: 2rem; + } + + h1 { + font-size: 32px; + } + + code { + font-family: Fira, FiraCode, monospace; + } + + details { + background: #333; + margin-bottom: 2rem; + padding: 0.5rem 1rem; + width: 40rem; + border-radius: 10px; + justify-content: center; + margin: auto; + } + + summary { + cursor: pointer; + } + + summary > * { + display: inline; + } + + @media screen and (max-width: 500px) { + details { + width: 50%; + } + `) } // eslint-disable-next-line no-inner-declarations diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index 2feee72be7..be95becb68 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -11,6 +11,7 @@ import Router from '@koa/router'; import send from 'koa-send'; import favicon from 'koa-favicon'; import views from 'koa-views'; +import sharp from 'sharp'; import { createBullBoard } from '@bull-board/api'; import { BullAdapter } from '@bull-board/api/bullAdapter.js'; import { KoaAdapter } from '@bull-board/koa'; @@ -140,6 +141,49 @@ router.get('/twemoji/(.*)', async ctx => { }); }); +router.get('/twemoji-badge/(.*)', async ctx => { + const path = ctx.path.replace('/twemoji-badge/', ''); + + if (!path.match(/^[0-9a-f-]+\.png$/)) { + ctx.status = 404; + return; + } + + const mask = await sharp( + `${_dirname}/../../../node_modules/@discordapp/twemoji/dist/svg/${path.replace('.png', '')}.svg`, + { density: 1000 }, + ) + .resize(488, 488) + .greyscale() + .normalise() + .linear(1.75, -(128 * 1.75) + 128) // 1.75x contrast + .flatten({ background: '#000' }) + .extend({ + top: 12, + bottom: 12, + left: 12, + right: 12, + background: '#000', + }) + .toColorspace('b-w') + .png() + .toBuffer(); + + const buffer = await sharp({ + create: { width: 512, height: 512, channels: 4, background: { r: 0, g: 0, b: 0, alpha: 0 } }, + }) + .pipelineColorspace('b-w') + .boolean(mask, 'eor') + .resize(96, 96) + .png() + .toBuffer(); + + ctx.set('Content-Security-Policy', 'default-src \'none\'; style-src \'unsafe-inline\''); + ctx.set('Cache-Control', 'max-age=2592000'); + ctx.set('Content-Type', 'image/png'); + ctx.body = buffer; +}); + // ServiceWorker router.get(`/sw.js`, async ctx => { await send(ctx as any, `/sw.js`, { diff --git a/packages/backend/src/server/web/views/bios.pug b/packages/backend/src/server/web/views/bios.pug index d81a3ee67f..39a151a29b 100644 --- a/packages/backend/src/server/web/views/bios.pug +++ b/packages/backend/src/server/web/views/bios.pug @@ -5,7 +5,7 @@ html head meta(charset='utf-8') meta(name='application-name' content='Misskey') - title Misskey BIOS + title Misskey Repair Tool style include ../bios.css script @@ -13,7 +13,7 @@ html body header - h1 Misskey BIOS #{version} + h1 Misskey Repair Tool #{version} main div.tabs button#ls edit local storage |