Compare commits

...

14 Commits

Author SHA1 Message Date
github-actions[bot] c69a13b592 Release: 2025.6.1 2025-06-16 02:33:14 +00:00
syuilo 40e35c051a Update CHANGELOG.md 2025-06-15 11:10:03 +09:00
syuilo b93717be33 Update CHANGELOG.md
Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com>
2025-06-15 11:08:53 +09:00
syuilo fe805fb7f0 enhance(frontend/image-effector): tweak fxs 2025-06-15 11:06:46 +09:00
syuilo e9af9d4451 enhance(frontend/image-effector): tweak fxs 2025-06-15 10:57:29 +09:00
syuilo ce90fee586 enhance(frontend/image-effector): add blockNoise fx 2025-06-15 10:55:11 +09:00
syuilo 5bec8ba6b0 enhance(frontend/image-effector): tweak fxs 2025-06-15 10:19:42 +09:00
syuilo 3dbfd80d65 enhance(frontend/image-effector): tweak colorAdjust fx 2025-06-15 09:25:57 +09:00
syuilo b33eeb1366 enhance(frontend/image-effector): tweak distort fx 2025-06-15 08:47:59 +09:00
syuilo 420756d744 Update CHANGELOG.md 2025-06-14 19:50:56 +09:00
かっこかり 32d721abf1 refactor(frontend): checkWordMuteの返り値が誤っている問題を修正 (#16188)
* refactor(frontend): checkWordMuteの返り値が誤っている問題を修正

* fix lint
2025-06-14 16:08:14 +09:00
github-actions[bot] 8ea6aa2ef3 Bump version to 2025.6.1-rc.0 2025-06-14 03:16:12 +00:00
syuilo bc07b79a23 fix(frontend): デッキのタイムラインカラムで新着ノート時のサウンドが再生されない問題を修正
Fix #16164
2025-06-14 11:36:42 +09:00
syuilo aae7961540 New Crowdin updates (#16187)
* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Chinese Simplified)
2025-06-13 10:31:14 +09:00
23 changed files with 252 additions and 69 deletions
+4 -1
View File
@@ -1,10 +1,12 @@
## 2025.6.1
### Note
- Misskey Webプラグインのnote_view_interruptorは不具合の影響により現在一時的に無効化されています。
- AiScript Misskey拡張APIMisskey Webプラグイン)の[note_view_interruptor](https://misskey-hub.net/ja/docs/for-developers/plugin/plugin-api-reference/#pluginregister_note_view_interruptorfn)は不具合の影響により現在一時的に無効化されています。
- Misskey Web投稿フォームのプレビュー切り替えは「...」メニュー内に配置されました
### Client
- Feat: 画像にウォーターマークを付与できるようになりました
- Feat: 画像の加工ができるようになりました(実験的)
- Enhance: ノートのリアクション一覧で、押せるリアクションを優先して表示できるようにするオプションを追加
- Enhance: 全てのチャットメッセージを既読にできるように(設定→その他)
- Enhance: ミュートした絵文字をデバイス間で同期できるように
@@ -13,6 +15,7 @@
- Fix: ユーザーの検索結果を追加で読み込むことができない問題を修正
- Fix: タッチ操作時にチャートのツールチップが消えなくなる場合がある問題を修正
- Fix: ウェルカムタイムラインでリアクションが表示されない問題を修正
- Fix: デッキのタイムラインカラムで新着ノート時のサウンドが再生されない問題を修正
### Server
- Feat: 全てのチャットメッセージを既読にするAPIを追加(chat/read-all)
+8
View File
@@ -12220,6 +12220,14 @@ export interface Locale extends ILocale {
*
*/
"checker": string;
/**
*
*/
"blockNoise": string;
/**
*
*/
"tearing": string;
};
};
}
+2
View File
@@ -3273,3 +3273,5 @@ _imageEffector:
stripe: "ストライプ"
polkadot: "ポルカドット"
checker: "チェッカー"
blockNoise: "ブロックノイズ"
tearing: "ティアリング"
+3 -3
View File
@@ -1631,7 +1631,7 @@ _serverSettings:
inquiryUrl: "联络地址"
inquiryUrlDescription: "用来指定诸如向服务运营商咨询的论坛地址,或记载了运营商联系方式之类的网页地址。"
openRegistration: "开放注册"
openRegistrationWarning: "开放注册有风险。建议仅当能够持续监控服务器并在出现问题时能够立即响应时才打开它。"
openRegistrationWarning: "开放注册有风险。建议仅当能够持续监控服务器并在出现问题时能够立即响应时才打开它。"
thisSettingWillAutomaticallyOffWhenModeratorsInactive: "若在一段时间内没有检测到管理活动,为防止垃圾信息,此设定将自动关闭。"
deliverSuspendedSoftware: "停止投递的软件"
deliverSuspendedSoftwareDescription: "可因安全漏洞之类的原因,停止向指定的服务器及服务器版本送信。版本信息由服务器提供,不保证可靠性。可使用 semver 范围来指定版本,但指定 >= 2024.3.1 将不包括如 2024.3.1-custom.0 等自定义版本,因此建议像 >= 2024.3.1-0 这样指定 prerelease 版本。"
@@ -2143,7 +2143,7 @@ _wordMute:
muteWordsDescription: "AND 条件用空格分隔,OR 条件用换行符分隔。"
muteWordsDescription2: "正则表达式用斜线包裹"
_instanceMute:
instanceMuteDescription: "隐藏服务器中所有帖子和转帖,包括这些服务器上用户回复。"
instanceMuteDescription: "隐藏服务器中所有帖子和转帖,包括这些服务器上用户回复。"
instanceMuteDescription2: "一行一个"
title: "下面实例中的帖子将被隐藏。"
heading: "已隐藏的服务器"
@@ -2493,7 +2493,7 @@ _profile:
avatarDecorationMax: "最多可添加 {max} 个挂件"
followedMessage: "被关注时显示的消息"
followedMessageDescription: "可以设置被关注时向对方显示的短消息。"
followedMessageDescriptionForLockedAccount: "需要批准才能关注的情况下,消息在请求被批准后显示。"
followedMessageDescriptionForLockedAccount: "需要批准才能关注的情况下,消息在请求被批准后显示。"
_exportOrImport:
allNotes: "所有帖子"
favoritedNotes: "收藏的帖子"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "misskey",
"version": "2025.6.1-beta.2",
"version": "2025.6.1",
"codename": "nasubi",
"repository": {
"type": "git",
@@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
v-if="v.type === 'boolean'"
v-model="layer.params[k]"
>
<template #label>{{ k }}</template>
<template #label>{{ fx.params[k].label ?? k }}</template>
</MkSwitch>
<MkRange
v-else-if="v.type === 'number'"
@@ -29,6 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:min="v.min"
:max="v.max"
:step="v.step"
:textConverter="fx.params[k].toViewValue"
@thumbDoubleClicked="() => {
if (fx.params[k].default != null) {
layer.params[k] = fx.params[k].default;
@@ -37,13 +38,13 @@ SPDX-License-Identifier: AGPL-3.0-only
}
}"
>
<template #label>{{ k }}</template>
<template #label>{{ fx.params[k].label ?? k }}</template>
</MkRange>
<MkRadios
v-else-if="v.type === 'number:enum'"
v-model="layer.params[k]"
>
<template #label>{{ k }}</template>
<template #label>{{ fx.params[k].label ?? k }}</template>
<option v-for="item in v.enum" :value="item.value">{{ item.label }}</option>
</MkRadios>
<div v-else-if="v.type === 'seed'">
@@ -55,7 +56,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:max="10000"
:step="1"
>
<template #label>{{ k }}</template>
<template #label>{{ fx.params[k].label ?? k }}</template>
</MkRange>
</div>
<MkInput
@@ -64,7 +65,7 @@ SPDX-License-Identifier: AGPL-3.0-only
type="color"
@update:modelValue="v => { const c = getRgb(v); if (c != null) layer.params[k] = c; }"
>
<template #label>{{ k }}</template>
<template #label>{{ fx.params[k].label ?? k }}</template>
</MkInput>
</div>
</div>
@@ -96,7 +96,7 @@ watch(layers, async () => {
}, { deep: true });
function addEffect(ev: MouseEvent) {
os.popupMenu(FXS.filter(fx => fx.id !== 'watermarkPlacement').map((fx) => ({
os.popupMenu(FXS.map((fx) => ({
text: fx.name,
action: () => {
layers.push({
+16 -8
View File
@@ -321,20 +321,27 @@ const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
url: `https://${host}/notes/${appearNote.id}`,
}));
/* Overload FunctionLint
/* eslint-disable no-redeclare */
/** checkOnlyでは純粋なワードミュート結果をbooleanで返却する */
function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: true): boolean;
function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: false): Array<string | string[]> | false | 'sensitiveMute';
*/
function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly = false): Array<string | string[]> | false | 'sensitiveMute' {
function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly?: false): Array<string | string[]> | false | 'sensitiveMute';
function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly = false): Array<string | string[]> | boolean | 'sensitiveMute' {
if (mutedWords != null) {
const result = checkWordMute(noteToCheck, $i, mutedWords);
if (Array.isArray(result)) return result;
if (Array.isArray(result)) {
return checkOnly ? (result.length > 0) : result;
}
const replyResult = noteToCheck.reply && checkWordMute(noteToCheck.reply, $i, mutedWords);
if (Array.isArray(replyResult)) return replyResult;
if (Array.isArray(replyResult)) {
return checkOnly ? (replyResult.length > 0) : replyResult;
}
const renoteResult = noteToCheck.renote && checkWordMute(noteToCheck.renote, $i, mutedWords);
if (Array.isArray(renoteResult)) return renoteResult;
if (Array.isArray(renoteResult)) {
return checkOnly ? (renoteResult.length > 0) : renoteResult;
}
}
if (checkOnly) return false;
@@ -345,6 +352,7 @@ function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string
return false;
}
/* eslint-enable no-redeclare */
const keymap = {
'r': () => {
@@ -417,7 +425,7 @@ if (!props.mock) {
const users = renotes.map(x => x.user);
if (users.length < 1) return;
if (users.length < 1 || renoteButton.value == null) return;
const { dispose } = os.popup(MkUsersTooltip, {
showing,
@@ -62,6 +62,7 @@ import { useInterval } from '@@/js/use-interval.js';
import { getScrollContainer, scrollToTop } from '@@/js/scroll.js';
import type { BasicTimelineType } from '@/timelines.js';
import type { PagingCtx } from '@/composables/use-pagination.js';
import type { SoundStore } from '@/preferences/def.js';
import { usePagination } from '@/composables/use-pagination.js';
import MkPullToRefresh from '@/components/MkPullToRefresh.vue';
import { useStream } from '@/stream.js';
@@ -83,6 +84,7 @@ const props = withDefaults(defineProps<{
channel?: string;
role?: string;
sound?: boolean;
customSound?: SoundStore | null;
withRenotes?: boolean;
withReplies?: boolean;
withSensitive?: boolean;
@@ -92,6 +94,8 @@ const props = withDefaults(defineProps<{
withReplies: false,
withSensitive: true,
onlyFiles: false,
sound: false,
customSound: null,
});
provide('inTimeline', true);
@@ -190,7 +194,11 @@ function prepend(note: Misskey.entities.Note) {
}
if (props.sound) {
sound.playMisskeySfx($i && (note.userId === $i.id) ? 'noteMy' : 'note');
if (props.customSound) {
sound.playMisskeySfxFile(props.customSound);
} else {
sound.playMisskeySfx($i && (note.userId === $i.id) ? 'noteMy' : 'note');
}
}
}
@@ -420,7 +428,7 @@ defineExpose({
background: var(--MI_THEME-panel);
}
.note {
.note:not(:empty) {
border-bottom: solid 0.5px var(--MI_THEME-divider);
}
@@ -26,6 +26,8 @@ SPDX-License-Identifier: AGPL-3.0-only
:withReplies="withReplies"
:withSensitive="withSensitive"
:onlyFiles="onlyFiles"
:sound="true"
:customSound="soundSetting"
/>
</XColumn>
</template>
@@ -542,7 +542,7 @@ function smallerVisibility(a: Visibility, b: Visibility): Visibility {
export function getRenoteMenu(props: {
note: Misskey.entities.Note;
renoteButton: ShallowRef<HTMLElement | undefined>;
renoteButton: ShallowRef<HTMLElement | null | undefined>;
mock?: boolean;
}) {
const appearNote = getAppearNote(props.note);
@@ -19,6 +19,8 @@ type ParamTypeToPrimitive = {
type ImageEffectorFxParamDefs = Record<string, {
type: keyof ParamTypeToPrimitive;
default: any;
label?: string;
toViewValue?: (v: any) => string;
}>;
export function defineImageEffectorFx<ID extends string, PS extends ImageEffectorFxParamDefs, US extends string[]>(fx: ImageEffectorFx<ID, PS, US>) {
@@ -10,20 +10,17 @@ import { FX_colorClamp } from './fxs/colorClamp.js';
import { FX_colorClampAdvanced } from './fxs/colorClampAdvanced.js';
import { FX_distort } from './fxs/distort.js';
import { FX_polkadot } from './fxs/polkadot.js';
import { FX_glitch } from './fxs/glitch.js';
import { FX_tearing } from './fxs/tearing.js';
import { FX_grayscale } from './fxs/grayscale.js';
import { FX_invert } from './fxs/invert.js';
import { FX_mirror } from './fxs/mirror.js';
import { FX_stripe } from './fxs/stripe.js';
import { FX_threshold } from './fxs/threshold.js';
import { FX_watermarkPlacement } from './fxs/watermarkPlacement.js';
import { FX_zoomLines } from './fxs/zoomLines.js';
import { FX_blockNoise } from './fxs/blockNoise.js';
import type { ImageEffectorFx } from './ImageEffector.js';
export const FXS = [
FX_watermarkPlacement,
FX_chromaticAberration,
FX_glitch,
FX_mirror,
FX_invert,
FX_grayscale,
@@ -36,4 +33,7 @@ export const FXS = [
FX_stripe,
FX_polkadot,
FX_checker,
FX_chromaticAberration,
FX_tearing,
FX_blockNoise,
] as const satisfies ImageEffectorFx<string, any>[];
@@ -0,0 +1,119 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import seedrandom from 'seedrandom';
import { defineImageEffectorFx } from '../ImageEffector.js';
import { i18n } from '@/i18n.js';
const shader = `#version 300 es
precision mediump float;
in vec2 in_uv;
uniform sampler2D in_texture;
uniform vec2 in_resolution;
uniform int u_amount;
uniform float u_shiftStrengths[128];
uniform vec2 u_shiftOrigins[128];
uniform vec2 u_shiftSizes[128];
uniform float u_channelShift;
out vec4 out_color;
void main() {
// TODO: ピクセル毎に計算する必要はないのでuniformにする
float aspect_ratio = min(in_resolution.x, in_resolution.y) / max(in_resolution.x, in_resolution.y);
float aspect_ratio_x = in_resolution.x > in_resolution.y ? 1.0 : aspect_ratio;
float aspect_ratio_y = in_resolution.x < in_resolution.y ? 1.0 : aspect_ratio;
float v = 0.0;
for (int i = 0; i < u_amount; i++) {
if (
in_uv.x * aspect_ratio_x > ((u_shiftOrigins[i].x * aspect_ratio_x) - u_shiftSizes[i].x) &&
in_uv.x * aspect_ratio_x < ((u_shiftOrigins[i].x * aspect_ratio_x) + u_shiftSizes[i].x) &&
in_uv.y * aspect_ratio_y > ((u_shiftOrigins[i].y * aspect_ratio_y) - u_shiftSizes[i].y) &&
in_uv.y * aspect_ratio_y < ((u_shiftOrigins[i].y * aspect_ratio_y) + u_shiftSizes[i].y)
) {
v += u_shiftStrengths[i];
}
}
float r = texture(in_texture, vec2(in_uv.x + (v * (1.0 + u_channelShift)), in_uv.y)).r;
float g = texture(in_texture, vec2(in_uv.x + v, in_uv.y)).g;
float b = texture(in_texture, vec2(in_uv.x + (v * (1.0 + (u_channelShift / 2.0))), in_uv.y)).b;
float a = texture(in_texture, vec2(in_uv.x + v, in_uv.y)).a;
out_color = vec4(r, g, b, a);
}
`;
export const FX_blockNoise = defineImageEffectorFx({
id: 'blockNoise' as const,
name: i18n.ts._imageEffector._fxs.glitch + ': ' + i18n.ts._imageEffector._fxs.blockNoise,
shader,
uniforms: ['amount', 'channelShift'] as const,
params: {
amount: {
type: 'number' as const,
default: 50,
min: 1,
max: 100,
step: 1,
},
strength: {
type: 'number' as const,
default: 0.05,
min: -1,
max: 1,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
width: {
type: 'number' as const,
default: 0.05,
min: 0.01,
max: 1,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
height: {
type: 'number' as const,
default: 0.01,
min: 0.01,
max: 1,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
channelShift: {
type: 'number' as const,
default: 0,
min: 0,
max: 10,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
seed: {
type: 'seed' as const,
default: 100,
},
},
main: ({ gl, program, u, params }) => {
gl.uniform1i(u.amount, params.amount);
gl.uniform1f(u.channelShift, params.channelShift);
const margin = 0;
const rnd = seedrandom(params.seed.toString());
for (let i = 0; i < params.amount; i++) {
const o = gl.getUniformLocation(program, `u_shiftOrigins[${i.toString()}]`);
gl.uniform2f(o, (rnd() * (1 + (margin * 2))) - margin, (rnd() * (1 + (margin * 2))) - margin);
const s = gl.getUniformLocation(program, `u_shiftStrengths[${i.toString()}]`);
gl.uniform1f(s, (1 - (rnd() * 2)) * params.strength);
const sizes = gl.getUniformLocation(program, `u_shiftSizes[${i.toString()}]`);
gl.uniform2f(sizes, params.width, params.height);
}
},
});
@@ -58,6 +58,7 @@ export const FX_checker = defineImageEffectorFx({
min: -1.0,
max: 1.0,
step: 0.01,
toViewValue: v => Math.round(v * 90) + '°',
},
scale: {
type: 'number' as const,
@@ -76,6 +77,7 @@ export const FX_checker = defineImageEffectorFx({
min: 0.0,
max: 1.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
},
main: ({ gl, u, params }) => {
@@ -72,7 +72,7 @@ void main() {
vec3 color = in_color.rgb;
color = color * u_brightness;
color += vec3(clamp(u_lightness, 0.0, 2.0) - 1.0);
color += vec3(u_lightness);
color = (color - 0.5) * u_contrast + 0.5;
vec3 hsl = rgb2hsl(color);
@@ -92,45 +92,50 @@ export const FX_colorAdjust = defineImageEffectorFx({
params: {
lightness: {
type: 'number' as const,
default: 100,
min: 0,
max: 200,
step: 1,
default: 0,
min: -1,
max: 1,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
contrast: {
type: 'number' as const,
default: 100,
default: 1,
min: 0,
max: 200,
step: 1,
max: 4,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
hue: {
type: 'number' as const,
default: 0,
min: -360,
max: 360,
step: 1,
min: -1,
max: 1,
step: 0.01,
toViewValue: v => Math.round(v * 180) + '°',
},
brightness: {
type: 'number' as const,
default: 100,
default: 1,
min: 0,
max: 200,
step: 1,
max: 4,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
saturation: {
type: 'number' as const,
default: 100,
default: 1,
min: 0,
max: 200,
step: 1,
max: 4,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
},
main: ({ gl, u, params }) => {
gl.uniform1f(u.brightness, params.brightness / 100);
gl.uniform1f(u.contrast, params.contrast / 100);
gl.uniform1f(u.hue, params.hue / 360);
gl.uniform1f(u.lightness, params.lightness / 100);
gl.uniform1f(u.saturation, params.saturation / 100);
gl.uniform1f(u.brightness, params.brightness);
gl.uniform1f(u.contrast, params.contrast);
gl.uniform1f(u.hue, params.hue / 2);
gl.uniform1f(u.lightness, params.lightness);
gl.uniform1f(u.saturation, params.saturation);
},
});
@@ -37,6 +37,7 @@ export const FX_colorClamp = defineImageEffectorFx({
min: 0.0,
max: 1.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
min: {
type: 'number' as const,
@@ -44,6 +45,7 @@ export const FX_colorClamp = defineImageEffectorFx({
min: -1.0,
max: 0.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
},
main: ({ gl, u, params }) => {
@@ -41,6 +41,7 @@ export const FX_colorClampAdvanced = defineImageEffectorFx({
min: 0.0,
max: 1.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
rMin: {
type: 'number' as const,
@@ -48,6 +49,7 @@ export const FX_colorClampAdvanced = defineImageEffectorFx({
min: -1.0,
max: 0.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
gMax: {
type: 'number' as const,
@@ -55,6 +57,7 @@ export const FX_colorClampAdvanced = defineImageEffectorFx({
min: 0.0,
max: 1.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
gMin: {
type: 'number' as const,
@@ -62,6 +65,7 @@ export const FX_colorClampAdvanced = defineImageEffectorFx({
min: -1.0,
max: 0.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
bMax: {
type: 'number' as const,
@@ -69,6 +73,7 @@ export const FX_colorClampAdvanced = defineImageEffectorFx({
min: 0.0,
max: 1.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
bMin: {
type: 'number' as const,
@@ -76,6 +81,7 @@ export const FX_colorClampAdvanced = defineImageEffectorFx({
min: -1.0,
max: 0.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
},
main: ({ gl, u, params }) => {
@@ -9,6 +9,10 @@ import { i18n } from '@/i18n.js';
const shader = `#version 300 es
precision mediump float;
const float PI = 3.141592653589793;
const float TWO_PI = 6.283185307179586;
const float HALF_PI = 1.5707963267948966;
in vec2 in_uv;
uniform sampler2D in_texture;
uniform vec2 in_resolution;
@@ -20,8 +24,8 @@ out vec4 out_color;
void main() {
float v = u_direction == 0 ?
sin(u_phase + in_uv.y * u_frequency) * u_strength :
sin(u_phase + in_uv.x * u_frequency) * u_strength;
sin((HALF_PI + (u_phase * PI) - (u_frequency / 2.0)) + in_uv.y * u_frequency) * u_strength :
sin((HALF_PI + (u_phase * PI) - (u_frequency / 2.0)) + in_uv.x * u_frequency) * u_strength;
vec4 in_color = u_direction == 0 ?
texture(in_texture, vec2(in_uv.x + v, in_uv.y)) :
texture(in_texture, vec2(in_uv.x, in_uv.y + v));
@@ -38,32 +42,34 @@ export const FX_distort = defineImageEffectorFx({
direction: {
type: 'number:enum' as const,
enum: [{ value: 0, label: 'v' }, { value: 1, label: 'h' }],
default: 0,
default: 1,
},
phase: {
type: 'number' as const,
default: 50.0,
min: 0.0,
max: 100,
default: 0.0,
min: -1.0,
max: 1.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
frequency: {
type: 'number' as const,
default: 50,
default: 30,
min: 0,
max: 100,
step: 0.1,
},
strength: {
type: 'number' as const,
default: 0.1,
default: 0.05,
min: 0,
max: 1,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
},
main: ({ gl, u, params }) => {
gl.uniform1f(u.phase, params.phase / 10);
gl.uniform1f(u.phase, params.phase);
gl.uniform1f(u.frequency, params.frequency);
gl.uniform1f(u.strength, params.strength);
gl.uniform1i(u.direction, params.direction);
@@ -90,6 +90,7 @@ export const FX_polkadot = defineImageEffectorFx({
min: -1.0,
max: 1.0,
step: 0.01,
toViewValue: v => Math.round(v * 90) + '°',
},
scale: {
type: 'number' as const,
@@ -111,6 +112,7 @@ export const FX_polkadot = defineImageEffectorFx({
min: 0.0,
max: 1.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
minorDivisions: {
type: 'number' as const,
@@ -132,6 +134,7 @@ export const FX_polkadot = defineImageEffectorFx({
min: 0.0,
max: 1.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
color: {
type: 'color' as const,
@@ -60,6 +60,7 @@ export const FX_stripe = defineImageEffectorFx({
min: -1.0,
max: 1.0,
step: 0.01,
toViewValue: v => Math.round(v * 90) + '°',
},
frequency: {
type: 'number' as const,
@@ -74,6 +75,7 @@ export const FX_stripe = defineImageEffectorFx({
min: 0.0,
max: 1.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
color: {
type: 'color' as const,
@@ -85,6 +87,7 @@ export const FX_stripe = defineImageEffectorFx({
min: 0.0,
max: 1.0,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
},
main: ({ gl, u, params }) => {
@@ -37,9 +37,9 @@ void main() {
}
`;
export const FX_glitch = defineImageEffectorFx({
id: 'glitch' as const,
name: i18n.ts._imageEffector._fxs.glitch,
export const FX_tearing = defineImageEffectorFx({
id: 'tearing' as const,
name: i18n.ts._imageEffector._fxs.glitch + ': ' + i18n.ts._imageEffector._fxs.tearing,
shader,
uniforms: ['amount', 'channelShift'] as const,
params: {
@@ -52,17 +52,19 @@ export const FX_glitch = defineImageEffectorFx({
},
strength: {
type: 'number' as const,
default: 5,
min: -100,
max: 100,
default: 0.05,
min: -1,
max: 1,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
size: {
type: 'number' as const,
default: 20,
default: 0.2,
min: 0,
max: 100,
max: 1,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
channelShift: {
type: 'number' as const,
@@ -70,6 +72,7 @@ export const FX_glitch = defineImageEffectorFx({
min: 0,
max: 10,
step: 0.01,
toViewValue: v => Math.round(v * 100) + '%',
},
seed: {
type: 'seed' as const,
@@ -87,10 +90,10 @@ export const FX_glitch = defineImageEffectorFx({
gl.uniform1f(o, rnd());
const s = gl.getUniformLocation(program, `u_shiftStrengths[${i.toString()}]`);
gl.uniform1f(s, (1 - (rnd() * 2)) * (params.strength / 100));
gl.uniform1f(s, (1 - (rnd() * 2)) * params.strength);
const h = gl.getUniformLocation(program, `u_shiftHeights[${i.toString()}]`);
gl.uniform1f(h, rnd() * (params.size / 100));
gl.uniform1f(h, rnd() * params.size);
}
},
});
+1 -1
View File
@@ -1,7 +1,7 @@
{
"type": "module",
"name": "misskey-js",
"version": "2025.6.1-beta.2",
"version": "2025.6.1",
"description": "Misskey SDK for JavaScript",
"license": "MIT",
"main": "./built/index.js",