Merge branch 'develop' into no-websocket
This commit is contained in:
commit
24b35321e9
|
@ -5,7 +5,7 @@
|
|||
"workspaceFolder": "/workspace",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "22.11.0"
|
||||
"version": "22.15.0"
|
||||
},
|
||||
"ghcr.io/devcontainers-extra/features/pnpm:2": {
|
||||
"version": "10.10.0"
|
||||
|
|
|
@ -1 +1 @@
|
|||
22.11.0
|
||||
22.15.0
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
## 2025.5.0
|
||||
|
||||
### Note
|
||||
- DockerのNode.jsが22.15.0に更新されました
|
||||
|
||||
### General
|
||||
-
|
||||
|
||||
|
@ -9,6 +12,7 @@
|
|||
- Enhance: タイムラインのパフォーマンスを向上
|
||||
- Fix: 一部のブラウザでアコーディオンメニューのアニメーションが動作しない問題を修正
|
||||
- Fix: ダイアログのお知らせが画面からはみ出ることがある問題を修正
|
||||
- Fix: ユーザーポップアップでエラーが生じてもインジケーターが表示され続けてしまう問題を修正
|
||||
|
||||
### Server
|
||||
- Enhance: 凍結されたユーザのノートが各種タイムラインで表示されないように `#15775`
|
||||
|
@ -21,6 +25,8 @@
|
|||
- Fix: チャンネルのフォロー一覧の結果が一部正しくないのを修正 (#12175)
|
||||
- Fix: ファイルをアップロードした際にファイル名が常に untitled になる問題を修正
|
||||
- Fix: ファイルのアップロードに失敗することがある問題を修正
|
||||
- 投稿フォーム上で画像のクロップを行うと、`Invalid Param.`エラーでノートが投稿出来なくなる問題も解決されます。
|
||||
- この事象によって既にノートが投稿出来ない状態になっている場合は、投稿フォーム右上のメニューから、下書きデータの「リセット」を行ってください。
|
||||
|
||||
## 2025.4.1
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# syntax = docker/dockerfile:1.4
|
||||
|
||||
ARG NODE_VERSION=22.11.0-bookworm
|
||||
ARG NODE_VERSION=22.15.0-bookworm
|
||||
|
||||
# build assets & compile TypeScript
|
||||
|
||||
|
|
|
@ -1425,6 +1425,7 @@ _settings:
|
|||
ifOff: "Quan es desactiva"
|
||||
enableSyncThemesBetweenDevices: "Sincronitzar els temes instal·lats entre dispositius"
|
||||
enablePullToRefresh: "Lliscar i actualitzar "
|
||||
enablePullToRefresh_description: "Amb el ratolí, llisca mentre prems la roda."
|
||||
_chat:
|
||||
showSenderName: "Mostrar el nom del remitent"
|
||||
sendOnEnter: "Introdueix per enviar"
|
||||
|
|
|
@ -1348,6 +1348,7 @@ readonly: "Read only"
|
|||
goToDeck: "Return to Deck"
|
||||
federationJobs: "Federation Jobs"
|
||||
driveAboutTip: "In Drive, a list of files you've uploaded in the past will be displayed. <br> \nYou can reuse these files when attaching them to notes, or you can upload files in advance to post later. <br> \n<b>Be careful when deleting a file, as it will not be available in all places where it was used (such as notes, pages, avatars, banners, etc.).</b> <br> \nYou can also create folders to organize your files."
|
||||
scrollToClose: "Scroll to close"
|
||||
_chat:
|
||||
noMessagesYet: "No messages yet"
|
||||
newMessage: "New message"
|
||||
|
@ -1425,6 +1426,7 @@ _settings:
|
|||
ifOff: "When turned off"
|
||||
enableSyncThemesBetweenDevices: "Synchronize installed themes across devices"
|
||||
enablePullToRefresh: "Pull to Refresh"
|
||||
enablePullToRefresh_description: "When using a mouse, drag while pressing in the scrolling wheel."
|
||||
_chat:
|
||||
showSenderName: "Show sender's name"
|
||||
sendOnEnter: "Press Enter to send"
|
||||
|
|
|
@ -1348,6 +1348,7 @@ readonly: "唯讀"
|
|||
goToDeck: "回去甲板"
|
||||
federationJobs: "聯邦通訊作業"
|
||||
driveAboutTip: "在「雲端硬碟」中,會顯示過去上傳的檔案列表。<br>\n可以在附加到貼文時重新利用,或者事先上傳之後再用於發布。<br>\n<b>請注意,刪除檔案後,之前使用過該檔案的所有地方(貼文、頁面、大頭貼、橫幅等)也會一併無法顯示。</b><br>\n也可以建立資料夾來整理檔案。"
|
||||
scrollToClose: "用滾輪關閉"
|
||||
_chat:
|
||||
noMessagesYet: "尚無訊息"
|
||||
newMessage: "新訊息"
|
||||
|
@ -1425,6 +1426,7 @@ _settings:
|
|||
ifOff: "關閉時"
|
||||
enableSyncThemesBetweenDevices: "在裝置之間同步已安裝的主題"
|
||||
enablePullToRefresh: "下拉更新"
|
||||
enablePullToRefresh_description: "使用滑鼠,按下並拖曳滾輪。"
|
||||
_chat:
|
||||
showSenderName: "顯示發送者的名稱"
|
||||
sendOnEnter: "按下 Enter 發送訊息"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "misskey",
|
||||
"version": "2025.5.0-alpha.0",
|
||||
"version": "2025.5.0-alpha.1",
|
||||
"codename": "nasubi",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import tsParser from '@typescript-eslint/parser';
|
||||
import globals from 'globals';
|
||||
import sharedConfig from '../shared/eslint.config.js';
|
||||
|
||||
export default [
|
||||
|
@ -6,6 +7,13 @@ export default [
|
|||
{
|
||||
ignores: ['**/node_modules', 'built', '@types/**/*', 'migration'],
|
||||
},
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx'],
|
||||
languageOptions: {
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env node
|
||||
import child_process from 'node:child_process';
|
||||
import path from 'node:path';
|
||||
import url from 'node:url';
|
||||
|
||||
import semver from 'semver';
|
||||
|
||||
const __filename = url.fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const args = [];
|
||||
args.push(...[
|
||||
...semver.satisfies(process.version, '^20.17.0 || ^22.0.0') ? ['--no-experimental-require-module'] : [],
|
||||
'--experimental-vm-modules',
|
||||
'--experimental-import-meta-resolve',
|
||||
path.join(__dirname, 'node_modules/jest/bin/jest.js'),
|
||||
...process.argv.slice(2),
|
||||
]);
|
||||
|
||||
child_process.spawn(process.execPath, args, { stdio: 'inherit' });
|
|
@ -22,12 +22,12 @@
|
|||
"typecheck": "tsc --noEmit && tsc -p test --noEmit && tsc -p test-federation --noEmit",
|
||||
"eslint": "eslint --quiet \"{src,test-federation}/**/*.ts\"",
|
||||
"lint": "pnpm typecheck && pnpm eslint",
|
||||
"jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --config jest.config.unit.cjs",
|
||||
"jest:e2e": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --config jest.config.e2e.cjs",
|
||||
"jest:fed": "node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --config jest.config.fed.cjs",
|
||||
"jest-and-coverage": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit --config jest.config.unit.cjs",
|
||||
"jest-and-coverage:e2e": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit --config jest.config.e2e.cjs",
|
||||
"jest-clear": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --clearCache",
|
||||
"jest": "cross-env NODE_ENV=test node ./jest.js --forceExit --config jest.config.unit.cjs",
|
||||
"jest:e2e": "cross-env NODE_ENV=test node ./jest.js --forceExit --config jest.config.e2e.cjs",
|
||||
"jest:fed": "node ./jest.js --forceExit --config jest.config.fed.cjs",
|
||||
"jest-and-coverage": "cross-env NODE_ENV=test node ./jest.js --coverage --forceExit --config jest.config.unit.cjs",
|
||||
"jest-and-coverage:e2e": "cross-env NODE_ENV=test node ./jest.js --coverage --forceExit --config jest.config.e2e.cjs",
|
||||
"jest-clear": "cross-env NODE_ENV=test node ./jest.js --clearCache",
|
||||
"test": "pnpm jest",
|
||||
"test:e2e": "pnpm build && pnpm build:test && pnpm jest:e2e",
|
||||
"test:fed": "pnpm jest:fed",
|
||||
|
|
|
@ -50,6 +50,10 @@ services:
|
|||
source: ../jest.config.fed.cjs
|
||||
target: /misskey/packages/backend/jest.config.fed.cjs
|
||||
read_only: true
|
||||
- type: bind
|
||||
source: ../jest.js
|
||||
target: /misskey/packages/backend/jest.js
|
||||
read_only: true
|
||||
- type: bind
|
||||
source: ../../misskey-js/built
|
||||
target: /misskey/packages/misskey-js/built
|
||||
|
|
|
@ -53,12 +53,12 @@ const MIN_SWIPE_DISTANCE = 20;
|
|||
// スワイプ時の動作を発火する最小の距離
|
||||
const SWIPE_DISTANCE_THRESHOLD = 70;
|
||||
|
||||
// スワイプを中断するY方向の移動距離
|
||||
const SWIPE_ABORT_Y_THRESHOLD = 75;
|
||||
|
||||
// スワイプできる最大の距離
|
||||
const MAX_SWIPE_DISTANCE = 120;
|
||||
|
||||
// スワイプ方向を判定する角度の許容範囲(度数)
|
||||
const SWIPE_DIRECTION_ANGLE_THRESHOLD = 50;
|
||||
|
||||
// ▲ しきい値 ▲ //
|
||||
|
||||
let startScreenX: number | null = null;
|
||||
|
@ -69,6 +69,7 @@ const currentTabIndex = computed(() => props.tabs.findIndex(tab => tab.key === t
|
|||
const pullDistance = ref(0);
|
||||
const isSwipingForClass = ref(false);
|
||||
let swipeAborted = false;
|
||||
let swipeDirectionLocked: 'horizontal' | 'vertical' | null = null;
|
||||
|
||||
function touchStart(event: TouchEvent) {
|
||||
if (!prefer.r.enableHorizontalSwipe.value) return;
|
||||
|
@ -79,6 +80,7 @@ function touchStart(event: TouchEvent) {
|
|||
|
||||
startScreenX = event.touches[0].screenX;
|
||||
startScreenY = event.touches[0].screenY;
|
||||
swipeDirectionLocked = null; // スワイプ方向をリセット
|
||||
}
|
||||
|
||||
function touchMove(event: TouchEvent) {
|
||||
|
@ -95,15 +97,24 @@ function touchMove(event: TouchEvent) {
|
|||
let distanceX = event.touches[0].screenX - startScreenX;
|
||||
let distanceY = event.touches[0].screenY - startScreenY;
|
||||
|
||||
if (Math.abs(distanceY) > SWIPE_ABORT_Y_THRESHOLD) {
|
||||
swipeAborted = true;
|
||||
// スワイプ方向をロック
|
||||
if (!swipeDirectionLocked) {
|
||||
const angle = Math.abs(Math.atan2(distanceY, distanceX) * (180 / Math.PI));
|
||||
if (angle > 90 - SWIPE_DIRECTION_ANGLE_THRESHOLD && angle < 90 + SWIPE_DIRECTION_ANGLE_THRESHOLD) {
|
||||
swipeDirectionLocked = 'vertical';
|
||||
} else {
|
||||
swipeDirectionLocked = 'horizontal';
|
||||
}
|
||||
}
|
||||
|
||||
// 縦方向のスワイプの場合は中断
|
||||
if (swipeDirectionLocked === 'vertical') {
|
||||
swipeAborted = true;
|
||||
pullDistance.value = 0;
|
||||
isSwiping.value = false;
|
||||
window.setTimeout(() => {
|
||||
isSwipingForClass.value = false;
|
||||
}, 400);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -164,6 +175,8 @@ function touchEnd(event: TouchEvent) {
|
|||
window.setTimeout(() => {
|
||||
isSwipingForClass.value = false;
|
||||
}, 400);
|
||||
|
||||
swipeDirectionLocked = null; // スワイプ方向をリセット
|
||||
}
|
||||
|
||||
/** 横スワイプに関与する可能性のある要素を調べる */
|
||||
|
@ -190,7 +203,7 @@ watch(tabModel, (newTab, oldTab) => {
|
|||
const newIndex = props.tabs.findIndex(tab => tab.key === newTab);
|
||||
const oldIndex = props.tabs.findIndex(tab => tab.key === oldTab);
|
||||
|
||||
if (oldIndex >= 0 && newIndex && oldIndex < newIndex) {
|
||||
if (oldIndex >= 0 && newIndex >= 0 && oldIndex < newIndex) {
|
||||
transitionName.value = 'swipeAnimationLeft';
|
||||
} else {
|
||||
transitionName.value = 'swipeAnimationRight';
|
||||
|
|
|
@ -12,7 +12,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
appear @afterLeave="emit('closed')"
|
||||
>
|
||||
<div v-if="showing" :class="$style.root" class="_popup _shadow" :style="{ zIndex, top: top + 'px', left: left + 'px' }" @mouseover="() => { emit('mouseover'); }" @mouseleave="() => { emit('mouseleave'); }">
|
||||
<div v-if="user != null">
|
||||
<MkError v-if="error" @retry="fetchUser()"/>
|
||||
<div v-else-if="user != null">
|
||||
<div :class="$style.banner" :style="user.bannerUrl ? { backgroundImage: `url(${prefer.s.disableShowingAnimatedImages ? getStaticImageUrl(user.bannerUrl) : user.bannerUrl})` } : ''">
|
||||
<span v-if="$i && $i.id != user.id && user.isFollowed" :class="$style.followed">{{ i18n.ts.followsYou }}</span>
|
||||
</div>
|
||||
|
@ -85,6 +86,7 @@ const zIndex = os.claimZIndex('middle');
|
|||
const user = ref<Misskey.entities.UserDetailed | null>(null);
|
||||
const top = ref(0);
|
||||
const left = ref(0);
|
||||
const error = ref(false);
|
||||
|
||||
function showMenu(ev: MouseEvent) {
|
||||
if (user.value == null) return;
|
||||
|
@ -92,19 +94,27 @@ function showMenu(ev: MouseEvent) {
|
|||
os.popupMenu(menu, ev.currentTarget ?? ev.target).finally(cleanup);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
async function fetchUser() {
|
||||
if (typeof props.q === 'object') {
|
||||
user.value = props.q;
|
||||
error.value = false;
|
||||
} else {
|
||||
const query = props.q.startsWith('@') ?
|
||||
const query: Omit<Misskey.entities.UsersShowRequest, 'userIds'> = props.q.startsWith('@') ?
|
||||
Misskey.acct.parse(props.q.substring(1)) :
|
||||
{ userId: props.q };
|
||||
|
||||
misskeyApi('users/show', query).then(res => {
|
||||
if (!props.showing) return;
|
||||
user.value = res;
|
||||
error.value = false;
|
||||
}, () => {
|
||||
error.value = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchUser();
|
||||
|
||||
const rect = props.source.getBoundingClientRect();
|
||||
const x = ((rect.left + (props.source.offsetWidth / 2)) - (300 / 2)) + window.scrollX;
|
||||
|
|
|
@ -301,7 +301,7 @@ export const PREF_DEF = {
|
|||
default: false,
|
||||
},
|
||||
enableHorizontalSwipe: {
|
||||
default: true,
|
||||
default: false,
|
||||
},
|
||||
enablePullToRefresh: {
|
||||
default: true,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"type": "module",
|
||||
"name": "misskey-js",
|
||||
"version": "2025.5.0-alpha.0",
|
||||
"version": "2025.5.0-alpha.1",
|
||||
"description": "Misskey SDK for JavaScript",
|
||||
"license": "MIT",
|
||||
"main": "./built/index.js",
|
||||
|
|
Loading…
Reference in New Issue