Compare commits
10 Commits
57ed2914d1
...
c8e4244091
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8e4244091 | ||
|
|
e800e45fb5 | ||
|
|
0d3eeb017f | ||
|
|
b97683cdb2 | ||
|
|
ece9679cc4 | ||
|
|
c5fd36094d | ||
|
|
b5a6e12439 | ||
|
|
1d171aeb96 | ||
|
|
b826a16231 | ||
|
|
9e38288da5 |
4
.github/workflows/api-misskey-js.yml
vendored
|
|
@ -19,10 +19,10 @@ jobs:
|
|||
uses: actions/checkout@v6.0.2
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
2
.github/workflows/changelog-check.yml
vendored
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
- name: Checkout head
|
||||
uses: actions/checkout@v6.0.2
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ jobs:
|
|||
|
||||
- name: setup node
|
||||
id: setup-node
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: pnpm
|
||||
|
|
|
|||
4
.github/workflows/get-api-diff.yml
vendored
|
|
@ -30,9 +30,9 @@ jobs:
|
|||
ref: ${{ matrix.ref }}
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/get-backend-memory.yml
vendored
|
|
@ -45,9 +45,9 @@ jobs:
|
|||
ref: ${{ matrix.ref }}
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
12
.github/workflows/lint.yml
vendored
|
|
@ -41,8 +41,8 @@ jobs:
|
|||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
@ -74,8 +74,8 @@ jobs:
|
|||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
@ -105,8 +105,8 @@ jobs:
|
|||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/locale.yml
vendored
|
|
@ -21,8 +21,8 @@ jobs:
|
|||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: ".node-version"
|
||||
cache: "pnpm"
|
||||
|
|
|
|||
4
.github/workflows/on-release-created.yml
vendored
|
|
@ -20,9 +20,9 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/storybook.yml
vendored
|
|
@ -37,9 +37,9 @@ jobs:
|
|||
if: github.event_name == 'pull_request_target'
|
||||
run: git checkout "$(git rev-list --parents -n1 HEAD | cut -d" " -f3)"
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
14
.github/workflows/test-backend.yml
vendored
|
|
@ -49,7 +49,7 @@ jobs:
|
|||
ports:
|
||||
- 56312:6379
|
||||
meilisearch:
|
||||
image: getmeili/meilisearch:v1.36.0
|
||||
image: getmeili/meilisearch:v1.38.2
|
||||
ports:
|
||||
- 57712:7700
|
||||
env:
|
||||
|
|
@ -61,7 +61,7 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
|
|
@ -93,7 +93,7 @@ jobs:
|
|||
fi
|
||||
done
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
|
|
@ -140,9 +140,9 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
|
|
@ -184,12 +184,12 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/test-federation.yml
vendored
|
|
@ -36,7 +36,7 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
|
|
@ -68,7 +68,7 @@ jobs:
|
|||
fi
|
||||
done
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
8
.github/workflows/test-frontend.yml
vendored
|
|
@ -32,9 +32,9 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
@ -86,9 +86,9 @@ jobs:
|
|||
#- uses: browser-actions/setup-firefox@latest
|
||||
# if: ${{ matrix.browser == 'firefox' }}
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/test-misskey-js.yml
vendored
|
|
@ -25,10 +25,10 @@ jobs:
|
|||
uses: actions/checkout@v6.0.2
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/test-production.yml
vendored
|
|
@ -20,9 +20,9 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/validate-api-json.yml
vendored
|
|
@ -21,9 +21,9 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
|
|
@ -4,13 +4,16 @@
|
|||
- 依存関係の更新
|
||||
|
||||
### Client
|
||||
- Enhance: アプリ内ウィンドウの初期サイズを画面サイズに応じて自動で調整するように
|
||||
- Fix: 絵文字パレットが空の状態でMisskeyについてのページが閲覧できない問題を修正
|
||||
- Fix: ウィンドウのタイトルをクリックしても最前面に出ないことがある問題を修正
|
||||
|
||||
### Server
|
||||
- Fix: 自分の行ったフォロワー限定投稿または指名投稿に自分自身でリアクションなどを行った場合のイベントが流れない問題を修正
|
||||
- Fix: 署名付きGETリクエストにおいてAcceptヘッダを署名の対象から除外(Acceptヘッダを正規化するCDNやリバースプロキシを使用している際に挙動がおかしくなる問題を修正)
|
||||
- Fix: WebSocket接続におけるノートの非表示ロジックを修正
|
||||
- Fix: チャンネルミュートを有効にしている際に、一部のタイムラインやノート一覧が空になる問題を修正
|
||||
- Fix: 初期読込時に必要なフロントエンドのアセットがすべて読み込まれていない問題を修正
|
||||
|
||||
|
||||
## 2026.3.1
|
||||
|
|
|
|||
14
Dockerfile
|
|
@ -1,6 +1,6 @@
|
|||
# syntax = docker/dockerfile:1.21
|
||||
# syntax = docker/dockerfile:1.4
|
||||
|
||||
ARG NODE_VERSION=22.22.0-bookworm
|
||||
ARG NODE_VERSION=22.15.0-bookworm
|
||||
|
||||
# build assets & compile TypeScript
|
||||
|
||||
|
|
@ -18,13 +18,10 @@ WORKDIR /misskey
|
|||
|
||||
COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
|
||||
COPY --link ["scripts", "./scripts"]
|
||||
COPY --link ["patches", "./patches"]
|
||||
COPY --link ["packages/backend/package.json", "./packages/backend/"]
|
||||
COPY --link ["packages/frontend-shared/package.json", "./packages/frontend-shared/"]
|
||||
COPY --link ["packages/frontend/package.json", "./packages/frontend/"]
|
||||
COPY --link ["packages/frontend-embed/package.json", "./packages/frontend-embed/"]
|
||||
COPY --link ["packages/frontend-builder/package.json", "./packages/frontend-builder/"]
|
||||
COPY --link ["packages/i18n/package.json", "./packages/i18n/"]
|
||||
COPY --link ["packages/icons-subsetter/package.json", "./packages/icons-subsetter/"]
|
||||
COPY --link ["packages/sw/package.json", "./packages/sw/"]
|
||||
COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"]
|
||||
|
|
@ -56,7 +53,6 @@ WORKDIR /misskey
|
|||
|
||||
COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
|
||||
COPY --link ["scripts", "./scripts"]
|
||||
COPY --link ["patches", "./patches"]
|
||||
COPY --link ["packages/backend/package.json", "./packages/backend/"]
|
||||
COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"]
|
||||
COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"]
|
||||
|
|
@ -74,8 +70,10 @@ FROM --platform=$TARGETPLATFORM node:${NODE_VERSION}-slim AS runner
|
|||
ARG UID="991"
|
||||
ARG GID="991"
|
||||
|
||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
RUN rm -rf /var/lib/dpkg/info/libc-bin.*
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
&& apt-get install -y \
|
||||
ffmpeg tini curl libjemalloc-dev libjemalloc2 \
|
||||
&& ln -s /usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so \
|
||||
&& groupadd -g "${GID}" misskey \
|
||||
|
|
@ -102,8 +100,6 @@ COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-js/
|
|||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-reversi/built ./packages/misskey-reversi/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-bubble-game/built ./packages/misskey-bubble-game/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/built ./packages/backend/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/src-js ./packages/backend/src-js
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/i18n/built ./packages/i18n/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/fluent-emojis /misskey/fluent-emojis
|
||||
COPY --chown=misskey:misskey . ./
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "misskey",
|
||||
"version": "2026.3.2-alpha.1",
|
||||
"version": "2026.3.2",
|
||||
"codename": "nasubi",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 27 KiB |
|
|
@ -10,7 +10,6 @@ import { type FastifyServerOptions } from 'fastify';
|
|||
import type * as Sentry from '@sentry/node';
|
||||
import type * as SentryVue from '@sentry/vue';
|
||||
import type { RedisOptions } from 'ioredis';
|
||||
import type { ManifestChunk } from 'vite';
|
||||
|
||||
type RedisOptionsSource = Partial<RedisOptions> & {
|
||||
host: string;
|
||||
|
|
@ -189,9 +188,7 @@ export type Config = {
|
|||
authUrl: string;
|
||||
driveUrl: string;
|
||||
userAgent: string;
|
||||
frontendEntry: ManifestChunk;
|
||||
frontendManifestExists: boolean;
|
||||
frontendEmbedEntry: ManifestChunk;
|
||||
frontendEmbedManifestExists: boolean;
|
||||
mediaProxy: string;
|
||||
externalMediaProxyEnabled: boolean;
|
||||
|
|
@ -250,12 +247,6 @@ export function loadConfig(): Config {
|
|||
|
||||
const frontendManifestExists = fs.existsSync(resolve(projectBuiltDir, '_frontend_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;
|
||||
|
||||
|
|
@ -337,9 +328,7 @@ export function loadConfig(): Config {
|
|||
config.videoThumbnailGenerator.endsWith('/') ? config.videoThumbnailGenerator.substring(0, config.videoThumbnailGenerator.length - 1) : config.videoThumbnailGenerator
|
||||
: null,
|
||||
userAgent: `Misskey/${version} (${config.url})`,
|
||||
frontendEntry: frontendManifest['src/_boot_.ts'],
|
||||
frontendManifestExists: frontendManifestExists,
|
||||
frontendEmbedEntry: frontendEmbedManifest['src/boot.ts'],
|
||||
frontendEmbedManifestExists: frontendEmbedManifestExists,
|
||||
perChannelMaxNoteCacheCount: config.perChannelMaxNoteCacheCount ?? 1000,
|
||||
perUserNotificationsMaxCount: config.perUserNotificationsMaxCount ?? 500,
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { dirname } from 'node:path';
|
||||
import { dirname, resolve } from 'node:path';
|
||||
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 { Injectable, Inject } from '@nestjs/common';
|
||||
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 { MetaEntityService } from '@/core/entities/MetaEntityService.js';
|
||||
import type { FastifyReply } from 'fastify';
|
||||
import type { Manifest } from 'vite';
|
||||
import type { Config } from '@/config.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 _dirname = dirname(_filename);
|
||||
|
||||
const frontendVitePublic = `${_dirname}/../../../../frontend/public/`;
|
||||
const frontendEmbedVitePublic = `${_dirname}/../../../../frontend-embed/public/`;
|
||||
let rootDir = _dirname;
|
||||
// 見つかるまで上に遡る
|
||||
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()
|
||||
export class HtmlTemplateService {
|
||||
private frontendBootloadersFetched = false;
|
||||
private frontendAssetsFetched = false;
|
||||
public frontendViteFiles: ViteFiles | null = null;
|
||||
public frontendBootloaderJs: string | null = null;
|
||||
public frontendBootloaderCss: string | null = null;
|
||||
public frontendEmbedViteFiles: ViteFiles | null = null;
|
||||
public frontendEmbedBootloaderJs: string | null = null;
|
||||
public frontendEmbedBootloaderCss: string | null = null;
|
||||
|
||||
|
|
@ -42,18 +55,92 @@ export class HtmlTemplateService {
|
|||
) {
|
||||
}
|
||||
|
||||
// 初期ロードで読み込むべきファイルのパスを収集する。
|
||||
// See https://ja.vite.dev/guide/backend-integration
|
||||
@bindThis
|
||||
private async prepareFrontendBootloaders() {
|
||||
if (this.frontendBootloadersFetched) return;
|
||||
this.frontendBootloadersFetched = true;
|
||||
private collectViteAssetFiles(manifest: Manifest): ViteFiles {
|
||||
const entryFile = Object.values(manifest).find((chunk) => chunk.isEntry);
|
||||
if (!entryFile) return {
|
||||
entryJs: null,
|
||||
css: [],
|
||||
modulePreloads: [],
|
||||
};
|
||||
|
||||
const [bootJs, bootCss, embedBootJs, embedBootCss] = await Promise.all([
|
||||
fsp.readFile(`${frontendVitePublic}loader/boot.js`, 'utf-8').catch(() => null),
|
||||
fsp.readFile(`${frontendVitePublic}loader/style.css`, 'utf-8').catch(() => null),
|
||||
fsp.readFile(`${frontendEmbedVitePublic}loader/boot.js`, 'utf-8').catch(() => null),
|
||||
fsp.readFile(`${frontendEmbedVitePublic}loader/style.css`, 'utf-8').catch(() => null),
|
||||
const seenChunkIds = new Set<string>();
|
||||
const cssFiles = new Set<string>();
|
||||
const modulePreloads = new Set<string>();
|
||||
|
||||
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) {
|
||||
this.frontendBootloaderJs = bootJs;
|
||||
}
|
||||
|
|
@ -62,6 +149,10 @@ export class HtmlTemplateService {
|
|||
this.frontendBootloaderCss = bootCss;
|
||||
}
|
||||
|
||||
if (embedFeViteManifest != null) {
|
||||
this.frontendEmbedViteFiles = this.collectViteAssetFiles(embedFeViteManifest);
|
||||
}
|
||||
|
||||
if (embedBootJs != null) {
|
||||
this.frontendEmbedBootloaderJs = embedBootJs;
|
||||
}
|
||||
|
|
@ -73,7 +164,7 @@ export class HtmlTemplateService {
|
|||
|
||||
@bindThis
|
||||
public async getCommonData(): Promise<CommonData> {
|
||||
await this.prepareFrontendBootloaders();
|
||||
await this.prepareFrontendAssets();
|
||||
|
||||
return {
|
||||
version: this.config.version,
|
||||
|
|
@ -90,8 +181,10 @@ export class HtmlTemplateService {
|
|||
metaJson: htmlSafeJsonStringify(await this.metaEntityService.packDetailed(this.meta)),
|
||||
now: Date.now(),
|
||||
federationEnabled: this.meta.federation !== 'none',
|
||||
frontendViteFiles: this.frontendViteFiles,
|
||||
frontendBootloaderJs: this.frontendBootloaderJs,
|
||||
frontendBootloaderCss: this.frontendBootloaderCss,
|
||||
frontendEmbedViteFiles: this.frontendEmbedViteFiles,
|
||||
frontendEmbedBootloaderJs: this.frontendEmbedBootloaderJs,
|
||||
frontendEmbedBootloaderCss: this.frontendEmbedBootloaderCss,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,6 +24,12 @@ export type MinimumCommonData = {
|
|||
config: Config;
|
||||
};
|
||||
|
||||
export type ViteFiles = {
|
||||
entryJs: string | null;
|
||||
css: string[];
|
||||
modulePreloads: string[];
|
||||
};
|
||||
|
||||
export type CommonData = MinimumCommonData & {
|
||||
langs: string[];
|
||||
instanceName: string;
|
||||
|
|
@ -36,8 +42,10 @@ export type CommonData = MinimumCommonData & {
|
|||
instanceUrl: string;
|
||||
now: number;
|
||||
federationEnabled: boolean;
|
||||
frontendViteFiles: ViteFiles | null;
|
||||
frontendBootloaderJs: string | null;
|
||||
frontendBootloaderCss: string | null;
|
||||
frontendEmbedViteFiles: ViteFiles | null;
|
||||
frontendEmbedBootloaderJs: string | null;
|
||||
frontendEmbedBootloaderCss: string | null;
|
||||
metaJson?: string;
|
||||
|
|
|
|||
|
|
@ -46,11 +46,11 @@ export function BaseEmbed(props: PropsWithChildren<CommonProps<{
|
|||
<link rel="icon" href={props.icon ?? '/favicon.ico'} />
|
||||
<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}`} />
|
||||
)) : null}
|
||||
))}
|
||||
|
||||
{props.titleSlot ?? <title safe>{props.title || 'Misskey'}</title>}
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ export function BaseEmbed(props: PropsWithChildren<CommonProps<{
|
|||
|
||||
<script>
|
||||
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)};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -53,11 +53,11 @@ export function Layout(props: PropsWithChildren<CommonProps<{
|
|||
{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.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}`} />
|
||||
)) : null}
|
||||
))}
|
||||
|
||||
{props.titleSlot ?? <title safe>{props.title || 'Misskey'}</title>}
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ export function Layout(props: PropsWithChildren<CommonProps<{
|
|||
|
||||
<script>
|
||||
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)};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template>
|
||||
<MkWindow
|
||||
ref="window"
|
||||
:initialWidth="800"
|
||||
:initialHeight="500"
|
||||
:canResize="true"
|
||||
@closed="emit('closed')"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template>
|
||||
<MkWindow
|
||||
ref="windowEl"
|
||||
:initialWidth="500"
|
||||
:initialHeight="500"
|
||||
:canResize="true"
|
||||
:closeButton="true"
|
||||
:buttonsLeft="buttonsLeft"
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
@afterLeave="emit('closed')"
|
||||
>
|
||||
<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">
|
||||
<span :class="$style.headerLeft">
|
||||
<template v-if="!minimized">
|
||||
|
|
@ -106,8 +106,8 @@ function capturePointer(evt: PointerEvent) {
|
|||
}
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
initialWidth: number;
|
||||
initialHeight: number | null;
|
||||
initialWidth?: number | null;
|
||||
initialHeight?: number | null;
|
||||
canResize?: boolean;
|
||||
closeButton?: boolean;
|
||||
mini?: boolean;
|
||||
|
|
@ -116,7 +116,7 @@ const props = withDefaults(defineProps<{
|
|||
buttonsLeft?: WindowButton[];
|
||||
buttonsRight?: WindowButton[];
|
||||
}>(), {
|
||||
initialWidth: 400,
|
||||
initialWidth: null,
|
||||
initialHeight: null,
|
||||
canResize: false,
|
||||
closeButton: true,
|
||||
|
|
@ -131,6 +131,12 @@ const emit = defineEmits<{
|
|||
(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);
|
||||
|
||||
const rootEl = useTemplateRef('rootEl');
|
||||
|
|
@ -216,7 +222,7 @@ function unMinimize() {
|
|||
if (position.left + windowWidth > browserWidth) main.style.left = browserWidth - windowWidth + 'px';
|
||||
}
|
||||
|
||||
function onBodyMousedown() {
|
||||
function onBodyPointerDown() {
|
||||
top();
|
||||
}
|
||||
|
||||
|
|
@ -484,8 +490,14 @@ function onBrowserResize() {
|
|||
}
|
||||
|
||||
onMounted(() => {
|
||||
applyTransformWidth(props.initialWidth);
|
||||
if (props.initialHeight) applyTransformHeight(props.initialHeight);
|
||||
let initialWidth = props.initialWidth;
|
||||
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) {
|
||||
applyTransformTop((window.innerHeight / 2) - (rootEl.value.offsetHeight / 2));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"type": "module",
|
||||
"name": "misskey-js",
|
||||
"version": "2026.3.2-alpha.1",
|
||||
"version": "2026.3.2",
|
||||
"description": "Misskey SDK for JavaScript",
|
||||
"license": "MIT",
|
||||
"main": "./built/index.js",
|
||||
|
|
|
|||