Compare commits

..
Author SHA1 Message Date
copilot-swe-agent[bot]andsyuilo 263d476ffe Fix iOS touch position offset in image masking
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-10-25 06:22:35 +00:00
copilot-swe-agent[bot] 3ab64ac688 Initial plan 2025-10-25 06:17:02 +00:00
syuilo ca76ba1871 Update CHANGELOG.md 2025-10-25 08:47:51 +09:00
syuilo 9f768b8022 fix(frontend): キャッシュをクリアするとテーマ再適用するまでレンダリングが正しく行われない問題を修正 2025-10-25 08:22:47 +09:00
github-actions[bot] 4ff826eb3d [skip ci] Update CHANGELOG.md (prepend template) 2025-10-24 06:31:38 +00:00
github-actions[bot] 60bcb9c6a9 Release: 2025.10.1 2025-10-24 06:31:32 +00:00
github-actions[bot] 0c85bfd56f Bump version to 2025.10.1-beta.4 2025-10-24 02:28:37 +00:00
syuilo 9d37f696b4 New Crowdin updates (#16692)
* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Chinese Traditional)
2025-10-24 11:15:30 +09:00
syuilo 2734ff6af7 Update CHANGELOG.md 2025-10-24 11:15:11 +09:00
Copilotandsyuilo 456504cf82 Fix touch position offset in image masking on iOS devices (#16702)
* Initial plan

* Fix iOS touch position offset in image masking feature

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-10-24 11:14:12 +09:00
syuilo 81cea6aed5 Update MkImageEffectorDialog.vue
related? #16703
2025-10-24 11:01:20 +09:00
syuilo 2d1b7c957a Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-10-24 10:41:55 +09:00
syuilo 5b6aa1496a Update about-misskey.vue 2025-10-24 10:40:11 +09:00
github-actions[bot] 259dd34b26 Bump version to 2025.10.1-beta.3 2025-10-23 10:25:35 +00:00
11 changed files with 59 additions and 73 deletions
+13
View File
@@ -1,3 +1,15 @@
## Unreleased
### General
-
### Client
- Fix: アプリ内からキャッシュをクリアするとテーマ再適用するまでレンダリングが正しく行われない問題を修正
### Server
-
## 2025.10.1
### General
@@ -13,6 +25,7 @@
- Fix: 一部のブラウザでバナー画像が上下中央に表示されない問題を修正
- Fix: ナビゲーションバーの設定で削除した項目をその場で再追加できない問題を修正
- Fix: ロールポリシーによりダイレクトメッセージが無効化されている際のデッキのダイレクトメッセージカラムの挙動を改善
- Fix: 画像のマスクでタッチ操作が不安定な問題を修正
- Fix: ウォーターマークの各種挙動修正
- ウォーターマークを回転させると歪む問題を修正
- ウォーターマークを敷き詰めると上下左右反転した画像/文字が表示される問題を修正
+1
View File
@@ -3201,6 +3201,7 @@ _watermarkEditor:
title: "워터마크 편집"
cover: "전체에 붙이기"
repeat: "전면에 깔기"
preserveBoundingRect: "회전 시 빠져나오지 않도록 조정"
opacity: "불투명도"
scale: "크기"
text: "텍스트"
+1
View File
@@ -3201,6 +3201,7 @@ _watermarkEditor:
title: "编辑水印"
cover: "覆盖全体"
repeat: "平铺"
preserveBoundingRect: "调整为旋转时不超出范围"
opacity: "不透明度"
scale: "大小"
text: "文本"
+1
View File
@@ -3200,6 +3200,7 @@ _watermarkEditor:
title: "編輯浮水印"
cover: "覆蓋整體"
repeat: "佈局"
preserveBoundingRect: "調整使其在旋轉時不會突出"
opacity: "透明度"
scale: "大小"
text: "文字"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "misskey",
"version": "2025.10.1-beta.2",
"version": "2025.10.1",
"codename": "nasubi",
"repository": {
"type": "git",
@@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.root">
<div :class="$style.container">
<div :class="$style.preview">
<canvas ref="canvasEl" :class="$style.previewCanvas" @pointerdown="onImagePointerdown"></canvas>
<canvas ref="canvasEl" :class="$style.previewCanvas" @pointerdown.prevent.stop="onImagePointerdown"></canvas>
<div :class="$style.previewContainer">
<div class="_acrylic" :class="$style.previewTitle">{{ i18n.ts.preview }}</div>
<div class="_acrylic" :class="$style.editControls">
@@ -242,31 +242,27 @@ function onImagePointerdown(ev: PointerEvent) {
const AW = canvasEl.value.clientWidth;
const AH = canvasEl.value.clientHeight;
const BW = imageBitmap.width;
const BH = imageBitmap.height;
const BW = canvasEl.value.width; // Canvas intrinsic width (render width)
const BH = canvasEl.value.height; // Canvas intrinsic height (render height)
let xOffset = 0;
let yOffset = 0;
// Calculate the scale factor for object-fit: contain
const scale = Math.min(AW / BW, AH / BH);
// Calculate the actual rendered size of the canvas content
const renderW = BW * scale;
const renderH = BH * scale;
// Calculate the offset to center the image
const xOffset = (AW - renderW) / 2;
const yOffset = (AH - renderH) / 2;
if (AW / AH < BW / BH) { // 横長
yOffset = AH - BH * (AW / BW);
} else { // 縦長
xOffset = AW - BW * (AH / BH);
}
const rect = canvasEl.value.getBoundingClientRect();
const pointerOffsetX = ev.clientX - rect.left;
const pointerOffsetY = ev.clientY - rect.top;
xOffset /= 2;
yOffset /= 2;
let startX = ev.offsetX - xOffset;
let startY = ev.offsetY - yOffset;
if (AW / AH < BW / BH) { // 横長
startX = startX / (Math.max(AW, AH) / Math.max(BH / BW, 1));
startY = startY / (Math.max(AW, AH) / Math.max(BW / BH, 1));
} else { // 縦長
startX = startX / (Math.min(AW, AH) / Math.max(BH / BW, 1));
startY = startY / (Math.min(AW, AH) / Math.max(BW / BH, 1));
}
// Convert from client coordinates to canvas coordinates
let startX = (pointerOffsetX - xOffset) / scale;
let startY = (pointerOffsetY - yOffset) / scale;
const id = genId();
if (penMode.value === 'fill') {
@@ -311,19 +307,15 @@ function onImagePointerdown(ev: PointerEvent) {
});
}
_move(ev.offsetX, ev.offsetY);
_move(ev.clientX, ev.clientY);
function _move(pointerX: number, pointerY: number) {
let x = pointerX - xOffset;
let y = pointerY - yOffset;
if (AW / AH < BW / BH) { // 横長
x = x / (Math.max(AW, AH) / Math.max(BH / BW, 1));
y = y / (Math.max(AW, AH) / Math.max(BW / BH, 1));
} else { // 縦長
x = x / (Math.min(AW, AH) / Math.max(BH / BW, 1));
y = y / (Math.min(AW, AH) / Math.max(BW / BH, 1));
}
function _move(pointerClientX: number, pointerClientY: number) {
const pointerX = pointerClientX - rect.left;
const pointerY = pointerClientY - rect.top;
// Convert from client coordinates to canvas coordinates
let x = (pointerX - xOffset) / scale;
let y = (pointerY - yOffset) / scale;
const scaleX = Math.abs(x - startX);
const scaleY = Math.abs(y - startY);
@@ -340,7 +332,7 @@ function onImagePointerdown(ev: PointerEvent) {
}
function move(ev: PointerEvent) {
_move(ev.offsetX, ev.offsetY);
_move(ev.clientX, ev.clientY);
}
function up() {
@@ -448,6 +440,7 @@ function onImagePointerdown(ev: PointerEvent) {
margin: 20px;
box-sizing: border-box;
object-fit: contain;
touch-action: none;
}
.controls {
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<component :is="link ? MkA : 'span'" v-user-preview="preview ? user.id : undefined" v-bind="bound" class="_noSelect" :class="[$style.root, { [$style.animation]: animation, [$style.cat]: user.isCat, [$style.square]: squareAvatars, [$style.mochimochi]: isMochimochi }]" :style="{ color }" :title="acct(user)" @click="onClick">
<component :is="link ? MkA : 'span'" v-user-preview="preview ? user.id : undefined" v-bind="bound" class="_noSelect" :class="[$style.root, { [$style.animation]: animation, [$style.cat]: user.isCat, [$style.square]: squareAvatars }]" :style="{ color }" :title="acct(user)" @click="onClick">
<MkImgWithBlurhash v-if="prefer.s.enableHighQualityImagePlaceholders" :class="$style.inner" :src="url" :hash="user.avatarBlurhash" :cover="true" :onlyAvgColor="true"/>
<img v-else :class="$style.inner" :src="url" alt="" decoding="async" style="pointer-events: none;"/>
<MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/>
@@ -55,7 +55,6 @@ import { prefer } from '@/preferences.js';
const animation = ref(prefer.s.animation);
const squareAvatars = ref(prefer.s.squareAvatars);
const isMochimochi = ref(false);
const props = withDefaults(defineProps<{
user: Misskey.entities.User;
@@ -92,13 +91,6 @@ const url = computed(() => {
function onClick(ev: MouseEvent): void {
if (props.link) return;
emit('click', ev);
// Trigger mochimochi animation
if (animation.value) {
isMochimochi.value = true;
setTimeout(() => {
isMochimochi.value = false;
}, 600);
}
}
function getDecorationUrl(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
@@ -352,29 +344,4 @@ watch(() => props.user.avatarBlurhash, () => {
filter: brightness(1);
}
}
@keyframes mochimochi {
0% {
transform: scale(1, 1);
}
20% {
transform: scale(0.9, 1.1);
}
40% {
transform: scale(1.1, 0.9);
}
60% {
transform: scale(0.95, 1.05);
}
80% {
transform: scale(1.02, 0.98);
}
100% {
transform: scale(1, 1);
}
}
.mochimochi {
animation: mochimochi 0.6s ease-in-out;
}
</style>
@@ -295,6 +295,9 @@ const patronsWithIcon = [{
}, {
name: 'しゃどかの',
icon: 'https://assets.misskey-hub.net/patrons/5bec3c6b402942619e03f7a2ae76d69e.jpg',
}, {
name: '大賀愛一郎',
icon: 'https://assets.misskey-hub.net/patrons/c701a797d1df4125970f25d3052250ac.jpg',
}];
const patrons = [
+6
View File
@@ -242,3 +242,9 @@ export async function installTheme(code: string): Promise<void> {
if (!theme) return;
await addTheme(theme);
}
export function clearAppliedThemeCache() {
miLocalStorage.removeItem('theme');
miLocalStorage.removeItem('themeId');
miLocalStorage.removeItem('themeCachedVersion');
}
+2 -1
View File
@@ -9,14 +9,15 @@ import * as os from '@/os.js';
import { miLocalStorage } from '@/local-storage.js';
import { fetchCustomEmojis } from '@/custom-emojis.js';
import { fetchInstance } from '@/instance.js';
import { clearAppliedThemeCache } from '@/theme.js';
export async function clearCache() {
os.waiting();
miLocalStorage.removeItem('instance');
miLocalStorage.removeItem('instanceCachedAt');
miLocalStorage.removeItem('theme');
miLocalStorage.removeItem('emojis');
miLocalStorage.removeItem('lastEmojisFetchedAt');
clearAppliedThemeCache();
await misskeyApiGet('clear-browser-cache', {}).catch(() => {
// ignore
});
+1 -1
View File
@@ -1,7 +1,7 @@
{
"type": "module",
"name": "misskey-js",
"version": "2025.10.1-beta.2",
"version": "2025.10.1",
"description": "Misskey SDK for JavaScript",
"license": "MIT",
"main": "./built/index.js",