Compare commits
No commits in common. "develop" and "2025.12.0" have entirely different histories.
|
|
@ -110,19 +110,10 @@ port: 3000
|
||||||
# Changes how the server interpret the origin IP of the request.
|
# Changes how the server interpret the origin IP of the request.
|
||||||
#
|
#
|
||||||
# Any format supported by Fastify is accepted.
|
# Any format supported by Fastify is accepted.
|
||||||
# Default: trust all proxies (i.e. trustProxy: true)
|
# Default: do not trust any proxies (i.e. trustProxy: false)
|
||||||
# See: https://fastify.dev/docs/latest/reference/server/#trustproxy
|
# See: https://fastify.dev/docs/latest/reference/server/#trustproxy
|
||||||
# To improve security, we recommend that you configure your settings appropriately.
|
|
||||||
# Incorrect configuration can cause issues such as difficulty signing in,
|
|
||||||
# so please configure your settings carefully.
|
|
||||||
#
|
#
|
||||||
#trustProxy:
|
# trustProxy: false
|
||||||
# - '10.0.0.0/8'
|
|
||||||
# - '172.16.0.0/12'
|
|
||||||
# - '192.168.0.0/16'
|
|
||||||
# - '127.0.0.1/32'
|
|
||||||
# - '::1/128'
|
|
||||||
# - 'fc00::/7'
|
|
||||||
|
|
||||||
# ┌──────────────────────────┐
|
# ┌──────────────────────────┐
|
||||||
#───┘ PostgreSQL configuration └────────────────────────────────
|
#───┘ PostgreSQL configuration └────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,13 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6.0.1
|
uses: actions/checkout@v4.3.0
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4.2.0
|
uses: pnpm/action-setup@v4.2.0
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout head
|
- name: Checkout head
|
||||||
uses: actions/checkout@v6.0.1
|
uses: actions/checkout@v4.3.0
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ jobs:
|
||||||
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
|
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v6.0.1
|
uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
@ -29,7 +29,7 @@ jobs:
|
||||||
|
|
||||||
- name: setup node
|
- name: setup node
|
||||||
id: setup-node
|
id: setup-node
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
|
|
@ -53,7 +53,7 @@ jobs:
|
||||||
|
|
||||||
# packages/misskey-js/generator/built/autogen
|
# packages/misskey-js/generator/built/autogen
|
||||||
- name: Upload Generated
|
- name: Upload Generated
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: generated-misskey-js
|
name: generated-misskey-js
|
||||||
path: packages/misskey-js/generator/built/autogen
|
path: packages/misskey-js/generator/built/autogen
|
||||||
|
|
@ -66,14 +66,14 @@ jobs:
|
||||||
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
|
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v6.0.1
|
uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||||
|
|
||||||
- name: Upload From Merged
|
- name: Upload From Merged
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: actual-misskey-js
|
name: actual-misskey-js
|
||||||
path: packages/misskey-js/src/autogen
|
path: packages/misskey-js/src/autogen
|
||||||
|
|
@ -86,13 +86,13 @@ jobs:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- name: download generated-misskey-js
|
- name: download generated-misskey-js
|
||||||
uses: actions/download-artifact@v7
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: generated-misskey-js
|
name: generated-misskey-js
|
||||||
path: misskey-js-generated
|
path: misskey-js-generated
|
||||||
|
|
||||||
- name: download actual-misskey-js
|
- name: download actual-misskey-js
|
||||||
uses: actions/download-artifact@v7
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: actual-misskey-js
|
name: actual-misskey-js
|
||||||
path: misskey-js-actual
|
path: misskey-js-actual
|
||||||
|
|
@ -113,9 +113,9 @@ jobs:
|
||||||
|
|
||||||
- name: send message
|
- name: send message
|
||||||
if: steps.check-changes.outputs.changes == 'true'
|
if: steps.check-changes.outputs.changes == 'true'
|
||||||
uses: thollander/actions-comment-pull-request@v3
|
uses: thollander/actions-comment-pull-request@v2
|
||||||
with:
|
with:
|
||||||
comment-tag: check-misskey-js-autogen
|
comment_tag: check-misskey-js-autogen
|
||||||
message: |-
|
message: |-
|
||||||
Thank you for sending us a great Pull Request! 👍
|
Thank you for sending us a great Pull Request! 👍
|
||||||
Please regenerate misskey-js type definitions! 🙏
|
Please regenerate misskey-js type definitions! 🙏
|
||||||
|
|
@ -127,9 +127,9 @@ jobs:
|
||||||
|
|
||||||
- name: send message
|
- name: send message
|
||||||
if: steps.check-changes.outputs.changes == 'false'
|
if: steps.check-changes.outputs.changes == 'false'
|
||||||
uses: thollander/actions-comment-pull-request@v3
|
uses: thollander/actions-comment-pull-request@v2
|
||||||
with:
|
with:
|
||||||
comment-tag: check-misskey-js-autogen
|
comment_tag: check-misskey-js-autogen
|
||||||
mode: delete
|
mode: delete
|
||||||
message: "Thank you!"
|
message: "Thank you!"
|
||||||
create_if_not_exists: false
|
create_if_not_exists: false
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6.0.1
|
uses: actions/checkout@v4.3.0
|
||||||
- name: Check version
|
- name: Check version
|
||||||
run: |
|
run: |
|
||||||
if [ "$(jq -r '.version' package.json)" != "$(jq -r '.version' packages/misskey-js/package.json)" ]; then
|
if [ "$(jq -r '.version' package.json)" != "$(jq -r '.version' packages/misskey-js/package.json)" ]; then
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6.0.1
|
uses: actions/checkout@v4.3.0
|
||||||
- name: Check
|
- name: Check
|
||||||
run: |
|
run: |
|
||||||
counter=0
|
counter=0
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ jobs:
|
||||||
check_copyright_year:
|
check_copyright_year:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
- run: |
|
- run: |
|
||||||
if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then
|
if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then
|
||||||
echo "Please change copyright year!"
|
echo "Please change copyright year!"
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ jobs:
|
||||||
wait_time: ${{ steps.get-wait-time.outputs.wait_time }}
|
wait_time: ${{ steps.get-wait-time.outputs.wait_time }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6.0.1
|
uses: actions/checkout@v4.3.0
|
||||||
|
|
||||||
- name: Check allowed users
|
- name: Check allowed users
|
||||||
id: check-allowed-users
|
id: check-allowed-users
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ jobs:
|
||||||
platform=${{ matrix.platform }}
|
platform=${{ matrix.platform }}
|
||||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
uses: actions/checkout@v6.0.1
|
uses: actions/checkout@v4.3.0
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
|
|
@ -53,7 +53,7 @@ jobs:
|
||||||
digest="${{ steps.build.outputs.digest }}"
|
digest="${{ steps.build.outputs.digest }}"
|
||||||
touch "/tmp/digests/${digest#sha256:}"
|
touch "/tmp/digests/${digest#sha256:}"
|
||||||
- name: Upload digest
|
- name: Upload digest
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: digests-${{ env.PLATFORM_PAIR }}
|
name: digests-${{ env.PLATFORM_PAIR }}
|
||||||
path: /tmp/digests/*
|
path: /tmp/digests/*
|
||||||
|
|
@ -66,7 +66,7 @@ jobs:
|
||||||
- build
|
- build
|
||||||
steps:
|
steps:
|
||||||
- name: Download digests
|
- name: Download digests
|
||||||
uses: actions/download-artifact@v7
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
path: /tmp/digests
|
path: /tmp/digests
|
||||||
pattern: digests-*
|
pattern: digests-*
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ jobs:
|
||||||
platform=${{ matrix.platform }}
|
platform=${{ matrix.platform }}
|
||||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
uses: actions/checkout@v6.0.1
|
uses: actions/checkout@v4.3.0
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
|
|
@ -64,7 +64,7 @@ jobs:
|
||||||
digest="${{ steps.build.outputs.digest }}"
|
digest="${{ steps.build.outputs.digest }}"
|
||||||
touch "/tmp/digests/${digest#sha256:}"
|
touch "/tmp/digests/${digest#sha256:}"
|
||||||
- name: Upload digest
|
- name: Upload digest
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: digests-${{ env.PLATFORM_PAIR }}
|
name: digests-${{ env.PLATFORM_PAIR }}
|
||||||
path: /tmp/digests/*
|
path: /tmp/digests/*
|
||||||
|
|
@ -77,7 +77,7 @@ jobs:
|
||||||
- build
|
- build
|
||||||
steps:
|
steps:
|
||||||
- name: Download digests
|
- name: Download digests
|
||||||
uses: actions/download-artifact@v7
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
path: /tmp/digests
|
path: /tmp/digests
|
||||||
pattern: digests-*
|
pattern: digests-*
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ jobs:
|
||||||
DOCKLE_VERSION: 0.4.15
|
DOCKLE_VERSION: 0.4.15
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
|
|
||||||
- name: Download and install dockle v${{ env.DOCKLE_VERSION }}
|
- name: Download and install dockle v${{ env.DOCKLE_VERSION }}
|
||||||
run: |
|
run: |
|
||||||
|
|
|
||||||
|
|
@ -25,14 +25,14 @@ jobs:
|
||||||
ref: refs/pull/${{ github.event.number }}/merge
|
ref: refs/pull/${{ github.event.number }}/merge
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
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.2.0
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
@ -48,7 +48,7 @@ jobs:
|
||||||
- name: Copy API.json
|
- name: Copy API.json
|
||||||
run: cp packages/backend/built/api.json ${{ matrix.api-json-name }}
|
run: cp packages/backend/built/api.json ${{ matrix.api-json-name }}
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: api-artifact-${{ matrix.api-json-name }}
|
name: api-artifact-${{ matrix.api-json-name }}
|
||||||
path: ${{ matrix.api-json-name }}
|
path: ${{ matrix.api-json-name }}
|
||||||
|
|
@ -61,7 +61,7 @@ jobs:
|
||||||
PR_NUMBER: ${{ github.event.number }}
|
PR_NUMBER: ${{ github.event.number }}
|
||||||
run: |
|
run: |
|
||||||
echo "$PR_NUMBER" > ./pr_number
|
echo "$PR_NUMBER" > ./pr_number
|
||||||
- uses: actions/upload-artifact@v6
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: api-artifact-pr-number
|
name: api-artifact-pr-number
|
||||||
path: pr_number
|
path: pr_number
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,14 @@ jobs:
|
||||||
- 56312:6379
|
- 56312:6379
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
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.2.0
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
@ -67,7 +67,7 @@ jobs:
|
||||||
# Start the server and measure memory usage
|
# Start the server and measure memory usage
|
||||||
node packages/backend/scripts/measure-memory.mjs > ${{ matrix.memory-json-name }}
|
node packages/backend/scripts/measure-memory.mjs > ${{ matrix.memory-json-name }}
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: memory-artifact-${{ matrix.memory-json-name }}
|
name: memory-artifact-${{ matrix.memory-json-name }}
|
||||||
path: ${{ matrix.memory-json-name }}
|
path: ${{ matrix.memory-json-name }}
|
||||||
|
|
@ -81,7 +81,7 @@ jobs:
|
||||||
PR_NUMBER: ${{ github.event.number }}
|
PR_NUMBER: ${{ github.event.number }}
|
||||||
run: |
|
run: |
|
||||||
echo "$PR_NUMBER" > ./pr_number
|
echo "$PR_NUMBER" > ./pr_number
|
||||||
- uses: actions/upload-artifact@v6
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: memory-artifact-pr-number
|
name: memory-artifact-pr-number
|
||||||
path: pr_number
|
path: pr_number
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,6 @@ jobs:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/labeler@v6
|
- uses: actions/labeler@v5
|
||||||
with:
|
with:
|
||||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,13 @@ jobs:
|
||||||
pnpm_install:
|
pnpm_install:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
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.2.0
|
||||||
- uses: actions/setup-node@v6.1.0
|
- uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
@ -69,13 +69,13 @@ jobs:
|
||||||
eslint-cache-version: v1
|
eslint-cache-version: v1
|
||||||
eslint-cache-path: ${{ github.workspace }}/node_modules/.cache/eslint-${{ matrix.workspace }}
|
eslint-cache-path: ${{ github.workspace }}/node_modules/.cache/eslint-${{ matrix.workspace }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
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.2.0
|
||||||
- uses: actions/setup-node@v6.1.0
|
- uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
@ -100,13 +100,13 @@ jobs:
|
||||||
- sw
|
- sw
|
||||||
- misskey-js
|
- misskey-js
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
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.2.0
|
||||||
- uses: actions/setup-node@v6.1.0
|
- uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,13 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
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.2.0
|
||||||
- uses: actions/setup-node@v6.1.0
|
- uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ".node-version"
|
node-version-file: ".node-version"
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,13 @@ jobs:
|
||||||
id-token: write
|
id-token: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4.2.0
|
uses: pnpm/action-setup@v4.2.0
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ jobs:
|
||||||
edit:
|
edit:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v4
|
||||||
# headが$GITHUB_REF_NAME, baseが$STABLE_BRANCHかつopenのPRを1つ取得
|
# headが$GITHUB_REF_NAME, baseが$STABLE_BRANCHかつopenのPRを1つ取得
|
||||||
- name: Get PR
|
- name: Get PR
|
||||||
run: |
|
run: |
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ jobs:
|
||||||
outputs:
|
outputs:
|
||||||
pr_number: ${{ steps.get_pr.outputs.pr_number }}
|
pr_number: ${{ steps.get_pr.outputs.pr_number }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v4
|
||||||
# headが$GITHUB_REF_NAME, baseが$STABLE_BRANCHかつopenのPRを1つ取得
|
# headが$GITHUB_REF_NAME, baseが$STABLE_BRANCHかつopenのPRを1つ取得
|
||||||
- name: Get PRs
|
- name: Get PRs
|
||||||
run: |
|
run: |
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ jobs:
|
||||||
# api-artifact
|
# api-artifact
|
||||||
steps:
|
steps:
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
uses: actions/github-script@v8.0.0
|
uses: actions/github-script@v7.1.0
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
@ -60,7 +60,7 @@ jobs:
|
||||||
- name: Echo full diff
|
- name: Echo full diff
|
||||||
run: cat ./api-full.json.diff
|
run: cat ./api-full.json.diff
|
||||||
- name: Upload full diff to Artifact
|
- name: Upload full diff to Artifact
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: api-artifact
|
name: api-artifact
|
||||||
path: |
|
path: |
|
||||||
|
|
@ -89,16 +89,16 @@ jobs:
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "$FOOTER" >> ./output.md
|
echo "$FOOTER" >> ./output.md
|
||||||
- uses: thollander/actions-comment-pull-request@v3
|
- uses: thollander/actions-comment-pull-request@v2
|
||||||
with:
|
with:
|
||||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
pr_number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||||
comment-tag: show_diff
|
comment_tag: show_diff
|
||||||
file-path: ./output.md
|
filePath: ./output.md
|
||||||
- name: Tell error to PR
|
- name: Tell error to PR
|
||||||
uses: thollander/actions-comment-pull-request@v3
|
uses: thollander/actions-comment-pull-request@v2
|
||||||
if: failure() && steps.load-pr-num.outputs.pr-number
|
if: failure() && steps.load-pr-num.outputs.pr-number
|
||||||
with:
|
with:
|
||||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
pr_number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||||
comment-tag: show_diff_error
|
comment_tag: show_diff_error
|
||||||
message: |
|
message: |
|
||||||
api.jsonの差分作成中にエラーが発生しました。詳細は[Workflowのログ](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})を確認してください。
|
api.jsonの差分作成中にエラーが発生しました。詳細は[Workflowのログ](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})を確認してください。
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
uses: actions/github-script@v8.0.0
|
uses: actions/github-script@v7.1.0
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
@ -107,16 +107,16 @@ jobs:
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "$FOOTER" >> ./output.md
|
echo "$FOOTER" >> ./output.md
|
||||||
- uses: thollander/actions-comment-pull-request@v3
|
- uses: thollander/actions-comment-pull-request@v2
|
||||||
with:
|
with:
|
||||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
pr_number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||||
comment-tag: show_memory_diff
|
comment_tag: show_memory_diff
|
||||||
file-path: ./output.md
|
filePath: ./output.md
|
||||||
- name: Tell error to PR
|
- name: Tell error to PR
|
||||||
uses: thollander/actions-comment-pull-request@v3
|
uses: thollander/actions-comment-pull-request@v2
|
||||||
if: failure() && steps.load-pr-num.outputs.pr-number
|
if: failure() && steps.load-pr-num.outputs.pr-number
|
||||||
with:
|
with:
|
||||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
pr_number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||||
comment-tag: show_memory_diff_error
|
comment_tag: show_memory_diff_error
|
||||||
message: |
|
message: |
|
||||||
An error occurred while comparing backend memory usage. See [workflow logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details.
|
An error occurred while comparing backend memory usage. See [workflow logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details.
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ jobs:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- name: Reply
|
- name: Reply
|
||||||
uses: actions/github-script@v8
|
uses: actions/github-script@v6
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const body = `To dev team (@misskey-dev/dev):
|
const body = `To dev team (@misskey-dev/dev):
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,12 @@ jobs:
|
||||||
NODE_OPTIONS: "--max_old_space_size=7168"
|
NODE_OPTIONS: "--max_old_space_size=7168"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
if: github.event_name != 'pull_request_target'
|
if: github.event_name != 'pull_request_target'
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
if: github.event_name == 'pull_request_target'
|
if: github.event_name == 'pull_request_target'
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
@ -39,7 +39,7 @@ jobs:
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4.2.0
|
uses: pnpm/action-setup@v4.2.0
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
@ -90,7 +90,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
||||||
- name: Notify that Chromatic detects changes
|
- name: Notify that Chromatic detects changes
|
||||||
uses: actions/github-script@v8.0.0
|
uses: actions/github-script@v7.1.0
|
||||||
if: github.event_name != 'pull_request_target' && steps.chromatic_push.outputs.success == 'false'
|
if: github.event_name != 'pull_request_target' && steps.chromatic_push.outputs.success == 'false'
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
@ -102,7 +102,7 @@ jobs:
|
||||||
body: 'Chromatic detects changes. Please [review the changes on Chromatic](https://www.chromatic.com/builds?appId=6428f7d7b962f0b79f97d6e4).'
|
body: 'Chromatic detects changes. Please [review the changes on Chromatic](https://www.chromatic.com/builds?appId=6428f7d7b962f0b79f97d6e4).'
|
||||||
})
|
})
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: storybook
|
name: storybook
|
||||||
path: packages/frontend/storybook-static
|
path: packages/frontend/storybook-static
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ jobs:
|
||||||
- 56312:6379
|
- 56312:6379
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
|
|
@ -86,7 +86,7 @@ jobs:
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ${{ matrix.node-version-file }}
|
node-version-file: ${{ matrix.node-version-file }}
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
@ -129,13 +129,13 @@ jobs:
|
||||||
- 56312:6379
|
- 56312:6379
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4.2.0
|
uses: pnpm/action-setup@v4.2.0
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ${{ matrix.node-version-file }}
|
node-version-file: ${{ matrix.node-version-file }}
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
@ -173,7 +173,7 @@ jobs:
|
||||||
POSTGRES_HOST_AUTH_METHOD: trust
|
POSTGRES_HOST_AUTH_METHOD: trust
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
|
|
@ -182,7 +182,7 @@ jobs:
|
||||||
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.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ${{ matrix.node-version-file }}
|
node-version-file: ${{ matrix.node-version-file }}
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ jobs:
|
||||||
- .node-version
|
- .node-version
|
||||||
- .github/min.node-version
|
- .github/min.node-version
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
|
|
@ -68,7 +68,7 @@ jobs:
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ${{ matrix.node-version-file }}
|
node-version-file: ${{ matrix.node-version-file }}
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
|
||||||
|
|
@ -28,13 +28,13 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4.2.0
|
uses: pnpm/action-setup@v4.2.0
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
@ -76,7 +76,7 @@ jobs:
|
||||||
- 56312:6379
|
- 56312:6379
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
# https://github.com/cypress-io/cypress-docker-images/issues/150
|
# https://github.com/cypress-io/cypress-docker-images/issues/150
|
||||||
|
|
@ -88,7 +88,7 @@ jobs:
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4.2.0
|
uses: pnpm/action-setup@v4.2.0
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
@ -113,12 +113,12 @@ jobs:
|
||||||
wait-on: 'http://localhost:61812'
|
wait-on: 'http://localhost:61812'
|
||||||
headed: true
|
headed: true
|
||||||
browser: ${{ matrix.browser }}
|
browser: ${{ matrix.browser }}
|
||||||
- uses: actions/upload-artifact@v6
|
- uses: actions/upload-artifact@v4
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.browser }}-cypress-screenshots
|
name: ${{ matrix.browser }}-cypress-screenshots
|
||||||
path: cypress/screenshots
|
path: cypress/screenshots
|
||||||
- uses: actions/upload-artifact@v6
|
- uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.browser }}-cypress-videos
|
name: ${{ matrix.browser }}-cypress-videos
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,13 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6.0.1
|
uses: actions/checkout@v4.3.0
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4.2.0
|
uses: pnpm/action-setup@v4.2.0
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,13 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4.2.0
|
uses: pnpm/action-setup@v4.2.0
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,13 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6.0.1
|
- uses: actions/checkout@v4.3.0
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4.2.0
|
uses: pnpm/action-setup@v4.2.0
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v6.1.0
|
uses: actions/setup-node@v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.node-version'
|
node-version-file: '.node-version'
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
|
||||||
31
CHANGELOG.md
31
CHANGELOG.md
|
|
@ -1,34 +1,3 @@
|
||||||
## 2025.12.2
|
|
||||||
|
|
||||||
### Note
|
|
||||||
v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`に変更」について、正しく環境に応じた設定を行わないとサインインが困難になるといった状態を緩和するために、以前のデフォルト値に戻す暫定対応を行いました。
|
|
||||||
|
|
||||||
**セキュリティを向上させるためには適切な設定を行うことを推奨しますが、間違った設定値を入れると上述のような不具合の原因となりますので、慎重に行ってください。**
|
|
||||||
|
|
||||||
### General
|
|
||||||
- 依存関係の更新
|
|
||||||
|
|
||||||
### Client
|
|
||||||
- Enhance: デッキのUI説明を追加
|
|
||||||
- Fix: バージョン表記のないPlayが正しく動作しない問題を修正
|
|
||||||
バージョン表記のないものは v0.x 系として実行されます。v1.x 系で動作させたい場合は必ずバージョン表記を含めてください。
|
|
||||||
- Fix: デッキUIでメニュー位置を下にしているとプロファイル削除ボタンが表示されないのを修正
|
|
||||||
|
|
||||||
|
|
||||||
## 2025.12.1
|
|
||||||
|
|
||||||
### Client
|
|
||||||
- Fix: 特定の条件下でMisskeyが起動せず空白のページが表示されることがある問題を軽減
|
|
||||||
- Fix: 初回読み込み時などに、言語設定で不整合が発生することがある問題を修正
|
|
||||||
- Fix: 削除されたノートのリノートが正しく動作されない問題を修正
|
|
||||||
- Fix: チャンネルオーナーが削除済みの時にチャンネルのヘッダーメニューが表示されない不具合を修正
|
|
||||||
- Fix: ドライブで登録日以外でソートする場合は月でグループ化して表示しないように
|
|
||||||
- Fix: `null` を返す note_view_intrruptor プラグインが動作しない問題を修正
|
|
||||||
|
|
||||||
### Server
|
|
||||||
- Fix: ジョブキューでSentryが有効にならない問題を修正
|
|
||||||
|
|
||||||
|
|
||||||
## 2025.12.0
|
## 2025.12.0
|
||||||
|
|
||||||
### Note
|
### Note
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ services:
|
||||||
env_file:
|
env_file:
|
||||||
- .config/docker.env
|
- .config/docker.env
|
||||||
volumes:
|
volumes:
|
||||||
- ./db:/var/lib/postgresql
|
- ./db:/var/lib/postgresql/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
||||||
interval: 5s
|
interval: 5s
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ services:
|
||||||
env_file:
|
env_file:
|
||||||
- .config/docker.env
|
- .config/docker.env
|
||||||
volumes:
|
volumes:
|
||||||
- ./db:/var/lib/postgresql
|
- ./db:/var/lib/postgresql/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
||||||
interval: 5s
|
interval: 5s
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,6 @@ files: "Dateien"
|
||||||
download: "Herunterladen"
|
download: "Herunterladen"
|
||||||
driveFileDeleteConfirm: "Möchtest du die Datei „{name}“ wirklich löschen? Einige Inhalte, die diese Datei verwenden, werden auch verschwinden."
|
driveFileDeleteConfirm: "Möchtest du die Datei „{name}“ wirklich löschen? Einige Inhalte, die diese Datei verwenden, werden auch verschwinden."
|
||||||
unfollowConfirm: "Möchtest du {name} wirklich nicht mehr folgen?"
|
unfollowConfirm: "Möchtest du {name} wirklich nicht mehr folgen?"
|
||||||
rejectFollowRequestConfirm: "Möchtest du die Follow-Anfrage von {name} ablehnen?"
|
|
||||||
exportRequested: "Du hast einen Export angefragt. Dies kann etwas Zeit in Anspruch nehmen. Sobald der Export abgeschlossen ist, wird er deiner Drive hinzugefügt."
|
exportRequested: "Du hast einen Export angefragt. Dies kann etwas Zeit in Anspruch nehmen. Sobald der Export abgeschlossen ist, wird er deiner Drive hinzugefügt."
|
||||||
importRequested: "Du hast einen Import angefragt. Dies kann etwas Zeit in Anspruch nehmen."
|
importRequested: "Du hast einen Import angefragt. Dies kann etwas Zeit in Anspruch nehmen."
|
||||||
lists: "Listen"
|
lists: "Listen"
|
||||||
|
|
@ -1019,7 +1018,6 @@ pushNotificationAlreadySubscribed: "Push-Benachrichtigungen sind bereits aktivie
|
||||||
pushNotificationNotSupported: "Entweder dein Browser oder deine Instanz unterstützt Push-Benachrichtigungen nicht"
|
pushNotificationNotSupported: "Entweder dein Browser oder deine Instanz unterstützt Push-Benachrichtigungen nicht"
|
||||||
sendPushNotificationReadMessage: "Push-Benachrichtigungen löschen, sobald sie gelesen wurden"
|
sendPushNotificationReadMessage: "Push-Benachrichtigungen löschen, sobald sie gelesen wurden"
|
||||||
sendPushNotificationReadMessageCaption: "Dies kann gegebenenfalls den Batterieverbrauch deines Gerätes erhöhen."
|
sendPushNotificationReadMessageCaption: "Dies kann gegebenenfalls den Batterieverbrauch deines Gerätes erhöhen."
|
||||||
pleaseAllowPushNotification: "Bitte erlauben Sie Benachrichtigungen in Ihrem Browser."
|
|
||||||
windowMaximize: "Maximieren"
|
windowMaximize: "Maximieren"
|
||||||
windowMinimize: "Minimieren"
|
windowMinimize: "Minimieren"
|
||||||
windowRestore: "Wiederherstellen"
|
windowRestore: "Wiederherstellen"
|
||||||
|
|
@ -1056,7 +1054,6 @@ permissionDeniedError: "Aktion verweigert"
|
||||||
permissionDeniedErrorDescription: "Dieses Benutzerkonto besitzt nicht die Berechtigung, um diese Aktion auszuführen."
|
permissionDeniedErrorDescription: "Dieses Benutzerkonto besitzt nicht die Berechtigung, um diese Aktion auszuführen."
|
||||||
preset: "Vorlage"
|
preset: "Vorlage"
|
||||||
selectFromPresets: "Aus Vorlagen wählen"
|
selectFromPresets: "Aus Vorlagen wählen"
|
||||||
custom: "Benutzerdefiniert"
|
|
||||||
achievements: "Errungenschaften"
|
achievements: "Errungenschaften"
|
||||||
gotInvalidResponseError: "Ungültige Antwort des Servers"
|
gotInvalidResponseError: "Ungültige Antwort des Servers"
|
||||||
gotInvalidResponseErrorDescription: "Eventuell ist der Server momentan nicht erreichbar oder untergeht Wartungsarbeiten. Bitte versuche es später noch einmal."
|
gotInvalidResponseErrorDescription: "Eventuell ist der Server momentan nicht erreichbar oder untergeht Wartungsarbeiten. Bitte versuche es später noch einmal."
|
||||||
|
|
@ -1246,7 +1243,6 @@ releaseToRefresh: "Zum Aktualisieren loslassen"
|
||||||
refreshing: "Wird aktualisiert..."
|
refreshing: "Wird aktualisiert..."
|
||||||
pullDownToRefresh: "Zum Aktualisieren ziehen"
|
pullDownToRefresh: "Zum Aktualisieren ziehen"
|
||||||
useGroupedNotifications: "Benachrichtigungen gruppieren"
|
useGroupedNotifications: "Benachrichtigungen gruppieren"
|
||||||
emailVerificationFailedError: "Es gab ein Problem bei der Überprüfung Ihrer E-Mail-Adresse. Der Link ist möglicherweise abgelaufen."
|
|
||||||
cwNotationRequired: "Ist \"Inhaltswarnung verwenden\" aktiviert, muss eine Beschreibung gegeben werden."
|
cwNotationRequired: "Ist \"Inhaltswarnung verwenden\" aktiviert, muss eine Beschreibung gegeben werden."
|
||||||
doReaction: "Reagieren"
|
doReaction: "Reagieren"
|
||||||
code: "Code"
|
code: "Code"
|
||||||
|
|
@ -1374,12 +1370,7 @@ defaultImageCompressionLevel: "Standard-Bildkomprimierungsstufe"
|
||||||
defaultImageCompressionLevel_description: "Ein niedrigerer Wert erhält die Bildqualität, erhöht aber die Dateigröße. <br>Höhere Werte reduzieren die Dateigröße, verringern aber die Bildqualität."
|
defaultImageCompressionLevel_description: "Ein niedrigerer Wert erhält die Bildqualität, erhöht aber die Dateigröße. <br>Höhere Werte reduzieren die Dateigröße, verringern aber die Bildqualität."
|
||||||
inMinutes: "Minute(n)"
|
inMinutes: "Minute(n)"
|
||||||
inDays: "Tag(en)"
|
inDays: "Tag(en)"
|
||||||
safeModeEnabled: "Der abgesicherte Modus ist aktiviert."
|
|
||||||
schedule: "Planen"
|
|
||||||
scheduled: "Geplant"
|
|
||||||
widgets: "Widgets"
|
widgets: "Widgets"
|
||||||
deviceInfo: "Geräteinformation"
|
|
||||||
youAreAdmin: "Sie sind ein Administrator"
|
|
||||||
presets: "Vorlage"
|
presets: "Vorlage"
|
||||||
_imageEditing:
|
_imageEditing:
|
||||||
_vars:
|
_vars:
|
||||||
|
|
|
||||||
|
|
@ -83,8 +83,6 @@ files: "Files"
|
||||||
download: "Download"
|
download: "Download"
|
||||||
driveFileDeleteConfirm: "Are you sure you want to delete \"{name}\"? All notes with this file attached will also be deleted."
|
driveFileDeleteConfirm: "Are you sure you want to delete \"{name}\"? All notes with this file attached will also be deleted."
|
||||||
unfollowConfirm: "Are you sure you want to unfollow {name}?"
|
unfollowConfirm: "Are you sure you want to unfollow {name}?"
|
||||||
cancelFollowRequestConfirm: "Are you sure that you want to cancel your follow request to {name}?"
|
|
||||||
rejectFollowRequestConfirm: "Are you sure that you want to reject the follow request from {name}?"
|
|
||||||
exportRequested: "You've requested an export. This may take a while. It will be added to your Drive once completed."
|
exportRequested: "You've requested an export. This may take a while. It will be added to your Drive once completed."
|
||||||
importRequested: "You've requested an import. This may take a while."
|
importRequested: "You've requested an import. This may take a while."
|
||||||
lists: "Lists"
|
lists: "Lists"
|
||||||
|
|
|
||||||
|
|
@ -1252,7 +1252,7 @@ detachAll: "Quitar todo"
|
||||||
angle: "Ángulo"
|
angle: "Ángulo"
|
||||||
flip: "Echar de un capirotazo"
|
flip: "Echar de un capirotazo"
|
||||||
showAvatarDecorations: "Mostrar decoraciones de avatar"
|
showAvatarDecorations: "Mostrar decoraciones de avatar"
|
||||||
releaseToRefresh: "Suelta para recargar"
|
releaseToRefresh: "Soltar para recargar"
|
||||||
refreshing: "Recargando..."
|
refreshing: "Recargando..."
|
||||||
pullDownToRefresh: "Tira hacia abajo para recargar"
|
pullDownToRefresh: "Tira hacia abajo para recargar"
|
||||||
useGroupedNotifications: "Mostrar notificaciones agrupadas"
|
useGroupedNotifications: "Mostrar notificaciones agrupadas"
|
||||||
|
|
|
||||||
|
|
@ -2890,15 +2890,6 @@ _deck:
|
||||||
usedAsMinWidthWhenFlexible: "「幅を自動調整」が有効の場合、これが幅の最小値となります"
|
usedAsMinWidthWhenFlexible: "「幅を自動調整」が有効の場合、これが幅の最小値となります"
|
||||||
flexible: "幅を自動調整"
|
flexible: "幅を自動調整"
|
||||||
enableSyncBetweenDevicesForProfiles: "プロファイル情報のデバイス間同期を有効にする"
|
enableSyncBetweenDevicesForProfiles: "プロファイル情報のデバイス間同期を有効にする"
|
||||||
showHowToUse: "UIの説明を見る"
|
|
||||||
|
|
||||||
_howToUse:
|
|
||||||
addColumn_title: "カラム追加"
|
|
||||||
addColumn_description: "カラムの種類を選んで追加できます。"
|
|
||||||
settings_title: "UI設定"
|
|
||||||
settings_description: "デッキUIの詳細設定を行えます。"
|
|
||||||
switchProfile_title: "プロファイル切り替え"
|
|
||||||
switchProfile_description: "UIのレイアウトをプロファイルとして保存し、いつでも切り替えられるようにできます。"
|
|
||||||
|
|
||||||
_columns:
|
_columns:
|
||||||
main: "メイン"
|
main: "メイン"
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ copyRemoteLink: "复制远程链接"
|
||||||
copyLinkRenote: "复制转帖链接"
|
copyLinkRenote: "复制转帖链接"
|
||||||
delete: "删除"
|
delete: "删除"
|
||||||
deleteAndEdit: "删除并编辑"
|
deleteAndEdit: "删除并编辑"
|
||||||
deleteAndEditConfirm: "要删除此帖并再次编辑吗?此帖下所有的回应、转发和回复也将被删除。"
|
deleteAndEditConfirm: "要删除此帖并再次编辑吗?对此帖的所有回应、转发和回复也将被删除。"
|
||||||
addToList: "添加至列表"
|
addToList: "添加至列表"
|
||||||
addToAntenna: "添加到天线"
|
addToAntenna: "添加到天线"
|
||||||
sendMessage: "发送消息"
|
sendMessage: "发送消息"
|
||||||
|
|
@ -136,7 +136,7 @@ emojiPicker: "表情符号选择器"
|
||||||
pinnedEmojisForReactionSettingDescription: "可以设置发表回应时置顶显示的表情符号"
|
pinnedEmojisForReactionSettingDescription: "可以设置发表回应时置顶显示的表情符号"
|
||||||
pinnedEmojisSettingDescription: "可以设置输入表情符号时置顶显示的表情符号"
|
pinnedEmojisSettingDescription: "可以设置输入表情符号时置顶显示的表情符号"
|
||||||
emojiPickerDisplay: "选择器显示设置"
|
emojiPickerDisplay: "选择器显示设置"
|
||||||
overwriteFromPinnedEmojisForReaction: "使用「置顶(回应)」设置覆盖"
|
overwriteFromPinnedEmojisForReaction: "从「置顶(回应)」设置覆盖"
|
||||||
overwriteFromPinnedEmojis: "从全局设置覆盖"
|
overwriteFromPinnedEmojis: "从全局设置覆盖"
|
||||||
reactionSettingDescription2: "拖动重新排序,单击删除,点击 + 添加。"
|
reactionSettingDescription2: "拖动重新排序,单击删除,点击 + 添加。"
|
||||||
rememberNoteVisibility: "保存上次设置的可见性"
|
rememberNoteVisibility: "保存上次设置的可见性"
|
||||||
|
|
@ -153,8 +153,8 @@ block: "拉黑"
|
||||||
unblock: "取消拉黑"
|
unblock: "取消拉黑"
|
||||||
suspend: "冻结"
|
suspend: "冻结"
|
||||||
unsuspend: "解除冻结"
|
unsuspend: "解除冻结"
|
||||||
blockConfirm: "确定要屏蔽吗?"
|
blockConfirm: "确定要拉黑吗?"
|
||||||
unblockConfirm: "确定要取消屏蔽吗?"
|
unblockConfirm: "确定要取消拉黑吗?"
|
||||||
suspendConfirm: "要冻结吗?"
|
suspendConfirm: "要冻结吗?"
|
||||||
unsuspendConfirm: "要解除冻结吗?"
|
unsuspendConfirm: "要解除冻结吗?"
|
||||||
selectList: "选择列表"
|
selectList: "选择列表"
|
||||||
|
|
@ -174,7 +174,7 @@ emojiUrl: "emoji 地址"
|
||||||
addEmoji: "添加表情符号"
|
addEmoji: "添加表情符号"
|
||||||
settingGuide: "推荐配置"
|
settingGuide: "推荐配置"
|
||||||
cacheRemoteFiles: "缓存远程文件"
|
cacheRemoteFiles: "缓存远程文件"
|
||||||
cacheRemoteFilesDescription: "启用此设定时,将在此服务器上缓存远程文件。虽然可以加快图片显示的速度,但是相对的会消耗大量的服务器存储空间。用户角色内的网盘容量决定了这个远程用户能在服务器上保留多少缓存。当超出了这个限制时,旧的文件将从缓存中被删除,成为链接。当禁用此设定时,则是从一开始就将远程文件保留为链接。此时推荐将 的 proxyRemoteFiles 设置为 true 以优化缩略图生成及保护用户隐私。"
|
cacheRemoteFilesDescription: "启用此设定时,将在此服务器上缓存远程文件。虽然可以加快图片显示的速度,但是相对的会消耗大量的服务器存储空间。用户角色内的网盘容量决定了这个远程用户能在服务器上保留多少缓存。当超出了这个限制时,旧的文件将从缓存中被删除,成为链接。当禁用此设定时,则是从一开始就将远程文件保留为链接。此时推荐将 default.yml 的 proxyRemoteFiles 设置为 true 以优化缩略图生成及保护用户隐私。"
|
||||||
youCanCleanRemoteFilesCache: "可以使用文件管理的🗑️按钮来删除所有的缓存。"
|
youCanCleanRemoteFilesCache: "可以使用文件管理的🗑️按钮来删除所有的缓存。"
|
||||||
cacheRemoteSensitiveFiles: "缓存远程敏感媒体文件"
|
cacheRemoteSensitiveFiles: "缓存远程敏感媒体文件"
|
||||||
cacheRemoteSensitiveFilesDescription: "如果禁用这项设定,远程服务器的敏感媒体将不会被缓存,而是直接链接。"
|
cacheRemoteSensitiveFilesDescription: "如果禁用这项设定,远程服务器的敏感媒体将不会被缓存,而是直接链接。"
|
||||||
|
|
@ -184,7 +184,7 @@ flagAsCat: "喵!!!!!!!!!!!!"
|
||||||
flagAsCatDescription: "喵喵喵??"
|
flagAsCatDescription: "喵喵喵??"
|
||||||
flagShowTimelineReplies: "在时间线上显示帖子的回复"
|
flagShowTimelineReplies: "在时间线上显示帖子的回复"
|
||||||
flagShowTimelineRepliesDescription: "启用时,时间线除了显示用户的帖子外,还会显示其他用户对帖子的回复。"
|
flagShowTimelineRepliesDescription: "启用时,时间线除了显示用户的帖子外,还会显示其他用户对帖子的回复。"
|
||||||
autoAcceptFollowed: "自动允许回关请求"
|
autoAcceptFollowed: "自动允许来自我关注的用户对我的关注请求"
|
||||||
addAccount: "添加账户"
|
addAccount: "添加账户"
|
||||||
reloadAccountsList: "更新账户列表"
|
reloadAccountsList: "更新账户列表"
|
||||||
loginFailed: "登录失败"
|
loginFailed: "登录失败"
|
||||||
|
|
@ -247,8 +247,8 @@ mediaSilencedInstancesDescription: "设置要隐藏媒体文件的服务器,
|
||||||
federationAllowedHosts: "允许联合的服务器"
|
federationAllowedHosts: "允许联合的服务器"
|
||||||
federationAllowedHostsDescription: "设定允许联合的服务器,以换行分隔。"
|
federationAllowedHostsDescription: "设定允许联合的服务器,以换行分隔。"
|
||||||
muteAndBlock: "屏蔽/拉黑"
|
muteAndBlock: "屏蔽/拉黑"
|
||||||
mutedUsers: "已静音的用户"
|
mutedUsers: "已屏蔽用户"
|
||||||
blockedUsers: "已屏蔽的用户"
|
blockedUsers: "已拉黑的用户"
|
||||||
noUsers: "无用户"
|
noUsers: "无用户"
|
||||||
editProfile: "编辑资料"
|
editProfile: "编辑资料"
|
||||||
noteDeleteConfirm: "确定要删除该帖子吗?"
|
noteDeleteConfirm: "确定要删除该帖子吗?"
|
||||||
|
|
@ -1344,7 +1344,7 @@ skip: "跳过"
|
||||||
restore: "恢复"
|
restore: "恢复"
|
||||||
syncBetweenDevices: "设备间同步"
|
syncBetweenDevices: "设备间同步"
|
||||||
preferenceSyncConflictTitle: "服务器上已存在设定值"
|
preferenceSyncConflictTitle: "服务器上已存在设定值"
|
||||||
preferenceSyncConflictText: "即将保存设定值到服务器,但检测到服务器上已有此设置的设定值。要使用哪个设定值?"
|
preferenceSyncConflictText: "服务器上已有此设置的设定值。要覆盖哪个设定值?"
|
||||||
preferenceSyncConflictChoiceMerge: "合并"
|
preferenceSyncConflictChoiceMerge: "合并"
|
||||||
preferenceSyncConflictChoiceServer: "服务器上的设定值"
|
preferenceSyncConflictChoiceServer: "服务器上的设定值"
|
||||||
preferenceSyncConflictChoiceDevice: "设备上的设定值"
|
preferenceSyncConflictChoiceDevice: "设备上的设定值"
|
||||||
|
|
@ -3270,7 +3270,7 @@ _watermarkEditor:
|
||||||
driveFileTypeWarn: "不支持此文件"
|
driveFileTypeWarn: "不支持此文件"
|
||||||
driveFileTypeWarnDescription: "请选择图像文件"
|
driveFileTypeWarnDescription: "请选择图像文件"
|
||||||
title: "编辑水印"
|
title: "编辑水印"
|
||||||
cover: "覆盖所有"
|
cover: "覆盖全体"
|
||||||
repeat: "平铺"
|
repeat: "平铺"
|
||||||
preserveBoundingRect: "调整为旋转时不超出范围"
|
preserveBoundingRect: "调整为旋转时不超出范围"
|
||||||
opacity: "不透明度"
|
opacity: "不透明度"
|
||||||
|
|
|
||||||
22
package.json
22
package.json
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"version": "2025.12.2-beta.2",
|
"version": "2025.12.0",
|
||||||
"codename": "nasubi",
|
"codename": "nasubi",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/misskey-dev/misskey.git"
|
"url": "https://github.com/misskey-dev/misskey.git"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.25.0",
|
"packageManager": "pnpm@10.24.0",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/misskey-js",
|
"packages/misskey-js",
|
||||||
"packages/i18n",
|
"packages/i18n",
|
||||||
|
|
@ -53,13 +53,15 @@
|
||||||
"cleanall": "pnpm clean-all"
|
"cleanall": "pnpm clean-all"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"chokidar": "5.0.0",
|
"chokidar": "4.0.3",
|
||||||
"lodash": "4.17.21"
|
"lodash": "4.17.21"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cssnano": "7.1.2",
|
"cssnano": "7.1.2",
|
||||||
"esbuild": "0.27.1",
|
"esbuild": "0.27.0",
|
||||||
"execa": "9.6.1",
|
"execa": "9.6.0",
|
||||||
|
"fast-glob": "3.3.3",
|
||||||
|
"glob": "13.0.0",
|
||||||
"ignore-walk": "8.0.0",
|
"ignore-walk": "8.0.0",
|
||||||
"js-yaml": "4.1.1",
|
"js-yaml": "4.1.1",
|
||||||
"postcss": "8.5.6",
|
"postcss": "8.5.6",
|
||||||
|
|
@ -71,15 +73,15 @@
|
||||||
"@eslint/js": "9.39.1",
|
"@eslint/js": "9.39.1",
|
||||||
"@misskey-dev/eslint-plugin": "2.2.0",
|
"@misskey-dev/eslint-plugin": "2.2.0",
|
||||||
"@types/js-yaml": "4.0.9",
|
"@types/js-yaml": "4.0.9",
|
||||||
"@types/node": "24.10.2",
|
"@types/node": "24.10.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.49.0",
|
"@typescript-eslint/eslint-plugin": "8.47.0",
|
||||||
"@typescript-eslint/parser": "8.49.0",
|
"@typescript-eslint/parser": "8.47.0",
|
||||||
"cross-env": "10.1.0",
|
"cross-env": "10.1.0",
|
||||||
"cypress": "15.7.1",
|
"cypress": "15.7.0",
|
||||||
"eslint": "9.39.1",
|
"eslint": "9.39.1",
|
||||||
"globals": "16.5.0",
|
"globals": "16.5.0",
|
||||||
"ncp": "2.0.0",
|
"ncp": "2.0.0",
|
||||||
"pnpm": "10.25.0",
|
"pnpm": "10.24.0",
|
||||||
"start-server-and-test": "2.1.3"
|
"start-server-and-test": "2.1.3"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -71,25 +71,26 @@
|
||||||
"utf-8-validate": "6.0.5"
|
"utf-8-validate": "6.0.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "3.948.0",
|
"@aws-sdk/client-s3": "3.940.0",
|
||||||
"@aws-sdk/lib-storage": "3.948.0",
|
"@aws-sdk/lib-storage": "3.940.0",
|
||||||
"@discordapp/twemoji": "16.0.1",
|
"@discordapp/twemoji": "16.0.1",
|
||||||
"@fastify/accepts": "5.0.4",
|
"@fastify/accepts": "5.0.3",
|
||||||
"@fastify/cors": "11.2.0",
|
"@fastify/cookie": "11.0.2",
|
||||||
|
"@fastify/cors": "11.1.0",
|
||||||
"@fastify/express": "4.0.2",
|
"@fastify/express": "4.0.2",
|
||||||
"@fastify/http-proxy": "11.4.1",
|
"@fastify/http-proxy": "11.3.0",
|
||||||
"@fastify/multipart": "9.3.0",
|
"@fastify/multipart": "9.3.0",
|
||||||
"@fastify/static": "8.3.0",
|
"@fastify/static": "8.3.0",
|
||||||
"@kitajs/html": "4.2.11",
|
"@kitajs/html": "4.2.11",
|
||||||
"@misskey-dev/sharp-read-bmp": "1.2.0",
|
"@misskey-dev/sharp-read-bmp": "1.2.0",
|
||||||
"@misskey-dev/summaly": "5.2.5",
|
"@misskey-dev/summaly": "5.2.5",
|
||||||
"@napi-rs/canvas": "0.1.84",
|
"@napi-rs/canvas": "0.1.83",
|
||||||
"@nestjs/common": "11.1.9",
|
"@nestjs/common": "11.1.9",
|
||||||
"@nestjs/core": "11.1.9",
|
"@nestjs/core": "11.1.9",
|
||||||
"@nestjs/testing": "11.1.9",
|
"@nestjs/testing": "11.1.9",
|
||||||
"@peertube/http-signature": "1.7.0",
|
"@peertube/http-signature": "1.7.0",
|
||||||
"@sentry/node": "10.29.0",
|
"@sentry/node": "10.27.0",
|
||||||
"@sentry/profiling-node": "10.29.0",
|
"@sentry/profiling-node": "10.27.0",
|
||||||
"@simplewebauthn/server": "13.2.2",
|
"@simplewebauthn/server": "13.2.2",
|
||||||
"@sinonjs/fake-timers": "15.0.0",
|
"@sinonjs/fake-timers": "15.0.0",
|
||||||
"@smithy/node-http-handler": "4.4.5",
|
"@smithy/node-http-handler": "4.4.5",
|
||||||
|
|
@ -104,11 +105,12 @@
|
||||||
"bcryptjs": "3.0.3",
|
"bcryptjs": "3.0.3",
|
||||||
"blurhash": "2.0.5",
|
"blurhash": "2.0.5",
|
||||||
"body-parser": "2.2.1",
|
"body-parser": "2.2.1",
|
||||||
"bullmq": "5.65.1",
|
"bullmq": "5.65.0",
|
||||||
"cacheable-lookup": "7.0.0",
|
"cacheable-lookup": "7.0.0",
|
||||||
|
"cbor": "10.0.11",
|
||||||
"chalk": "5.6.2",
|
"chalk": "5.6.2",
|
||||||
"chalk-template": "1.1.2",
|
"chalk-template": "1.1.2",
|
||||||
"chokidar": "5.0.0",
|
"chokidar": "4.0.3",
|
||||||
"color-convert": "3.1.3",
|
"color-convert": "3.1.3",
|
||||||
"content-disposition": "1.0.1",
|
"content-disposition": "1.0.1",
|
||||||
"date-fns": "4.1.0",
|
"date-fns": "4.1.0",
|
||||||
|
|
@ -129,6 +131,7 @@
|
||||||
"is-svg": "6.1.0",
|
"is-svg": "6.1.0",
|
||||||
"json5": "2.2.3",
|
"json5": "2.2.3",
|
||||||
"jsonld": "9.0.0",
|
"jsonld": "9.0.0",
|
||||||
|
"jsrsasign": "11.1.0",
|
||||||
"juice": "11.0.3",
|
"juice": "11.0.3",
|
||||||
"meilisearch": "0.54.0",
|
"meilisearch": "0.54.0",
|
||||||
"mfm-js": "0.25.0",
|
"mfm-js": "0.25.0",
|
||||||
|
|
@ -142,6 +145,7 @@
|
||||||
"node-html-parser": "7.0.1",
|
"node-html-parser": "7.0.1",
|
||||||
"nodemailer": "7.0.11",
|
"nodemailer": "7.0.11",
|
||||||
"nsfwjs": "4.2.0",
|
"nsfwjs": "4.2.0",
|
||||||
|
"oauth": "0.10.2",
|
||||||
"oauth2orize": "1.12.0",
|
"oauth2orize": "1.12.0",
|
||||||
"oauth2orize-pkce": "0.1.2",
|
"oauth2orize-pkce": "0.1.2",
|
||||||
"os-utils": "0.0.14",
|
"os-utils": "0.0.14",
|
||||||
|
|
@ -166,13 +170,14 @@
|
||||||
"slacc": "0.0.10",
|
"slacc": "0.0.10",
|
||||||
"strict-event-emitter-types": "2.0.0",
|
"strict-event-emitter-types": "2.0.0",
|
||||||
"stringz": "2.1.0",
|
"stringz": "2.1.0",
|
||||||
"systeminformation": "5.27.14",
|
"systeminformation": "5.27.11",
|
||||||
"tinycolor2": "1.6.0",
|
"tinycolor2": "1.6.0",
|
||||||
"tmp": "0.2.5",
|
"tmp": "0.2.5",
|
||||||
"tsc-alias": "1.8.16",
|
"tsc-alias": "1.8.16",
|
||||||
"typeorm": "0.3.28",
|
"tsconfig-paths": "4.2.0",
|
||||||
|
"typeorm": "0.3.27",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
"ulid": "3.0.2",
|
"ulid": "3.0.1",
|
||||||
"vary": "1.1.2",
|
"vary": "1.1.2",
|
||||||
"web-push": "3.6.7",
|
"web-push": "3.6.7",
|
||||||
"ws": "8.18.3",
|
"ws": "8.18.3",
|
||||||
|
|
@ -182,7 +187,7 @@
|
||||||
"@jest/globals": "29.7.0",
|
"@jest/globals": "29.7.0",
|
||||||
"@kitajs/ts-html-plugin": "4.1.3",
|
"@kitajs/ts-html-plugin": "4.1.3",
|
||||||
"@nestjs/platform-express": "11.1.9",
|
"@nestjs/platform-express": "11.1.9",
|
||||||
"@sentry/vue": "10.29.0",
|
"@sentry/vue": "10.27.0",
|
||||||
"@simplewebauthn/types": "12.0.0",
|
"@simplewebauthn/types": "12.0.0",
|
||||||
"@swc/jest": "0.2.39",
|
"@swc/jest": "0.2.39",
|
||||||
"@types/accepts": "1.3.7",
|
"@types/accepts": "1.3.7",
|
||||||
|
|
@ -194,10 +199,12 @@
|
||||||
"@types/http-link-header": "1.0.7",
|
"@types/http-link-header": "1.0.7",
|
||||||
"@types/jest": "29.5.14",
|
"@types/jest": "29.5.14",
|
||||||
"@types/jsonld": "1.5.15",
|
"@types/jsonld": "1.5.15",
|
||||||
|
"@types/jsrsasign": "10.5.15",
|
||||||
"@types/mime-types": "3.0.1",
|
"@types/mime-types": "3.0.1",
|
||||||
"@types/ms": "2.1.0",
|
"@types/ms": "2.1.0",
|
||||||
"@types/node": "24.10.2",
|
"@types/node": "24.10.1",
|
||||||
"@types/nodemailer": "7.0.4",
|
"@types/nodemailer": "7.0.4",
|
||||||
|
"@types/oauth": "0.9.6",
|
||||||
"@types/oauth2orize": "1.11.5",
|
"@types/oauth2orize": "1.11.5",
|
||||||
"@types/oauth2orize-pkce": "0.1.2",
|
"@types/oauth2orize-pkce": "0.1.2",
|
||||||
"@types/pg": "8.15.6",
|
"@types/pg": "8.15.6",
|
||||||
|
|
@ -207,7 +214,7 @@
|
||||||
"@types/rename": "1.0.7",
|
"@types/rename": "1.0.7",
|
||||||
"@types/sanitize-html": "2.16.0",
|
"@types/sanitize-html": "2.16.0",
|
||||||
"@types/semver": "7.7.1",
|
"@types/semver": "7.7.1",
|
||||||
"@types/simple-oauth2": "5.0.8",
|
"@types/simple-oauth2": "5.0.7",
|
||||||
"@types/sinonjs__fake-timers": "15.0.1",
|
"@types/sinonjs__fake-timers": "15.0.1",
|
||||||
"@types/supertest": "6.0.3",
|
"@types/supertest": "6.0.3",
|
||||||
"@types/tinycolor2": "1.4.6",
|
"@types/tinycolor2": "1.4.6",
|
||||||
|
|
@ -215,21 +222,21 @@
|
||||||
"@types/vary": "1.1.3",
|
"@types/vary": "1.1.3",
|
||||||
"@types/web-push": "3.6.4",
|
"@types/web-push": "3.6.4",
|
||||||
"@types/ws": "8.18.1",
|
"@types/ws": "8.18.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.49.0",
|
"@typescript-eslint/eslint-plugin": "8.48.0",
|
||||||
"@typescript-eslint/parser": "8.49.0",
|
"@typescript-eslint/parser": "8.48.0",
|
||||||
"aws-sdk-client-mock": "4.1.0",
|
"aws-sdk-client-mock": "4.1.0",
|
||||||
"cbor": "10.0.11",
|
|
||||||
"cross-env": "10.1.0",
|
"cross-env": "10.1.0",
|
||||||
"eslint-plugin-import": "2.32.0",
|
"eslint-plugin-import": "2.32.0",
|
||||||
"execa": "9.6.1",
|
"execa": "9.6.0",
|
||||||
"fkill": "10.0.1",
|
"fkill": "10.0.1",
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
"jest-mock": "29.7.0",
|
"jest-mock": "29.7.0",
|
||||||
|
"jest-util": "29.7.0",
|
||||||
"js-yaml": "4.1.1",
|
"js-yaml": "4.1.1",
|
||||||
"nodemon": "3.1.11",
|
"nodemon": "3.1.11",
|
||||||
"pid-port": "2.0.0",
|
"pid-port": "2.0.0",
|
||||||
"simple-oauth2": "5.1.0",
|
"simple-oauth2": "5.1.0",
|
||||||
"supertest": "7.1.4",
|
"supertest": "7.1.4",
|
||||||
"vite": "7.2.7"
|
"vite": "7.2.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import * as fs from 'node:fs';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import { dirname } from 'node:path';
|
import { dirname } from 'node:path';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import si from 'systeminformation';
|
||||||
import { Mutex } from 'async-mutex';
|
import { Mutex } from 'async-mutex';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
|
@ -83,7 +84,6 @@ export class AiService {
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
private async getCpuFlags(): Promise<string[]> {
|
private async getCpuFlags(): Promise<string[]> {
|
||||||
const si = await import('systeminformation');
|
|
||||||
const str = await si.cpuFlags();
|
const str = await si.cpuFlags();
|
||||||
return str.split(/\s+/);
|
return str.split(/\s+/);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import si from 'systeminformation';
|
||||||
import Xev from 'xev';
|
import Xev from 'xev';
|
||||||
import * as osUtils from 'os-utils';
|
import * as osUtils from 'os-utils';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
|
import type { OnApplicationShutdown } from '@nestjs/common';
|
||||||
import { MiMeta } from '@/models/_.js';
|
import { MiMeta } from '@/models/_.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { OnApplicationShutdown } from '@nestjs/common';
|
|
||||||
|
|
||||||
const ev = new Xev();
|
const ev = new Xev();
|
||||||
|
|
||||||
|
|
@ -96,14 +97,12 @@ function cpuUsage(): Promise<number> {
|
||||||
|
|
||||||
// MEMORY STAT
|
// MEMORY STAT
|
||||||
async function mem() {
|
async function mem() {
|
||||||
const si = await import('systeminformation');
|
|
||||||
const data = await si.mem();
|
const data = await si.mem();
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NETWORK STAT
|
// NETWORK STAT
|
||||||
async function net() {
|
async function net() {
|
||||||
const si = await import('systeminformation');
|
|
||||||
const iface = await si.networkInterfaceDefault();
|
const iface = await si.networkInterfaceDefault();
|
||||||
const data = await si.networkStats(iface);
|
const data = await si.networkStats(iface);
|
||||||
return data[0];
|
return data[0];
|
||||||
|
|
@ -111,6 +110,5 @@ async function net() {
|
||||||
|
|
||||||
// FS STAT
|
// FS STAT
|
||||||
async function fs() {
|
async function fs() {
|
||||||
const si = await import('systeminformation');
|
|
||||||
return await si.disksIO().catch(() => ({ rIO_sec: 0, wIO_sec: 0 }));
|
return await si.disksIO().catch(() => ({ rIO_sec: 0, wIO_sec: 0 }));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as os from 'node:os';
|
import * as os from 'node:os';
|
||||||
|
import sysUtils from 'systeminformation';
|
||||||
import type Logger from '@/logger.js';
|
import type Logger from '@/logger.js';
|
||||||
|
|
||||||
export async function showMachineInfo(parentLogger: Logger) {
|
export async function showMachineInfo(parentLogger: Logger) {
|
||||||
const logger = parentLogger.createSubLogger('machine');
|
const logger = parentLogger.createSubLogger('machine');
|
||||||
logger.debug(`Hostname: ${os.hostname()}`);
|
logger.debug(`Hostname: ${os.hostname()}`);
|
||||||
logger.debug(`Platform: ${process.platform} Arch: ${process.arch}`);
|
logger.debug(`Platform: ${process.platform} Arch: ${process.arch}`);
|
||||||
logger.debug(`CPU: ${os.cpus().length} core MEM: ${(os.totalmem() / 1024 / 1024 / 1024).toFixed(1)}GB (available: ${(os.freemem() / 1024 / 1024 / 1024).toFixed(1)}GB)`);
|
const mem = await sysUtils.mem();
|
||||||
|
const totalmem = (mem.total / 1024 / 1024 / 1024).toFixed(1);
|
||||||
|
const availmem = (mem.available / 1024 / 1024 / 1024).toFixed(1);
|
||||||
|
logger.debug(`CPU: ${os.cpus().length} core MEM: ${totalmem}GB (available: ${availmem}GB)`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
|
||||||
}
|
}
|
||||||
|
|
||||||
let Sentry: typeof import('@sentry/node') | undefined;
|
let Sentry: typeof import('@sentry/node') | undefined;
|
||||||
if (this.config.sentryForBackend) {
|
if (Sentry != null) {
|
||||||
import('@sentry/node').then((mod) => {
|
import('@sentry/node').then((mod) => {
|
||||||
Sentry = mod;
|
Sentry = mod;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ export class ServerService implements OnApplicationShutdown {
|
||||||
@bindThis
|
@bindThis
|
||||||
public async launch(): Promise<void> {
|
public async launch(): Promise<void> {
|
||||||
const fastify = Fastify({
|
const fastify = Fastify({
|
||||||
trustProxy: this.config.trustProxy ?? true,
|
trustProxy: this.config.trustProxy ?? false,
|
||||||
logger: false,
|
logger: false,
|
||||||
});
|
});
|
||||||
this.#fastify = fastify;
|
this.#fastify = fastify;
|
||||||
|
|
|
||||||
|
|
@ -313,17 +313,13 @@ export class ApiCallService implements OnApplicationShutdown {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ep.meta.limit) {
|
if (ep.meta.limit) {
|
||||||
let limitActor: string | null;
|
// koa will automatically load the `X-Forwarded-For` header if `proxy: true` is configured in the app.
|
||||||
|
let limitActor: string;
|
||||||
if (user) {
|
if (user) {
|
||||||
limitActor = user.id;
|
limitActor = user.id;
|
||||||
} else {
|
|
||||||
if (request.ip === '::1' || request.ip === '127.0.0.1') {
|
|
||||||
console.warn('request ip is localhost, maybe caused by misconfiguration of trustProxy or reverse proxy');
|
|
||||||
limitActor = null;
|
|
||||||
} else {
|
} else {
|
||||||
limitActor = getIpHash(request.ip);
|
limitActor = getIpHash(request.ip);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const limit = Object.assign({}, ep.meta.limit);
|
const limit = Object.assign({}, ep.meta.limit);
|
||||||
|
|
||||||
|
|
@ -334,7 +330,7 @@ export class ApiCallService implements OnApplicationShutdown {
|
||||||
// TODO: 毎リクエスト計算するのもあれだしキャッシュしたい
|
// TODO: 毎リクエスト計算するのもあれだしキャッシュしたい
|
||||||
const factor = user ? (await this.roleService.getUserPolicies(user.id)).rateLimitFactor : 1;
|
const factor = user ? (await this.roleService.getUserPolicies(user.id)).rateLimitFactor : 1;
|
||||||
|
|
||||||
if (limitActor != null && factor > 0) {
|
if (factor > 0) {
|
||||||
// Rate limit
|
// Rate limit
|
||||||
const rateLimit = await this.rateLimiterService.limit(limit as IEndpointMeta['limit'] & { key: NonNullable<string> }, limitActor, factor);
|
const rateLimit = await this.rateLimiterService.limit(limit as IEndpointMeta['limit'] & { key: NonNullable<string> }, limitActor, factor);
|
||||||
if (rateLimit != null) {
|
if (rateLimit != null) {
|
||||||
|
|
|
||||||
|
|
@ -89,9 +89,6 @@ export class SigninApiService {
|
||||||
return { error };
|
return { error };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.ip === '::1' || request.ip === '127.0.0.1') {
|
|
||||||
console.warn('request ip is localhost, maybe caused by misconfiguration of trustProxy or reverse proxy');
|
|
||||||
} else {
|
|
||||||
// not more than 1 attempt per second and not more than 10 attempts per hour
|
// not more than 1 attempt per second and not more than 10 attempts per hour
|
||||||
const rateLimit = await this.rateLimiterService.limit({ key: 'signin', duration: 60 * 60 * 1000, max: 10, minInterval: 1000 }, getIpHash(request.ip));
|
const rateLimit = await this.rateLimiterService.limit({ key: 'signin', duration: 60 * 60 * 1000, max: 10, minInterval: 1000 }, getIpHash(request.ip));
|
||||||
if (rateLimit != null) {
|
if (rateLimit != null) {
|
||||||
|
|
@ -104,7 +101,6 @@ export class SigninApiService {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof username !== 'string') {
|
if (typeof username !== 'string') {
|
||||||
reply.code(400);
|
reply.code(400);
|
||||||
|
|
|
||||||
|
|
@ -84,9 +84,6 @@ export class SigninWithPasskeyApiService {
|
||||||
return error(status ?? 500, failure ?? { id: '4e30e80c-e338-45a0-8c8f-44455efa3b76' });
|
return error(status ?? 500, failure ?? { id: '4e30e80c-e338-45a0-8c8f-44455efa3b76' });
|
||||||
};
|
};
|
||||||
|
|
||||||
if (request.ip === '::1' || request.ip === '127.0.0.1') {
|
|
||||||
console.warn('request ip is localhost, maybe caused by misconfiguration of trustProxy or reverse proxy');
|
|
||||||
} else {
|
|
||||||
try {
|
try {
|
||||||
// Not more than 1 API call per 250ms and not more than 100 attempts per 30min
|
// Not more than 1 API call per 250ms and not more than 100 attempts per 30min
|
||||||
// NOTE: 1 Sign-in require 2 API calls
|
// NOTE: 1 Sign-in require 2 API calls
|
||||||
|
|
@ -101,7 +98,6 @@ export class SigninWithPasskeyApiService {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Initiate Passkey Auth challenge with context
|
// Initiate Passkey Auth challenge with context
|
||||||
if (!credential) {
|
if (!credential) {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as os from 'node:os';
|
import * as os from 'node:os';
|
||||||
|
import si from 'systeminformation';
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
import * as Redis from 'ioredis';
|
import * as Redis from 'ioredis';
|
||||||
|
|
@ -111,8 +112,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
|
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async () => {
|
super(meta, paramDef, async () => {
|
||||||
const si = await import('systeminformation');
|
|
||||||
|
|
||||||
const memStats = await si.mem();
|
const memStats = await si.mem();
|
||||||
const fsStats = await si.fsSize();
|
const fsStats = await si.fsSize();
|
||||||
const netInterface = await si.networkInterfaceDefault();
|
const netInterface = await si.networkInterfaceDefault();
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as os from 'node:os';
|
import * as os from 'node:os';
|
||||||
|
import si from 'systeminformation';
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import { MiMeta } from '@/models/_.js';
|
import { MiMeta } from '@/models/_.js';
|
||||||
|
|
@ -92,8 +93,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const si = await import('systeminformation');
|
|
||||||
|
|
||||||
const memStats = await si.mem();
|
const memStats = await si.mem();
|
||||||
const fsStats = await si.fsSize();
|
const fsStats = await si.fsSize();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- type: bind
|
- type: bind
|
||||||
source: ./volumes/db.a
|
source: ./volumes/db.a
|
||||||
target: /var/lib/postgresql
|
target: /var/lib/postgresql/data
|
||||||
bind:
|
bind:
|
||||||
create_host_path: true
|
create_host_path: true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- type: bind
|
- type: bind
|
||||||
source: ./volumes/db.b
|
source: ./volumes/db.b
|
||||||
target: /var/lib/postgresql
|
target: /var/lib/postgresql/data
|
||||||
bind:
|
bind:
|
||||||
create_host_path: true
|
create_host_path: true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/estree": "1.0.8",
|
"@types/estree": "1.0.8",
|
||||||
"@types/node": "24.10.2",
|
"@types/node": "24.10.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.49.0",
|
"@typescript-eslint/eslint-plugin": "8.48.0",
|
||||||
"@typescript-eslint/parser": "8.49.0",
|
"@typescript-eslint/parser": "8.48.0",
|
||||||
"rollup": "4.53.3",
|
"rollup": "4.53.3",
|
||||||
"typescript": "5.9.3"
|
"typescript": "5.9.3"
|
||||||
},
|
},
|
||||||
|
|
@ -21,6 +21,6 @@
|
||||||
"i18n": "workspace:*",
|
"i18n": "workspace:*",
|
||||||
"estree-walker": "3.0.3",
|
"estree-walker": "3.0.3",
|
||||||
"magic-string": "0.30.21",
|
"magic-string": "0.30.21",
|
||||||
"vite": "7.2.7"
|
"vite": "7.2.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
"@rollup/pluginutils": "5.3.0",
|
"@rollup/pluginutils": "5.3.0",
|
||||||
"@twemoji/parser": "16.0.0",
|
"@twemoji/parser": "16.0.0",
|
||||||
"@vitejs/plugin-vue": "6.0.2",
|
"@vitejs/plugin-vue": "6.0.2",
|
||||||
|
"@vue/compiler-sfc": "3.5.25",
|
||||||
|
"astring": "1.9.0",
|
||||||
"buraha": "0.0.1",
|
"buraha": "0.0.1",
|
||||||
"estree-walker": "3.0.3",
|
"estree-walker": "3.0.3",
|
||||||
"frontend-shared": "workspace:*",
|
"frontend-shared": "workspace:*",
|
||||||
|
|
@ -26,11 +28,14 @@
|
||||||
"misskey-js": "workspace:*",
|
"misskey-js": "workspace:*",
|
||||||
"punycode.js": "2.3.1",
|
"punycode.js": "2.3.1",
|
||||||
"rollup": "4.53.3",
|
"rollup": "4.53.3",
|
||||||
"sass": "1.95.1",
|
"sass": "1.94.2",
|
||||||
"shiki": "3.19.0",
|
"shiki": "3.17.0",
|
||||||
"tinycolor2": "1.6.0",
|
"tinycolor2": "1.6.0",
|
||||||
|
"tsc-alias": "1.8.16",
|
||||||
|
"tsconfig-paths": "4.2.0",
|
||||||
|
"typescript": "5.9.3",
|
||||||
"uuid": "13.0.0",
|
"uuid": "13.0.0",
|
||||||
"vite": "7.2.7",
|
"vite": "7.2.4",
|
||||||
"vue": "3.5.25"
|
"vue": "3.5.25"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -39,30 +44,30 @@
|
||||||
"@testing-library/vue": "8.1.0",
|
"@testing-library/vue": "8.1.0",
|
||||||
"@types/estree": "1.0.8",
|
"@types/estree": "1.0.8",
|
||||||
"@types/micromatch": "4.0.10",
|
"@types/micromatch": "4.0.10",
|
||||||
"@types/node": "24.10.2",
|
"@types/node": "24.10.1",
|
||||||
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
||||||
"@types/tinycolor2": "1.4.6",
|
"@types/tinycolor2": "1.4.6",
|
||||||
"@types/ws": "8.18.1",
|
"@types/ws": "8.18.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.49.0",
|
"@typescript-eslint/eslint-plugin": "8.48.0",
|
||||||
"@typescript-eslint/parser": "8.49.0",
|
"@typescript-eslint/parser": "8.48.0",
|
||||||
"@vitest/coverage-v8": "4.0.15",
|
"@vitest/coverage-v8": "4.0.14",
|
||||||
"@vue/runtime-core": "3.5.25",
|
"@vue/runtime-core": "3.5.25",
|
||||||
"acorn": "8.15.0",
|
"acorn": "8.15.0",
|
||||||
"cross-env": "10.1.0",
|
"cross-env": "10.1.0",
|
||||||
"eslint-plugin-import": "2.32.0",
|
"eslint-plugin-import": "2.32.0",
|
||||||
"eslint-plugin-vue": "10.6.2",
|
"eslint-plugin-vue": "10.6.2",
|
||||||
|
"fast-glob": "3.3.3",
|
||||||
"happy-dom": "20.0.11",
|
"happy-dom": "20.0.11",
|
||||||
"intersection-observer": "0.12.2",
|
"intersection-observer": "0.12.2",
|
||||||
"micromatch": "4.0.8",
|
"micromatch": "4.0.8",
|
||||||
"msw": "2.12.4",
|
"msw": "2.12.3",
|
||||||
"nodemon": "3.1.11",
|
"nodemon": "3.1.11",
|
||||||
"prettier": "3.7.4",
|
"prettier": "3.7.1",
|
||||||
"start-server-and-test": "2.1.3",
|
"start-server-and-test": "2.1.3",
|
||||||
"tsx": "4.21.0",
|
"tsx": "4.20.6",
|
||||||
"typescript": "5.9.3",
|
|
||||||
"vite-plugin-turbosnap": "1.0.3",
|
"vite-plugin-turbosnap": "1.0.3",
|
||||||
"vue-component-type-helpers": "3.1.8",
|
"vue-component-type-helpers": "3.1.5",
|
||||||
"vue-eslint-parser": "10.2.0",
|
"vue-eslint-parser": "10.2.0",
|
||||||
"vue-tsc": "3.1.8"
|
"vue-tsc": "3.1.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,8 +70,6 @@
|
||||||
importAppScript();
|
importAppScript();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem('lang', lang);
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
async function addStyle(styleText) {
|
async function addStyle(styleText) {
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,14 @@ import { fileURLToPath } from 'node:url';
|
||||||
import { dirname } from 'node:path';
|
import { dirname } from 'node:path';
|
||||||
import * as esbuild from 'esbuild';
|
import * as esbuild from 'esbuild';
|
||||||
import { build } from 'esbuild';
|
import { build } from 'esbuild';
|
||||||
|
import { globSync } from 'glob';
|
||||||
import { execa } from 'execa';
|
import { execa } from 'execa';
|
||||||
|
|
||||||
const _filename = fileURLToPath(import.meta.url);
|
const _filename = fileURLToPath(import.meta.url);
|
||||||
const _dirname = dirname(_filename);
|
const _dirname = dirname(_filename);
|
||||||
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
|
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
|
||||||
|
|
||||||
const entryPoints = fs.globSync('./js/**/**.{ts,tsx}');
|
const entryPoints = globSync('./js/**/**.{ts,tsx}');
|
||||||
|
|
||||||
/** @type {import('esbuild').BuildOptions} */
|
/** @type {import('esbuild').BuildOptions} */
|
||||||
const options = {
|
const options = {
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,10 @@
|
||||||
"lint": "pnpm typecheck && pnpm eslint"
|
"lint": "pnpm typecheck && pnpm eslint"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "24.10.2",
|
"@types/node": "24.10.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.49.0",
|
"@typescript-eslint/eslint-plugin": "8.48.0",
|
||||||
"@typescript-eslint/parser": "8.49.0",
|
"@typescript-eslint/parser": "8.48.0",
|
||||||
"esbuild": "0.27.1",
|
"esbuild": "0.27.0",
|
||||||
"eslint-plugin-vue": "10.6.2",
|
"eslint-plugin-vue": "10.6.2",
|
||||||
"nodemon": "3.1.11",
|
"nodemon": "3.1.11",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,12 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { existsSync, readFileSync, globSync } from 'node:fs';
|
import { existsSync, readFileSync } from 'node:fs';
|
||||||
import { writeFile } from 'node:fs/promises';
|
import { writeFile } from 'node:fs/promises';
|
||||||
import { basename, dirname } from 'node:path/posix';
|
import { basename, dirname } from 'node:path/posix';
|
||||||
import { GENERATOR, type State, generate } from 'astring';
|
import { GENERATOR, type State, generate } from 'astring';
|
||||||
import type * as estree from 'estree';
|
import type * as estree from 'estree';
|
||||||
|
import glob from 'fast-glob';
|
||||||
import { format } from 'prettier';
|
import { format } from 'prettier';
|
||||||
|
|
||||||
interface SatisfiesExpression extends estree.BaseExpression {
|
interface SatisfiesExpression extends estree.BaseExpression {
|
||||||
|
|
@ -438,37 +439,38 @@ function toStories(component: string): Promise<string> {
|
||||||
|
|
||||||
// glob('src/{components,pages,ui,widgets}/**/*.vue')
|
// glob('src/{components,pages,ui,widgets}/**/*.vue')
|
||||||
(async () => {
|
(async () => {
|
||||||
const components = [
|
const globs = await Promise.all([
|
||||||
globSync('src/components/global/Mk*.vue'),
|
glob('src/components/global/Mk*.vue'),
|
||||||
globSync('src/components/global/RouterView.vue'),
|
glob('src/components/global/RouterView.vue'),
|
||||||
globSync('src/components/MkAbuseReportWindow.vue'),
|
glob('src/components/MkAbuseReportWindow.vue'),
|
||||||
globSync('src/components/MkAccountMoved.vue'),
|
glob('src/components/MkAccountMoved.vue'),
|
||||||
globSync('src/components/MkAchievements.vue'),
|
glob('src/components/MkAchievements.vue'),
|
||||||
globSync('src/components/MkAnalogClock.vue'),
|
glob('src/components/MkAnalogClock.vue'),
|
||||||
globSync('src/components/MkAnimBg.vue'),
|
glob('src/components/MkAnimBg.vue'),
|
||||||
globSync('src/components/MkAnnouncementDialog.vue'),
|
glob('src/components/MkAnnouncementDialog.vue'),
|
||||||
globSync('src/components/MkAntennaEditor.vue'),
|
glob('src/components/MkAntennaEditor.vue'),
|
||||||
globSync('src/components/MkAntennaEditorDialog.vue'),
|
glob('src/components/MkAntennaEditorDialog.vue'),
|
||||||
globSync('src/components/MkAsUi.vue'),
|
glob('src/components/MkAsUi.vue'),
|
||||||
globSync('src/components/MkAutocomplete.vue'),
|
glob('src/components/MkAutocomplete.vue'),
|
||||||
globSync('src/components/MkAvatars.vue'),
|
glob('src/components/MkAvatars.vue'),
|
||||||
globSync('src/components/Mk[B-E]*.vue'),
|
glob('src/components/Mk[B-E]*.vue'),
|
||||||
globSync('src/components/MkFlashPreview.vue'),
|
glob('src/components/MkFlashPreview.vue'),
|
||||||
globSync('src/components/MkGalleryPostPreview.vue'),
|
glob('src/components/MkGalleryPostPreview.vue'),
|
||||||
globSync('src/components/MkSignupServerRules.vue'),
|
glob('src/components/MkSignupServerRules.vue'),
|
||||||
globSync('src/components/MkUserSetupDialog.vue'),
|
glob('src/components/MkUserSetupDialog.vue'),
|
||||||
globSync('src/components/MkUserSetupDialog.*.vue'),
|
glob('src/components/MkUserSetupDialog.*.vue'),
|
||||||
globSync('src/components/MkImgPreviewDialog.vue'),
|
glob('src/components/MkImgPreviewDialog.vue'),
|
||||||
globSync('src/components/MkInstanceCardMini.vue'),
|
glob('src/components/MkInstanceCardMini.vue'),
|
||||||
globSync('src/components/MkInviteCode.vue'),
|
glob('src/components/MkInviteCode.vue'),
|
||||||
globSync('src/components/MkTagItem.vue'),
|
glob('src/components/MkTagItem.vue'),
|
||||||
globSync('src/components/MkRoleSelectDialog.vue'),
|
glob('src/components/MkRoleSelectDialog.vue'),
|
||||||
globSync('src/components/grid/MkGrid.vue'),
|
glob('src/components/grid/MkGrid.vue'),
|
||||||
globSync('src/pages/admin/custom-emojis-manager2.vue'),
|
glob('src/pages/admin/custom-emojis-manager2.vue'),
|
||||||
globSync('src/pages/admin/overview.ap-requests.vue'),
|
glob('src/pages/admin/overview.ap-requests.vue'),
|
||||||
globSync('src/pages/user/home.vue'),
|
glob('src/pages/user/home.vue'),
|
||||||
globSync('src/pages/search.vue'),
|
glob('src/pages/search.vue'),
|
||||||
].flat();
|
]);
|
||||||
|
const components = globs.flat();
|
||||||
await Promise.all(components.map(async (component) => {
|
await Promise.all(components.map(async (component) => {
|
||||||
const stories = component.replace(/\.vue$/, '.stories.ts');
|
const stories = component.replace(/\.vue$/, '.stories.ts');
|
||||||
await writeFile(stories, await toStories(component));
|
await writeFile(stories, await toStories(component));
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import {
|
||||||
type PluginOption
|
type PluginOption
|
||||||
} from 'vite';
|
} from 'vite';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
|
import { glob } from 'glob';
|
||||||
import JSON5 from 'json5';
|
import JSON5 from 'json5';
|
||||||
import MagicString, { SourceMap } from 'magic-string';
|
import MagicString, { SourceMap } from 'magic-string';
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
|
|
@ -723,7 +724,7 @@ export function pluginCreateSearchIndexVirtualModule(options: Options, asigner:
|
||||||
|
|
||||||
async load(id) {
|
async load(id) {
|
||||||
if (id == '\0' + allSearchIndexFile) {
|
if (id == '\0' + allSearchIndexFile) {
|
||||||
const files = options.targetFilePaths.map((filePathPattern) => fs.globSync(filePathPattern)).flat();
|
const files = await Promise.all(options.targetFilePaths.map(async (filePathPattern) => await glob(filePathPattern))).then(paths => paths.flat());
|
||||||
let generatedFile = '';
|
let generatedFile = '';
|
||||||
let arrayElements = '';
|
let arrayElements = '';
|
||||||
for (let file of files) {
|
for (let file of files) {
|
||||||
|
|
|
||||||
|
|
@ -19,19 +19,21 @@
|
||||||
"@analytics/google-analytics": "1.1.0",
|
"@analytics/google-analytics": "1.1.0",
|
||||||
"@discordapp/twemoji": "16.0.1",
|
"@discordapp/twemoji": "16.0.1",
|
||||||
"@github/webauthn-json": "2.1.1",
|
"@github/webauthn-json": "2.1.1",
|
||||||
"@mcaptcha/vanilla-glue": "0.1.0-rc2",
|
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
||||||
"i18n": "workspace:*",
|
"i18n": "workspace:*",
|
||||||
"@misskey-dev/browser-image-resizer": "2024.1.0",
|
"@misskey-dev/browser-image-resizer": "2024.1.0",
|
||||||
"@rollup/plugin-json": "6.1.0",
|
"@rollup/plugin-json": "6.1.0",
|
||||||
"@rollup/plugin-replace": "6.0.3",
|
"@rollup/plugin-replace": "6.0.3",
|
||||||
"@rollup/pluginutils": "5.3.0",
|
"@rollup/pluginutils": "5.3.0",
|
||||||
"@sentry/vue": "10.29.0",
|
"@sentry/vue": "10.27.0",
|
||||||
"@syuilo/aiscript": "1.2.0",
|
"@syuilo/aiscript": "1.2.0",
|
||||||
"@syuilo/aiscript-0-19-0": "npm:@syuilo/aiscript@^0.19.0",
|
"@syuilo/aiscript-0-19-0": "npm:@syuilo/aiscript@^0.19.0",
|
||||||
"@twemoji/parser": "16.0.0",
|
"@twemoji/parser": "16.0.0",
|
||||||
"@vitejs/plugin-vue": "6.0.2",
|
"@vitejs/plugin-vue": "6.0.2",
|
||||||
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.16",
|
"@vue/compiler-sfc": "3.5.25",
|
||||||
|
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.15",
|
||||||
"analytics": "0.8.19",
|
"analytics": "0.8.19",
|
||||||
|
"astring": "1.9.0",
|
||||||
"broadcast-channel": "7.2.0",
|
"broadcast-channel": "7.2.0",
|
||||||
"buraha": "0.0.1",
|
"buraha": "0.0.1",
|
||||||
"canvas-confetti": "1.9.4",
|
"canvas-confetti": "1.9.4",
|
||||||
|
|
@ -44,9 +46,10 @@
|
||||||
"compare-versions": "6.1.1",
|
"compare-versions": "6.1.1",
|
||||||
"cropperjs": "2.1.0",
|
"cropperjs": "2.1.0",
|
||||||
"date-fns": "4.1.0",
|
"date-fns": "4.1.0",
|
||||||
|
"estree-walker": "3.0.3",
|
||||||
"eventemitter3": "5.0.1",
|
"eventemitter3": "5.0.1",
|
||||||
"execa": "9.6.1",
|
"execa": "9.6.0",
|
||||||
"exifreader": "4.33.1",
|
"exifreader": "4.32.0",
|
||||||
"frontend-shared": "workspace:*",
|
"frontend-shared": "workspace:*",
|
||||||
"icons-subsetter": "workspace:*",
|
"icons-subsetter": "workspace:*",
|
||||||
"idb-keyval": "6.2.2",
|
"idb-keyval": "6.2.2",
|
||||||
|
|
@ -54,8 +57,9 @@
|
||||||
"ios-haptics": "0.1.4",
|
"ios-haptics": "0.1.4",
|
||||||
"is-file-animated": "1.0.2",
|
"is-file-animated": "1.0.2",
|
||||||
"json5": "2.2.3",
|
"json5": "2.2.3",
|
||||||
|
"magic-string": "0.30.21",
|
||||||
"matter-js": "0.20.0",
|
"matter-js": "0.20.0",
|
||||||
"mediabunny": "1.25.8",
|
"mediabunny": "1.25.3",
|
||||||
"mfm-js": "0.25.0",
|
"mfm-js": "0.25.0",
|
||||||
"misskey-bubble-game": "workspace:*",
|
"misskey-bubble-game": "workspace:*",
|
||||||
"misskey-js": "workspace:*",
|
"misskey-js": "workspace:*",
|
||||||
|
|
@ -66,14 +70,18 @@
|
||||||
"qr-scanner": "1.4.2",
|
"qr-scanner": "1.4.2",
|
||||||
"rollup": "4.53.3",
|
"rollup": "4.53.3",
|
||||||
"sanitize-html": "2.17.0",
|
"sanitize-html": "2.17.0",
|
||||||
"sass": "1.95.1",
|
"sass": "1.94.2",
|
||||||
"shiki": "3.19.0",
|
"shiki": "3.17.0",
|
||||||
|
"strict-event-emitter-types": "2.0.0",
|
||||||
"textarea-caret": "3.1.0",
|
"textarea-caret": "3.1.0",
|
||||||
"three": "0.181.2",
|
"three": "0.181.2",
|
||||||
"throttle-debounce": "5.0.2",
|
"throttle-debounce": "5.0.2",
|
||||||
"tinycolor2": "1.6.0",
|
"tinycolor2": "1.6.0",
|
||||||
|
"tsc-alias": "1.8.16",
|
||||||
|
"tsconfig-paths": "4.2.0",
|
||||||
|
"typescript": "5.9.3",
|
||||||
"v-code-diff": "1.13.1",
|
"v-code-diff": "1.13.1",
|
||||||
"vite": "7.2.7",
|
"vite": "7.2.4",
|
||||||
"vue": "3.5.25",
|
"vue": "3.5.25",
|
||||||
"vuedraggable": "next",
|
"vuedraggable": "next",
|
||||||
"wanakana": "5.3.1"
|
"wanakana": "5.3.1"
|
||||||
|
|
@ -82,7 +90,7 @@
|
||||||
"@misskey-dev/summaly": "5.2.5",
|
"@misskey-dev/summaly": "5.2.5",
|
||||||
"@storybook/addon-essentials": "8.6.14",
|
"@storybook/addon-essentials": "8.6.14",
|
||||||
"@storybook/addon-interactions": "8.6.14",
|
"@storybook/addon-interactions": "8.6.14",
|
||||||
"@storybook/addon-links": "10.1.5",
|
"@storybook/addon-links": "10.1.0",
|
||||||
"@storybook/addon-mdx-gfm": "8.6.14",
|
"@storybook/addon-mdx-gfm": "8.6.14",
|
||||||
"@storybook/addon-storysource": "8.6.14",
|
"@storybook/addon-storysource": "8.6.14",
|
||||||
"@storybook/blocks": "8.6.14",
|
"@storybook/blocks": "8.6.14",
|
||||||
|
|
@ -90,59 +98,58 @@
|
||||||
"@storybook/core-events": "8.6.14",
|
"@storybook/core-events": "8.6.14",
|
||||||
"@storybook/manager-api": "8.6.14",
|
"@storybook/manager-api": "8.6.14",
|
||||||
"@storybook/preview-api": "8.6.14",
|
"@storybook/preview-api": "8.6.14",
|
||||||
"@storybook/react": "10.1.5",
|
"@storybook/react": "10.1.0",
|
||||||
"@storybook/react-vite": "10.1.5",
|
"@storybook/react-vite": "10.1.0",
|
||||||
"@storybook/test": "8.6.14",
|
"@storybook/test": "8.6.14",
|
||||||
"@storybook/theming": "8.6.14",
|
"@storybook/theming": "8.6.14",
|
||||||
"@storybook/types": "8.6.14",
|
"@storybook/types": "8.6.14",
|
||||||
"@storybook/vue3": "10.1.5",
|
"@storybook/vue3": "10.1.0",
|
||||||
"@storybook/vue3-vite": "10.1.5",
|
"@storybook/vue3-vite": "10.1.0",
|
||||||
"@tabler/icons-webfont": "3.35.0",
|
"@tabler/icons-webfont": "3.35.0",
|
||||||
"@testing-library/vue": "8.1.0",
|
"@testing-library/vue": "8.1.0",
|
||||||
"@types/canvas-confetti": "1.9.0",
|
"@types/canvas-confetti": "1.9.0",
|
||||||
"@types/estree": "1.0.8",
|
"@types/estree": "1.0.8",
|
||||||
"@types/matter-js": "0.20.2",
|
"@types/matter-js": "0.20.2",
|
||||||
"@types/micromatch": "4.0.10",
|
"@types/micromatch": "4.0.10",
|
||||||
"@types/node": "24.10.2",
|
"@types/node": "24.10.1",
|
||||||
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
||||||
"@types/sanitize-html": "2.16.0",
|
"@types/sanitize-html": "2.16.0",
|
||||||
"@types/seedrandom": "3.0.8",
|
"@types/seedrandom": "3.0.8",
|
||||||
"@types/throttle-debounce": "5.0.2",
|
"@types/throttle-debounce": "5.0.2",
|
||||||
"@types/tinycolor2": "1.4.6",
|
"@types/tinycolor2": "1.4.6",
|
||||||
"@typescript-eslint/eslint-plugin": "8.49.0",
|
"@types/ws": "8.18.1",
|
||||||
"@typescript-eslint/parser": "8.49.0",
|
"@typescript-eslint/eslint-plugin": "8.48.0",
|
||||||
"@vitest/coverage-v8": "4.0.15",
|
"@typescript-eslint/parser": "8.48.0",
|
||||||
|
"@vitest/coverage-v8": "4.0.14",
|
||||||
"@vue/compiler-core": "3.5.25",
|
"@vue/compiler-core": "3.5.25",
|
||||||
|
"@vue/runtime-core": "3.5.25",
|
||||||
"acorn": "8.15.0",
|
"acorn": "8.15.0",
|
||||||
"astring": "1.9.0",
|
|
||||||
"cross-env": "10.1.0",
|
"cross-env": "10.1.0",
|
||||||
"cypress": "15.7.1",
|
"cypress": "15.7.0",
|
||||||
"eslint-plugin-import": "2.32.0",
|
"eslint-plugin-import": "2.32.0",
|
||||||
"eslint-plugin-vue": "10.6.2",
|
"eslint-plugin-vue": "10.6.2",
|
||||||
"estree-walker": "3.0.3",
|
"fast-glob": "3.3.3",
|
||||||
"happy-dom": "20.0.11",
|
"happy-dom": "20.0.11",
|
||||||
"intersection-observer": "0.12.2",
|
"intersection-observer": "0.12.2",
|
||||||
"magic-string": "0.30.21",
|
|
||||||
"micromatch": "4.0.8",
|
"micromatch": "4.0.8",
|
||||||
"minimatch": "10.1.1",
|
"minimatch": "10.1.1",
|
||||||
"msw": "2.12.4",
|
"msw": "2.12.3",
|
||||||
"msw-storybook-addon": "2.0.6",
|
"msw-storybook-addon": "2.0.6",
|
||||||
"nodemon": "3.1.11",
|
"nodemon": "3.1.11",
|
||||||
"prettier": "3.7.4",
|
"prettier": "3.7.1",
|
||||||
"react": "19.2.1",
|
"react": "19.2.0",
|
||||||
"react-dom": "19.2.1",
|
"react-dom": "19.2.0",
|
||||||
"seedrandom": "3.0.5",
|
"seedrandom": "3.0.5",
|
||||||
"start-server-and-test": "2.1.3",
|
"start-server-and-test": "2.1.3",
|
||||||
"storybook": "10.1.5",
|
"storybook": "10.1.0",
|
||||||
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
||||||
"tsx": "4.21.0",
|
"tsx": "4.20.6",
|
||||||
"typescript": "5.9.3",
|
"vite-plugin-glsl": "1.5.4",
|
||||||
"vite-plugin-glsl": "1.5.5",
|
|
||||||
"vite-plugin-turbosnap": "1.0.3",
|
"vite-plugin-turbosnap": "1.0.3",
|
||||||
"vitest": "4.0.15",
|
"vitest": "4.0.14",
|
||||||
"vitest-fetch-mock": "0.4.5",
|
"vitest-fetch-mock": "0.4.5",
|
||||||
"vue-component-type-helpers": "3.1.8",
|
"vue-component-type-helpers": "3.1.5",
|
||||||
"vue-eslint-parser": "10.2.0",
|
"vue-eslint-parser": "10.2.0",
|
||||||
"vue-tsc": "3.1.8"
|
"vue-tsc": "3.1.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,6 @@
|
||||||
console.error('invalid lang value detected!!!', typeof lang, lang);
|
console.error('invalid lang value detected!!!', typeof lang, lang);
|
||||||
lang = 'en-US';
|
lang = 'en-US';
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem('lang', lang);
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region Script
|
//#region Script
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
<MkButton v-if="foldersPaginator.canFetchOlder.value" primary rounded @click="foldersPaginator.fetchOlder()">{{ i18n.ts.loadMore }}</MkButton>
|
<MkButton v-if="foldersPaginator.canFetchOlder.value" primary rounded @click="foldersPaginator.fetchOlder()">{{ i18n.ts.loadMore }}</MkButton>
|
||||||
|
|
||||||
<template v-if="shouldBeGroupedByDate">
|
|
||||||
<MkStickyContainer v-for="(item, i) in filesTimeline" :key="`${item.date.getFullYear()}/${item.date.getMonth() + 1}`">
|
<MkStickyContainer v-for="(item, i) in filesTimeline" :key="`${item.date.getFullYear()}/${item.date.getMonth() + 1}`">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div :class="$style.date">
|
<div :class="$style.date">
|
||||||
|
|
@ -112,29 +111,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
/>
|
/>
|
||||||
</TransitionGroup>
|
</TransitionGroup>
|
||||||
</MkStickyContainer>
|
</MkStickyContainer>
|
||||||
</template>
|
|
||||||
<TransitionGroup
|
|
||||||
v-else
|
|
||||||
tag="div"
|
|
||||||
:enterActiveClass="prefer.s.animation ? $style.transition_files_enterActive : ''"
|
|
||||||
:leaveActiveClass="prefer.s.animation ? $style.transition_files_leaveActive : ''"
|
|
||||||
:enterFromClass="prefer.s.animation ? $style.transition_files_enterFrom : ''"
|
|
||||||
:leaveToClass="prefer.s.animation ? $style.transition_files_leaveTo : ''"
|
|
||||||
:moveClass="prefer.s.animation ? $style.transition_files_move : ''"
|
|
||||||
:class="$style.files"
|
|
||||||
>
|
|
||||||
<XFile
|
|
||||||
v-for="file in filesPaginator.items.value" :key="file.id"
|
|
||||||
:class="$style.file"
|
|
||||||
:file="file"
|
|
||||||
:folder="folder"
|
|
||||||
:isSelected="selectedFiles.some(x => x.id === file.id)"
|
|
||||||
@click="onFileClick($event, file)"
|
|
||||||
@dragstart="onFileDragstart(file, $event)"
|
|
||||||
@dragend="isDragSource = false"
|
|
||||||
/>
|
|
||||||
</TransitionGroup>
|
|
||||||
|
|
||||||
<MkButton v-show="filesPaginator.canFetchOlder.value" :class="$style.loadMore" primary rounded @click="filesPaginator.fetchOlder()">{{ i18n.ts.loadMore }}</MkButton>
|
<MkButton v-show="filesPaginator.canFetchOlder.value" :class="$style.loadMore" primary rounded @click="filesPaginator.fetchOlder()">{{ i18n.ts.loadMore }}</MkButton>
|
||||||
|
|
||||||
<div v-if="filesPaginator.items.value.length == 0 && foldersPaginator.items.value.length == 0 && !fetching" :class="$style.empty">
|
<div v-if="filesPaginator.items.value.length == 0 && foldersPaginator.items.value.length == 0 && !fetching" :class="$style.empty">
|
||||||
|
|
@ -241,7 +217,6 @@ const foldersPaginator = markRaw(new Paginator('drive/folders', {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const filesTimeline = makeDateGroupedTimelineComputedRef(filesPaginator.items, 'month');
|
const filesTimeline = makeDateGroupedTimelineComputedRef(filesPaginator.items, 'month');
|
||||||
const shouldBeGroupedByDate = computed(() => ['+createdAt', '-createdAt'].includes(sortModeSelect.value));
|
|
||||||
|
|
||||||
watch(folder, () => emit('cd', folder.value));
|
watch(folder, () => emit('cd', folder.value));
|
||||||
watch(sortModeSelect, () => {
|
watch(sortModeSelect, () => {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</MkModalWindow>
|
</MkModalWindow>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { defineProps, ref } from 'vue';
|
||||||
import MkModalWindow from './MkModalWindow.vue';
|
import MkModalWindow from './MkModalWindow.vue';
|
||||||
import type * as Misskey from 'misskey-js';
|
import type * as Misskey from 'misskey-js';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="!hardMuted && !hideByPlugin && muted === false"
|
v-if="!hardMuted && muted === false"
|
||||||
ref="rootEl"
|
ref="rootEl"
|
||||||
v-hotkey="keymap"
|
v-hotkey="keymap"
|
||||||
:class="[$style.root, { [$style.showActionsOnlyHover]: prefer.s.showNoteActionsOnlyHover, [$style.skipRender]: prefer.s.skipNoteRender }]"
|
:class="[$style.root, { [$style.showActionsOnlyHover]: prefer.s.showNoteActionsOnlyHover, [$style.skipRender]: prefer.s.skipNoteRender }]"
|
||||||
|
|
@ -38,10 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<span v-if="note.channel" style="margin-left: 0.5em;" :title="note.channel.name"><i class="ti ti-device-tv"></i></span>
|
<span v-if="note.channel" style="margin-left: 0.5em;" :title="note.channel.name"><i class="ti ti-device-tv"></i></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="isRenote && note.renote == null" :class="$style.deleted">
|
<div v-if="renoteCollapsed" :class="$style.collapsedRenoteTarget">
|
||||||
{{ i18n.ts.deletedNote }}
|
|
||||||
</div>
|
|
||||||
<div v-else-if="renoteCollapsed" :class="$style.collapsedRenoteTarget">
|
|
||||||
<MkAvatar :class="$style.collapsedRenoteTargetAvatar" :user="appearNote.user" link preview/>
|
<MkAvatar :class="$style.collapsedRenoteTargetAvatar" :user="appearNote.user" link preview/>
|
||||||
<Mfm :text="getNoteSummary(appearNote)" :plain="true" :nowrap="true" :author="appearNote.user" :nyaize="'respect'" :class="$style.collapsedRenoteTargetText" @click="renoteCollapsed = false"/>
|
<Mfm :text="getNoteSummary(appearNote)" :plain="true" :nowrap="true" :author="appearNote.user" :nyaize="'respect'" :class="$style.collapsedRenoteTargetText" @click="renoteCollapsed = false"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -161,7 +158,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="!hardMuted && !hideByPlugin" :class="$style.muted" @click="muted = false">
|
<div v-else-if="!hardMuted" :class="$style.muted" @click="muted = false">
|
||||||
<I18n v-if="muted === 'sensitiveMute'" :src="i18n.ts.userSaysSomethingSensitive" tag="small">
|
<I18n v-if="muted === 'sensitiveMute'" :src="i18n.ts.userSaysSomethingSensitive" tag="small">
|
||||||
<template #name>
|
<template #name>
|
||||||
<MkA v-user-preview="appearNote.userId" :to="userPage(appearNote.user)">
|
<MkA v-user-preview="appearNote.userId" :to="userPage(appearNote.user)">
|
||||||
|
|
@ -270,7 +267,6 @@ let note = deepClone(props.note);
|
||||||
|
|
||||||
// plugin
|
// plugin
|
||||||
const noteViewInterruptors = getPluginHandlers('note_view_interruptor');
|
const noteViewInterruptors = getPluginHandlers('note_view_interruptor');
|
||||||
const hideByPlugin = ref(false);
|
|
||||||
if (noteViewInterruptors.length > 0) {
|
if (noteViewInterruptors.length > 0) {
|
||||||
let result: Misskey.entities.Note | null = deepClone(note);
|
let result: Misskey.entities.Note | null = deepClone(note);
|
||||||
for (const interruptor of noteViewInterruptors) {
|
for (const interruptor of noteViewInterruptors) {
|
||||||
|
|
@ -280,12 +276,8 @@ if (noteViewInterruptors.length > 0) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result == null) {
|
|
||||||
hideByPlugin.value = true;
|
|
||||||
} else {
|
|
||||||
note = result as Misskey.entities.Note;
|
note = result as Misskey.entities.Note;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const isRenote = Misskey.note.isPureRenote(note);
|
const isRenote = Misskey.note.isPureRenote(note);
|
||||||
const appearNote = getAppearNote(note) ?? note;
|
const appearNote = getAppearNote(note) ?? note;
|
||||||
|
|
@ -1152,14 +1144,4 @@ function emitUpdReaction(emoji: string, delta: number) {
|
||||||
opacity: .8;
|
opacity: .8;
|
||||||
font-size: 95%;
|
font-size: 95%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.deleted {
|
|
||||||
text-align: center;
|
|
||||||
padding: 32px;
|
|
||||||
margin: 6px 32px 28px;
|
|
||||||
--color: light-dark(rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.15));
|
|
||||||
background-size: auto auto;
|
|
||||||
background-image: repeating-linear-gradient(135deg, transparent, transparent 10px, var(--color) 4px, var(--color) 14px);
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="!muted && !hideByPlugin && !isDeleted"
|
v-if="!muted && !isDeleted"
|
||||||
ref="rootEl"
|
ref="rootEl"
|
||||||
v-hotkey="keymap"
|
v-hotkey="keymap"
|
||||||
:class="$style.root"
|
:class="$style.root"
|
||||||
|
|
@ -43,10 +43,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
|
<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="isRenote && note.renote == null" :class="$style.deleted">
|
|
||||||
{{ i18n.ts.deletedNote }}
|
|
||||||
</div>
|
|
||||||
<template v-else>
|
|
||||||
<article :class="$style.note" @contextmenu.stop="onContextmenu">
|
<article :class="$style.note" @contextmenu.stop="onContextmenu">
|
||||||
<header :class="$style.noteHeader">
|
<header :class="$style.noteHeader">
|
||||||
<MkAvatar :class="$style.noteHeaderAvatar" :user="appearNote.user" indicator link preview/>
|
<MkAvatar :class="$style.noteHeaderAvatar" :user="appearNote.user" indicator link preview/>
|
||||||
|
|
@ -191,7 +187,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkNoteSub v-for="note in replies" :key="note.id" :note="note" :class="$style.reply" :detail="true"/>
|
<MkNoteSub v-for="note in replies" :key="note.id" :note="note" :class="$style.reply" :detail="true"/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="tab === 'renotes'" :class="$style.tab_renotes">
|
<div v-else-if="tab === 'renotes'" :class="$style.tab_renotes">
|
||||||
<MkPagination :paginator="renotesPaginator" :forceDisableInfiniteScroll="true">
|
<MkPagination :paginator="renotesPaginator">
|
||||||
<template #default="{ items }">
|
<template #default="{ items }">
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); grid-gap: 12px;">
|
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); grid-gap: 12px;">
|
||||||
<MkA v-for="item in items" :key="item.id" :to="userPage(item.user)">
|
<MkA v-for="item in items" :key="item.id" :to="userPage(item.user)">
|
||||||
|
|
@ -208,7 +204,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<span style="margin-left: 4px;">{{ $appearNote.reactions[reaction] }}</span>
|
<span style="margin-left: 4px;">{{ $appearNote.reactions[reaction] }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<MkPagination v-if="reactionTabType" :key="reactionTabType" :paginator="reactionsPaginator" :forceDisableInfiniteScroll="true">
|
<MkPagination v-if="reactionTabType" :key="reactionTabType" :paginator="reactionsPaginator">
|
||||||
<template #default="{ items }">
|
<template #default="{ items }">
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); grid-gap: 12px;">
|
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); grid-gap: 12px;">
|
||||||
<MkA v-for="item in items" :key="item.id" :to="userPage(item.user)">
|
<MkA v-for="item in items" :key="item.id" :to="userPage(item.user)">
|
||||||
|
|
@ -219,7 +215,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</MkPagination>
|
</MkPagination>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="muted" class="_panel" :class="$style.muted" @click="muted = false">
|
<div v-else-if="muted" class="_panel" :class="$style.muted" @click="muted = false">
|
||||||
<I18n :src="i18n.ts.userSaysSomething" tag="small">
|
<I18n :src="i18n.ts.userSaysSomething" tag="small">
|
||||||
|
|
@ -294,7 +289,6 @@ let note = deepClone(props.note);
|
||||||
|
|
||||||
// plugin
|
// plugin
|
||||||
const noteViewInterruptors = getPluginHandlers('note_view_interruptor');
|
const noteViewInterruptors = getPluginHandlers('note_view_interruptor');
|
||||||
const hideByPlugin = ref(false);
|
|
||||||
if (noteViewInterruptors.length > 0) {
|
if (noteViewInterruptors.length > 0) {
|
||||||
let result: Misskey.entities.Note | null = deepClone(note);
|
let result: Misskey.entities.Note | null = deepClone(note);
|
||||||
for (const interruptor of noteViewInterruptors) {
|
for (const interruptor of noteViewInterruptors) {
|
||||||
|
|
@ -304,12 +298,8 @@ if (noteViewInterruptors.length > 0) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result == null) {
|
|
||||||
hideByPlugin.value = true;
|
|
||||||
} else {
|
|
||||||
note = result as Misskey.entities.Note;
|
note = result as Misskey.entities.Note;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const isRenote = Misskey.note.isPureRenote(note);
|
const isRenote = Misskey.note.isPureRenote(note);
|
||||||
const appearNote = getAppearNote(note) ?? note;
|
const appearNote = getAppearNote(note) ?? note;
|
||||||
|
|
@ -954,14 +944,4 @@ function loadConversation() {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.deleted {
|
|
||||||
text-align: center;
|
|
||||||
padding: 32px;
|
|
||||||
margin: 6px 32px 32px;
|
|
||||||
--color: light-dark(rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.15));
|
|
||||||
background-size: auto auto;
|
|
||||||
background-image: repeating-linear-gradient(135deg, transparent, transparent 10px, var(--color) 4px, var(--color) 14px);
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
:class="[$style.root]"
|
:class="[$style.root, { [$style.modal]: modal, _popup: modal }]"
|
||||||
@dragover.stop="onDragover"
|
@dragover.stop="onDragover"
|
||||||
@dragenter="onDragenter"
|
@dragenter="onDragenter"
|
||||||
@dragleave="onDragleave"
|
@dragleave="onDragleave"
|
||||||
|
|
@ -114,7 +114,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { watch, nextTick, onMounted, defineAsyncComponent, provide, shallowRef, ref, computed, useTemplateRef, onUnmounted } from 'vue';
|
import { inject, watch, nextTick, onMounted, defineAsyncComponent, provide, shallowRef, ref, computed, useTemplateRef, onUnmounted } from 'vue';
|
||||||
import * as mfm from 'mfm-js';
|
import * as mfm from 'mfm-js';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||||
|
|
@ -161,6 +161,8 @@ import { closeTip } from '@/tips.js';
|
||||||
|
|
||||||
const $i = ensureSignin();
|
const $i = ensureSignin();
|
||||||
|
|
||||||
|
const modal = inject(DI.inModal, false);
|
||||||
|
|
||||||
const props = withDefaults(defineProps<PostFormProps & {
|
const props = withDefaults(defineProps<PostFormProps & {
|
||||||
fixed?: boolean;
|
fixed?: boolean;
|
||||||
autofocus?: boolean;
|
autofocus?: boolean;
|
||||||
|
|
@ -1445,6 +1447,13 @@ defineExpose({
|
||||||
.root {
|
.root {
|
||||||
position: relative;
|
position: relative;
|
||||||
container-type: inline-size;
|
container-type: inline-size;
|
||||||
|
|
||||||
|
&.modal {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 520px;
|
||||||
|
overflow-x: clip;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region header
|
//#region header
|
||||||
|
|
@ -1713,8 +1722,7 @@ html[data-color-scheme=light] .preview {
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 90px;
|
min-height: 90px;
|
||||||
max-height: 500px;
|
height: 100%;
|
||||||
field-sizing: content;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.textCount {
|
.textCount {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkPostForm
|
<MkPostForm
|
||||||
ref="form"
|
ref="form"
|
||||||
:class="$style.form"
|
:class="$style.form"
|
||||||
class="_popup"
|
|
||||||
v-bind="props"
|
v-bind="props"
|
||||||
autofocus
|
autofocus
|
||||||
freezeAfterPosted
|
freezeAfterPosted
|
||||||
|
|
@ -74,8 +73,7 @@ function onModalClosed() {
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
.form {
|
.form {
|
||||||
width: 100%;
|
max-height: 100%;
|
||||||
max-width: 520px;
|
|
||||||
margin: 0 auto auto auto;
|
margin: 0 auto auto auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template v-if="showDecoration">
|
<template v-if="showDecoration">
|
||||||
<img
|
<img
|
||||||
v-for="decoration in decorations ?? user.avatarDecorations"
|
v-for="decoration in decorations ?? user.avatarDecorations"
|
||||||
:class="[$style.decoration, { [$style.decorationBlink]: getDecorationIsBrink(decoration) }]"
|
:class="[$style.decoration, { [$style.decorationBlink]: decoration.blink }]"
|
||||||
:src="getDecorationUrl(decoration)"
|
:src="getDecorationUrl(decoration)"
|
||||||
:style="{
|
:style="{
|
||||||
rotate: getDecorationAngle(decoration),
|
rotate: getDecorationAngle(decoration),
|
||||||
|
|
@ -56,16 +56,13 @@ import { prefer } from '@/preferences.js';
|
||||||
const animation = ref(prefer.s.animation);
|
const animation = ref(prefer.s.animation);
|
||||||
const squareAvatars = ref(prefer.s.squareAvatars);
|
const squareAvatars = ref(prefer.s.squareAvatars);
|
||||||
|
|
||||||
type Decoration = Misskey.entities.UserDetailed['avatarDecorations'][number];
|
|
||||||
type DecorationEditorDecoration = Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'> & { blink?: boolean; };
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
user: Misskey.entities.User;
|
user: Misskey.entities.User;
|
||||||
target?: string | null;
|
target?: string | null;
|
||||||
link?: boolean;
|
link?: boolean;
|
||||||
preview?: boolean;
|
preview?: boolean;
|
||||||
indicator?: boolean;
|
indicator?: boolean;
|
||||||
decorations?: DecorationEditorDecoration[];
|
decorations?: (Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'> & { blink?: boolean; })[];
|
||||||
forceShowDecoration?: boolean;
|
forceShowDecoration?: boolean;
|
||||||
}>(), {
|
}>(), {
|
||||||
target: null,
|
target: null,
|
||||||
|
|
@ -96,31 +93,27 @@ function onClick(ev: MouseEvent): void {
|
||||||
emit('click', ev);
|
emit('click', ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDecorationUrl(decoration: Decoration | DecorationEditorDecoration) {
|
function getDecorationUrl(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||||
if (prefer.s.disableShowingAnimatedImages || prefer.s.dataSaver.avatar) return getStaticImageUrl(decoration.url);
|
if (prefer.s.disableShowingAnimatedImages || prefer.s.dataSaver.avatar) return getStaticImageUrl(decoration.url);
|
||||||
return decoration.url;
|
return decoration.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDecorationAngle(decoration: Decoration | DecorationEditorDecoration) {
|
function getDecorationAngle(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||||
const angle = decoration.angle ?? 0;
|
const angle = decoration.angle ?? 0;
|
||||||
return angle === 0 ? undefined : `${angle * 360}deg`;
|
return angle === 0 ? undefined : `${angle * 360}deg`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDecorationScale(decoration: Decoration | DecorationEditorDecoration) {
|
function getDecorationScale(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||||
const scaleX = decoration.flipH ? -1 : 1;
|
const scaleX = decoration.flipH ? -1 : 1;
|
||||||
return scaleX === 1 ? undefined : `${scaleX} 1`;
|
return scaleX === 1 ? undefined : `${scaleX} 1`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDecorationOffset(decoration: Decoration | DecorationEditorDecoration) {
|
function getDecorationOffset(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
|
||||||
const offsetX = decoration.offsetX ?? 0;
|
const offsetX = decoration.offsetX ?? 0;
|
||||||
const offsetY = decoration.offsetY ?? 0;
|
const offsetY = decoration.offsetY ?? 0;
|
||||||
return offsetX === 0 && offsetY === 0 ? undefined : `${offsetX * 100}% ${offsetY * 100}%`;
|
return offsetX === 0 && offsetY === 0 ? undefined : `${offsetX * 100}% ${offsetY * 100}%`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDecorationIsBrink(decoration: Decoration | DecorationEditorDecoration) {
|
|
||||||
return 'blink' in decoration && decoration.blink === true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const color = ref<string | undefined>();
|
const color = ref<string | undefined>();
|
||||||
|
|
||||||
watch(() => props.user.avatarBlurhash, () => {
|
watch(() => props.user.avatarBlurhash, () => {
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ export const components = {
|
||||||
SearchIcon: SearchIcon,
|
SearchIcon: SearchIcon,
|
||||||
};
|
};
|
||||||
|
|
||||||
declare module 'vue' {
|
declare module '@vue/runtime-core' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
I18n: typeof I18n;
|
I18n: typeof I18n;
|
||||||
RouterView: typeof RouterView;
|
RouterView: typeof RouterView;
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<SearchMarker>
|
<SearchMarker>
|
||||||
<MkFolder :defaultOpen="true">
|
<MkFolder :defaultOpen="true">
|
||||||
<template #icon><SearchIcon><i class="ti ti-bolt"></i></SearchIcon></template>
|
<template #icon><SearchIcon><i class="ti ti-bolt"></i></SearchIcon></template>
|
||||||
<template #label><SearchLabel>Misskey® Reactions Boost Technology™ (RBT)</SearchLabel></template>
|
<template #label><SearchLabel>Misskey® Reactions Boost Technology™ (RBT)</SearchLabel><span class="_beta">{{ i18n.ts.beta }}</span></template>
|
||||||
<template v-if="rbtForm.savedState.enableReactionsBuffering" #suffix>Enabled</template>
|
<template v-if="rbtForm.savedState.enableReactionsBuffering" #suffix>Enabled</template>
|
||||||
<template v-else #suffix>Disabled</template>
|
<template v-else #suffix>Disabled</template>
|
||||||
<template v-if="rbtForm.modified.value" #footer>
|
<template v-if="rbtForm.modified.value" #footer>
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,7 @@ async function search() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const headerActions = computed(() => {
|
const headerActions = computed(() => {
|
||||||
if (channel.value) {
|
if (channel.value && channel.value.userId) {
|
||||||
const headerItems: PageHeaderItem[] = [];
|
const headerItems: PageHeaderItem[] = [];
|
||||||
|
|
||||||
headerItems.push({
|
headerItems.push({
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ function start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getIsLegacy(version: string | null): boolean {
|
function getIsLegacy(version: string | null): boolean {
|
||||||
if (version == null) return true;
|
if (version == null) return false;
|
||||||
try {
|
try {
|
||||||
return compareVersions(version, '1.0.0') < 0;
|
return compareVersions(version, '1.0.0') < 0;
|
||||||
} catch {
|
} catch {
|
||||||
|
|
@ -206,7 +206,7 @@ async function run() {
|
||||||
if (!flash.value) return;
|
if (!flash.value) return;
|
||||||
|
|
||||||
const version = utils.getLangVersion(flash.value.script);
|
const version = utils.getLangVersion(flash.value.script);
|
||||||
const isLegacy = getIsLegacy(version);
|
const isLegacy = version != null && getIsLegacy(version);
|
||||||
|
|
||||||
const { Interpreter, Parser, values } = isLegacy ? (await import('@syuilo/aiscript-0-19-0') as any) : await import('@syuilo/aiscript');
|
const { Interpreter, Parser, values } = isLegacy ? (await import('@syuilo/aiscript-0-19-0') as any) : await import('@syuilo/aiscript');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<SearchMarker :keywords="['lockdown']">
|
<SearchMarker :keywords="['lockdown']">
|
||||||
<FormSection>
|
<FormSection>
|
||||||
<template #label><SearchLabel>{{ i18n.ts.lockdown }}</SearchLabel></template>
|
<template #label><SearchLabel>{{ i18n.ts.lockdown }}</SearchLabel><span class="_beta">{{ i18n.ts.beta }}</span></template>
|
||||||
|
|
||||||
<div class="_gaps_m">
|
<div class="_gaps_m">
|
||||||
<SearchMarker :keywords="['login', 'signin']">
|
<SearchMarker :keywords="['login', 'signin']">
|
||||||
|
|
@ -213,9 +213,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, watch } from 'vue';
|
import { ref, computed, watch } from 'vue';
|
||||||
import type { MkSelectItem } from '@/components/MkSelect.vue';
|
|
||||||
import MkSwitch from '@/components/MkSwitch.vue';
|
import MkSwitch from '@/components/MkSwitch.vue';
|
||||||
import MkSelect from '@/components/MkSelect.vue';
|
import MkSelect from '@/components/MkSelect.vue';
|
||||||
|
import type { MkSelectItem } from '@/components/MkSelect.vue';
|
||||||
import FormSection from '@/components/form/section.vue';
|
import FormSection from '@/components/form/section.vue';
|
||||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<SearchMarker :keywords="['follow', 'message']">
|
<SearchMarker :keywords="['follow', 'message']">
|
||||||
<MkInput v-model="profile.followedMessage" :max="200" manualSave :mfmPreview="false">
|
<MkInput v-model="profile.followedMessage" :max="200" manualSave :mfmPreview="false">
|
||||||
<template #label><SearchLabel>{{ i18n.ts._profile.followedMessage }}</SearchLabel></template>
|
<template #label><SearchLabel>{{ i18n.ts._profile.followedMessage }}</SearchLabel><span class="_beta">{{ i18n.ts.beta }}</span></template>
|
||||||
<template #caption>
|
<template #caption>
|
||||||
<div><SearchText>{{ i18n.ts._profile.followedMessageDescription }}</SearchText></div>
|
<div><SearchText>{{ i18n.ts._profile.followedMessageDescription }}</SearchText></div>
|
||||||
<div>{{ i18n.ts._profile.followedMessageDescriptionForLockedAccount }}</div>
|
<div>{{ i18n.ts._profile.followedMessageDescriptionForLockedAccount }}</div>
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<SearchMarker :keywords="['signin', 'login', 'history', 'log']">
|
<SearchMarker :keywords="['signin', 'login', 'history', 'log']">
|
||||||
<FormSection>
|
<FormSection>
|
||||||
<template #label><SearchLabel>{{ i18n.ts.signinHistory }}</SearchLabel></template>
|
<template #label><SearchLabel>{{ i18n.ts.signinHistory }}</SearchLabel></template>
|
||||||
<MkPagination :paginator="paginator" withControl :forceDisableInfiniteScroll="true">
|
<MkPagination :paginator="paginator" withControl>
|
||||||
<template #default="{items}">
|
<template #default="{items}">
|
||||||
<div>
|
<div>
|
||||||
<div v-for="item in items" :key="item.id" v-panel class="timnmucd">
|
<div v-for="item in items" :key="item.id" v-panel class="timnmucd">
|
||||||
|
|
|
||||||
|
|
@ -257,23 +257,20 @@ export class PreferencesManager extends EventEmitter<PreferencesManagerEvents> {
|
||||||
|
|
||||||
this.rewriteRawState(key, v);
|
this.rewriteRawState(key, v);
|
||||||
|
|
||||||
const record = this.getMatchedRecordOf(key);
|
|
||||||
|
|
||||||
const _save = () => {
|
|
||||||
this.save();
|
|
||||||
this.emit('committed', {
|
this.emit('committed', {
|
||||||
key,
|
key,
|
||||||
value: v,
|
value: v,
|
||||||
oldValue: this.s[key],
|
oldValue: this.s[key],
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
const record = this.getMatchedRecordOf(key);
|
||||||
|
|
||||||
if (parseScope(record[0]).account == null && isAccountDependentKey(key) && currentAccount != null) {
|
if (parseScope(record[0]).account == null && isAccountDependentKey(key) && currentAccount != null) {
|
||||||
this.profile.preferences[key].push([makeScope({
|
this.profile.preferences[key].push([makeScope({
|
||||||
server: host,
|
server: host,
|
||||||
account: currentAccount.id,
|
account: currentAccount.id,
|
||||||
}), v, {}]);
|
}), v, {}]);
|
||||||
_save();
|
this.save();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -281,12 +278,12 @@ export class PreferencesManager extends EventEmitter<PreferencesManagerEvents> {
|
||||||
this.profile.preferences[key].push([makeScope({
|
this.profile.preferences[key].push([makeScope({
|
||||||
server: host,
|
server: host,
|
||||||
}), v, {}]);
|
}), v, {}]);
|
||||||
_save();
|
this.save();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
record[1] = v;
|
record[1] = v;
|
||||||
_save();
|
this.save();
|
||||||
|
|
||||||
if (record[2].sync) {
|
if (record[2].sync) {
|
||||||
// awaitの必要なし
|
// awaitの必要なし
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ export const TIPS = [
|
||||||
'clips',
|
'clips',
|
||||||
'userLists',
|
'userLists',
|
||||||
'postForm',
|
'postForm',
|
||||||
'deck',
|
|
||||||
'tl.home',
|
'tl.home',
|
||||||
'tl.local',
|
'tl.local',
|
||||||
'tl.social',
|
'tl.social',
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<i v-if="store.r.realtimeMode.value" class="ti ti-bolt ti-fw"></i>
|
<i v-if="store.r.realtimeMode.value" class="ti ti-bolt ti-fw"></i>
|
||||||
<i v-else class="ti ti-bolt-off ti-fw"></i>
|
<i v-else class="ti ti-bolt-off ti-fw"></i>
|
||||||
</button>
|
</button>
|
||||||
<button v-if="!iconOnly && showWidgetButton" v-tooltip.noDelay.right="i18n.ts.widgets" class="_button" :class="[$style.widget]" @click="() => emit('widgetButtonClick')">
|
|
||||||
<i class="ti ti-apps ti-fw"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.middle">
|
<div :class="$style.middle">
|
||||||
<MkA v-tooltip.noDelay.right="i18n.ts.timeline" :class="$style.item" :activeClass="$style.active" to="/" exact>
|
<MkA v-tooltip.noDelay.right="i18n.ts.timeline" :class="$style.item" :activeClass="$style.active" to="/" exact>
|
||||||
|
|
@ -54,7 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</MkA>
|
</MkA>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.bottom">
|
<div :class="$style.bottom">
|
||||||
<button v-if="iconOnly && showWidgetButton" v-tooltip.noDelay.right="i18n.ts.widgets" class="_button" :class="[$style.widget]" @click="() => emit('widgetButtonClick')">
|
<button v-if="showWidgetButton" v-tooltip.noDelay.right="i18n.ts.widgets" class="_button" :class="[$style.widget]" @click="() => emit('widgetButtonClick')">
|
||||||
<i class="ti ti-apps ti-fw"></i>
|
<i class="ti ti-apps ti-fw"></i>
|
||||||
</button>
|
</button>
|
||||||
<button v-if="iconOnly" v-tooltip.noDelay.right="i18n.ts.realtimeMode" class="_button" :class="[$style.realtimeMode, store.r.realtimeMode.value ? $style.on : null]" @click="toggleRealtimeMode">
|
<button v-if="iconOnly" v-tooltip.noDelay.right="i18n.ts.realtimeMode" class="_button" :class="[$style.realtimeMode, store.r.realtimeMode.value ? $style.on : null]" @click="toggleRealtimeMode">
|
||||||
|
|
@ -439,12 +436,6 @@ function menuEdit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.widget {
|
|
||||||
display: inline-block;
|
|
||||||
width: var(--top-height);
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bottom {
|
.bottom {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
|
|
||||||
|
|
@ -38,39 +38,36 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
@headerWheel="onWheel"
|
@headerWheel="onWheel"
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
<div v-if="layout.length === 0" class="_panel _gaps" :class="$style.onboarding">
|
<div v-if="layout.length === 0" class="_panel" :class="$style.onboarding">
|
||||||
<div>{{ i18n.ts._deck.introduction }}</div>
|
<div>{{ i18n.ts._deck.introduction }}</div>
|
||||||
<div>{{ i18n.ts._deck.introduction2 }}</div>
|
<div>{{ i18n.ts._deck.introduction2 }}</div>
|
||||||
<MkInfo v-if="!store.r.tips.value.deck" closable @close="closeTip('deck')">
|
|
||||||
<button class="_textButton" @click="showTour">{{ i18n.ts._deck.showHowToUse }}</button>
|
|
||||||
</MkInfo>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="prefer.r['deck.menuPosition'].value === 'right'" :class="$style.sideMenu">
|
<div v-if="prefer.r['deck.menuPosition'].value === 'right'" :class="$style.sideMenu">
|
||||||
<div :class="$style.sideMenuTop">
|
<div :class="$style.sideMenuTop">
|
||||||
<button ref="swicthProfileButtonEl" v-tooltip.noDelay.left="`${i18n.ts._deck.profile}: ${prefer.s['deck.profile']}`" :class="$style.sideMenuButton" class="_button" @click="switchProfileMenu"><i class="ti ti-caret-down"></i></button>
|
<button v-tooltip.noDelay.left="`${i18n.ts._deck.profile}: ${prefer.s['deck.profile']}`" :class="$style.sideMenuButton" class="_button" @click="switchProfileMenu"><i class="ti ti-caret-down"></i></button>
|
||||||
<button v-tooltip.noDelay.left="i18n.ts._deck.deleteProfile" :class="$style.sideMenuButton" class="_button" @click="deleteProfile"><i class="ti ti-trash"></i></button>
|
<button v-tooltip.noDelay.left="i18n.ts._deck.deleteProfile" :class="$style.sideMenuButton" class="_button" @click="deleteProfile"><i class="ti ti-trash"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.sideMenuMiddle">
|
<div :class="$style.sideMenuMiddle">
|
||||||
<button ref="addColumnButtonEl" v-tooltip.noDelay.left="i18n.ts._deck.addColumn" :class="$style.sideMenuButton" class="_button" @click="addColumn"><i class="ti ti-plus"></i></button>
|
<button v-tooltip.noDelay.left="i18n.ts._deck.addColumn" :class="$style.sideMenuButton" class="_button" @click="addColumn"><i class="ti ti-plus"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.sideMenuBottom">
|
<div :class="$style.sideMenuBottom">
|
||||||
<button ref="settingsButtonEl" v-tooltip.noDelay.left="i18n.ts.settings" :class="$style.sideMenuButton" class="_button" @click="showSettings"><i class="ti ti-settings-2"></i></button>
|
<button v-tooltip.noDelay.left="i18n.ts.settings" :class="$style.sideMenuButton" class="_button" @click="showSettings"><i class="ti ti-settings-2"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="prefer.r['deck.menuPosition'].value === 'bottom'" :class="$style.bottomMenu">
|
<div v-if="prefer.r['deck.menuPosition'].value === 'bottom'" :class="$style.bottomMenu">
|
||||||
<div :class="$style.bottomMenuLeft">
|
<div :class="$style.bottomMenuLeft">
|
||||||
<button ref="swicthProfileButtonEl" v-tooltip.noDelay.top="`${i18n.ts._deck.profile}: ${prefer.s['deck.profile']}`" :class="$style.bottomMenuButton" class="_button" @click="switchProfileMenu"><i class="ti ti-caret-down"></i></button>
|
<button v-tooltip.noDelay.left="`${i18n.ts._deck.profile}: ${prefer.s['deck.profile']}`" :class="$style.bottomMenuButton" class="_button" @click="switchProfileMenu"><i class="ti ti-caret-down"></i></button>
|
||||||
<button v-tooltip.noDelay.top="i18n.ts._deck.deleteProfile" :class="$style.bottomMenuButton" class="_button" @click="deleteProfile"><i class="ti ti-trash"></i></button>
|
<button v-tooltip.noDelay.left="i18n.ts._deck.deleteProfile" :class="$style.bottomMenuButton" class="_button" @click="deleteProfile"><i class="ti ti-trash"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.bottomMenuMiddle">
|
<div :class="$style.bottomMenuMiddle">
|
||||||
<button ref="addColumnButtonEl" v-tooltip.noDelay.top="i18n.ts._deck.addColumn" :class="$style.bottomMenuButton" class="_button" @click="addColumn"><i class="ti ti-plus"></i></button>
|
<button v-tooltip.noDelay.left="i18n.ts._deck.addColumn" :class="$style.bottomMenuButton" class="_button" @click="addColumn"><i class="ti ti-plus"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.bottomMenuRight">
|
<div :class="$style.bottomMenuRight">
|
||||||
<button ref="settingsButtonEl" v-tooltip.noDelay.top="i18n.ts.settings" :class="$style.bottomMenuButton" class="_button" @click="showSettings"><i class="ti ti-settings-2"></i></button>
|
<button v-tooltip.noDelay.left="i18n.ts.settings" :class="$style.bottomMenuButton" class="_button" @click="showSettings"><i class="ti ti-settings-2"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -99,7 +96,6 @@ import { $i } from '@/i.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { deviceKind } from '@/utility/device-kind.js';
|
import { deviceKind } from '@/utility/device-kind.js';
|
||||||
import { prefer } from '@/preferences.js';
|
import { prefer } from '@/preferences.js';
|
||||||
import { store } from '@/store.js';
|
|
||||||
import XMainColumn from '@/ui/deck/main-column.vue';
|
import XMainColumn from '@/ui/deck/main-column.vue';
|
||||||
import XTlColumn from '@/ui/deck/tl-column.vue';
|
import XTlColumn from '@/ui/deck/tl-column.vue';
|
||||||
import XAntennaColumn from '@/ui/deck/antenna-column.vue';
|
import XAntennaColumn from '@/ui/deck/antenna-column.vue';
|
||||||
|
|
@ -111,13 +107,10 @@ import XMentionsColumn from '@/ui/deck/mentions-column.vue';
|
||||||
import XDirectColumn from '@/ui/deck/direct-column.vue';
|
import XDirectColumn from '@/ui/deck/direct-column.vue';
|
||||||
import XRoleTimelineColumn from '@/ui/deck/role-timeline-column.vue';
|
import XRoleTimelineColumn from '@/ui/deck/role-timeline-column.vue';
|
||||||
import XChatColumn from '@/ui/deck/chat-column.vue';
|
import XChatColumn from '@/ui/deck/chat-column.vue';
|
||||||
import MkInfo from '@/components/MkInfo.vue';
|
|
||||||
import { mainRouter } from '@/router.js';
|
import { mainRouter } from '@/router.js';
|
||||||
import { columns, layout, columnTypes, switchProfileMenu, addColumn as addColumnToStore, deleteProfile as deleteProfile_ } from '@/deck.js';
|
import { columns, layout, columnTypes, switchProfileMenu, addColumn as addColumnToStore, deleteProfile as deleteProfile_ } from '@/deck.js';
|
||||||
import { shouldSuggestRestoreBackup } from '@/preferences/utility.js';
|
import { shouldSuggestRestoreBackup } from '@/preferences/utility.js';
|
||||||
import { shouldSuggestReload } from '@/utility/reload-suggest.js';
|
import { shouldSuggestReload } from '@/utility/reload-suggest.js';
|
||||||
import { startTour } from '@/utility/tour.js';
|
|
||||||
import { closeTip } from '@/tips.js';
|
|
||||||
|
|
||||||
const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue'));
|
const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue'));
|
||||||
const XAnnouncements = defineAsyncComponent(() => import('@/ui/_common_/announcements.vue'));
|
const XAnnouncements = defineAsyncComponent(() => import('@/ui/_common_/announcements.vue'));
|
||||||
|
|
@ -170,9 +163,6 @@ function showSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const columnsEl = useTemplateRef('columnsEl');
|
const columnsEl = useTemplateRef('columnsEl');
|
||||||
const addColumnButtonEl = useTemplateRef('addColumnButtonEl');
|
|
||||||
const settingsButtonEl = useTemplateRef('settingsButtonEl');
|
|
||||||
const swicthProfileButtonEl = useTemplateRef('swicthProfileButtonEl');
|
|
||||||
|
|
||||||
const addColumn = async (ev) => {
|
const addColumn = async (ev) => {
|
||||||
const { canceled, result: column } = await os.select({
|
const { canceled, result: column } = await os.select({
|
||||||
|
|
@ -228,30 +218,6 @@ async function deleteProfile() {
|
||||||
os.success();
|
os.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
function showTour() {
|
|
||||||
if (addColumnButtonEl.value == null ||
|
|
||||||
settingsButtonEl.value == null ||
|
|
||||||
swicthProfileButtonEl.value == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
startTour([{
|
|
||||||
element: addColumnButtonEl.value,
|
|
||||||
title: i18n.ts._deck._howToUse.addColumn_title,
|
|
||||||
description: i18n.ts._deck._howToUse.addColumn_description,
|
|
||||||
}, {
|
|
||||||
element: settingsButtonEl.value,
|
|
||||||
title: i18n.ts._deck._howToUse.settings_title,
|
|
||||||
description: i18n.ts._deck._howToUse.settings_description,
|
|
||||||
}, {
|
|
||||||
element: swicthProfileButtonEl.value,
|
|
||||||
title: i18n.ts._deck._howToUse.switchProfile_title,
|
|
||||||
description: i18n.ts._deck._howToUse.switchProfile_description,
|
|
||||||
}]).then(() => {
|
|
||||||
closeTip('deck');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
window.document.documentElement.style.overflowY = 'hidden';
|
window.document.documentElement.style.overflowY = 'hidden';
|
||||||
window.document.documentElement.style.scrollBehavior = 'auto';
|
window.document.documentElement.style.scrollBehavior = 'auto';
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -379,7 +345,7 @@ window.document.documentElement.style.scrollBehavior = 'auto';
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottomMenuButton {
|
.bottomMenuButton {
|
||||||
display: inline-block;
|
display: block;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ async function setAntenna() {
|
||||||
})),
|
})),
|
||||||
} : undefined),
|
} : undefined),
|
||||||
],
|
],
|
||||||
default: antennas.find(x => x.id === props.column.antennaId)?.id,
|
default: props.column.antennaId,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (canceled || antennaIdOrOperation == null) return;
|
if (canceled || antennaIdOrOperation == null) return;
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ async function setChannel() {
|
||||||
items: channels.map(x => ({
|
items: channels.map(x => ({
|
||||||
value: x.id, label: x.name,
|
value: x.id, label: x.name,
|
||||||
})),
|
})),
|
||||||
default: channels.find(x => x.id === props.column.channelId)?.id,
|
default: props.column.channelId,
|
||||||
});
|
});
|
||||||
if (canceled || chosenChannelId == null) return;
|
if (canceled || chosenChannelId == null) return;
|
||||||
const chosenChannel = channels.find(x => x.id === chosenChannelId)!;
|
const chosenChannel = channels.find(x => x.id === chosenChannelId)!;
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ async function setList() {
|
||||||
})),
|
})),
|
||||||
} : undefined),
|
} : undefined),
|
||||||
],
|
],
|
||||||
default: lists.find(x => x.id === props.column.listId)?.id,
|
default: props.column.listId,
|
||||||
});
|
});
|
||||||
if (canceled || listIdOrOperation == null) return;
|
if (canceled || listIdOrOperation == null) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ async function setRole() {
|
||||||
items: roles.map(x => ({
|
items: roles.map(x => ({
|
||||||
value: x.id, label: x.name,
|
value: x.id, label: x.name,
|
||||||
})),
|
})),
|
||||||
default: roles.find(x => x.id === props.column.roleId)?.id,
|
default: props.column.roleId,
|
||||||
});
|
});
|
||||||
if (canceled || roleId == null) return;
|
if (canceled || roleId == null) return;
|
||||||
const role = roles.find(x => x.id === roleId)!;
|
const role = roles.find(x => x.id === roleId)!;
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,6 @@ async function setType() {
|
||||||
}, {
|
}, {
|
||||||
value: 'global', label: i18n.ts._timelines.global,
|
value: 'global', label: i18n.ts._timelines.global,
|
||||||
}],
|
}],
|
||||||
default: props.column.tl,
|
|
||||||
});
|
});
|
||||||
if (canceled) {
|
if (canceled) {
|
||||||
if (props.column.tl == null) {
|
if (props.column.tl == null) {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<XTitlebar v-if="prefer.r.showTitlebar.value" style="flex-shrink: 0;"/>
|
<XTitlebar v-if="prefer.r.showTitlebar.value" style="flex-shrink: 0;"/>
|
||||||
|
|
||||||
<div :class="$style.nonTitlebarArea">
|
<div :class="$style.nonTitlebarArea">
|
||||||
<XSidebar v-if="!isMobile" :class="$style.sidebar" :showWidgetButton="!showWidgetsSide" @widgetButtonClick="widgetsShowing = true"/>
|
<XSidebar v-if="!isMobile" :class="$style.sidebar" :showWidgetButton="!isDesktop" @widgetButtonClick="widgetsShowing = true"/>
|
||||||
|
|
||||||
<div :class="[$style.contents, !isMobile && prefer.r.showTitlebar.value ? $style.withSidebarAndTitlebar : null]" @contextmenu.stop="onContextmenu">
|
<div :class="[$style.contents, !isMobile && prefer.r.showTitlebar.value ? $style.withSidebarAndTitlebar : null]" @contextmenu.stop="onContextmenu">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<XMobileFooterMenu v-if="isMobile" ref="navFooter" v-model:drawerMenuShowing="drawerMenuShowing" v-model:widgetsShowing="widgetsShowing"/>
|
<XMobileFooterMenu v-if="isMobile" ref="navFooter" v-model:drawerMenuShowing="drawerMenuShowing" v-model:widgetsShowing="widgetsShowing"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="showWidgetsSide && !pageMetadata?.needWideArea" :class="$style.widgets">
|
<div v-if="isDesktop && !pageMetadata?.needWideArea" :class="$style.widgets">
|
||||||
<XWidgets/>
|
<XWidgets/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -64,8 +64,7 @@ const DESKTOP_THRESHOLD = 1100;
|
||||||
const MOBILE_THRESHOLD = 500;
|
const MOBILE_THRESHOLD = 500;
|
||||||
|
|
||||||
// デスクトップでウィンドウを狭くしたときモバイルUIが表示されて欲しいことはあるので deviceKind === 'desktop' の判定は行わない
|
// デスクトップでウィンドウを狭くしたときモバイルUIが表示されて欲しいことはあるので deviceKind === 'desktop' の判定は行わない
|
||||||
const showWidgetsSide = window.innerWidth >= DESKTOP_THRESHOLD;
|
const isDesktop = ref(window.innerWidth >= DESKTOP_THRESHOLD);
|
||||||
|
|
||||||
const isMobile = ref(deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD);
|
const isMobile = ref(deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD);
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener('resize', () => {
|
||||||
isMobile.value = deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD;
|
isMobile.value = deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD;
|
||||||
|
|
@ -103,6 +102,14 @@ if (window.innerWidth > 1024) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!isDesktop.value) {
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
if (window.innerWidth >= DESKTOP_THRESHOLD) isDesktop.value = true;
|
||||||
|
}, { passive: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const onContextmenu = (ev) => {
|
const onContextmenu = (ev) => {
|
||||||
if (isLink(ev.target)) return;
|
if (isLink(ev.target)) return;
|
||||||
if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(ev.target.tagName) || ev.target.attributes['contenteditable']) return;
|
if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(ev.target.tagName) || ev.target.attributes['contenteditable']) return;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { watch as chokidarWatch } from 'chokidar';
|
||||||
import * as esbuild from 'esbuild';
|
import * as esbuild from 'esbuild';
|
||||||
import { build } from 'esbuild';
|
import { build } from 'esbuild';
|
||||||
import { execa } from 'execa';
|
import { execa } from 'execa';
|
||||||
|
import { globSync } from 'glob';
|
||||||
import { generateLocaleInterface } from './scripts/generateLocaleInterface.js';
|
import { generateLocaleInterface } from './scripts/generateLocaleInterface.js';
|
||||||
import type { BuildOptions, BuildResult, Plugin, PluginBuild } from 'esbuild';
|
import type { BuildOptions, BuildResult, Plugin, PluginBuild } from 'esbuild';
|
||||||
|
|
||||||
|
|
@ -21,7 +22,7 @@ const _rootPackage = JSON.parse(fs.readFileSync(resolve(_rootPackageDir, 'packag
|
||||||
const _frontendLocalesDir = resolve(_dirname, '../../built/_frontend_dist_/locales');
|
const _frontendLocalesDir = resolve(_dirname, '../../built/_frontend_dist_/locales');
|
||||||
const _localesDir = resolve(_rootPackageDir, 'locales');
|
const _localesDir = resolve(_rootPackageDir, 'locales');
|
||||||
|
|
||||||
const entryPoints = fs.globSync('./src/**/**.{ts,tsx}');
|
const entryPoints = globSync('./src/**/**.{ts,tsx}');
|
||||||
|
|
||||||
const options: BuildOptions = {
|
const options: BuildOptions = {
|
||||||
entryPoints,
|
entryPoints,
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,15 @@
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/js-yaml": "4.0.9",
|
"@types/js-yaml": "4.0.9",
|
||||||
"@types/node": "24.10.2",
|
"@types/node": "24.10.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.49.0",
|
"@typescript-eslint/eslint-plugin": "8.47.0",
|
||||||
"@typescript-eslint/parser": "8.49.0",
|
"@typescript-eslint/parser": "8.47.0",
|
||||||
"chokidar": "5.0.0",
|
"chokidar": "4.0.3",
|
||||||
"esbuild": "0.27.1",
|
"esbuild": "0.27.0",
|
||||||
"execa": "9.6.1",
|
"execa": "9.6.0",
|
||||||
|
"glob": "11.1.0",
|
||||||
"nodemon": "3.1.11",
|
"nodemon": "3.1.11",
|
||||||
"tsx": "4.21.0",
|
"tsx": "4.20.6",
|
||||||
"typescript": "5.9.3"
|
"typescript": "5.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
||||||
|
|
@ -10936,36 +10936,6 @@ export interface Locale extends ILocale {
|
||||||
* プロファイル情報のデバイス間同期を有効にする
|
* プロファイル情報のデバイス間同期を有効にする
|
||||||
*/
|
*/
|
||||||
"enableSyncBetweenDevicesForProfiles": string;
|
"enableSyncBetweenDevicesForProfiles": string;
|
||||||
/**
|
|
||||||
* UIの説明を見る
|
|
||||||
*/
|
|
||||||
"showHowToUse": string;
|
|
||||||
"_howToUse": {
|
|
||||||
/**
|
|
||||||
* カラム追加
|
|
||||||
*/
|
|
||||||
"addColumn_title": string;
|
|
||||||
/**
|
|
||||||
* カラムの種類を選んで追加できます。
|
|
||||||
*/
|
|
||||||
"addColumn_description": string;
|
|
||||||
/**
|
|
||||||
* UI設定
|
|
||||||
*/
|
|
||||||
"settings_title": string;
|
|
||||||
/**
|
|
||||||
* デッキUIの詳細設定を行えます。
|
|
||||||
*/
|
|
||||||
"settings_description": string;
|
|
||||||
/**
|
|
||||||
* プロファイル切り替え
|
|
||||||
*/
|
|
||||||
"switchProfile_title": string;
|
|
||||||
/**
|
|
||||||
* UIのレイアウトをプロファイルとして保存し、いつでも切り替えられるようにできます。
|
|
||||||
*/
|
|
||||||
"switchProfile_description": string;
|
|
||||||
};
|
|
||||||
"_columns": {
|
"_columns": {
|
||||||
/**
|
/**
|
||||||
* メイン
|
* メイン
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,16 @@
|
||||||
"lint": "pnpm typecheck && pnpm eslint"
|
"lint": "pnpm typecheck && pnpm eslint"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "24.10.2",
|
"@types/node": "24.10.1",
|
||||||
"@types/wawoff2": "1.0.2",
|
"@types/wawoff2": "1.0.2",
|
||||||
"@typescript-eslint/eslint-plugin": "8.49.0",
|
"@typescript-eslint/eslint-plugin": "8.48.0",
|
||||||
"@typescript-eslint/parser": "8.49.0"
|
"@typescript-eslint/parser": "8.48.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tabler/icons-webfont": "3.35.0",
|
"@tabler/icons-webfont": "3.35.0",
|
||||||
"harfbuzzjs": "0.4.13",
|
"harfbuzzjs": "0.4.13",
|
||||||
"tsx": "4.21.0",
|
"tiny-glob": "0.2.9",
|
||||||
|
"tsx": "4.20.6",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
"wawoff2": "2.0.1"
|
"wawoff2": "2.0.1"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { promises as fsp, existsSync } from 'node:fs';
|
import { promises as fsp, existsSync } from 'fs';
|
||||||
import path from 'node:path';
|
import path from 'path';
|
||||||
|
import glob from 'tiny-glob';
|
||||||
import { generateSubsettedFont } from './subsetter.js';
|
import { generateSubsettedFont } from './subsetter.js';
|
||||||
|
|
||||||
const filesToScan = {
|
const filesToScan = {
|
||||||
|
|
@ -46,8 +47,8 @@ async function main() {
|
||||||
const iconsToPack = new Set<string>();
|
const iconsToPack = new Set<string>();
|
||||||
|
|
||||||
const cwd = path.resolve(process.cwd(), '../../');
|
const cwd = path.resolve(process.cwd(), '../../');
|
||||||
const files = fsp.glob(dir, { cwd });
|
const files = await glob(dir, { cwd });
|
||||||
for await (const file of files) {
|
for (const file of files) {
|
||||||
//console.log(`Scanning ${file}`);
|
//console.log(`Scanning ${file}`);
|
||||||
const content = await fsp.readFile(path.resolve(cwd, file), 'utf-8');
|
const content = await fsp.readFile(path.resolve(cwd, file), 'utf-8');
|
||||||
const classRegex = /ti-[a-z0-9-]+/g;
|
const classRegex = /ti-[a-z0-9-]+/g;
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,14 @@ import { fileURLToPath } from 'node:url';
|
||||||
import { dirname } from 'node:path';
|
import { dirname } from 'node:path';
|
||||||
import * as esbuild from 'esbuild';
|
import * as esbuild from 'esbuild';
|
||||||
import { build } from 'esbuild';
|
import { build } from 'esbuild';
|
||||||
|
import { globSync } from 'glob';
|
||||||
import { execa } from 'execa';
|
import { execa } from 'execa';
|
||||||
|
|
||||||
const _filename = fileURLToPath(import.meta.url);
|
const _filename = fileURLToPath(import.meta.url);
|
||||||
const _dirname = dirname(_filename);
|
const _dirname = dirname(_filename);
|
||||||
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
|
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
|
||||||
|
|
||||||
const entryPoints = fs.globSync('./src/**/**.{ts,tsx}');
|
const entryPoints = globSync('./src/**/**.{ts,tsx}');
|
||||||
|
|
||||||
/** @type {import('esbuild').BuildOptions} */
|
/** @type {import('esbuild').BuildOptions} */
|
||||||
const options = {
|
const options = {
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,13 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/matter-js": "0.20.2",
|
"@types/matter-js": "0.20.2",
|
||||||
"@types/node": "24.10.2",
|
"@types/node": "24.10.1",
|
||||||
"@types/seedrandom": "3.0.8",
|
"@types/seedrandom": "3.0.8",
|
||||||
"@typescript-eslint/eslint-plugin": "8.49.0",
|
"@typescript-eslint/eslint-plugin": "8.48.0",
|
||||||
"@typescript-eslint/parser": "8.49.0",
|
"@typescript-eslint/parser": "8.48.0",
|
||||||
"esbuild": "0.27.1",
|
"esbuild": "0.27.0",
|
||||||
"execa": "9.6.1",
|
"execa": "9.6.0",
|
||||||
|
"glob": "11.1.0",
|
||||||
"nodemon": "3.1.11",
|
"nodemon": "3.1.11",
|
||||||
"typescript": "5.9.3"
|
"typescript": "5.9.3"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,14 @@ import { fileURLToPath } from 'node:url';
|
||||||
import { dirname } from 'node:path';
|
import { dirname } from 'node:path';
|
||||||
import * as esbuild from 'esbuild';
|
import * as esbuild from 'esbuild';
|
||||||
import { build } from 'esbuild';
|
import { build } from 'esbuild';
|
||||||
|
import { globSync } from 'glob';
|
||||||
import { execa } from 'execa';
|
import { execa } from 'execa';
|
||||||
|
|
||||||
const _filename = fileURLToPath(import.meta.url);
|
const _filename = fileURLToPath(import.meta.url);
|
||||||
const _dirname = dirname(_filename);
|
const _dirname = dirname(_filename);
|
||||||
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
|
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
|
||||||
|
|
||||||
const entryPoints = fs.globSync('./src/**/**.{ts,tsx}');
|
const entryPoints = globSync('./src/**/**.{ts,tsx}');
|
||||||
|
|
||||||
/** @type {import('esbuild').BuildOptions} */
|
/** @type {import('esbuild').BuildOptions} */
|
||||||
const options = {
|
const options = {
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@readme/openapi-parser": "5.2.1",
|
"@readme/openapi-parser": "5.2.1",
|
||||||
"@types/node": "24.10.2",
|
"@types/node": "24.10.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.49.0",
|
"@typescript-eslint/eslint-plugin": "8.47.0",
|
||||||
"@typescript-eslint/parser": "8.49.0",
|
"@typescript-eslint/parser": "8.47.0",
|
||||||
"openapi-types": "12.1.3",
|
"openapi-types": "12.1.3",
|
||||||
"openapi-typescript": "7.10.1",
|
"openapi-typescript": "7.10.1",
|
||||||
"ts-case-convert": "2.1.0",
|
"ts-case-convert": "2.1.0",
|
||||||
"tsx": "4.21.0",
|
"tsx": "4.20.6",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
"eslint": "9.39.1"
|
"eslint": "9.39.1"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"name": "misskey-js",
|
"name": "misskey-js",
|
||||||
"version": "2025.12.2-beta.2",
|
"version": "2025.12.0",
|
||||||
"description": "Misskey SDK for JavaScript",
|
"description": "Misskey SDK for JavaScript",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "./built/index.js",
|
"main": "./built/index.js",
|
||||||
|
|
@ -37,18 +37,19 @@
|
||||||
"directory": "packages/misskey-js"
|
"directory": "packages/misskey-js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@microsoft/api-extractor": "7.55.2",
|
"@microsoft/api-extractor": "7.55.1",
|
||||||
"@types/node": "24.10.2",
|
"@types/node": "24.10.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.49.0",
|
"@typescript-eslint/eslint-plugin": "8.47.0",
|
||||||
"@typescript-eslint/parser": "8.49.0",
|
"@typescript-eslint/parser": "8.47.0",
|
||||||
"@vitest/coverage-v8": "4.0.15",
|
"@vitest/coverage-v8": "4.0.13",
|
||||||
"esbuild": "0.27.1",
|
"esbuild": "0.27.0",
|
||||||
"execa": "9.6.1",
|
"execa": "9.6.0",
|
||||||
|
"glob": "13.0.0",
|
||||||
"ncp": "2.0.0",
|
"ncp": "2.0.0",
|
||||||
"nodemon": "3.1.11",
|
"nodemon": "3.1.11",
|
||||||
"tsd": "0.33.0",
|
"tsd": "0.33.0",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
"vitest": "4.0.15",
|
"vitest": "4.0.13",
|
||||||
"vitest-websocket-mock": "0.5.0"
|
"vitest-websocket-mock": "0.5.0"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,14 @@ import { fileURLToPath } from 'node:url';
|
||||||
import { dirname } from 'node:path';
|
import { dirname } from 'node:path';
|
||||||
import * as esbuild from 'esbuild';
|
import * as esbuild from 'esbuild';
|
||||||
import { build } from 'esbuild';
|
import { build } from 'esbuild';
|
||||||
|
import { globSync } from 'glob';
|
||||||
import { execa } from 'execa';
|
import { execa } from 'execa';
|
||||||
|
|
||||||
const _filename = fileURLToPath(import.meta.url);
|
const _filename = fileURLToPath(import.meta.url);
|
||||||
const _dirname = dirname(_filename);
|
const _dirname = dirname(_filename);
|
||||||
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
|
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
|
||||||
|
|
||||||
const entryPoints = fs.globSync('./src/**/**.{ts,tsx}');
|
const entryPoints = globSync('./src/**/**.{ts,tsx}');
|
||||||
|
|
||||||
/** @type {import('esbuild').BuildOptions} */
|
/** @type {import('esbuild').BuildOptions} */
|
||||||
const options = {
|
const options = {
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,12 @@
|
||||||
"lint": "pnpm typecheck && pnpm eslint"
|
"lint": "pnpm typecheck && pnpm eslint"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "24.10.2",
|
"@types/node": "24.10.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.49.0",
|
"@typescript-eslint/eslint-plugin": "8.48.0",
|
||||||
"@typescript-eslint/parser": "8.49.0",
|
"@typescript-eslint/parser": "8.48.0",
|
||||||
"esbuild": "0.27.1",
|
"esbuild": "0.27.0",
|
||||||
"execa": "9.6.1",
|
"execa": "9.6.0",
|
||||||
|
"glob": "11.1.0",
|
||||||
"nodemon": "3.1.11",
|
"nodemon": "3.1.11",
|
||||||
"typescript": "5.9.3"
|
"typescript": "5.9.3"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,12 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"i18n": "workspace:*",
|
"i18n": "workspace:*",
|
||||||
"esbuild": "0.27.1",
|
"esbuild": "0.27.0",
|
||||||
"idb-keyval": "6.2.2",
|
"idb-keyval": "6.2.2",
|
||||||
"misskey-js": "workspace:*"
|
"misskey-js": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/parser": "8.49.0",
|
"@typescript-eslint/parser": "8.48.0",
|
||||||
"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.74",
|
"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.74",
|
||||||
"eslint-plugin-import": "2.32.0",
|
"eslint-plugin-import": "2.32.0",
|
||||||
"nodemon": "3.1.11",
|
"nodemon": "3.1.11",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const FETCH_TIMEOUT_MS = 10000;
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
*/
|
*/
|
||||||
import { get, set } from 'idb-keyval';
|
import { get, set } from 'idb-keyval';
|
||||||
import { I18n } from '@@/js/i18n.js';
|
import { I18n } from '@@/js/i18n.js';
|
||||||
import { FETCH_TIMEOUT_MS } from '@/const.js';
|
|
||||||
import type { Locale } from 'i18n';
|
import type { Locale } from 'i18n';
|
||||||
|
|
||||||
class SwLang {
|
class SwLang {
|
||||||
|
|
@ -38,21 +37,11 @@ class SwLang {
|
||||||
|
|
||||||
// _DEV_がtrueの場合は常に最新化
|
// _DEV_がtrueの場合は常に最新化
|
||||||
if (!localeRes || _DEV_) {
|
if (!localeRes || _DEV_) {
|
||||||
const controller = new AbortController();
|
localeRes = await fetch(localeUrl);
|
||||||
const timeout = globalThis.setTimeout(() => {
|
|
||||||
controller.abort('locale-fetch-timeout');
|
|
||||||
}, FETCH_TIMEOUT_MS);
|
|
||||||
|
|
||||||
try {
|
|
||||||
localeRes = await fetch(localeUrl, { signal: controller.signal });
|
|
||||||
|
|
||||||
const clone = localeRes.clone();
|
const clone = localeRes.clone();
|
||||||
if (!clone.clone().ok) throw new Error('locale fetching error');
|
if (!clone.clone().ok) throw new Error('locale fetching error');
|
||||||
|
|
||||||
caches.open(this.cacheName).then(cache => cache.put(localeUrl, clone));
|
caches.open(this.cacheName).then(cache => cache.put(localeUrl, clone));
|
||||||
} finally {
|
|
||||||
globalThis.clearTimeout(timeout);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new I18n<Locale>(await localeRes.json());
|
return new I18n<Locale>(await localeRes.json());
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
import { get } from 'idb-keyval';
|
import { get } from 'idb-keyval';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import { FETCH_TIMEOUT_MS } from '@/const.js';
|
|
||||||
import type { PushNotificationDataMap } from '@/types.js';
|
import type { PushNotificationDataMap } from '@/types.js';
|
||||||
import type { I18n } from '@@/js/i18n.js';
|
import type { I18n } from '@@/js/i18n.js';
|
||||||
import type { Locale } from 'i18n';
|
import type { Locale } from 'i18n';
|
||||||
|
|
@ -13,67 +12,8 @@ import { createEmptyNotification, createNotification } from '@/scripts/create-no
|
||||||
import { swLang } from '@/scripts/lang.js';
|
import { swLang } from '@/scripts/lang.js';
|
||||||
import * as swos from '@/scripts/operations.js';
|
import * as swos from '@/scripts/operations.js';
|
||||||
|
|
||||||
async function respondToNavigation(request: Request): Promise<Response> {
|
globalThis.addEventListener('install', () => {
|
||||||
const controller = new AbortController();
|
// ev.waitUntil(globalThis.skipWaiting());
|
||||||
const timeout = globalThis.setTimeout(() => {
|
|
||||||
controller.abort('navigation-timeout');
|
|
||||||
}, FETCH_TIMEOUT_MS);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(request, { signal: controller.signal });
|
|
||||||
|
|
||||||
if (response?.status && response.status < 500) return response;
|
|
||||||
if (response?.type === 'opaqueredirect') return response;
|
|
||||||
} catch (error) {
|
|
||||||
if (_DEV_) {
|
|
||||||
console.warn('navigation fetch failed; showing offline page', error);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
globalThis.clearTimeout(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only show offline page when network request actually fails
|
|
||||||
const html = await offlineContentHTML();
|
|
||||||
return new Response(html, {
|
|
||||||
status: 200,
|
|
||||||
headers: {
|
|
||||||
'content-type': 'text/html',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function offlineContentHTML() {
|
|
||||||
let i18n: Partial<I18n<Locale>>;
|
|
||||||
try {
|
|
||||||
i18n = await (swLang.i18n ?? await swLang.fetchLocale()) as Partial<I18n<Locale>>;
|
|
||||||
} catch {
|
|
||||||
i18n = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const messages = {
|
|
||||||
title: i18n.ts?._offlineScreen.title ?? 'Offline - Could not connect to server',
|
|
||||||
header: i18n.ts?._offlineScreen.header ?? 'Could not connect to server',
|
|
||||||
reload: i18n.ts?.reload ?? 'Reload',
|
|
||||||
};
|
|
||||||
|
|
||||||
return `<!DOCTYPE html><html lang="ja"><head><meta charset="UTF-8"><meta content="width=device-width,initial-scale=1"name="viewport"><title>${messages.title}</title><style>body{background-color:#0c1210;color:#dee7e4;font-family:Hiragino Maru Gothic Pro,BIZ UDGothic,Roboto,HelveticaNeue,Arial,sans-serif;line-height:1.35;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;margin:0;padding:24px;box-sizing:border-box}.icon{max-width:120px;width:100%;height:auto;margin-bottom:20px;}.message{text-align:center;font-size:20px;font-weight:700;margin-bottom:20px}.version{text-align:center;font-size:90%;margin-bottom:20px}button{padding:7px 14px;min-width:100px;font-weight:700;font-family:Hiragino Maru Gothic Pro,BIZ UDGothic,Roboto,HelveticaNeue,Arial,sans-serif;line-height:1.35;border-radius:99rem;background-color:#b4e900;color:#192320;border:none;cursor:pointer;-webkit-tap-highlight-color:transparent}button:hover{background-color:#c6ff03}</style></head><body><svg class="icon"fill="none"height="24"stroke="currentColor"stroke-linecap="round"stroke-linejoin="round"stroke-width="2"viewBox="0 0 24 24"width="24"xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z"fill="none"stroke="none"/><path d="M9.58 5.548c.24 -.11 .492 -.207 .752 -.286c1.88 -.572 3.956 -.193 5.444 1c1.488 1.19 2.162 3.007 1.77 4.769h.99c1.913 0 3.464 1.56 3.464 3.486c0 .957 -.383 1.824 -1.003 2.454m-2.997 1.033h-11.343c-2.572 -.004 -4.657 -2.011 -4.657 -4.487c0 -2.475 2.085 -4.482 4.657 -4.482c.13 -.582 .37 -1.128 .7 -1.62"/><path d="M3 3l18 18"/></svg><div class="message">${messages.header}</div><div class="version">v${_VERSION_}</div><button onclick="reloadPage()">${messages.reload}</button><script>function reloadPage(){location.reload(!0)}</script></body></html>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
globalThis.addEventListener('install', (ev) => {
|
|
||||||
// 次の問題が発生するため、ServiceWorkerAutoPreload をオプトアウトする必要がある
|
|
||||||
// https://issues.chromium.org/issues/466790291
|
|
||||||
if ('addRoutes' in ev) {
|
|
||||||
// doc: https://developer.mozilla.org/en-US/docs/Web/API/InstallEvent/addRoutes
|
|
||||||
// @ts-expect-error 実験的なAPIなので型定義がない
|
|
||||||
ev.addRoutes({
|
|
||||||
condition: {
|
|
||||||
// doc: https://developer.mozilla.org/ja/docs/Web/API/URLPattern
|
|
||||||
// @ts-expect-error 実験的なAPIなので型定義がない
|
|
||||||
urlPattern: new URLPattern({}),
|
|
||||||
},
|
|
||||||
source: 'fetch-event',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
globalThis.addEventListener('activate', ev => {
|
globalThis.addEventListener('activate', ev => {
|
||||||
|
|
@ -88,6 +28,17 @@ globalThis.addEventListener('activate', ev => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function offlineContentHTML() {
|
||||||
|
const i18n = await (swLang.i18n ?? swLang.fetchLocale()) as Partial<I18n<Locale>>;
|
||||||
|
const messages = {
|
||||||
|
title: i18n.ts?._offlineScreen.title ?? 'Offline - Could not connect to server',
|
||||||
|
header: i18n.ts?._offlineScreen.header ?? 'Could not connect to server',
|
||||||
|
reload: i18n.ts?.reload ?? 'Reload',
|
||||||
|
};
|
||||||
|
|
||||||
|
return `<!DOCTYPE html><html lang="ja"><head><meta charset="UTF-8"><meta content="width=device-width,initial-scale=1"name="viewport"><title>${messages.title}</title><style>body{background-color:#0c1210;color:#dee7e4;font-family:Hiragino Maru Gothic Pro,BIZ UDGothic,Roboto,HelveticaNeue,Arial,sans-serif;line-height:1.35;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;margin:0;padding:24px;box-sizing:border-box}.icon{max-width:120px;width:100%;height:auto;margin-bottom:20px;}.message{text-align:center;font-size:20px;font-weight:700;margin-bottom:20px}.version{text-align:center;font-size:90%;margin-bottom:20px}button{padding:7px 14px;min-width:100px;font-weight:700;font-family:Hiragino Maru Gothic Pro,BIZ UDGothic,Roboto,HelveticaNeue,Arial,sans-serif;line-height:1.35;border-radius:99rem;background-color:#b4e900;color:#192320;border:none;cursor:pointer;-webkit-tap-highlight-color:transparent}button:hover{background-color:#c6ff03}</style></head><body><svg class="icon"fill="none"height="24"stroke="currentColor"stroke-linecap="round"stroke-linejoin="round"stroke-width="2"viewBox="0 0 24 24"width="24"xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z"fill="none"stroke="none"/><path d="M9.58 5.548c.24 -.11 .492 -.207 .752 -.286c1.88 -.572 3.956 -.193 5.444 1c1.488 1.19 2.162 3.007 1.77 4.769h.99c1.913 0 3.464 1.56 3.464 3.486c0 .957 -.383 1.824 -1.003 2.454m-2.997 1.033h-11.343c-2.572 -.004 -4.657 -2.011 -4.657 -4.487c0 -2.475 2.085 -4.482 4.657 -4.482c.13 -.582 .37 -1.128 .7 -1.62"/><path d="M3 3l18 18"/></svg><div class="message">${messages.header}</div><div class="version">v${_VERSION_}</div><button onclick="reloadPage()">${messages.reload}</button><script>function reloadPage(){location.reload(!0)}</script></body></html>`;
|
||||||
|
}
|
||||||
|
|
||||||
globalThis.addEventListener('fetch', ev => {
|
globalThis.addEventListener('fetch', ev => {
|
||||||
let isHTMLRequest = false;
|
let isHTMLRequest = false;
|
||||||
if (ev.request.headers.get('sec-fetch-dest') === 'document') {
|
if (ev.request.headers.get('sec-fetch-dest') === 'document') {
|
||||||
|
|
@ -99,7 +50,18 @@ globalThis.addEventListener('fetch', ev => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isHTMLRequest) return;
|
if (!isHTMLRequest) return;
|
||||||
ev.respondWith(respondToNavigation(ev.request));
|
ev.respondWith(
|
||||||
|
fetch(ev.request)
|
||||||
|
.catch(async () => {
|
||||||
|
const html = await offlineContentHTML();
|
||||||
|
return new Response(html, {
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
'content-type': 'text/html',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
globalThis.addEventListener('push', ev => {
|
globalThis.addEventListener('push', ev => {
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue