summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/web
diff options
context:
space:
mode:
Diffstat (limited to 'packages/backend/src/server/web')
-rw-r--r--packages/backend/src/server/web/boot.js181
-rw-r--r--packages/backend/src/server/web/index.ts44
-rw-r--r--packages/backend/src/server/web/views/bios.pug4
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