Compare commits

...

13 Commits

Author SHA1 Message Date
unknown cc751dc13a Disable nyaize
API report (misskey.js) / report (push) Has been cancelled
2026-04-16 15:00:50 +09:00
unknown a3fd4ed09d Use default true to square avatars 2026-04-16 14:24:54 +09:00
unknown b160f93713 Revert "Adjust Dockerfile for deployment"
This reverts commit c8e4244091.
2026-04-14 21:39:21 +09:00
unknown c8e4244091 Adjust Dockerfile for deployment 2026-04-14 18:13:23 +09:00
unknown e800e45fb5 Replace splash image 2026-04-14 18:13:14 +09:00
unknown 0d3eeb017f Replace favicon and app icons 2026-04-14 18:13:06 +09:00
github-actions[bot] b97683cdb2 Release: 2026.3.2 2026-03-31 12:14:38 +00:00
github-actions[bot] ece9679cc4 Bump version to 2026.3.2-beta.0 2026-03-23 11:14:32 +00:00
かっこかり c5fd36094d enhance(frontend): ウィンドウの初期サイズを画面サイズから動的に決めるように (#17257)
* enhance(frontend): ウィンドウの初期サイズを画面サイズから動的に決めるように

* Update Changelog

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-03-22 13:32:45 +09:00
かっこかり b5a6e12439 fix(frontend): ウィンドウのタイトルをクリックしても最前面に出ないのを修正 (#17255)
* fix(frontend): ウィンドウのタイトルをクリックしても最前面に出ないのを修正

* Update Changelog
2026-03-22 13:21:14 +09:00
github-actions[bot] 1d171aeb96 Bump version to 2026.3.2-alpha.2 2026-03-21 03:32:26 +00:00
かっこかり b826a16231 fix(backend): 初期読込時に必要なフロントエンドのアセットがすべて読み込まれていない問題を修正 (#17254)
* fix: バックエンドのCSS読み込みの方法が悪いのを修正

* fix: 使用されないpreloadを削除

* Update Changelog

* add comments
2026-03-21 12:26:50 +09:00
renovate[bot] 9e38288da5 chore(deps): update [github actions] update dependencies (#17253)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-20 20:24:58 +09:00
34 changed files with 202 additions and 101 deletions
+2 -2
View File
@@ -19,10 +19,10 @@ jobs:
uses: actions/checkout@v6.0.2 uses: actions/checkout@v6.0.2
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
- name: Checkout head - name: Checkout head
uses: actions/checkout@v6.0.2 uses: actions/checkout@v6.0.2
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -29,7 +29,7 @@ jobs:
- name: setup node - name: setup node
id: setup-node id: setup-node
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: pnpm cache: pnpm
+2 -2
View File
@@ -30,9 +30,9 @@ jobs:
ref: ${{ matrix.ref }} ref: ${{ matrix.ref }}
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
+2 -2
View File
@@ -45,9 +45,9 @@ jobs:
ref: ${{ matrix.ref }} ref: ${{ matrix.ref }}
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
+6 -6
View File
@@ -41,8 +41,8 @@ jobs:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- uses: actions/setup-node@v6.2.0 - uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
@@ -74,8 +74,8 @@ jobs:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- uses: actions/setup-node@v6.2.0 - uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
@@ -105,8 +105,8 @@ jobs:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- uses: actions/setup-node@v6.2.0 - uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
+2 -2
View File
@@ -21,8 +21,8 @@ jobs:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- uses: actions/setup-node@v6.2.0 - uses: actions/setup-node@v6.3.0
with: with:
node-version-file: ".node-version" node-version-file: ".node-version"
cache: "pnpm" cache: "pnpm"
+2 -2
View File
@@ -20,9 +20,9 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
+2 -2
View File
@@ -37,9 +37,9 @@ jobs:
if: github.event_name == 'pull_request_target' if: github.event_name == 'pull_request_target'
run: git checkout "$(git rev-list --parents -n1 HEAD | cut -d" " -f3)" run: git checkout "$(git rev-list --parents -n1 HEAD | cut -d" " -f3)"
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
+7 -7
View File
@@ -49,7 +49,7 @@ jobs:
ports: ports:
- 56312:6379 - 56312:6379
meilisearch: meilisearch:
image: getmeili/meilisearch:v1.36.0 image: getmeili/meilisearch:v1.38.2
ports: ports:
- 57712:7700 - 57712:7700
env: env:
@@ -61,7 +61,7 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Get current date - name: Get current date
id: current-date id: current-date
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
@@ -93,7 +93,7 @@ jobs:
fi fi
done done
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: ${{ matrix.node-version-file }} node-version-file: ${{ matrix.node-version-file }}
cache: 'pnpm' cache: 'pnpm'
@@ -140,9 +140,9 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: ${{ matrix.node-version-file }} node-version-file: ${{ matrix.node-version-file }}
cache: 'pnpm' cache: 'pnpm'
@@ -184,12 +184,12 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Get current date - name: Get current date
id: current-date id: current-date
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: ${{ matrix.node-version-file }} node-version-file: ${{ matrix.node-version-file }}
cache: 'pnpm' cache: 'pnpm'
+2 -2
View File
@@ -36,7 +36,7 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Get current date - name: Get current date
id: current-date id: current-date
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
@@ -68,7 +68,7 @@ jobs:
fi fi
done done
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: ${{ matrix.node-version-file }} node-version-file: ${{ matrix.node-version-file }}
cache: 'pnpm' cache: 'pnpm'
+4 -4
View File
@@ -32,9 +32,9 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
@@ -86,9 +86,9 @@ jobs:
#- uses: browser-actions/setup-firefox@latest #- uses: browser-actions/setup-firefox@latest
# if: ${{ matrix.browser == 'firefox' }} # if: ${{ matrix.browser == 'firefox' }}
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
+2 -2
View File
@@ -25,10 +25,10 @@ jobs:
uses: actions/checkout@v6.0.2 uses: actions/checkout@v6.0.2
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
+2 -2
View File
@@ -20,9 +20,9 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
+2 -2
View File
@@ -21,9 +21,9 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.2.0 uses: pnpm/action-setup@v4.4.0
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.2.0 uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
+3
View File
@@ -4,13 +4,16 @@
- 依存関係の更新 - 依存関係の更新
### Client ### Client
- Enhance: アプリ内ウィンドウの初期サイズを画面サイズに応じて自動で調整するように
- Fix: 絵文字パレットが空の状態でMisskeyについてのページが閲覧できない問題を修正 - Fix: 絵文字パレットが空の状態でMisskeyについてのページが閲覧できない問題を修正
- Fix: ウィンドウのタイトルをクリックしても最前面に出ないことがある問題を修正
### Server ### Server
- Fix: 自分の行ったフォロワー限定投稿または指名投稿に自分自身でリアクションなどを行った場合のイベントが流れない問題を修正 - Fix: 自分の行ったフォロワー限定投稿または指名投稿に自分自身でリアクションなどを行った場合のイベントが流れない問題を修正
- Fix: 署名付きGETリクエストにおいてAcceptヘッダを署名の対象から除外(Acceptヘッダを正規化するCDNやリバースプロキシを使用している際に挙動がおかしくなる問題を修正) - Fix: 署名付きGETリクエストにおいてAcceptヘッダを署名の対象から除外(Acceptヘッダを正規化するCDNやリバースプロキシを使用している際に挙動がおかしくなる問題を修正)
- Fix: WebSocket接続におけるノートの非表示ロジックを修正 - Fix: WebSocket接続におけるノートの非表示ロジックを修正
- Fix: チャンネルミュートを有効にしている際に、一部のタイムラインやノート一覧が空になる問題を修正 - Fix: チャンネルミュートを有効にしている際に、一部のタイムラインやノート一覧が空になる問題を修正
- Fix: 初期読込時に必要なフロントエンドのアセットがすべて読み込まれていない問題を修正
## 2026.3.1 ## 2026.3.1
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "misskey", "name": "misskey",
"version": "2026.3.2-alpha.1", "version": "2026.3.2",
"codename": "nasubi", "codename": "nasubi",
"repository": { "repository": {
"type": "git", "type": "git",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 27 KiB

-11
View File
@@ -10,7 +10,6 @@ import { type FastifyServerOptions } from 'fastify';
import type * as Sentry from '@sentry/node'; import type * as Sentry from '@sentry/node';
import type * as SentryVue from '@sentry/vue'; import type * as SentryVue from '@sentry/vue';
import type { RedisOptions } from 'ioredis'; import type { RedisOptions } from 'ioredis';
import type { ManifestChunk } from 'vite';
type RedisOptionsSource = Partial<RedisOptions> & { type RedisOptionsSource = Partial<RedisOptions> & {
host: string; host: string;
@@ -189,9 +188,7 @@ export type Config = {
authUrl: string; authUrl: string;
driveUrl: string; driveUrl: string;
userAgent: string; userAgent: string;
frontendEntry: ManifestChunk;
frontendManifestExists: boolean; frontendManifestExists: boolean;
frontendEmbedEntry: ManifestChunk;
frontendEmbedManifestExists: boolean; frontendEmbedManifestExists: boolean;
mediaProxy: string; mediaProxy: string;
externalMediaProxyEnabled: boolean; externalMediaProxyEnabled: boolean;
@@ -250,12 +247,6 @@ export function loadConfig(): Config {
const frontendManifestExists = fs.existsSync(resolve(projectBuiltDir, '_frontend_vite_/manifest.json')); const frontendManifestExists = fs.existsSync(resolve(projectBuiltDir, '_frontend_vite_/manifest.json'));
const frontendEmbedManifestExists = fs.existsSync(resolve(projectBuiltDir, '_frontend_embed_vite_/manifest.json')); const frontendEmbedManifestExists = fs.existsSync(resolve(projectBuiltDir, '_frontend_embed_vite_/manifest.json'));
const frontendManifest = frontendManifestExists ?
JSON.parse(fs.readFileSync(resolve(projectBuiltDir, '_frontend_vite_/manifest.json'), 'utf-8'))
: { 'src/_boot_.ts': { file: null } };
const frontendEmbedManifest = frontendEmbedManifestExists ?
JSON.parse(fs.readFileSync(resolve(projectBuiltDir, '_frontend_embed_vite_/manifest.json'), 'utf-8'))
: { 'src/boot.ts': { file: null } };
const config = JSON.parse(fs.readFileSync(compiledConfigFilePath, 'utf-8')) as Source; const config = JSON.parse(fs.readFileSync(compiledConfigFilePath, 'utf-8')) as Source;
@@ -337,9 +328,7 @@ export function loadConfig(): Config {
config.videoThumbnailGenerator.endsWith('/') ? config.videoThumbnailGenerator.substring(0, config.videoThumbnailGenerator.length - 1) : config.videoThumbnailGenerator config.videoThumbnailGenerator.endsWith('/') ? config.videoThumbnailGenerator.substring(0, config.videoThumbnailGenerator.length - 1) : config.videoThumbnailGenerator
: null, : null,
userAgent: `Misskey/${version} (${config.url})`, userAgent: `Misskey/${version} (${config.url})`,
frontendEntry: frontendManifest['src/_boot_.ts'],
frontendManifestExists: frontendManifestExists, frontendManifestExists: frontendManifestExists,
frontendEmbedEntry: frontendEmbedManifest['src/boot.ts'],
frontendEmbedManifestExists: frontendEmbedManifestExists, frontendEmbedManifestExists: frontendEmbedManifestExists,
perChannelMaxNoteCacheCount: config.perChannelMaxNoteCacheCount ?? 1000, perChannelMaxNoteCacheCount: config.perChannelMaxNoteCacheCount ?? 1000,
perUserNotificationsMaxCount: config.perUserNotificationsMaxCount ?? 500, perUserNotificationsMaxCount: config.perUserNotificationsMaxCount ?? 500,
@@ -3,9 +3,9 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { dirname } from 'node:path'; import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url'; import { fileURLToPath } from 'node:url';
import { promises as fsp } from 'node:fs'; import { promises as fsp, existsSync } from 'node:fs';
import { languages } from 'i18n/const'; import { languages } from 'i18n/const';
import { Injectable, Inject } from '@nestjs/common'; import { Injectable, Inject } from '@nestjs/common';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
@@ -13,21 +13,34 @@ import { bindThis } from '@/decorators.js';
import { htmlSafeJsonStringify } from '@/misc/json-stringify-html-safe.js'; import { htmlSafeJsonStringify } from '@/misc/json-stringify-html-safe.js';
import { MetaEntityService } from '@/core/entities/MetaEntityService.js'; import { MetaEntityService } from '@/core/entities/MetaEntityService.js';
import type { FastifyReply } from 'fastify'; import type { FastifyReply } from 'fastify';
import type { Manifest } from 'vite';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import type { MiMeta } from '@/models/Meta.js'; import type { MiMeta } from '@/models/Meta.js';
import type { CommonData } from './views/_.js'; import type { CommonData, ViteFiles } from './views/_.js';
const _filename = fileURLToPath(import.meta.url); const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename); const _dirname = dirname(_filename);
const frontendVitePublic = `${_dirname}/../../../../frontend/public/`; let rootDir = _dirname;
const frontendEmbedVitePublic = `${_dirname}/../../../../frontend-embed/public/`; // 見つかるまで上に遡る
while (!existsSync(resolve(rootDir, 'packages'))) {
const parentDir = dirname(rootDir);
if (parentDir === rootDir) {
throw new Error('Cannot find root directory');
}
rootDir = parentDir;
}
const frontendViteBuilt = resolve(rootDir, 'built/_frontend_vite_');
const frontendEmbedViteBuilt = resolve(rootDir, 'built/_frontend_embed_vite_');
@Injectable() @Injectable()
export class HtmlTemplateService { export class HtmlTemplateService {
private frontendBootloadersFetched = false; private frontendAssetsFetched = false;
public frontendViteFiles: ViteFiles | null = null;
public frontendBootloaderJs: string | null = null; public frontendBootloaderJs: string | null = null;
public frontendBootloaderCss: string | null = null; public frontendBootloaderCss: string | null = null;
public frontendEmbedViteFiles: ViteFiles | null = null;
public frontendEmbedBootloaderJs: string | null = null; public frontendEmbedBootloaderJs: string | null = null;
public frontendEmbedBootloaderCss: string | null = null; public frontendEmbedBootloaderCss: string | null = null;
@@ -42,18 +55,92 @@ export class HtmlTemplateService {
) { ) {
} }
// 初期ロードで読み込むべきファイルのパスを収集する。
// See https://ja.vite.dev/guide/backend-integration
@bindThis @bindThis
private async prepareFrontendBootloaders() { private collectViteAssetFiles(manifest: Manifest): ViteFiles {
if (this.frontendBootloadersFetched) return; const entryFile = Object.values(manifest).find((chunk) => chunk.isEntry);
this.frontendBootloadersFetched = true; if (!entryFile) return {
entryJs: null,
css: [],
modulePreloads: [],
};
const [bootJs, bootCss, embedBootJs, embedBootCss] = await Promise.all([ const seenChunkIds = new Set<string>();
fsp.readFile(`${frontendVitePublic}loader/boot.js`, 'utf-8').catch(() => null), const cssFiles = new Set<string>();
fsp.readFile(`${frontendVitePublic}loader/style.css`, 'utf-8').catch(() => null), const modulePreloads = new Set<string>();
fsp.readFile(`${frontendEmbedVitePublic}loader/boot.js`, 'utf-8').catch(() => null),
fsp.readFile(`${frontendEmbedVitePublic}loader/style.css`, 'utf-8').catch(() => null), if (entryFile.css) {
entryFile.css.forEach((css) => cssFiles.add(css));
}
if (entryFile.imports != null && Array.isArray(entryFile.imports)) {
function collectImports(imports: string[], recursive = false) {
for (const importId of imports) {
if (seenChunkIds.has(importId)) continue;
seenChunkIds.add(importId);
const importedChunk = manifest[importId];
if (!importedChunk) return;
if (importedChunk.css) {
importedChunk.css.forEach((css) => cssFiles.add(css));
}
if (importedChunk.imports != null && Array.isArray(importedChunk.imports)) {
collectImports(importedChunk.imports, true);
}
if (!recursive) {
modulePreloads.add(importedChunk.file);
}
}
}
collectImports(entryFile.imports);
}
return {
entryJs: entryFile.file,
css: Array.from(cssFiles),
modulePreloads: Array.from(modulePreloads),
};
}
@bindThis
private async prepareFrontendAssets() {
if (this.frontendAssetsFetched) return;
this.frontendAssetsFetched = true;
const [
bootJs,
bootCss,
embedBootJs,
embedBootCss,
] = await Promise.all([
fsp.readFile(resolve(frontendViteBuilt, 'loader/boot.js'), 'utf-8').catch(() => null),
fsp.readFile(resolve(frontendViteBuilt, 'loader/style.css'), 'utf-8').catch(() => null),
fsp.readFile(resolve(frontendEmbedViteBuilt, 'loader/boot.js'), 'utf-8').catch(() => null),
fsp.readFile(resolve(frontendEmbedViteBuilt, 'loader/style.css'), 'utf-8').catch(() => null),
]); ]);
let feViteManifest: Manifest | null = null;
let embedFeViteManifest: Manifest | null = null;
if (this.config.frontendManifestExists) {
const manifestContent = await fsp.readFile(resolve(frontendViteBuilt, 'manifest.json'), 'utf-8').catch(() => null);
feViteManifest = manifestContent ? JSON.parse(manifestContent) : null;
}
if (this.config.frontendEmbedManifestExists) {
const manifestContent = await fsp.readFile(resolve(frontendEmbedViteBuilt, 'manifest.json'), 'utf-8').catch(() => null);
embedFeViteManifest = manifestContent ? JSON.parse(manifestContent) : null;
}
if (feViteManifest != null) {
this.frontendViteFiles = this.collectViteAssetFiles(feViteManifest);
}
if (bootJs != null) { if (bootJs != null) {
this.frontendBootloaderJs = bootJs; this.frontendBootloaderJs = bootJs;
} }
@@ -62,6 +149,10 @@ export class HtmlTemplateService {
this.frontendBootloaderCss = bootCss; this.frontendBootloaderCss = bootCss;
} }
if (embedFeViteManifest != null) {
this.frontendEmbedViteFiles = this.collectViteAssetFiles(embedFeViteManifest);
}
if (embedBootJs != null) { if (embedBootJs != null) {
this.frontendEmbedBootloaderJs = embedBootJs; this.frontendEmbedBootloaderJs = embedBootJs;
} }
@@ -73,7 +164,7 @@ export class HtmlTemplateService {
@bindThis @bindThis
public async getCommonData(): Promise<CommonData> { public async getCommonData(): Promise<CommonData> {
await this.prepareFrontendBootloaders(); await this.prepareFrontendAssets();
return { return {
version: this.config.version, version: this.config.version,
@@ -90,8 +181,10 @@ export class HtmlTemplateService {
metaJson: htmlSafeJsonStringify(await this.metaEntityService.packDetailed(this.meta)), metaJson: htmlSafeJsonStringify(await this.metaEntityService.packDetailed(this.meta)),
now: Date.now(), now: Date.now(),
federationEnabled: this.meta.federation !== 'none', federationEnabled: this.meta.federation !== 'none',
frontendViteFiles: this.frontendViteFiles,
frontendBootloaderJs: this.frontendBootloaderJs, frontendBootloaderJs: this.frontendBootloaderJs,
frontendBootloaderCss: this.frontendBootloaderCss, frontendBootloaderCss: this.frontendBootloaderCss,
frontendEmbedViteFiles: this.frontendEmbedViteFiles,
frontendEmbedBootloaderJs: this.frontendEmbedBootloaderJs, frontendEmbedBootloaderJs: this.frontendEmbedBootloaderJs,
frontendEmbedBootloaderCss: this.frontendEmbedBootloaderCss, frontendEmbedBootloaderCss: this.frontendEmbedBootloaderCss,
}; };
@@ -24,6 +24,12 @@ export type MinimumCommonData = {
config: Config; config: Config;
}; };
export type ViteFiles = {
entryJs: string | null;
css: string[];
modulePreloads: string[];
};
export type CommonData = MinimumCommonData & { export type CommonData = MinimumCommonData & {
langs: string[]; langs: string[];
instanceName: string; instanceName: string;
@@ -36,8 +42,10 @@ export type CommonData = MinimumCommonData & {
instanceUrl: string; instanceUrl: string;
now: number; now: number;
federationEnabled: boolean; federationEnabled: boolean;
frontendViteFiles: ViteFiles | null;
frontendBootloaderJs: string | null; frontendBootloaderJs: string | null;
frontendBootloaderCss: string | null; frontendBootloaderCss: string | null;
frontendEmbedViteFiles: ViteFiles | null;
frontendEmbedBootloaderJs: string | null; frontendEmbedBootloaderJs: string | null;
frontendEmbedBootloaderCss: string | null; frontendEmbedBootloaderCss: string | null;
metaJson?: string; metaJson?: string;
@@ -46,11 +46,11 @@ export function BaseEmbed(props: PropsWithChildren<CommonProps<{
<link rel="icon" href={props.icon ?? '/favicon.ico'} /> <link rel="icon" href={props.icon ?? '/favicon.ico'} />
<link rel="apple-touch-icon" href={props.appleTouchIcon ?? '/apple-touch-icon.png'} /> <link rel="apple-touch-icon" href={props.appleTouchIcon ?? '/apple-touch-icon.png'} />
{!props.config.frontendEmbedManifestExists ? <script type="module" src="/embed_vite/@vite/client"></script> : null} {props.frontendEmbedViteFiles == null ? <script type="module" src="/embed_vite/@vite/client"></script> : null}
{props.config.frontendEmbedEntry.css != null ? props.config.frontendEmbedEntry.css.map((href) => ( {(props.frontendEmbedViteFiles?.css ?? []).map((href) => (
<link rel="stylesheet" href={`/embed_vite/${href}`} /> <link rel="stylesheet" href={`/embed_vite/${href}`} />
)) : null} ))}
{props.titleSlot ?? <title safe>{props.title || 'Misskey'}</title>} {props.titleSlot ?? <title safe>{props.title || 'Misskey'}</title>}
@@ -62,7 +62,7 @@ export function BaseEmbed(props: PropsWithChildren<CommonProps<{
<script> <script>
const VERSION = '{props.version}'; const VERSION = '{props.version}';
const CLIENT_ENTRY = {JSON.stringify(props.config.frontendEmbedEntry.file)}; const CLIENT_ENTRY = {JSON.stringify(props.frontendEmbedViteFiles?.entryJs ?? null)};
const LANGS = {JSON.stringify(props.langs)}; const LANGS = {JSON.stringify(props.langs)};
</script> </script>
@@ -53,11 +53,11 @@ export function Layout(props: PropsWithChildren<CommonProps<{
{props.infoImageUrl != null ? <link rel="prefetch" as="image" href={props.infoImageUrl} /> : null} {props.infoImageUrl != null ? <link rel="prefetch" as="image" href={props.infoImageUrl} /> : null}
{props.notFoundImageUrl != null ? <link rel="prefetch" as="image" href={props.notFoundImageUrl} /> : null} {props.notFoundImageUrl != null ? <link rel="prefetch" as="image" href={props.notFoundImageUrl} /> : null}
{!props.config.frontendManifestExists ? <script type="module" src="/vite/@vite/client"></script> : null} {props.frontendViteFiles == null ? <script type="module" src="/vite/@vite/client"></script> : null}
{props.config.frontendEntry.css != null ? props.config.frontendEntry.css.map((href) => ( {(props.frontendViteFiles?.css ?? []).map((href) => (
<link rel="stylesheet" href={`/vite/${href}`} /> <link rel="stylesheet" href={`/vite/${href}`} />
)) : null} ))}
{props.titleSlot ?? <title safe>{props.title || 'Misskey'}</title>} {props.titleSlot ?? <title safe>{props.title || 'Misskey'}</title>}
@@ -80,7 +80,7 @@ export function Layout(props: PropsWithChildren<CommonProps<{
<script> <script>
const VERSION = '{props.version}'; const VERSION = '{props.version}';
const CLIENT_ENTRY = {JSON.stringify(props.config.frontendEntry.file)}; const CLIENT_ENTRY = {JSON.stringify(props.frontendViteFiles?.entryJs ?? null)};
const LANGS = {JSON.stringify(props.langs)}; const LANGS = {JSON.stringify(props.langs)};
</script> </script>
@@ -6,8 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<MkWindow <MkWindow
ref="window" ref="window"
:initialWidth="800"
:initialHeight="500"
:canResize="true" :canResize="true"
@closed="emit('closed')" @closed="emit('closed')"
> >
@@ -6,8 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<MkWindow <MkWindow
ref="windowEl" ref="windowEl"
:initialWidth="500"
:initialHeight="500"
:canResize="true" :canResize="true"
:closeButton="true" :closeButton="true"
:buttonsLeft="buttonsLeft" :buttonsLeft="buttonsLeft"
+19 -7
View File
@@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
@afterLeave="emit('closed')" @afterLeave="emit('closed')"
> >
<div v-if="showing" ref="rootEl" :class="[$style.root, { [$style.maximized]: maximized }]"> <div v-if="showing" ref="rootEl" :class="[$style.root, { [$style.maximized]: maximized }]">
<div :class="$style.body" class="_shadow" @mousedown="onBodyMousedown" @keydown="onKeydown"> <div :class="$style.body" class="_shadow" @pointerdown="onBodyPointerDown" @keydown="onKeydown">
<div :class="[$style.header, { [$style.mini]: mini }]" @contextmenu.prevent.stop="onContextmenu"> <div :class="[$style.header, { [$style.mini]: mini }]" @contextmenu.prevent.stop="onContextmenu">
<span :class="$style.headerLeft"> <span :class="$style.headerLeft">
<template v-if="!minimized"> <template v-if="!minimized">
@@ -106,8 +106,8 @@ function capturePointer(evt: PointerEvent) {
} }
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
initialWidth: number; initialWidth?: number | null;
initialHeight: number | null; initialHeight?: number | null;
canResize?: boolean; canResize?: boolean;
closeButton?: boolean; closeButton?: boolean;
mini?: boolean; mini?: boolean;
@@ -116,7 +116,7 @@ const props = withDefaults(defineProps<{
buttonsLeft?: WindowButton[]; buttonsLeft?: WindowButton[];
buttonsRight?: WindowButton[]; buttonsRight?: WindowButton[];
}>(), { }>(), {
initialWidth: 400, initialWidth: null,
initialHeight: null, initialHeight: null,
canResize: false, canResize: false,
closeButton: true, closeButton: true,
@@ -131,6 +131,12 @@ const emit = defineEmits<{
(ev: 'closed'): void; (ev: 'closed'): void;
}>(); }>();
const INITIAL_WINDOW_WIDTH_RATIO = 0.5;
const INITIAL_WINDOW_HEIGHT_RATIO = 0.75;
const INITIAL_WINDOW_WIDTH_MIN = 400; // スクリーンの最小幅に合わせるのはapplyTransormWidthの担当
const INITIAL_WINDOW_WIDTH_MAX = 1000; // 画面幅いっぱいに広がるのを防止するための最大幅
const INITIAL_WINDOW_HEIGHT_MIN = 500; // スクリーンの最小幅に合わせるのはapplyTransormHeightの担当
provide('inWindow', true); provide('inWindow', true);
const rootEl = useTemplateRef('rootEl'); const rootEl = useTemplateRef('rootEl');
@@ -216,7 +222,7 @@ function unMinimize() {
if (position.left + windowWidth > browserWidth) main.style.left = browserWidth - windowWidth + 'px'; if (position.left + windowWidth > browserWidth) main.style.left = browserWidth - windowWidth + 'px';
} }
function onBodyMousedown() { function onBodyPointerDown() {
top(); top();
} }
@@ -484,8 +490,14 @@ function onBrowserResize() {
} }
onMounted(() => { onMounted(() => {
applyTransformWidth(props.initialWidth); let initialWidth = props.initialWidth;
if (props.initialHeight) applyTransformHeight(props.initialHeight); let initialHeight = props.initialHeight;
if (initialWidth == null) initialWidth = Math.min(Math.max(Math.round(window.innerWidth * INITIAL_WINDOW_WIDTH_RATIO), INITIAL_WINDOW_WIDTH_MIN), INITIAL_WINDOW_WIDTH_MAX);
if (initialHeight == null) initialHeight = Math.max(Math.round(window.innerHeight * INITIAL_WINDOW_HEIGHT_RATIO), INITIAL_WINDOW_HEIGHT_MIN);
applyTransformWidth(initialWidth);
applyTransformHeight(initialHeight);
if (rootEl.value) { if (rootEl.value) {
applyTransformTop((window.innerHeight / 2) - (rootEl.value.offsetHeight / 2)); applyTransformTop((window.innerHeight / 2) - (rootEl.value.offsetHeight / 2));
@@ -133,9 +133,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<div class="_gaps_m"> <div class="_gaps_m">
<SearchMarker :keywords="['cat']"> <SearchMarker :keywords="['cat']">
<MkSwitch v-model="profile.isCat"> <MkSwitch v-model="profile.isCat" :disabled="true">
<template #label><SearchLabel>{{ i18n.ts.flagAsCat }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.flagAsCat }}</SearchLabel></template>
<template #caption>{{ i18n.ts.flagAsCatDescription }}</template> <template #caption>nyaizeは無効化しています</template>
</MkSwitch> </MkSwitch>
</SearchMarker> </SearchMarker>
+1 -1
View File
@@ -313,7 +313,7 @@ export const store = markRaw(new Pizzax('base', {
}, },
squareAvatars: { squareAvatars: {
where: 'device', where: 'device',
default: false, default: true,
}, },
showAvatarDecorations: { showAvatarDecorations: {
where: 'device', where: 'device',
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"type": "module", "type": "module",
"name": "misskey-js", "name": "misskey-js",
"version": "2026.3.2-alpha.1", "version": "2026.3.2",
"description": "Misskey SDK for JavaScript", "description": "Misskey SDK for JavaScript",
"license": "MIT", "license": "MIT",
"main": "./built/index.js", "main": "./built/index.js",
+12 -12
View File
@@ -12,16 +12,16 @@ const koRegex3 = /(야(?=\?))|(야$)|(야(?= ))/gm;
export function nyaize(text: string): string { export function nyaize(text: string): string {
return text return text
// ja-JP // // ja-JP
.replaceAll('な', 'にゃ').replaceAll('ナ', 'ニャ').replaceAll('ナ', 'ニャ') // .replaceAll('な', 'にゃ').replaceAll('ナ', 'ニャ').replaceAll('ナ', 'ニャ')
// en-US // // en-US
.replace(enRegex1, x => x === 'A' ? 'YA' : 'ya') // .replace(enRegex1, x => x === 'A' ? 'YA' : 'ya')
.replace(enRegex2, x => x === 'ING' ? 'YAN' : 'yan') // .replace(enRegex2, x => x === 'ING' ? 'YAN' : 'yan')
.replace(enRegex3, x => x === 'ONE' ? 'NYAN' : 'nyan') // .replace(enRegex3, x => x === 'ONE' ? 'NYAN' : 'nyan')
// ko-KR // // ko-KR
.replace(koRegex1, match => !isNaN(match.charCodeAt(0)) ? String.fromCharCode( // .replace(koRegex1, match => !isNaN(match.charCodeAt(0)) ? String.fromCharCode(
match.charCodeAt(0) + '냐'.charCodeAt(0) - '나'.charCodeAt(0), // match.charCodeAt(0) + '냐'.charCodeAt(0) - '나'.charCodeAt(0),
) : match) // ) : match)
.replace(koRegex2, '다냥') // .replace(koRegex2, '다냥')
.replace(koRegex3, '냥'); // .replace(koRegex3, '냥');
} }