1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-01 01:05:50 +02:00

Compare commits

...

3 Commits

Author SHA1 Message Date
renovate[bot]
142f11023f chore(deps): update [github actions] update dependencies 2026-04-30 20:58:40 +00:00
github-actions[bot]
665adfccb7 Bump version to 2026.4.0-beta.2 2026-04-30 02:31:32 +00:00
かっこかり
973b5b50a9 fix(frontend): まれにリアクション・絵文字ピッカーが動作しなくなる問題を修正 (#17349)
* Revert "fix(frontend): popupのりアクティビティがチャンクをまたいで切れる事がある問題を修正"

This reverts commit 0a93f526dd.

* fix: iOS PWA でリアクション・絵文字ピッカーが動作しない問題を修正

Agent-Logs-Url: https://github.com/lqvp/misskey-tempura/sessions/44526368-0e6a-4a94-8991-fcdc094d2b96

Co-authored-by: lqvp <183242690+lqvp@users.noreply.github.com>

* refactor

* fix

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lqvp <183242690+lqvp@users.noreply.github.com>
2026-04-30 11:29:23 +09:00
24 changed files with 198 additions and 176 deletions

View File

@@ -19,7 +19,7 @@ jobs:
uses: actions/checkout@v6.0.2 uses: actions/checkout@v6.0.2
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v6.3.0 uses: actions/setup-node@v6.3.0

View File

@@ -25,7 +25,7 @@ jobs:
ref: refs/pull/${{ github.event.pull_request.number }}/merge ref: refs/pull/${{ github.event.pull_request.number }}/merge
- name: setup pnpm - name: setup pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v6
- name: setup node - name: setup node
id: setup-node id: setup-node
@@ -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@v7
with: with:
name: generated-misskey-js name: generated-misskey-js
path: packages/misskey-js/generator/built/autogen path: packages/misskey-js/generator/built/autogen
@@ -73,7 +73,7 @@ jobs:
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@v7
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@v8
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@v8
with: with:
name: actual-misskey-js name: actual-misskey-js
path: misskey-js-actual path: misskey-js-actual

View File

@@ -29,15 +29,15 @@ jobs:
- name: Check out the repo - name: Check out the repo
uses: actions/checkout@v6.0.2 uses: actions/checkout@v6.0.2
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v4
- name: Log in to Docker Hub - name: Log in to Docker Hub
uses: docker/login-action@v3 uses: docker/login-action@v4
with: with:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push by digest - name: Build and push by digest
id: build id: build
uses: docker/build-push-action@v6 uses: docker/build-push-action@v7
with: with:
context: . context: .
push: true push: true
@@ -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@v7
with: with:
name: digests-${{ env.PLATFORM_PAIR }} name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/* path: /tmp/digests/*
@@ -66,15 +66,15 @@ jobs:
- build - build
steps: steps:
- name: Download digests - name: Download digests
uses: actions/download-artifact@v7 uses: actions/download-artifact@v8
with: with:
path: /tmp/digests path: /tmp/digests
pattern: digests-* pattern: digests-*
merge-multiple: true merge-multiple: true
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v4
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v3 uses: docker/login-action@v4
with: with:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}

View File

@@ -34,21 +34,21 @@ jobs:
- name: Check out the repo - name: Check out the repo
uses: actions/checkout@v6.0.2 uses: actions/checkout@v6.0.2
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v4
- name: Docker meta - name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v5 uses: docker/metadata-action@v6
with: with:
images: ${{ env.REGISTRY_IMAGE }} images: ${{ env.REGISTRY_IMAGE }}
tags: ${{ env.TAGS }} tags: ${{ env.TAGS }}
- name: Log in to Docker Hub - name: Log in to Docker Hub
uses: docker/login-action@v3 uses: docker/login-action@v4
with: with:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push to Docker Hub - name: Build and Push to Docker Hub
id: build id: build
uses: docker/build-push-action@v6 uses: docker/build-push-action@v7
with: with:
context: . context: .
push: true push: true
@@ -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@v7
with: with:
name: digests-${{ env.PLATFORM_PAIR }} name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/* path: /tmp/digests/*
@@ -77,21 +77,21 @@ jobs:
- build - build
steps: steps:
- name: Download digests - name: Download digests
uses: actions/download-artifact@v7 uses: actions/download-artifact@v8
with: with:
path: /tmp/digests path: /tmp/digests
pattern: digests-* pattern: digests-*
merge-multiple: true merge-multiple: true
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v4
- name: Docker meta - name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v5 uses: docker/metadata-action@v6
with: with:
images: ${{ env.REGISTRY_IMAGE }} images: ${{ env.REGISTRY_IMAGE }}
tags: ${{ env.TAGS }} tags: ${{ env.TAGS }}
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v3 uses: docker/login-action@v4
with: with:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}

View File

@@ -30,7 +30,7 @@ jobs:
ref: ${{ matrix.ref }} ref: ${{ matrix.ref }}
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.3.0 uses: actions/setup-node@v6.3.0
with: with:
@@ -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@v7
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@v7
with: with:
name: api-artifact-pr-number name: api-artifact-pr-number
path: pr_number path: pr_number

View File

@@ -35,7 +35,7 @@ jobs:
POSTGRES_DB: test-misskey POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
redis: redis:
image: redis:7 image: redis:8
ports: ports:
- 56312:6379 - 56312:6379
@@ -45,7 +45,7 @@ jobs:
ref: ${{ matrix.ref }} ref: ${{ matrix.ref }}
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.3.0 uses: actions/setup-node@v6.3.0
with: with:
@@ -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@v7
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@v7
with: with:
name: memory-artifact-pr-number name: memory-artifact-pr-number
path: pr_number path: pr_number

View File

@@ -41,7 +41,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- uses: actions/setup-node@v6.3.0 - uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -74,14 +74,14 @@ jobs:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- uses: actions/setup-node@v6.3.0 - uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
- run: pnpm i --frozen-lockfile - run: pnpm i --frozen-lockfile
- name: Restore eslint cache - name: Restore eslint cache
uses: actions/cache@v4.3.0 uses: actions/cache@v5.0.5
with: with:
path: ${{ env.eslint-cache-path }} path: ${{ env.eslint-cache-path }}
key: eslint-${{ env.eslint-cache-version }}-${{ matrix.workspace }}-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ github.ref_name }}-${{ github.sha }} key: eslint-${{ env.eslint-cache-version }}-${{ matrix.workspace }}-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ github.ref_name }}-${{ github.sha }}
@@ -105,7 +105,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- uses: actions/setup-node@v6.3.0 - uses: actions/setup-node@v6.3.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'

View File

@@ -21,7 +21,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- uses: actions/setup-node@v6.3.0 - uses: actions/setup-node@v6.3.0
with: with:
node-version-file: ".node-version" node-version-file: ".node-version"

View File

@@ -20,7 +20,7 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.3.0 uses: actions/setup-node@v6.3.0
with: with:

View File

@@ -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@v9
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@v7
with: with:
name: api-artifact name: api-artifact
path: | path: |

View File

@@ -15,7 +15,7 @@ jobs:
steps: steps:
- name: Download artifact - name: Download artifact
uses: actions/github-script@v8.0.0 uses: actions/github-script@v9
with: with:
script: | script: |
const fs = require('fs'); const fs = require('fs');

View File

@@ -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@v9
with: with:
script: | script: |
const body = `To dev team (@misskey-dev/dev): const body = `To dev team (@misskey-dev/dev):

View File

@@ -37,7 +37,7 @@ jobs:
if: github.event_name == 'pull_request_target' if: github.event_name == 'pull_request_target'
run: git checkout "$(git rev-list --parents -n1 HEAD | cut -d" " -f3)" run: git checkout "$(git rev-list --parents -n1 HEAD | cut -d" " -f3)"
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.3.0 uses: actions/setup-node@v6.3.0
with: with:
@@ -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@v9
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@v7
with: with:
name: storybook name: storybook
path: packages/frontend/storybook-static path: packages/frontend/storybook-static

View File

@@ -45,7 +45,7 @@ jobs:
POSTGRES_DB: test-misskey POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
redis: redis:
image: redis:7 image: redis:8
ports: ports:
- 56312:6379 - 56312:6379
meilisearch: meilisearch:
@@ -61,13 +61,13 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Get current date - name: Get current date
id: current-date id: current-date
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
- name: Setup and Restore ffmpeg/ffprobe Cache - name: Setup and Restore ffmpeg/ffprobe Cache
id: cache-ffmpeg id: cache-ffmpeg
uses: actions/cache@v4 uses: actions/cache@v5
with: with:
path: | path: |
/usr/local/bin/ffmpeg /usr/local/bin/ffmpeg
@@ -107,7 +107,7 @@ jobs:
- name: Test - name: Test
run: pnpm --filter backend test-and-coverage run: pnpm --filter backend test-and-coverage
- name: Upload to Codecov - name: Upload to Codecov
uses: codecov/codecov-action@v5 uses: codecov/codecov-action@v6
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/coverage/coverage-final.json files: ./packages/backend/coverage/coverage-final.json
@@ -131,7 +131,7 @@ jobs:
POSTGRES_DB: test-misskey POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
redis: redis:
image: redis:7 image: redis:8
ports: ports:
- 56312:6379 - 56312:6379
@@ -140,7 +140,7 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.3.0 uses: actions/setup-node@v6.3.0
with: with:
@@ -156,7 +156,7 @@ jobs:
- name: Test - name: Test
run: pnpm --filter backend test-and-coverage:e2e run: pnpm --filter backend test-and-coverage:e2e
- name: Upload to Codecov - name: Upload to Codecov
uses: codecov/codecov-action@v5 uses: codecov/codecov-action@v6
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/coverage/coverage-final.json files: ./packages/backend/coverage/coverage-final.json
@@ -184,7 +184,7 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Get current date - name: Get current date
id: current-date id: current-date
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT

View File

@@ -36,13 +36,13 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Get current date - name: Get current date
id: current-date id: current-date
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
- name: Setup and Restore ffmpeg/ffprobe Cache - name: Setup and Restore ffmpeg/ffprobe Cache
id: cache-ffmpeg id: cache-ffmpeg
uses: actions/cache@v4 uses: actions/cache@v5
with: with:
path: | path: |
/usr/local/bin/ffmpeg /usr/local/bin/ffmpeg

View File

@@ -32,7 +32,7 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.3.0 uses: actions/setup-node@v6.3.0
with: with:
@@ -48,7 +48,7 @@ jobs:
- name: Test - name: Test
run: pnpm --filter frontend test-and-coverage run: pnpm --filter frontend test-and-coverage
- name: Upload Coverage - name: Upload Coverage
uses: codecov/codecov-action@v5 uses: codecov/codecov-action@v6
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/frontend/coverage/coverage-final.json files: ./packages/frontend/coverage/coverage-final.json
@@ -71,7 +71,7 @@ jobs:
POSTGRES_DB: test-misskey POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
redis: redis:
image: redis:7 image: redis:8
ports: ports:
- 56312:6379 - 56312:6379
@@ -86,7 +86,7 @@ jobs:
#- uses: browser-actions/setup-firefox@latest #- uses: browser-actions/setup-firefox@latest
# if: ${{ matrix.browser == 'firefox' }} # if: ${{ matrix.browser == 'firefox' }}
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.3.0 uses: actions/setup-node@v6.3.0
with: with:
@@ -105,7 +105,7 @@ jobs:
- name: Cypress install - name: Cypress install
run: pnpm exec cypress install run: pnpm exec cypress install
- name: Cypress run - name: Cypress run
uses: cypress-io/github-action@v6 uses: cypress-io/github-action@v7.1.9
timeout-minutes: 15 timeout-minutes: 15
with: with:
install: false install: false
@@ -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@v7
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@v7
if: always() if: always()
with: with:
name: ${{ matrix.browser }}-cypress-videos name: ${{ matrix.browser }}-cypress-videos

View File

@@ -25,7 +25,7 @@ jobs:
uses: actions/checkout@v6.0.2 uses: actions/checkout@v6.0.2
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v6.3.0 uses: actions/setup-node@v6.3.0
@@ -48,7 +48,7 @@ jobs:
CI: true CI: true
- name: Upload Coverage - name: Upload Coverage
uses: codecov/codecov-action@v5 uses: codecov/codecov-action@v6
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/misskey-js/coverage/coverage-final.json files: ./packages/misskey-js/coverage/coverage-final.json

View File

@@ -20,7 +20,7 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.3.0 uses: actions/setup-node@v6.3.0
with: with:

View File

@@ -21,7 +21,7 @@ jobs:
with: with:
submodules: true submodules: true
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4.4.0 uses: pnpm/action-setup@v6.0.3
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6.3.0 uses: actions/setup-node@v6.3.0
with: with:

View File

@@ -1,6 +1,6 @@
{ {
"name": "misskey", "name": "misskey",
"version": "2026.4.0-beta.1", "version": "2026.4.0-beta.2",
"codename": "nasubi", "codename": "nasubi",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@@ -5,9 +5,9 @@
// TODO: なんでもかんでもos.tsに突っ込むのやめたいのでよしなに分割する // TODO: なんでもかんでもos.tsに突っ込むのやめたいのでよしなに分割する
import { markRaw, ref, defineAsyncComponent, nextTick, effectScope, isRef, shallowReactive, watch } from 'vue'; import { markRaw, ref, defineAsyncComponent, nextTick } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import type { Component, MaybeRef, ShallowReactive } from 'vue'; import type { Component, MaybeRef } from 'vue';
import type { ComponentEmit, ComponentProps as CP } from 'vue-component-type-helpers'; import type { ComponentEmit, ComponentProps as CP } from 'vue-component-type-helpers';
import type { Form, GetFormResultType } from '@/utility/form.js'; import type { Form, GetFormResultType } from '@/utility/form.js';
import type { MenuItem } from '@/types/menu.js'; import type { MenuItem } from '@/types/menu.js';
@@ -145,7 +145,7 @@ let popupIdCount = 0;
export const popups = ref<{ export const popups = ref<{
id: number; id: number;
component: Component; component: Component;
props: ShallowReactive<Record<string, any>>; props: Record<string, any>;
events: Record<string, any>; events: Record<string, any>;
}[]>([]); }[]>([]);
@@ -183,32 +183,6 @@ type ComponentEmitsObject<C extends Component, IE = OverloadToUnion<ComponentEmi
: (...args: any[]) => void; : (...args: any[]) => void;
}>; }>;
// ref をそのまま保持せず popup 側の reactive props に同期するようにして、スコープをまたいでリアクティビティが切れるのを防止する
function normalizePopupProps<T extends Record<string, any>>(props: T): {
resolvedProps: ShallowReactive<T>;
stopSync: () => void;
} {
const resolvedProps = shallowReactive<T>({} as T) as T; // shallowReactiveの返り値はreadonlyだが、実際には書き換えるので元の型で扱う
const scope = effectScope();
scope.run(() => {
for (const [key, value] of Object.entries(props)) {
if (isRef(value)) {
watch(value, (resolvedValue) => {
resolvedProps[key as keyof T] = resolvedValue as T[keyof T];
}, { immediate: true });
} else {
resolvedProps[key as keyof T] = value;
}
}
});
return {
resolvedProps: resolvedProps as ShallowReactive<T>,
stopSync: () => scope.stop(),
};
}
// NOTE: ジェネリック型つきのコンポーネントでは、emitsの型推論がうまく働かない型変数を取り出すことはできないため // NOTE: ジェネリック型つきのコンポーネントでは、emitsの型推論がうまく働かない型変数を取り出すことはできないため
// NOTE: emitsがOverloadToUnionで対応しているオーバーロードの数を超える場合は、OverloadToUnionの個数を増やせばOK // NOTE: emitsがOverloadToUnionで対応しているオーバーロードの数を超える場合は、OverloadToUnionの個数を増やせばOK
export function popup<T extends Component>( export function popup<T extends Component>(
@@ -219,24 +193,20 @@ export function popup<T extends Component>(
markRaw(component); markRaw(component);
const id = ++popupIdCount; const id = ++popupIdCount;
const { resolvedProps, stopSync } = normalizePopupProps(props);
let disposed = false;
const dispose = () => { const dispose = () => {
if (disposed) return; // このsetTimeoutが無いと挙動がおかしくなる(autocompleteが閉じなくなる)。Vueのバグ
disposed = true;
stopSync();
nextTick(() => { nextTick(() => {
popups.value = popups.value.filter(p => p.id !== id); popups.value = popups.value.filter(p => p.id !== id);
}); });
}; };
const state = {
popups.value.push({
component, component,
props: resolvedProps, props,
events, events,
id, id,
}); };
popups.value.push(state);
return { return {
dispose, dispose,

View File

@@ -3,9 +3,9 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { defineAsyncComponent, ref, watch } from 'vue'; import { markRaw, shallowRef, ref, watch } from 'vue';
import type { Ref } from 'vue'; import type MkEmojiPickerDialog__TypeReferenceOnly from '@/components/MkEmojiPickerDialog.vue';
import { popup } from '@/os.js'; import { popup, popupAsyncWithDialog } from '@/os.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
/** /**
@@ -15,53 +15,77 @@ import { prefer } from '@/preferences.js';
* 一度表示したダイアログを連続で使用できることが望ましいシーンでの利用が想定される。 * 一度表示したダイアログを連続で使用できることが望ましいシーンでの利用が想定される。
*/ */
class EmojiPicker { class EmojiPicker {
private anchorElement: Ref<HTMLElement | null> = ref(null); private loadedComponent: typeof MkEmojiPickerDialog__TypeReferenceOnly | null = null;
private manualShowing = ref(false); private emojisRef = ref<string[]>([]);
private onChosen?: (emoji: string) => void;
private onClosed?: () => void;
constructor() { constructor() {
// nop // nop
} }
public async init() { public init() {
const emojisRef = ref<string[]>([]); // コンポーネントをプリロードしてキャッシュしておく。
// iOS PWA では await を挟むとユーザーアクティベーションが失われfocusが効かなくなるため、
watch([prefer.r.emojiPaletteForMain, prefer.r.emojiPalettes], () => { // show() 呼び出し時には同期的に popup() できるよう事前にコンポーネントを解決しておく。
emojisRef.value = prefer.s.emojiPaletteForMain == null ? prefer.s.emojiPalettes[0].emojis : prefer.s.emojiPalettes.find(palette => palette.id === prefer.s.emojiPaletteForMain)?.emojis ?? []; import('@/components/MkEmojiPickerDialog.vue').then(m => {
}, { this.loadedComponent = markRaw(m.default);
immediate: true, }).catch(err => {
console.error('[EmojiPicker] Failed to preload MkEmojiPickerDialog:', err);
}); });
await popup(defineAsyncComponent(() => import('@/components/MkEmojiPickerDialog.vue')), { watch([prefer.r.emojiPaletteForMain, prefer.r.emojiPalettes], () => {
anchorElement: this.anchorElement, this.emojisRef.value = prefer.s.emojiPaletteForMain == null ? prefer.s.emojiPalettes[0].emojis : prefer.s.emojiPalettes.find(palette => palette.id === prefer.s.emojiPaletteForMain)?.emojis ?? [];
pinnedEmojis: emojisRef,
asReactionPicker: false,
manualShowing: this.manualShowing,
choseAndClose: false,
}, { }, {
done: emoji => { immediate: true,
if (this.onChosen) this.onChosen(emoji);
},
close: () => {
this.manualShowing.value = false;
},
closed: () => {
this.anchorElement.value = null;
if (this.onClosed) this.onClosed();
},
}); });
} }
public show( public show(
anchorElement: HTMLElement, anchorElement: HTMLElement,
onChosen?: EmojiPicker['onChosen'], onChosen?: (emoji: string) => void,
onClosed?: EmojiPicker['onClosed'], onClosed?: () => void,
) { ) {
this.anchorElement.value = anchorElement; const anchorRef = shallowRef(anchorElement);
this.manualShowing.value = true;
this.onChosen = onChosen; if (this.loadedComponent) {
this.onClosed = onClosed; // コンポーネント解決済みのため同期的に popup() できる。
// ユーザーアクティベーションコンテキストが維持されiOSでもfocusが機能する。
const { dispose } = popup(this.loadedComponent, {
anchorElement: anchorRef,
pinnedEmojis: this.emojisRef,
asReactionPicker: false,
choseAndClose: false,
}, {
done: (emoji: string) => {
if (onChosen) onChosen(emoji);
},
closed: () => {
if (onClosed) onClosed();
dispose();
},
});
} else {
// フォールバック: 初回タップがプリロード完了前
popupAsyncWithDialog(
import('@/components/MkEmojiPickerDialog.vue').then(m => {
this.loadedComponent = markRaw(m.default);
return this.loadedComponent;
}),
{
anchorElement: anchorRef,
pinnedEmojis: this.emojisRef,
asReactionPicker: false,
choseAndClose: false,
},
{
done: (emoji: string) => {
if (onChosen) onChosen(emoji);
},
closed: () => {
if (onClosed) onClosed();
},
},
);
}
} }
} }

View File

@@ -4,57 +4,85 @@
*/ */
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { defineAsyncComponent, ref, watch } from 'vue'; import { markRaw, shallowRef, ref, watch } from 'vue';
import type { Ref } from 'vue'; import type MkEmojiPickerDialog__TypeReferenceOnly from '@/components/MkEmojiPickerDialog.vue';
import { popup } from '@/os.js'; import { popup, popupAsyncWithDialog } from '@/os.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
class ReactionPicker { class ReactionPicker {
private anchorElement: Ref<HTMLElement | null> = ref(null); private loadedComponent: typeof MkEmojiPickerDialog__TypeReferenceOnly | null = null;
private manualShowing = ref(false); private reactionsRef = ref<string[]>([]);
private targetNote: Ref<Misskey.entities.Note | null> = ref(null);
private onChosen?: (reaction: string) => void;
private onClosed?: () => void;
constructor() { constructor() {
// nop // nop
} }
public async init() { public init() {
const reactionsRef = ref<string[]>([]); // コンポーネントをプリロードしてキャッシュしておく。
// iOS PWA では await を挟むとユーザーアクティベーションが失われfocusが効かなくなるため、
// show() 呼び出し時には同期的に popup() できるよう事前にコンポーネントを解決しておく。
import('@/components/MkEmojiPickerDialog.vue').then(m => {
this.loadedComponent = markRaw(m.default);
}).catch(err => {
console.error('[ReactionPicker] Failed to preload MkEmojiPickerDialog:', err);
});
watch([prefer.r.emojiPaletteForReaction, prefer.r.emojiPalettes], () => { watch([prefer.r.emojiPaletteForReaction, prefer.r.emojiPalettes], () => {
reactionsRef.value = prefer.s.emojiPaletteForReaction == null ? prefer.s.emojiPalettes[0].emojis : prefer.s.emojiPalettes.find(palette => palette.id === prefer.s.emojiPaletteForReaction)?.emojis ?? []; this.reactionsRef.value = prefer.s.emojiPaletteForReaction == null ? prefer.s.emojiPalettes[0].emojis : prefer.s.emojiPalettes.find(palette => palette.id === prefer.s.emojiPaletteForReaction)?.emojis ?? [];
}, { }, {
immediate: true, immediate: true,
}); });
await popup(defineAsyncComponent(() => import('@/components/MkEmojiPickerDialog.vue')), {
anchorElement: this.anchorElement,
pinnedEmojis: reactionsRef,
asReactionPicker: true,
targetNote: this.targetNote,
manualShowing: this.manualShowing,
}, {
done: reaction => {
if (this.onChosen) this.onChosen(reaction);
},
close: () => {
this.manualShowing.value = false;
},
closed: () => {
this.anchorElement.value = null;
if (this.onClosed) this.onClosed();
},
});
} }
public show(anchorElement: HTMLElement | null, targetNote: Misskey.entities.Note | null, onChosen?: ReactionPicker['onChosen'], onClosed?: ReactionPicker['onClosed']) { public show(
this.anchorElement.value = anchorElement; anchorElement: HTMLElement | null,
this.targetNote.value = targetNote; targetNote: Misskey.entities.Note | null,
this.manualShowing.value = true; onChosen?: (reaction: string) => void,
this.onChosen = onChosen; onClosed?: () => void,
this.onClosed = onClosed; ) {
const anchorRef = shallowRef(anchorElement);
const targetNoteRef = ref(targetNote);
if (this.loadedComponent) {
// 通常パス: コンポーネント解決済みのため同期的に popup() できる。
// ユーザーアクティベーションコンテキストが維持されiOSでもfocusが機能する。
const { dispose } = popup(this.loadedComponent, {
anchorElement: anchorRef,
pinnedEmojis: this.reactionsRef,
asReactionPicker: true,
targetNote: targetNoteRef,
}, {
done: (reaction: string) => {
if (onChosen) onChosen(reaction);
},
closed: () => {
if (onClosed) onClosed();
dispose();
},
});
} else {
// フォールバック: 初回タップがプリロード完了前
popupAsyncWithDialog(
import('@/components/MkEmojiPickerDialog.vue').then(m => {
this.loadedComponent = markRaw(m.default);
return this.loadedComponent;
}),
{
anchorElement: anchorRef,
pinnedEmojis: this.reactionsRef,
asReactionPicker: true,
targetNote: targetNoteRef,
},
{
done: (reaction: string) => {
if (onChosen) onChosen(reaction);
},
closed: () => {
if (onClosed) onClosed();
},
},
);
}
} }
} }

View File

@@ -1,7 +1,7 @@
{ {
"type": "module", "type": "module",
"name": "misskey-js", "name": "misskey-js",
"version": "2026.4.0-beta.1", "version": "2026.4.0-beta.2",
"description": "Misskey SDK for JavaScript", "description": "Misskey SDK for JavaScript",
"license": "MIT", "license": "MIT",
"main": "./built/index.js", "main": "./built/index.js",