This commit is contained in:
sim1222 2023-02-22 18:07:27 +09:00
parent b161f38710
commit ec956731e7
No known key found for this signature in database
GPG Key ID: 04EF48D01BEB0298
90 changed files with 886 additions and 24 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<title>Misskey API</title>
<!-- needed for adaptive design -->
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
<!--
ReDoc doesn't change outer page styles
-->
<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<redoc spec-url="/api.json" expand-responses="200" expand-single-schema-field="true"></redoc>
<script src="https://cdn.jsdelivr.net/npm/redoc@2.0.0-rc.50/bundles/redoc.standalone.js" integrity="sha256-WJbngBWN9vp6vkEuzeoSj5tE5saW9Hfj6/SinkzhL2s=" crossorigin="anonymous"></script>
</body>
</html>

View File

@ -0,0 +1,4 @@
user-agent: *
allow: /
# todo: sitemap

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,24 @@
Tabler Icons
https://github.com/tabler/tabler-icons/blob/master/LICENSE
====
MIT License
Copyright (c) 2020-2022 Paweł Kuna
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1011 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

309
packages/frontend/boot.js Normal file
View File

@ -0,0 +1,309 @@
/**
* BOOT LOADER
* サーバーからレスポンスされるHTMLに埋め込まれるスクリプトで以下の役割を持ちます
* - 翻訳ファイルをフェッチする
* - バージョンに基づいて適切なメインスクリプトを読み込む
* - キャッシュされたコンパイル済みテーマを適用する
* - クライアントの設定値に基づいて対応するHTMLクラス等を設定する
* テーマをこの段階で設定するのはメインスクリプトが読み込まれる間もテーマを適用したいためです
* : webpackは介さないためこのファイルではrequireやimportは使えません
*/
'use strict';
// ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔なので
(async () => {
window.onerror = (e) => {
console.error(e);
renderError('SOMETHING_HAPPENED', e);
};
window.onunhandledrejection = (e) => {
console.error(e);
renderError('SOMETHING_HAPPENED_IN_PROMISE', e);
};
let forceError = localStorage.getItem('forceError');
if (forceError != null) {
renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.')
}
//#region Detect language & fetch translations
if (!localStorage.hasOwnProperty('locale')) {
// const supportedLangs = LANGS;
const supportedLangs = ['en-US', 'ja-JP'];
let lang = localStorage.getItem('lang');
if (lang == null || !supportedLangs.includes(lang)) {
if (supportedLangs.includes(navigator.language)) {
lang = navigator.language;
} else {
lang = supportedLangs.find(x => x.split('-')[0] === navigator.language);
// Fallback
if (lang == null) lang = 'en-US';
}
}
// const metaRes = await window.fetch('/api/meta', {
// method: 'POST',
// body: JSON.stringify({}),
// credentials: 'omit',
// cache: 'no-cache',
// headers: {
// 'Content-Type': 'application/json',
// },
// });
// if (metaRes.status !== 200) {
// renderError('META_FETCH');
// return;
// }
// const meta = await metaRes.json();
const meta = { "version": "13.6.1-simkey", "uri": "https://kokt.club", "langs": [], "repositoryUrl": "https://github.com/misskey-dev/misskey", "feedbackUrl": "https://github.com/misskey-dev/misskey/issues/new", "disableRegistration": false, "emailRequiredForSignup": false, "enableHcaptcha": false, "hcaptchaSiteKey": null, "enableRecaptcha": true, "recaptchaSiteKey": "6LcSVvkhAAAAAHfnEeJhfI_XJLnfn8-gPHqZ4K5z", "enableTurnstile": false, "turnstileSiteKey": null, "swPublickey": "BJO5qBTaw1t5O448MwtH4jikC9JG0V682uVftWHPNU05-PE5-aAuj14zBLPPpgJP_ifpndg0cVn0Ka3oE453ZkA", "themeColor": null, "mascotImageUrl": "/assets/ai.png", "bannerUrl": "https://s3.kokt.club/files/a952f48b-7720-4b00-9d15-f044150db378.webp", "errorImageUrl": "https://xn--931a.moe/aiart/yubitun.png", "iconUrl": "https://s3.kokt.club/files/e2149c00-311a-4348-a548-0877831b4b08.png", "backgroundImageUrl": "https://s3.kokt.club/files/a952f48b-7720-4b00-9d15-f044150db378.webp", "logoImageUrl": null, "maxNoteTextLength": 8192, "defaultLightTheme": null, "defaultDarkTheme": null, "ads": [], "enableEmail": true, "enableTwitterIntegration": false, "enableGithubIntegration": false, "enableDiscordIntegration": false, "enableServiceWorker": true, "translatorAvailable": true, "policies": { "gtlAvailable": true, "ltlAvailable": true, "canPublicNote": true, "canInvite": false, "canManageCustomEmojis": false, "canHideAds": false, "driveCapacityMb": 20480, "pinLimit": 5, "antennaLimit": 10, "wordMuteLimit": 200, "webhookLimit": 10, "clipLimit": 20, "noteEachClipsLimit": 2000, "userListLimit": 15, "userEachUserListsLimit": 100, "rateLimitFactor": 1 } }
const v = meta.version;
if (v == null) {
renderError('META_FETCH_V');
return;
}
const localRes = await window.fetch(`/assets/locales/${lang}.${v}.json`);
// const localRes = await window.fetch(`/assets/locales/${lang}.json`);
if (localRes.status === 200) {
localStorage.setItem('lang', lang);
localStorage.setItem('locale', await localRes.text());
localStorage.setItem('localeVersion', v);
} else {
renderError('LOCALE_FETCH');
return;
}
}
//#endregion
//#region Script
function importAppScript() {
import(`/${CLIENT_ENTRY}`)
.catch(async e => {
console.error(e);
renderError('APP_IMPORT', e);
});
}
// タイミングによっては、この時点でDOMの構築が済んでいる場合とそうでない場合とがある
if (document.readyState !== 'loading') {
importAppScript();
} else {
window.addEventListener('DOMContentLoaded', () => {
importAppScript();
});
}
//#endregion
//#region Theme
const theme = localStorage.getItem('theme');
if (theme) {
for (const [k, v] of Object.entries(JSON.parse(theme))) {
document.documentElement.style.setProperty(`--${k}`, v.toString());
// HTMLの theme-color 適用
if (k === 'htmlThemeColor') {
for (const tag of document.head.children) {
if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') {
tag.setAttribute('content', v);
break;
}
}
}
}
}
const colorSchema = localStorage.getItem('colorSchema');
if (colorSchema) {
document.documentElement.style.setProperty('color-schema', colorSchema);
}
//#endregion
const fontSize = localStorage.getItem('fontSize');
if (fontSize) {
document.documentElement.classList.add('f-' + fontSize);
}
const useSystemFont = localStorage.getItem('useSystemFont');
if (useSystemFont) {
document.documentElement.classList.add('useSystemFont');
}
const wallpaper = localStorage.getItem('wallpaper');
if (wallpaper) {
document.documentElement.style.backgroundImage = `url(${wallpaper})`;
}
const customCss = localStorage.getItem('customCss');
if (customCss && customCss.length > 0) {
const style = document.createElement('style');
style.innerHTML = customCss;
document.head.appendChild(style);
}
async function addStyle(styleText) {
let css = document.createElement('style');
css.appendChild(document.createTextNode(styleText));
document.head.appendChild(css);
}
function renderError(code, details) {
let errorsElement = document.getElementById('errors');
if (!errorsElement) {
document.body.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();">
<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>
<p>Update your os and browser.</p>
<p>Disable an adblocker.</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>
</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%;
}
`)
}
})();

164
packages/frontend/config.ts Normal file
View File

@ -0,0 +1,164 @@
/**
* Config loader
*/
import * as fs from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
import * as yaml from 'js-yaml';
/**
*
*/
export type Source = {
repository_url?: string;
feedback_url?: string;
url: string;
port: number;
disableHsts?: boolean;
db: {
host: string;
port: number;
db: string;
user: string;
pass: string;
disableCache?: boolean;
extra?: { [x: string]: string };
};
redis: {
host: string;
port: number;
family?: number;
pass: string;
db?: number;
prefix?: string;
};
elasticsearch: {
host: string;
port: number;
ssl?: boolean;
user?: string;
pass?: string;
index?: string;
};
proxy?: string;
proxySmtp?: string;
proxyBypassHosts?: string[];
allowedPrivateNetworks?: string[];
maxFileSize?: number;
accesslog?: string;
clusterLimit?: number;
id: string;
outgoingAddressFamily?: 'ipv4' | 'ipv6' | 'dual';
deliverJobConcurrency?: number;
inboxJobConcurrency?: number;
deliverJobPerSec?: number;
inboxJobPerSec?: number;
deliverJobMaxAttempts?: number;
inboxJobMaxAttempts?: number;
mediaProxy?: string;
proxyRemoteFiles?: boolean;
videoThumbnailGenerator?: string;
signToActivityPubGet?: boolean;
};
/**
* Misskeyが自動的に()
*/
export type Mixin = {
version: string;
host: string;
hostname: string;
scheme: string;
wsScheme: string;
apiUrl: string;
wsUrl: string;
authUrl: string;
driveUrl: string;
userAgent: string;
clientEntry: string;
clientManifestExists: boolean;
mediaProxy: string;
externalMediaProxyEnabled: boolean;
videoThumbnailGenerator: string | null;
};
export type Config = Source & Mixin;
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
/**
* Path of configuration directory
*/
const dir = `${_dirname}/../../../.config`;
/**
* Path of configuration file
*/
const path = process.env.NODE_ENV === 'test'
? `${dir}/test.yml`
: `${dir}/default.yml`;
export function loadConfig() {
const meta = JSON.parse(fs.readFileSync(`${_dirname}/../../../built/meta.json`, 'utf-8'));
const clientManifestExists = fs.existsSync(_dirname + '/../../../built/_vite_/manifest.json');
const clientManifest = clientManifestExists ?
JSON.parse(fs.readFileSync(`${_dirname}/../../../built/_vite_/manifest.json`, 'utf-8'))
: { 'src/init.ts': { file: 'src/init.ts' } };
const config = yaml.load(fs.readFileSync(path, 'utf-8')) as Source;
const mixin = {} as Mixin;
const url = tryCreateUrl(config.url);
config.url = url.origin;
config.port = config.port ?? parseInt(process.env.PORT ?? '', 10);
mixin.version = meta.version;
mixin.host = url.host;
mixin.hostname = url.hostname;
mixin.scheme = url.protocol.replace(/:$/, '');
mixin.wsScheme = mixin.scheme.replace('http', 'ws');
mixin.wsUrl = `${mixin.wsScheme}://${mixin.host}`;
mixin.apiUrl = `${mixin.scheme}://${mixin.host}/api`;
mixin.authUrl = `${mixin.scheme}://${mixin.host}/auth`;
mixin.driveUrl = `${mixin.scheme}://${mixin.host}/files`;
mixin.userAgent = `Misskey/${meta.version} (${config.url})`;
mixin.clientEntry = clientManifest['src/init.ts'];
mixin.clientManifestExists = clientManifestExists;
const externalMediaProxy = config.mediaProxy ?
config.mediaProxy.endsWith('/') ? config.mediaProxy.substring(0, config.mediaProxy.length - 1) : config.mediaProxy
: null;
const internalMediaProxy = `${mixin.scheme}://${mixin.host}/proxy`;
mixin.mediaProxy = externalMediaProxy ?? internalMediaProxy;
mixin.externalMediaProxyEnabled = externalMediaProxy !== null && externalMediaProxy !== internalMediaProxy;
mixin.videoThumbnailGenerator = config.videoThumbnailGenerator ?
config.videoThumbnailGenerator.endsWith('/') ? config.videoThumbnailGenerator.substring(0, config.videoThumbnailGenerator.length - 1) : config.videoThumbnailGenerator
: null;
if (!config.redis.prefix) config.redis.prefix = mixin.host;
return Object.assign(config, mixin);
}
function tryCreateUrl(url: string) {
try {
return new URL(url);
} catch (e) {
throw `url="${url}" is not a valid URL.`;
}
}

View File

@ -0,0 +1,66 @@
export const MAX_NOTE_TEXT_LENGTH = 3000;
export const USER_ONLINE_THRESHOLD = 1000 * 60 * 10; // 10min
export const USER_ACTIVE_THRESHOLD = 1000 * 60 * 60 * 24 * 3; // 3days
//#region hard limits
// If you change DB_* values, you must also change the DB schema.
/**
* Maximum note text length that can be stored in DB.
* Surrogate pairs count as one
*/
export const DB_MAX_NOTE_TEXT_LENGTH = 8192;
/**
* Maximum image description length that can be stored in DB.
* Surrogate pairs count as one
*/
export const DB_MAX_IMAGE_COMMENT_LENGTH = 512;
//#endregion
// ブラウザで直接表示することを許可するファイルの種類のリスト
// ここに含まれないものは application/octet-stream としてレスポンスされる
// SVGはXSSを生むので許可しない
export const FILE_TYPE_BROWSERSAFE = [
// Images
'image/png',
'image/gif',
'image/jpeg',
'image/webp',
'image/avif',
'image/apng',
'image/bmp',
'image/tiff',
'image/x-icon',
// OggS
'audio/opus',
'video/ogg',
'audio/ogg',
'application/ogg',
// ISO/IEC base media file format
'video/quicktime',
'video/mp4',
'audio/mp4',
'video/x-m4v',
'audio/x-m4a',
'video/3gpp',
'video/3gpp2',
'video/mpeg',
'audio/mpeg',
'video/webm',
'audio/webm',
'audio/aac',
'audio/x-flac',
'audio/vnd.wave',
];
/*
https://github.com/sindresorhus/file-type/blob/main/supported.js
https://github.com/sindresorhus/file-type/blob/main/core.js
https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers
*/

View File

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="application-name" content="Misskey">
<meta name="referrer" content="origin">
<meta name="theme-color" content="#86b300">
<meta name="theme-color-orig" content="#86b300">
<meta property="twitter:card" content="summary">
<meta property="og:site_name" content="Misskey">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/assets/favicon.ico">
<link rel="apple-touch-icon" href="/assets/apple-touch-icon.png">
<link rel="manifest" href="/manifest.json">
<link rel="search" type="application/opensearchdescription+xml" title="Misskey"
href="https://xn--931a.moe/opensearch.xml">
<link rel="prefetch" href="https://xn--931a.moe/assets/info.jpg">
<link rel="prefetch" href="https://xn--931a.moe/assets/not-found.jpg">
<link rel="prefetch" href="https://xn--931a.moe/assets/error.jpg">
<link rel="stylesheet" href="/assets/tabler-icons/tabler-icons.min.css?v2.2.0">
<!-- <link rel="modulepreload" href="/vite/client"> -->
<title>Misskey</title>
<meta name="description" content="✨🌎✨ A interplanetary communication platform ✨🚀✨">
<meta property='og:title' content="Misskey">
<meta property='og:description' content="✨🌎✨ A interplanetary communication platform ✨🚀✨">
<meta property='og:image' content="img">
<link rel="stylesheet" href="./style.css">
<script src="./boot.js"></script>
</head>
<body>
<noscript>
<p>
JavaScriptを有効にしてください<br>
Please turn on your JavaScript
</p>
</noscript>
<div id="splash">
<img src="/static-assets/splash.png">
<div id="splashSpinner">
<svg class="spinner bg" viewBox="0 0 152 152" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1,0,0,1,12,12)">
<circle cx="64" cy="64" r="64" style="fill:none;stroke:currentColor;stroke-width:24px;" />
</g>
</svg>
<svg class="spinner fg" viewBox="0 0 152 152" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1,0,0,1,12,12)">
<path d="M128,64C128,28.654 99.346,0 64,0C99.346,0 128,28.654 128,64Z"
style="fill:none;stroke:currentColor;stroke-width:24px;" />
</g>
</svg>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="application-name" content="Misskey">
<meta name="referrer" content="origin">
<meta name="theme-color" content="#86b300">
<meta name="theme-color-orig" content="#86b300">
<meta property="twitter:card" content="summary">
<meta property="og:site_name" content="Misskey">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/assets/favicon.ico">
<link rel="apple-touch-icon" href="/assets/apple-touch-icon.png">
<link rel="manifest" href="/manifest.json">
<link rel="search" type="application/opensearchdescription+xml" title="Misskey"
href="https://xn--931a.moe/opensearch.xml">
<link rel="prefetch" href="https://xn--931a.moe/assets/info.jpg">
<link rel="prefetch" href="https://xn--931a.moe/assets/not-found.jpg">
<link rel="prefetch" href="https://xn--931a.moe/assets/error.jpg">
<!-- <link rel="stylesheet" href="/assets/tabler-icons/tabler-icons.min.css?v2.2.0"> -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/icons@latest/iconfont/tabler-icons.min.css" />
<!-- <link rel="modulepreload" href="/vite/client"> -->
<title>Misskey</title>
<meta name="description" content="✨🌎✨ A interplanetary communication platform ✨🚀✨">
<meta property='og:title' content="Misskey">
<meta property='og:description' content="✨🌎✨ A interplanetary communication platform ✨🚀✨">
<meta property='og:image' content="img">
<link rel="stylesheet" href="./style.css">
<!-- <script src="./boot.js"></script> -->
</head>
<body>
<noscript>
<p>
JavaScriptを有効にしてください<br>
Please turn on your JavaScript
</p>
</noscript>
<div id="splash">
<img src="/static-assets/splash.png">
<div id="splashSpinner">
<svg class="spinner bg" viewBox="0 0 152 152" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1,0,0,1,12,12)">
<circle cx="64" cy="64" r="64" style="fill:none;stroke:currentColor;stroke-width:24px;" />
</g>
</svg>
<svg class="spinner fg" viewBox="0 0 152 152" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1,0,0,1,12,12)">
<path d="M128,64C128,28.654 99.346,0 64,0C99.346,0 128,28.654 128,64Z"
style="fill:none;stroke:currentColor;stroke-width:24px;" />
</g>
</svg>
</div>
<div id="app"></div>
<script type="module" src="./src/init.ts"></script>
</div>
</body>
</html>

View File

@ -0,0 +1,28 @@
{
"short_name": "Misskey",
"name": "Misskey",
"start_url": "/",
"display": "standalone",
"background_color": "#313a42",
"theme_color": "#86b300",
"icons": [
{
"src": "/static-assets/icons/192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/static-assets/icons/512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"share_target": {
"action": "/share/",
"params": {
"title": "title",
"text": "text",
"url": "url"
}
}
}

View File

@ -173,18 +173,18 @@ if ($i && $i.token) {
}
//#endregion
const fetchInstanceMetaPromise = fetchInstance();
// const fetchInstanceMetaPromise = fetchInstance();
fetchInstanceMetaPromise.then(() => {
miLocalStorage.setItem('v', instance.version);
// fetchInstanceMetaPromise.then(() => {
// miLocalStorage.setItem('v', instance.version);
// Init service worker
initializeSw();
});
// // Init service worker
// initializeSw();
// });
try {
await fetchCustomEmojis();
} catch (err) {}
// try {
// await fetchCustomEmojis();
// } catch (err) {}
const app = createApp(
window.location.search === '?zen' ? defineAsyncComponent(() => import('@/ui/zen.vue')) :

View File

@ -68,9 +68,11 @@ export default defineComponent({
},
created() {
os.api('meta', { detail: true }).then(meta => {
this.meta = meta;
});
// os.api('meta', { detail: true }).then(meta => {
// this.meta = meta;
// });
this.meta = { 'version': '13.6.1-simkey', 'uri': 'https://kokt.club', 'langs': [], 'repositoryUrl': 'https://github.com/misskey-dev/misskey', 'feedbackUrl': 'https://github.com/misskey-dev/misskey/issues/new', 'disableRegistration': false, 'emailRequiredForSignup': false, 'enableHcaptcha': false, 'hcaptchaSiteKey': null, 'enableRecaptcha': true, 'recaptchaSiteKey': '6LcSVvkhAAAAAHfnEeJhfI_XJLnfn8-gPHqZ4K5z', 'enableTurnstile': false, 'turnstileSiteKey': null, 'swPublickey': 'BJO5qBTaw1t5O448MwtH4jikC9JG0V682uVftWHPNU05-PE5-aAuj14zBLPPpgJP_ifpndg0cVn0Ka3oE453ZkA', 'themeColor': null, 'mascotImageUrl': '/assets/ai.png', 'bannerUrl': 'https://s3.kokt.club/files/a952f48b-7720-4b00-9d15-f044150db378.webp', 'errorImageUrl': 'https://xn--931a.moe/aiart/yubitun.png', 'iconUrl': 'https://s3.kokt.club/files/e2149c00-311a-4348-a548-0877831b4b08.png', 'backgroundImageUrl': 'https://s3.kokt.club/files/a952f48b-7720-4b00-9d15-f044150db378.webp', 'logoImageUrl': null, 'maxNoteTextLength': 8192, 'defaultLightTheme': null, 'defaultDarkTheme': null, 'ads': [], 'enableEmail': true, 'enableTwitterIntegration': false, 'enableGithubIntegration': false, 'enableDiscordIntegration': false, 'enableServiceWorker': true, 'translatorAvailable': true, 'policies': { 'gtlAvailable': true, 'ltlAvailable': true, 'canPublicNote': true, 'canInvite': false, 'canManageCustomEmojis': false, 'canHideAds': false, 'driveCapacityMb': 20480, 'pinLimit': 5, 'antennaLimit': 10, 'wordMuteLimit': 200, 'webhookLimit': 10, 'clipLimit': 20, 'noteEachClipsLimit': 2000, 'userListLimit': 15, 'userEachUserListsLimit': 100, 'rateLimitFactor': 1 } };
os.api('stats').then(stats => {
this.stats = stats;

View File

@ -1,23 +1,22 @@
<template>
<div v-if="meta">
<XSetup v-if="meta.requireSetup"/>
<XEntrance v-else/>
<div>
<XEntrance/>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import XSetup from './welcome.setup.vue';
import XEntrance from './welcome.entrance.a.vue';
import { instanceName } from '@/config';
import * as os from '@/os';
import { definePageMetadata } from '@/scripts/page-metadata';
let meta = $ref(null);
// let meta = $ref(null);
const meta = { 'version': '13.6.1-simkey', 'uri': 'https://kokt.club', 'langs': [], 'repositoryUrl': 'https://github.com/misskey-dev/misskey', 'feedbackUrl': 'https://github.com/misskey-dev/misskey/issues/new', 'disableRegistration': false, 'emailRequiredForSignup': false, 'enableHcaptcha': false, 'hcaptchaSiteKey': null, 'enableRecaptcha': true, 'recaptchaSiteKey': '6LcSVvkhAAAAAHfnEeJhfI_XJLnfn8-gPHqZ4K5z', 'enableTurnstile': false, 'turnstileSiteKey': null, 'swPublickey': 'BJO5qBTaw1t5O448MwtH4jikC9JG0V682uVftWHPNU05-PE5-aAuj14zBLPPpgJP_ifpndg0cVn0Ka3oE453ZkA', 'themeColor': null, 'mascotImageUrl': '/assets/ai.png', 'bannerUrl': 'https://s3.kokt.club/files/a952f48b-7720-4b00-9d15-f044150db378.webp', 'errorImageUrl': 'https://xn--931a.moe/aiart/yubitun.png', 'iconUrl': 'https://s3.kokt.club/files/e2149c00-311a-4348-a548-0877831b4b08.png', 'backgroundImageUrl': 'https://s3.kokt.club/files/a952f48b-7720-4b00-9d15-f044150db378.webp', 'logoImageUrl': null, 'maxNoteTextLength': 8192, 'defaultLightTheme': null, 'defaultDarkTheme': null, 'ads': [], 'enableEmail': true, 'enableTwitterIntegration': false, 'enableGithubIntegration': false, 'enableDiscordIntegration': false, 'enableServiceWorker': true, 'translatorAvailable': true, 'policies': { 'gtlAvailable': true, 'ltlAvailable': true, 'canPublicNote': true, 'canInvite': false, 'canManageCustomEmojis': false, 'canHideAds': false, 'driveCapacityMb': 20480, 'pinLimit': 5, 'antennaLimit': 10, 'wordMuteLimit': 200, 'webhookLimit': 10, 'clipLimit': 20, 'noteEachClipsLimit': 2000, 'userListLimit': 15, 'userEachUserListsLimit': 100, 'rateLimitFactor': 1 } };
os.api('meta', { detail: true }).then(res => {
meta = res;
});
// os.api('meta', { detail: true }).then(res => {
// meta = res;
// });
const headerActions = $computed(() => []);

View File

@ -6,7 +6,7 @@ export function char2twemojiFilePath(char: string): string {
if (!codes.includes('200d')) codes = codes.filter(x => x !== 'fe0f');
codes = codes.filter(x => x && x.length);
const fileName = codes.join('-');
return `${twemojiSvgBase}/${fileName}.svg`;
return `https://simkey.net/${twemojiSvgBase}/${fileName}.svg`;
}
export function char2fluentEmojiFilePath(char: string): string {

View File

@ -0,0 +1,70 @@
html {
background-color: var(--bg);
color: var(--fg);
}
#splash {
position: fixed;
z-index: 10000;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
cursor: wait;
background-color: var(--bg);
opacity: 1;
transition: opacity 0.5s ease;
}
#splashIcon {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
width: 64px;
height: 64px;
pointer-events: none;
}
#splashSpinner {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
display: inline-block;
width: 28px;
height: 28px;
transform: translateY(70px);
color: var(--accent);
}
#splashSpinner > .spinner {
position: absolute;
top: 0;
left: 0;
width: 28px;
height: 28px;
fill-rule: evenodd;
clip-rule: evenodd;
stroke-linecap: round;
stroke-linejoin: round;
stroke-miterlimit: 1.5;
}
#splashSpinner > .spinner.bg {
opacity: 0.275;
}
#splashSpinner > .spinner.fg {
animation: splashSpinner 0.5s linear infinite;
}
@keyframes splashSpinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

View File

@ -39,7 +39,7 @@ function toBase62(n: number): string {
export default defineConfig(({ command, mode }) => {
return {
base: '/vite/',
// base: '/vite/',
plugins: [
pluginVue({
@ -53,7 +53,8 @@ export default defineConfig(({ command, mode }) => {
alias: {
'@/': __dirname + '/src/',
'/client-assets/': __dirname + '/assets/',
'/static-assets/': __dirname + '/../backend/assets/',
// '/static-assets/': __dirname + '/../backend/assets/',
'/static-assets/': __dirname + '/assets/',
'/fluent-emojis/': __dirname + '/../../fluent-emojis/dist/',
'/fluent-emoji/': __dirname + '/../../fluent-emojis/dist/',
},
@ -104,7 +105,8 @@ export default defineConfig(({ command, mode }) => {
},
},
cssCodeSplit: true,
outDir: __dirname + '/../../built/_vite_',
// outDir: __dirname + '/../../built/_vite_',
outDir: __dirname + '/built/',
assetsDir: '.',
emptyOutDir: false,
sourcemap: process.env.NODE_ENV === 'development',