diff options
| author | syuilo <4439005+syuilo@users.noreply.github.com> | 2025-10-24 10:41:55 +0900 |
|---|---|---|
| committer | syuilo <4439005+syuilo@users.noreply.github.com> | 2025-10-24 10:41:55 +0900 |
| commit | 2d1b7c957adcfe2e0d0c34f570e424a7d20a8787 (patch) | |
| tree | 538528e6ea38cb05d15bf8d79b49fdd1c107114b | |
| parent | Update about-misskey.vue (diff) | |
| parent | Bump version to 2025.10.1-beta.3 (diff) | |
| download | misskey-2d1b7c957adcfe2e0d0c34f570e424a7d20a8787.tar.gz misskey-2d1b7c957adcfe2e0d0c34f570e424a7d20a8787.tar.bz2 misskey-2d1b7c957adcfe2e0d0c34f570e424a7d20a8787.zip | |
Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | package.json | 2 | ||||
| -rw-r--r-- | packages/frontend-shared/js/emojilist.ts | 11 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkAnimBg.fragment.glsl | 111 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkAnimBg.vertex.glsl | 15 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkAnimBg.vue | 123 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkReactionsViewer.reaction.vue | 6 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkSuperMenu.vue | 4 | ||||
| -rw-r--r-- | packages/frontend/src/composables/use-uploader.ts | 4 | ||||
| -rw-r--r-- | packages/frontend/src/directives/appear.ts | 3 | ||||
| -rw-r--r-- | packages/frontend/src/directives/tooltip.ts | 5 | ||||
| -rw-r--r-- | packages/frontend/src/directives/user-preview.ts | 2 | ||||
| -rw-r--r-- | packages/frontend/src/type.ts | 8 | ||||
| -rw-r--r-- | packages/frontend/src/types/misc.ts | 6 | ||||
| -rw-r--r-- | packages/frontend/src/utility/snowfall-effect.fragment.glsl | 23 | ||||
| -rw-r--r-- | packages/frontend/src/utility/snowfall-effect.ts | 57 | ||||
| -rw-r--r-- | packages/frontend/src/utility/snowfall-effect.vertex.glsl | 37 | ||||
| -rw-r--r-- | packages/misskey-js/package.json | 2 |
18 files changed, 226 insertions, 194 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e0957a145..f503759432 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - ウォーターマークを回転させた際に画面からはみ出た部分を考慮できるように - Fix: 投票が終了した後に投票結果が正しく表示されない問題を修正 - Fix: ダークモードの同期が機能しない場合がある問題を修正 +- Fix: iOSで動画の圧縮を行うと音声トラックが失われる問題を修正 ### Server - Enhance: 管理者/モデレーターはファイルのアップロード制限をバイパスするように diff --git a/package.json b/package.json index abc399593c..251df75971 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2025.10.1-beta.2", + "version": "2025.10.1-beta.3", "codename": "nasubi", "repository": { "type": "git", diff --git a/packages/frontend-shared/js/emojilist.ts b/packages/frontend-shared/js/emojilist.ts index 09bea06719..20ddd0f7d7 100644 --- a/packages/frontend-shared/js/emojilist.ts +++ b/packages/frontend-shared/js/emojilist.ts @@ -39,13 +39,18 @@ for (let i = 0; i < emojilist.length; i++) { export const emojiCharByCategory = _charGroupByCategory; -export function getUnicodeEmoji(char: string): UnicodeEmojiDef | string { +export function getUnicodeEmojiOrNull(char: string): UnicodeEmojiDef | null { // Colorize it because emojilist.json assumes that return unicodeEmojisMap.get(colorizeEmoji(char)) // カラースタイル絵文字がjsonに無い場合はテキストスタイル絵文字にフォールバックする ?? unicodeEmojisMap.get(char) - // それでも見つからない場合はそのまま返す(絵文字情報がjsonに無い場合、このフォールバックが無いとレンダリングに失敗する) - ?? char; + // それでも見つからない場合はnullを返す + ?? null; +} + +export function getUnicodeEmoji(char: string): UnicodeEmojiDef | string { + // 絵文字が見つからない場合はそのまま返す(絵文字情報がjsonに無い場合、このフォールバックが無いとレンダリングに失敗する) + return getUnicodeEmojiOrNull(char) ?? char; } export function isSupportedEmoji(char: string): boolean { diff --git a/packages/frontend/src/components/MkAnimBg.fragment.glsl b/packages/frontend/src/components/MkAnimBg.fragment.glsl new file mode 100644 index 0000000000..d40872bb7a --- /dev/null +++ b/packages/frontend/src/components/MkAnimBg.fragment.glsl @@ -0,0 +1,111 @@ +#version 300 es +precision mediump float; + +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +vec3 mod289(vec3 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; +} + +vec2 mod289(vec2 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; +} + +vec3 permute(vec3 x) { + return mod289(((x*34.0)+1.0)*x); +} + +float snoise(vec2 v) { + const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439); + + vec2 i = floor(v + dot(v, C.yy)); + vec2 x0 = v - i + dot(i, C.xx); + + vec2 i1; + i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + vec4 x12 = x0.xyxy + C.xxzz; + x12.xy -= i1; + + i = mod289(i); + vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0)); + + vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0); + m = m*m; + m = m*m; + + vec3 x = 2.0 * fract(p * C.www) - 1.0; + vec3 h = abs(x) - 0.5; + vec3 ox = floor(x + 0.5); + vec3 a0 = x - ox; + + m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h); + + vec3 g; + g.x = a0.x * x0.x + h.x * x0.y; + g.yz = a0.yz * x12.xz + h.yz * x12.yw; + return 130.0 * dot(m, g); +} + +in vec2 in_uv; +uniform float u_time; +uniform vec2 u_resolution; +uniform float u_spread; +uniform float u_speed; +uniform float u_warp; +uniform float u_focus; +uniform float u_itensity; +out vec4 out_color; + +float circle(in vec2 _pos, in vec2 _origin, in float _radius) { + float SPREAD = 0.7 * u_spread; + float SPEED = 0.00055 * u_speed; + float WARP = 1.5 * u_warp; + float FOCUS = 1.15 * u_focus; + + vec2 dist = _pos - _origin; + + float distortion = snoise(vec2( + _pos.x * 1.587 * WARP + u_time * SPEED * 0.5, + _pos.y * 1.192 * WARP + u_time * SPEED * 0.3 + )) * 0.5 + 0.5; + + float feather = 0.01 + SPREAD * pow(distortion, FOCUS); + + return 1.0 - smoothstep( + _radius - (_radius * feather), + _radius + (_radius * feather), + dot( dist, dist ) * 4.0 + ); +} + +void main() { + vec3 green = vec3(1.0) - vec3(153.0 / 255.0, 211.0 / 255.0, 221.0 / 255.0); + vec3 purple = vec3(1.0) - vec3(195.0 / 255.0, 165.0 / 255.0, 242.0 / 255.0); + vec3 orange = vec3(1.0) - vec3(255.0 / 255.0, 156.0 / 255.0, 136.0 / 255.0); + + float ratio = u_resolution.x / u_resolution.y; + + vec2 uv = vec2(in_uv.x, in_uv.y / ratio) * 0.5 + 0.5; + + vec3 color = vec3(0.0); + + float greenMix = snoise(in_uv * 1.31 + u_time * 0.8 * 0.00017) * 0.5 + 0.5; + float purpleMix = snoise(in_uv * 1.26 + u_time * 0.8 * -0.0001) * 0.5 + 0.5; + float orangeMix = snoise(in_uv * 1.34 + u_time * 0.8 * 0.00015) * 0.5 + 0.5; + + float alphaOne = 0.35 + 0.65 * pow(snoise(vec2(u_time * 0.00012, uv.x)) * 0.5 + 0.5, 1.2); + float alphaTwo = 0.35 + 0.65 * pow(snoise(vec2((u_time + 1561.0) * 0.00014, uv.x )) * 0.5 + 0.5, 1.2); + float alphaThree = 0.35 + 0.65 * pow(snoise(vec2((u_time + 3917.0) * 0.00013, uv.x )) * 0.5 + 0.5, 1.2); + + color += vec3(circle(uv, vec2(0.22 + sin(u_time * 0.000201) * 0.06, 0.80 + cos(u_time * 0.000151) * 0.06), 0.15)) * alphaOne * (purple * purpleMix + orange * orangeMix); + color += vec3(circle(uv, vec2(0.90 + cos(u_time * 0.000166) * 0.06, 0.42 + sin(u_time * 0.000138) * 0.06), 0.18)) * alphaTwo * (green * greenMix + purple * purpleMix); + color += vec3(circle(uv, vec2(0.19 + sin(u_time * 0.000112) * 0.06, 0.25 + sin(u_time * 0.000192) * 0.06), 0.09)) * alphaThree * (orange * orangeMix); + + color *= u_itensity + 1.0 * pow(snoise(vec2(in_uv.y + u_time * 0.00013, in_uv.x + u_time * -0.00009)) * 0.5 + 0.5, 2.0); + + vec3 inverted = vec3(1.0) - color; + out_color = vec4(color, max(max(color.x, color.y), color.z)); +} diff --git a/packages/frontend/src/components/MkAnimBg.vertex.glsl b/packages/frontend/src/components/MkAnimBg.vertex.glsl new file mode 100644 index 0000000000..56d6b017b1 --- /dev/null +++ b/packages/frontend/src/components/MkAnimBg.vertex.glsl @@ -0,0 +1,15 @@ +#version 300 es + +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +in vec2 position; +uniform vec2 u_scale; +out vec2 in_uv; + +void main() { + gl_Position = vec4(position, 0.0, 1.0); + in_uv = position / u_scale; +} diff --git a/packages/frontend/src/components/MkAnimBg.vue b/packages/frontend/src/components/MkAnimBg.vue index 0e1018dcbf..bcdc604bb8 100644 --- a/packages/frontend/src/components/MkAnimBg.vue +++ b/packages/frontend/src/components/MkAnimBg.vue @@ -10,6 +10,8 @@ SPDX-License-Identifier: AGPL-3.0-only <script lang="ts" setup> import { onMounted, onUnmounted, useTemplateRef } from 'vue'; import isChromatic from 'chromatic/isChromatic'; +import vertexShaderSource from './MkAnimBg.vertex.glsl'; +import fragmentShaderSource from './MkAnimBg.fragment.glsl'; import { initShaderProgram } from '@/utility/webgl.js'; const canvasEl = useTemplateRef('canvasEl'); @@ -42,126 +44,7 @@ onMounted(() => { const positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); - const shaderProgram = initShaderProgram(gl, `#version 300 es - in vec2 position; - uniform vec2 u_scale; - out vec2 in_uv; - - void main() { - gl_Position = vec4(position, 0.0, 1.0); - in_uv = position / u_scale; - } - `, `#version 300 es - precision mediump float; - - vec3 mod289(vec3 x) { - return x - floor(x * (1.0 / 289.0)) * 289.0; - } - - vec2 mod289(vec2 x) { - return x - floor(x * (1.0 / 289.0)) * 289.0; - } - - vec3 permute(vec3 x) { - return mod289(((x*34.0)+1.0)*x); - } - - float snoise(vec2 v) { - const vec4 C = vec4(0.211324865405187, - 0.366025403784439, - -0.577350269189626, - 0.024390243902439); - - vec2 i = floor(v + dot(v, C.yy) ); - vec2 x0 = v - i + dot(i, C.xx); - - vec2 i1; - i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); - vec4 x12 = x0.xyxy + C.xxzz; - x12.xy -= i1; - - i = mod289(i); - vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) - + i.x + vec3(0.0, i1.x, 1.0 )); - - vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0); - m = m*m ; - m = m*m ; - - vec3 x = 2.0 * fract(p * C.www) - 1.0; - vec3 h = abs(x) - 0.5; - vec3 ox = floor(x + 0.5); - vec3 a0 = x - ox; - - m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); - - vec3 g; - g.x = a0.x * x0.x + h.x * x0.y; - g.yz = a0.yz * x12.xz + h.yz * x12.yw; - return 130.0 * dot(m, g); - } - - in vec2 in_uv; - uniform float u_time; - uniform vec2 u_resolution; - uniform float u_spread; - uniform float u_speed; - uniform float u_warp; - uniform float u_focus; - uniform float u_itensity; - out vec4 out_color; - - float circle( in vec2 _pos, in vec2 _origin, in float _radius ) { - float SPREAD = 0.7 * u_spread; - float SPEED = 0.00055 * u_speed; - float WARP = 1.5 * u_warp; - float FOCUS = 1.15 * u_focus; - - vec2 dist = _pos - _origin; - - float distortion = snoise( vec2( - _pos.x * 1.587 * WARP + u_time * SPEED * 0.5, - _pos.y * 1.192 * WARP + u_time * SPEED * 0.3 - ) ) * 0.5 + 0.5; - - float feather = 0.01 + SPREAD * pow( distortion, FOCUS ); - - return 1.0 - smoothstep( - _radius - ( _radius * feather ), - _radius + ( _radius * feather ), - dot( dist, dist ) * 4.0 - ); - } - - void main() { - vec3 green = vec3( 1.0 ) - vec3( 153.0 / 255.0, 211.0 / 255.0, 221.0 / 255.0 ); - vec3 purple = vec3( 1.0 ) - vec3( 195.0 / 255.0, 165.0 / 255.0, 242.0 / 255.0 ); - vec3 orange = vec3( 1.0 ) - vec3( 255.0 / 255.0, 156.0 / 255.0, 136.0 / 255.0 ); - - float ratio = u_resolution.x / u_resolution.y; - - vec2 uv = vec2( in_uv.x, in_uv.y / ratio ) * 0.5 + 0.5; - - vec3 color = vec3( 0.0 ); - - float greenMix = snoise( in_uv * 1.31 + u_time * 0.8 * 0.00017 ) * 0.5 + 0.5; - float purpleMix = snoise( in_uv * 1.26 + u_time * 0.8 * -0.0001 ) * 0.5 + 0.5; - float orangeMix = snoise( in_uv * 1.34 + u_time * 0.8 * 0.00015 ) * 0.5 + 0.5; - - float alphaOne = 0.35 + 0.65 * pow( snoise( vec2( u_time * 0.00012, uv.x ) ) * 0.5 + 0.5, 1.2 ); - float alphaTwo = 0.35 + 0.65 * pow( snoise( vec2( ( u_time + 1561.0 ) * 0.00014, uv.x ) ) * 0.5 + 0.5, 1.2 ); - float alphaThree = 0.35 + 0.65 * pow( snoise( vec2( ( u_time + 3917.0 ) * 0.00013, uv.x ) ) * 0.5 + 0.5, 1.2 ); - - color += vec3( circle( uv, vec2( 0.22 + sin( u_time * 0.000201 ) * 0.06, 0.80 + cos( u_time * 0.000151 ) * 0.06 ), 0.15 ) ) * alphaOne * ( purple * purpleMix + orange * orangeMix ); - color += vec3( circle( uv, vec2( 0.90 + cos( u_time * 0.000166 ) * 0.06, 0.42 + sin( u_time * 0.000138 ) * 0.06 ), 0.18 ) ) * alphaTwo * ( green * greenMix + purple * purpleMix ); - color += vec3( circle( uv, vec2( 0.19 + sin( u_time * 0.000112 ) * 0.06, 0.25 + sin( u_time * 0.000192 ) * 0.06 ), 0.09 ) ) * alphaThree * ( orange * orangeMix ); - - color *= u_itensity + 1.0 * pow( snoise( vec2( in_uv.y + u_time * 0.00013, in_uv.x + u_time * -0.00009 ) ) * 0.5 + 0.5, 2.0 ); - - vec3 inverted = vec3( 1.0 ) - color; - out_color = vec4(color, max(max(color.x, color.y), color.z)); - } - `); + const shaderProgram = initShaderProgram(gl, vertexShaderSource, fragmentShaderSource); if (shaderProgram == null) return; gl.useProgram(shaderProgram); diff --git a/packages/frontend/src/components/MkReactionsViewer.reaction.vue b/packages/frontend/src/components/MkReactionsViewer.reaction.vue index d96f0e2420..7c60288883 100644 --- a/packages/frontend/src/components/MkReactionsViewer.reaction.vue +++ b/packages/frontend/src/components/MkReactionsViewer.reaction.vue @@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only <script lang="ts" setup> import { computed, inject, onMounted, useTemplateRef, watch } from 'vue'; import * as Misskey from 'misskey-js'; -import { getUnicodeEmoji } from '@@/js/emojilist.js'; +import { getUnicodeEmojiOrNull } from '@@/js/emojilist.js'; import MkCustomEmojiDetailedDialog from './MkCustomEmojiDetailedDialog.vue'; import type { MenuItem } from '@/types/menu'; import XDetails from '@/components/MkReactionsViewer.details.vue'; @@ -60,11 +60,11 @@ const buttonEl = useTemplateRef('buttonEl'); const emojiName = computed(() => props.reaction.replace(/:/g, '').replace(/@\./, '')); const canToggle = computed(() => { - const emoji = customEmojisMap.get(emojiName.value) ?? getUnicodeEmoji(props.reaction); + const emoji = customEmojisMap.get(emojiName.value) ?? getUnicodeEmojiOrNull(props.reaction); // TODO //return !props.reaction.match(/@\w/) && $i && emoji && checkReactionPermissions($i, props.note, emoji); - return !props.reaction.match(/@\w/) && $i && emoji; + return props.reaction.match(/@\w/) == null && $i != null && emoji != null; }); const canGetInfo = computed(() => !props.reaction.match(/@\w/) && props.reaction.includes(':')); const isLocalCustomEmoji = props.reaction[0] === ':' && props.reaction.includes('@.'); diff --git a/packages/frontend/src/components/MkSuperMenu.vue b/packages/frontend/src/components/MkSuperMenu.vue index dbc673333c..236afa127c 100644 --- a/packages/frontend/src/components/MkSuperMenu.vue +++ b/packages/frontend/src/components/MkSuperMenu.vue @@ -64,6 +64,8 @@ SPDX-License-Identifier: AGPL-3.0-only </template> <script lang="ts"> +import type { Awaitable } from '@/types/misc.js'; + export type SuperMenuDef = { title?: string; items: ({ @@ -80,7 +82,7 @@ export type SuperMenuDef = { text: string; danger?: boolean; active?: boolean; - action: (ev: MouseEvent) => void | Promise<void>; + action: (ev: MouseEvent) => Awaitable<void>; } | { type?: 'link'; to: string; diff --git a/packages/frontend/src/composables/use-uploader.ts b/packages/frontend/src/composables/use-uploader.ts index 12b6e85940..e4aa1fda53 100644 --- a/packages/frontend/src/composables/use-uploader.ts +++ b/packages/frontend/src/composables/use-uploader.ts @@ -634,7 +634,9 @@ export function useUploader(options: { bitrate: item.compressionLevel === 1 ? mediabunny.QUALITY_VERY_HIGH : item.compressionLevel === 2 ? mediabunny.QUALITY_MEDIUM : mediabunny.QUALITY_VERY_LOW, }, audio: { - bitrate: item.compressionLevel === 1 ? mediabunny.QUALITY_VERY_HIGH : item.compressionLevel === 2 ? mediabunny.QUALITY_MEDIUM : mediabunny.QUALITY_VERY_LOW, + // Explicitly keep audio (don't discard) and copy it if possible + // without re-encoding to avoid WebCodecs limitations on iOS Safari + discard: false, }, }); diff --git a/packages/frontend/src/directives/appear.ts b/packages/frontend/src/directives/appear.ts index f714871420..117dc397da 100644 --- a/packages/frontend/src/directives/appear.ts +++ b/packages/frontend/src/directives/appear.ts @@ -5,6 +5,7 @@ import { throttle } from 'throttle-debounce'; import type { Directive } from 'vue'; +import type { Awaitable } from '@/types/misc.js'; interface HTMLElementWithObserver extends HTMLElement { _observer_?: IntersectionObserver; @@ -31,4 +32,4 @@ export const appearDirective = { unmounted(src) { if (src._observer_) src._observer_.disconnect(); }, -} as Directive<HTMLElementWithObserver, () => void>; +} as Directive<HTMLElementWithObserver, (() => Awaitable<void>) | null | undefined>; diff --git a/packages/frontend/src/directives/tooltip.ts b/packages/frontend/src/directives/tooltip.ts index 9cfa8d657d..8839d9a939 100644 --- a/packages/frontend/src/directives/tooltip.ts +++ b/packages/frontend/src/directives/tooltip.ts @@ -15,7 +15,7 @@ const start = isTouchUsing ? 'touchstart' : 'mouseenter'; const end = isTouchUsing ? 'touchend' : 'mouseleave'; type TooltipDirectiveState = { - text: string; + text: string | null | undefined; _close: null | (() => void); showTimer: number | null; hideTimer: number | null; @@ -53,6 +53,7 @@ export const tooltipDirective = { if (binding.arg === 'dialog') { el.addEventListener('click', (ev) => { + if (binding.value == null) return; ev.preventDefault(); ev.stopPropagation(); alert({ @@ -128,4 +129,4 @@ export const tooltipDirective = { if (self.checkTimer) window.clearTimeout(self.checkTimer); self.close(); }, -} as Directive<TooltipDirectiveElement, string, TooltipDirectiveModifiers, TooltipDirectiveArg>; +} as Directive<TooltipDirectiveElement, string | null | undefined, TooltipDirectiveModifiers, TooltipDirectiveArg>; diff --git a/packages/frontend/src/directives/user-preview.ts b/packages/frontend/src/directives/user-preview.ts index 76e345a108..f81f5dbef8 100644 --- a/packages/frontend/src/directives/user-preview.ts +++ b/packages/frontend/src/directives/user-preview.ts @@ -131,4 +131,4 @@ export const userPreviewDirective = { if (self == null) return; self.preview.detach(); }, -} as Directive<UserPreviewDirectiveElement, string | Misskey.entities.UserDetailed>; +} as Directive<UserPreviewDirectiveElement, string | Misskey.entities.UserDetailed | null | undefined>; diff --git a/packages/frontend/src/type.ts b/packages/frontend/src/type.ts deleted file mode 100644 index 5ff27158d2..0000000000 --- a/packages/frontend/src/type.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -export type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }; - -export type WithNonNullable<T, K extends keyof T> = T & { [P in K]-?: NonNullable<T[P]> }; diff --git a/packages/frontend/src/types/misc.ts b/packages/frontend/src/types/misc.ts new file mode 100644 index 0000000000..3ddd732531 --- /dev/null +++ b/packages/frontend/src/types/misc.ts @@ -0,0 +1,6 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export type Awaitable <T> = T | Promise<T>; diff --git a/packages/frontend/src/utility/snowfall-effect.fragment.glsl b/packages/frontend/src/utility/snowfall-effect.fragment.glsl new file mode 100644 index 0000000000..560af039e8 --- /dev/null +++ b/packages/frontend/src/utility/snowfall-effect.fragment.glsl @@ -0,0 +1,23 @@ +#version 300 es +precision mediump float; + +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +in vec4 v_color; +in float v_rotation; +uniform sampler2D u_texture; +out vec4 out_color; + +void main() { + vec2 rotated = vec2( + cos(v_rotation) * (gl_PointCoord.x - 0.5) + sin(v_rotation) * (gl_PointCoord.y - 0.5) + 0.5, + cos(v_rotation) * (gl_PointCoord.y - 0.5) - sin(v_rotation) * (gl_PointCoord.x - 0.5) + 0.5 + ); + + vec4 snowflake = texture(u_texture, rotated); + + out_color = vec4(snowflake.rgb * v_color.xyz, snowflake.a * v_color.a); +} diff --git a/packages/frontend/src/utility/snowfall-effect.ts b/packages/frontend/src/utility/snowfall-effect.ts index 65398e6a43..cefa720ebf 100644 --- a/packages/frontend/src/utility/snowfall-effect.ts +++ b/packages/frontend/src/utility/snowfall-effect.ts @@ -3,59 +3,12 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -export class SnowfallEffect { - private VERTEX_SOURCE = `#version 300 es - in vec4 a_position; - in vec4 a_color; - in vec3 a_rotation; - in vec3 a_speed; - in float a_size; - out vec4 v_color; - out float v_rotation; - uniform float u_time; - uniform mat4 u_projection; - uniform vec3 u_worldSize; - uniform float u_gravity; - uniform float u_wind; - uniform float u_spin_factor; - uniform float u_turbulence; - - void main() { - v_color = a_color; - v_rotation = a_rotation.x + (u_time * u_spin_factor) * a_rotation.y; - - vec3 pos = a_position.xyz; - - pos.x = mod(pos.x + u_time + u_wind * a_speed.x, u_worldSize.x * 2.0) - u_worldSize.x; - pos.y = mod(pos.y - u_time * a_speed.y * u_gravity, u_worldSize.y * 2.0) - u_worldSize.y; - - pos.x += sin(u_time * a_speed.z * u_turbulence) * a_rotation.z; - pos.z += cos(u_time * a_speed.z * u_turbulence) * a_rotation.z; - - gl_Position = u_projection * vec4(pos.xyz, a_position.w); - gl_PointSize = (a_size / gl_Position.w) * 100.0; - } - `; +import vertexSource from './snowfall-effect.vertex.glsl'; +import fragmentSource from './snowfall-effect.fragment.glsl'; - private FRAGMENT_SOURCE = `#version 300 es - precision mediump float; - - in vec4 v_color; - in float v_rotation; - uniform sampler2D u_texture; - out vec4 out_color; - - void main() { - vec2 rotated = vec2( - cos(v_rotation) * (gl_PointCoord.x - 0.5) + sin(v_rotation) * (gl_PointCoord.y - 0.5) + 0.5, - cos(v_rotation) * (gl_PointCoord.y - 0.5) - sin(v_rotation) * (gl_PointCoord.x - 0.5) + 0.5 - ); - - vec4 snowflake = texture(u_texture, rotated); - - out_color = vec4(snowflake.rgb * v_color.xyz, snowflake.a * v_color.a); - } - `; +export class SnowfallEffect { + private VERTEX_SOURCE = vertexSource; + private FRAGMENT_SOURCE = fragmentSource; private gl: WebGLRenderingContext; private program: WebGLProgram; diff --git a/packages/frontend/src/utility/snowfall-effect.vertex.glsl b/packages/frontend/src/utility/snowfall-effect.vertex.glsl new file mode 100644 index 0000000000..bfca1a76ee --- /dev/null +++ b/packages/frontend/src/utility/snowfall-effect.vertex.glsl @@ -0,0 +1,37 @@ +#version 300 es + +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +in vec4 a_position; +in vec4 a_color; +in vec3 a_rotation; +in vec3 a_speed; +in float a_size; +out vec4 v_color; +out float v_rotation; +uniform float u_time; +uniform mat4 u_projection; +uniform vec3 u_worldSize; +uniform float u_gravity; +uniform float u_wind; +uniform float u_spin_factor; +uniform float u_turbulence; + +void main() { + v_color = a_color; + v_rotation = a_rotation.x + (u_time * u_spin_factor) * a_rotation.y; + + vec3 pos = a_position.xyz; + + pos.x = mod(pos.x + u_time + u_wind * a_speed.x, u_worldSize.x * 2.0) - u_worldSize.x; + pos.y = mod(pos.y - u_time * a_speed.y * u_gravity, u_worldSize.y * 2.0) - u_worldSize.y; + + pos.x += sin(u_time * a_speed.z * u_turbulence) * a_rotation.z; + pos.z += cos(u_time * a_speed.z * u_turbulence) * a_rotation.z; + + gl_Position = u_projection * vec4(pos.xyz, a_position.w); + gl_PointSize = (a_size / gl_Position.w) * 100.0; +} diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index 6f067fbbc7..6af1945a31 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "misskey-js", - "version": "2025.10.1-beta.2", + "version": "2025.10.1-beta.3", "description": "Misskey SDK for JavaScript", "license": "MIT", "main": "./built/index.js", |