summaryrefslogtreecommitdiff
path: root/packages/frontend/src/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src/scripts')
-rw-r--r--packages/frontend/src/scripts/aiscript/api.ts1
-rw-r--r--packages/frontend/src/scripts/aiscript/ui.ts2
-rw-r--r--packages/frontend/src/scripts/array.ts5
-rw-r--r--packages/frontend/src/scripts/autocomplete.ts26
-rw-r--r--packages/frontend/src/scripts/cache.ts12
-rw-r--r--packages/frontend/src/scripts/clone.ts2
-rw-r--r--packages/frontend/src/scripts/collapsed.ts19
-rw-r--r--packages/frontend/src/scripts/form.ts3
-rw-r--r--packages/frontend/src/scripts/gen-search-query.ts2
-rw-r--r--packages/frontend/src/scripts/get-drive-file-menu.ts29
-rw-r--r--packages/frontend/src/scripts/get-user-menu.ts46
-rw-r--r--packages/frontend/src/scripts/idle-render.ts17
-rw-r--r--packages/frontend/src/scripts/isFfVisibleForMe.ts11
-rw-r--r--packages/frontend/src/scripts/lookup.ts7
-rw-r--r--packages/frontend/src/scripts/sound.ts4
-rw-r--r--packages/frontend/src/scripts/theme-editor.ts2
-rw-r--r--packages/frontend/src/scripts/theme.ts4
-rw-r--r--packages/frontend/src/scripts/upload/compress-config.ts10
-rw-r--r--packages/frontend/src/scripts/upload/isWebpSupported.ts10
-rw-r--r--packages/frontend/src/scripts/url.ts2
-rw-r--r--packages/frontend/src/scripts/use-note-capture.ts4
21 files changed, 173 insertions, 45 deletions
diff --git a/packages/frontend/src/scripts/aiscript/api.ts b/packages/frontend/src/scripts/aiscript/api.ts
index b6b7445b67..5453fe827d 100644
--- a/packages/frontend/src/scripts/aiscript/api.ts
+++ b/packages/frontend/src/scripts/aiscript/api.ts
@@ -11,6 +11,7 @@ export function createAiScriptEnv(opts) {
USER_NAME: $i ? values.STR($i.name) : values.NULL,
USER_USERNAME: $i ? values.STR($i.username) : values.NULL,
CUSTOM_EMOJIS: utils.jsToVal(customEmojis.value),
+ CURRENT_URL: values.STR(window.location.href),
'Mk:dialog': values.FN_NATIVE(async ([title, text, type]) => {
await os.alert({
type: type ? type.value : 'info',
diff --git a/packages/frontend/src/scripts/aiscript/ui.ts b/packages/frontend/src/scripts/aiscript/ui.ts
index 2ca1b164ae..c26ae5a4df 100644
--- a/packages/frontend/src/scripts/aiscript/ui.ts
+++ b/packages/frontend/src/scripts/aiscript/ui.ts
@@ -510,7 +510,7 @@ export function registerAsUiLib(components: Ref<AsUiComponent>[], done: (root: R
// Ui:root.update({ children: [...] }) の糖衣構文
'Ui:render': values.FN_NATIVE(([children], opts) => {
utils.assertArray(children);
-
+
rootComponent.value.children = children.value.map(v => {
utils.assertObject(v);
return v.value.get('id').value;
diff --git a/packages/frontend/src/scripts/array.ts b/packages/frontend/src/scripts/array.ts
index 4620c8b735..c9a146e707 100644
--- a/packages/frontend/src/scripts/array.ts
+++ b/packages/frontend/src/scripts/array.ts
@@ -78,8 +78,9 @@ export function maximum(xs: number[]): number {
export function groupBy<T>(f: EndoRelation<T>, xs: T[]): T[][] {
const groups = [] as T[][];
for (const x of xs) {
- if (groups.length !== 0 && f(groups[groups.length - 1][0], x)) {
- groups[groups.length - 1].push(x);
+ const lastGroup = groups.at(-1);
+ if (lastGroup !== undefined && f(lastGroup[0], x)) {
+ lastGroup.push(x);
} else {
groups.push([x]);
}
diff --git a/packages/frontend/src/scripts/autocomplete.ts b/packages/frontend/src/scripts/autocomplete.ts
index 1bae3790f5..564573ae8a 100644
--- a/packages/frontend/src/scripts/autocomplete.ts
+++ b/packages/frontend/src/scripts/autocomplete.ts
@@ -65,7 +65,7 @@ export class Autocomplete {
*/
private onInput() {
const caretPos = this.textarea.selectionStart;
- const text = this.text.substr(0, caretPos).split('\n').pop()!;
+ const text = this.text.substring(0, caretPos).split('\n').pop()!;
const mentionIndex = text.lastIndexOf('@');
const hashtagIndex = text.lastIndexOf('#');
@@ -91,7 +91,7 @@ export class Autocomplete {
let opened = false;
if (isMention) {
- const username = text.substr(mentionIndex + 1);
+ const username = text.substring(mentionIndex + 1);
if (username !== '' && username.match(/^[a-zA-Z0-9_]+$/)) {
this.open('user', username);
opened = true;
@@ -102,7 +102,7 @@ export class Autocomplete {
}
if (isHashtag && !opened) {
- const hashtag = text.substr(hashtagIndex + 1);
+ const hashtag = text.substring(hashtagIndex + 1);
if (!hashtag.includes(' ')) {
this.open('hashtag', hashtag);
opened = true;
@@ -110,7 +110,7 @@ export class Autocomplete {
}
if (isEmoji && !opened) {
- const emoji = text.substr(emojiIndex + 1);
+ const emoji = text.substring(emojiIndex + 1);
if (!emoji.includes(' ')) {
this.open('emoji', emoji);
opened = true;
@@ -118,7 +118,7 @@ export class Autocomplete {
}
if (isMfmTag && !opened) {
- const mfmTag = text.substr(mfmTagIndex + 1);
+ const mfmTag = text.substring(mfmTagIndex + 1);
if (!mfmTag.includes(' ')) {
this.open('mfmTag', mfmTag.replace('[', ''));
opened = true;
@@ -208,9 +208,9 @@ export class Autocomplete {
if (type === 'user') {
const source = this.text;
- const before = source.substr(0, caret);
+ const before = source.substring(0, caret);
const trimmedBefore = before.substring(0, before.lastIndexOf('@'));
- const after = source.substr(caret);
+ const after = source.substring(caret);
const acct = value.host === null ? value.username : `${value.username}@${toASCII(value.host)}`;
@@ -226,9 +226,9 @@ export class Autocomplete {
} else if (type === 'hashtag') {
const source = this.text;
- const before = source.substr(0, caret);
+ const before = source.substring(0, caret);
const trimmedBefore = before.substring(0, before.lastIndexOf('#'));
- const after = source.substr(caret);
+ const after = source.substring(caret);
// 挿入
this.text = `${trimmedBefore}#${value} ${after}`;
@@ -242,9 +242,9 @@ export class Autocomplete {
} else if (type === 'emoji') {
const source = this.text;
- const before = source.substr(0, caret);
+ const before = source.substring(0, caret);
const trimmedBefore = before.substring(0, before.lastIndexOf(':'));
- const after = source.substr(caret);
+ const after = source.substring(caret);
// 挿入
this.text = trimmedBefore + value + after;
@@ -258,9 +258,9 @@ export class Autocomplete {
} else if (type === 'mfmTag') {
const source = this.text;
- const before = source.substr(0, caret);
+ const before = source.substring(0, caret);
const trimmedBefore = before.substring(0, before.lastIndexOf('$'));
- const after = source.substr(caret);
+ const after = source.substring(caret);
// 挿入
this.text = `${trimmedBefore}$[${value} ]${after}`;
diff --git a/packages/frontend/src/scripts/cache.ts b/packages/frontend/src/scripts/cache.ts
index 858e5f03bf..a61d858353 100644
--- a/packages/frontend/src/scripts/cache.ts
+++ b/packages/frontend/src/scripts/cache.ts
@@ -1,7 +1,8 @@
+import { ref } from "vue";
export class Cache<T> {
private cachedAt: number | null = null;
- private value: T | undefined;
+ public value = ref<T | undefined>();
private lifetime: number;
constructor(lifetime: Cache<never>['lifetime']) {
@@ -10,21 +11,20 @@ export class Cache<T> {
public set(value: T): void {
this.cachedAt = Date.now();
- this.value = value;
+ this.value.value = value;
}
- public get(): T | undefined {
+ private get(): T | undefined {
if (this.cachedAt == null) return undefined;
if ((Date.now() - this.cachedAt) > this.lifetime) {
- this.value = undefined;
+ this.value.value = undefined;
this.cachedAt = null;
return undefined;
}
- return this.value;
+ return this.value.value;
}
public delete() {
- this.value = undefined;
this.cachedAt = null;
}
diff --git a/packages/frontend/src/scripts/clone.ts b/packages/frontend/src/scripts/clone.ts
index 16fad24129..cf8fa64ba3 100644
--- a/packages/frontend/src/scripts/clone.ts
+++ b/packages/frontend/src/scripts/clone.ts
@@ -1,5 +1,7 @@
// structredCloneが遅いため
// SEE: http://var.blog.jp/archives/86038606.html
+// あと、Vue RefをIndexedDBに保存しようとしてstructredCloneを使ったらエラーになった
+// https://github.com/misskey-dev/misskey/pull/8098#issuecomment-1114144045
type Cloneable = string | number | boolean | null | { [key: string]: Cloneable } | Cloneable[];
diff --git a/packages/frontend/src/scripts/collapsed.ts b/packages/frontend/src/scripts/collapsed.ts
new file mode 100644
index 0000000000..1bf56f233b
--- /dev/null
+++ b/packages/frontend/src/scripts/collapsed.ts
@@ -0,0 +1,19 @@
+import * as mfm from 'mfm-js';
+import * as misskey from 'misskey-js';
+import { extractUrlFromMfm } from './extract-url-from-mfm';
+
+export function shouldCollapsed(note: misskey.entities.Note): boolean {
+ const urls = note.text ? extractUrlFromMfm(mfm.parse(note.text)) : null;
+ const collapsed = note.cw == null && note.text != null && (
+ (note.text.includes('$[x2')) ||
+ (note.text.includes('$[x3')) ||
+ (note.text.includes('$[x4')) ||
+ (note.text.includes('$[scale')) ||
+ (note.text.split('\n').length > 9) ||
+ (note.text.length > 500) ||
+ (note.files.length >= 5) ||
+ (!!urls && urls.length >= 4)
+ );
+
+ return collapsed;
+}
diff --git a/packages/frontend/src/scripts/form.ts b/packages/frontend/src/scripts/form.ts
index 7f321cc0ae..635803a2bc 100644
--- a/packages/frontend/src/scripts/form.ts
+++ b/packages/frontend/src/scripts/form.ts
@@ -1,3 +1,4 @@
+type EnumItem = string | {label: string; value: string;};
export type FormItem = {
label?: string;
type: 'string';
@@ -20,7 +21,7 @@ export type FormItem = {
type: 'enum';
default: string | null;
hidden?: boolean;
- enum: string[];
+ enum: EnumItem[];
} | {
label?: string;
type: 'radio';
diff --git a/packages/frontend/src/scripts/gen-search-query.ts b/packages/frontend/src/scripts/gen-search-query.ts
index da7d622632..956e0f35d0 100644
--- a/packages/frontend/src/scripts/gen-search-query.ts
+++ b/packages/frontend/src/scripts/gen-search-query.ts
@@ -5,7 +5,7 @@ export async function genSearchQuery(v: any, q: string) {
let host: string;
let userId: string;
if (q.split(' ').some(x => x.startsWith('@'))) {
- for (const at of q.split(' ').filter(x => x.startsWith('@')).map(x => x.substr(1))) {
+ for (const at of q.split(' ').filter(x => x.startsWith('@')).map(x => x.substring(1))) {
if (at.includes('.')) {
if (at === localHost || at === '.') {
host = null;
diff --git a/packages/frontend/src/scripts/get-drive-file-menu.ts b/packages/frontend/src/scripts/get-drive-file-menu.ts
index 060c8a1a11..9b488087e2 100644
--- a/packages/frontend/src/scripts/get-drive-file-menu.ts
+++ b/packages/frontend/src/scripts/get-drive-file-menu.ts
@@ -3,6 +3,8 @@ import { defineAsyncComponent } from 'vue';
import { i18n } from '@/i18n';
import copyToClipboard from '@/scripts/copy-to-clipboard';
import * as os from '@/os';
+import { MenuItem } from '@/types/menu';
+import { defaultStore } from '@/store';
function rename(file: Misskey.entities.DriveFile) {
os.inputText({
@@ -66,8 +68,10 @@ async function deleteFile(file: Misskey.entities.DriveFile) {
});
}
-export function getDriveFileMenu(file: Misskey.entities.DriveFile) {
- return [{
+export function getDriveFileMenu(file: Misskey.entities.DriveFile, folder?: Misskey.entities.DriveFolder | null): MenuItem[] {
+ const isImage = file.type.startsWith('image/');
+ let menu;
+ menu = [{
text: i18n.ts.rename,
icon: 'ti ti-forms',
action: () => rename(file),
@@ -79,7 +83,14 @@ export function getDriveFileMenu(file: Misskey.entities.DriveFile) {
text: i18n.ts.describeFile,
icon: 'ti ti-text-caption',
action: () => describe(file),
- }, null, {
+ }, ...isImage ? [{
+ text: i18n.ts.cropImage,
+ icon: 'ti ti-crop',
+ action: () => os.cropImage(file, {
+ aspectRatio: NaN,
+ uploadFolder: folder ? folder.id : folder
+ }),
+ }] : [], null, {
text: i18n.ts.createNoteFromTheFile,
icon: 'ti ti-pencil',
action: () => os.post({
@@ -102,4 +113,16 @@ export function getDriveFileMenu(file: Misskey.entities.DriveFile) {
danger: true,
action: () => deleteFile(file),
}];
+
+ if (defaultStore.state.devMode) {
+ menu = menu.concat([null, {
+ icon: 'ti ti-id',
+ text: i18n.ts.copyFileId,
+ action: () => {
+ copyToClipboard(file.id);
+ },
+ }]);
+ }
+
+ return menu;
}
diff --git a/packages/frontend/src/scripts/get-user-menu.ts b/packages/frontend/src/scripts/get-user-menu.ts
index b055d26473..1c93d58b44 100644
--- a/packages/frontend/src/scripts/get-user-menu.ts
+++ b/packages/frontend/src/scripts/get-user-menu.ts
@@ -1,14 +1,15 @@
+import { toUnicode } from 'punycode';
import { defineAsyncComponent } from 'vue';
import * as misskey from 'misskey-js';
import { i18n } from '@/i18n';
import copyToClipboard from '@/scripts/copy-to-clipboard';
-import { host } from '@/config';
+import { host, url } from '@/config';
import * as os from '@/os';
import { defaultStore, userActions } from '@/store';
import { $i, iAmModerator } from '@/account';
import { mainRouter } from '@/router';
import { Router } from '@/nirax';
-import { rolesCache, userListsCache } from '@/cache';
+import { antennasCache, rolesCache, userListsCache } from '@/cache';
export function getUserMenu(user: misskey.entities.UserDetailed, router: Router = mainRouter) {
const meId = $i ? $i.id : null;
@@ -138,6 +139,13 @@ export function getUserMenu(user: misskey.entities.UserDetailed, router: Router
copyToClipboard(`${user.host ?? host}/@${user.username}.atom`);
},
}, {
+ icon: 'ti ti-share',
+ text: i18n.ts.copyProfileUrl,
+ action: () => {
+ const canonical = user.host === null ? `@${user.username}` : `@${user.username}@${toUnicode(user.host)}`;
+ copyToClipboard(`${url}/${canonical}`);
+ },
+ }, {
icon: 'ti ti-mail',
text: i18n.ts.sendMessage,
action: () => {
@@ -158,11 +166,39 @@ export function getUserMenu(user: misskey.entities.UserDetailed, router: Router
return lists.map(list => ({
text: list.name,
- action: () => {
- os.apiWithDialog('users/lists/push', {
+ action: async () => {
+ await os.apiWithDialog('users/lists/push', {
listId: list.id,
userId: user.id,
});
+ userListsCache.delete();
+ },
+ }));
+ },
+ }, {
+ type: 'parent',
+ icon: 'ti ti-antenna',
+ text: i18n.ts.addToAntenna,
+ children: async () => {
+ const antennas = await antennasCache.fetch(() => os.api('antennas/list'));
+ const canonical = user.host === null ? `@${user.username}` : `@${user.username}@${toUnicode(user.host)}`;
+ return antennas.filter((a) => a.src === 'users').map(antenna => ({
+ text: antenna.name,
+ action: async () => {
+ await os.apiWithDialog('antennas/update', {
+ antennaId: antenna.id,
+ name: antenna.name,
+ keywords: antenna.keywords,
+ excludeKeywords: antenna.excludeKeywords,
+ src: antenna.src,
+ userListId: antenna.userListId,
+ users: [...antenna.users, canonical],
+ caseSensitive: antenna.caseSensitive,
+ withReplies: antenna.withReplies,
+ withFile: antenna.withFile,
+ notify: antenna.notify,
+ });
+ antennasCache.delete();
},
}));
},
@@ -196,7 +232,7 @@ export function getUserMenu(user: misskey.entities.UserDetailed, router: Router
default: 'indefinitely',
});
if (canceled) return;
-
+
const expiresAt = period === 'indefinitely' ? null
: period === 'oneHour' ? Date.now() + (1000 * 60 * 60)
: period === 'oneDay' ? Date.now() + (1000 * 60 * 60 * 24)
diff --git a/packages/frontend/src/scripts/idle-render.ts b/packages/frontend/src/scripts/idle-render.ts
index ccce8b02bf..a1470b82e9 100644
--- a/packages/frontend/src/scripts/idle-render.ts
+++ b/packages/frontend/src/scripts/idle-render.ts
@@ -1,3 +1,20 @@
+const requestIdleCallback: typeof globalThis.requestIdleCallback = globalThis.requestIdleCallback ?? ((callback) => {
+ const start = performance.now();
+ const timeoutId = setTimeout(() => {
+ callback({
+ didTimeout: false, // polyfill でタイムアウト発火することはない
+ timeRemaining() {
+ const diff = performance.now() - start;
+ return Math.max(0, 50 - diff); // <https://www.w3.org/TR/requestidlecallback/#idle-periods>
+ },
+ });
+ });
+ return timeoutId;
+});
+const cancelIdleCallback: typeof globalThis.cancelIdleCallback = globalThis.cancelIdleCallback ?? ((timeoutId) => {
+ clearTimeout(timeoutId);
+});
+
class IdlingRenderScheduler {
#renderers: Set<FrameRequestCallback>;
#rafId: number;
diff --git a/packages/frontend/src/scripts/isFfVisibleForMe.ts b/packages/frontend/src/scripts/isFfVisibleForMe.ts
new file mode 100644
index 0000000000..0ddd3f377d
--- /dev/null
+++ b/packages/frontend/src/scripts/isFfVisibleForMe.ts
@@ -0,0 +1,11 @@
+import * as misskey from 'misskey-js';
+import { $i } from '@/account';
+
+export function isFfVisibleForMe(user: misskey.entities.UserDetailed): boolean {
+ if ($i && $i.id === user.id) return true;
+
+ if (user.ffVisibility === 'private') return false;
+ if (user.ffVisibility === 'followers' && !user.isFollowing) return false;
+
+ return true;
+}
diff --git a/packages/frontend/src/scripts/lookup.ts b/packages/frontend/src/scripts/lookup.ts
index ce5b03fc38..3f357a3c92 100644
--- a/packages/frontend/src/scripts/lookup.ts
+++ b/packages/frontend/src/scripts/lookup.ts
@@ -6,18 +6,19 @@ import { Router } from '@/nirax';
export async function lookup(router?: Router) {
const _router = router ?? mainRouter;
- const { canceled, result: query } = await os.inputText({
+ const { canceled, result: temp } = await os.inputText({
title: i18n.ts.lookup,
});
+ const query = temp ? temp.trim() : '';
if (canceled) return;
-
+
if (query.startsWith('@') && !query.includes(' ')) {
_router.push(`/${query}`);
return;
}
if (query.startsWith('#')) {
- _router.push(`/tags/${encodeURIComponent(query.substr(1))}`);
+ _router.push(`/tags/${encodeURIComponent(query.substring(1))}`);
return;
}
diff --git a/packages/frontend/src/scripts/sound.ts b/packages/frontend/src/scripts/sound.ts
index 7a5dd4dbfa..68136cdcfe 100644
--- a/packages/frontend/src/scripts/sound.ts
+++ b/packages/frontend/src/scripts/sound.ts
@@ -132,9 +132,7 @@ export function play(type: 'noteMy' | 'note' | 'antenna' | 'channel' | 'notifica
}
export function playFile(file: string, volume: number) {
- const masterVolume = soundConfigStore.state.sound_masterVolume;
- if (masterVolume === 0) return;
-
const audio = setVolume(getAudio(file), volume);
+ if (audio.volume === 0) return;
audio.play();
}
diff --git a/packages/frontend/src/scripts/theme-editor.ts b/packages/frontend/src/scripts/theme-editor.ts
index 944875ff15..001d87381c 100644
--- a/packages/frontend/src/scripts/theme-editor.ts
+++ b/packages/frontend/src/scripts/theme-editor.ts
@@ -35,7 +35,7 @@ export const fromThemeString = (str?: string) : ThemeValue => {
} else if (str.startsWith('"')) {
return {
type: 'css',
- value: str.substr(1).trim(),
+ value: str.substring(1).trim(),
};
} else {
return str;
diff --git a/packages/frontend/src/scripts/theme.ts b/packages/frontend/src/scripts/theme.ts
index f2e8253565..bc61256cac 100644
--- a/packages/frontend/src/scripts/theme.ts
+++ b/packages/frontend/src/scripts/theme.ts
@@ -98,7 +98,7 @@ function compile(theme: Theme): Record<string, string> {
function getColor(val: string): tinycolor.Instance {
// ref (prop)
if (val[0] === '@') {
- return getColor(theme.props[val.substr(1)]);
+ return getColor(theme.props[val.substring(1)]);
}
// ref (const)
@@ -109,7 +109,7 @@ function compile(theme: Theme): Record<string, string> {
// func
else if (val[0] === ':') {
const parts = val.split('<');
- const func = parts.shift().substr(1);
+ const func = parts.shift().substring(1);
const arg = parseFloat(parts.shift());
const color = getColor(parts.join('<'));
diff --git a/packages/frontend/src/scripts/upload/compress-config.ts b/packages/frontend/src/scripts/upload/compress-config.ts
index 793c78ad20..55d469c5e4 100644
--- a/packages/frontend/src/scripts/upload/compress-config.ts
+++ b/packages/frontend/src/scripts/upload/compress-config.ts
@@ -1,7 +1,15 @@
import isAnimated from 'is-file-animated';
+import { isWebpSupported } from './isWebpSupported';
import type { BrowserImageResizerConfig } from 'browser-image-resizer';
const compressTypeMap = {
+ 'image/jpeg': { quality: 0.90, mimeType: 'image/webp' },
+ 'image/png': { quality: 1, mimeType: 'image/webp' },
+ 'image/webp': { quality: 0.90, mimeType: 'image/webp' },
+ 'image/svg+xml': { quality: 1, mimeType: 'image/webp' },
+} as const;
+
+const compressTypeMapFallback = {
'image/jpeg': { quality: 0.85, mimeType: 'image/jpeg' },
'image/png': { quality: 1, mimeType: 'image/png' },
'image/webp': { quality: 0.85, mimeType: 'image/jpeg' },
@@ -9,7 +17,7 @@ const compressTypeMap = {
} as const;
export async function getCompressionConfig(file: File): Promise<BrowserImageResizerConfig | undefined> {
- const imgConfig = compressTypeMap[file.type];
+ const imgConfig = (isWebpSupported() ? compressTypeMap : compressTypeMapFallback)[file.type];
if (!imgConfig || await isAnimated(file)) {
return;
}
diff --git a/packages/frontend/src/scripts/upload/isWebpSupported.ts b/packages/frontend/src/scripts/upload/isWebpSupported.ts
new file mode 100644
index 0000000000..cde8b9d785
--- /dev/null
+++ b/packages/frontend/src/scripts/upload/isWebpSupported.ts
@@ -0,0 +1,10 @@
+let isWebpSupportedCache: boolean | undefined;
+export function isWebpSupported() {
+ if (isWebpSupportedCache === undefined) {
+ const canvas = document.createElement('canvas');
+ canvas.width = 1;
+ canvas.height = 1;
+ isWebpSupportedCache = canvas.toDataURL('image/webp').startsWith('data:image/webp');
+ }
+ return isWebpSupportedCache;
+}
diff --git a/packages/frontend/src/scripts/url.ts b/packages/frontend/src/scripts/url.ts
index b6a997449a..07737d6228 100644
--- a/packages/frontend/src/scripts/url.ts
+++ b/packages/frontend/src/scripts/url.ts
@@ -2,7 +2,7 @@
* 1. 配列に何も入っていない時はクエリを付けない
* 2. プロパティがundefinedの時はクエリを付けない
* (new URLSearchParams(obj)ではそこまで丁寧なことをしてくれない)
- */
+ */
export function query(obj: Record<string, any>): string {
const params = Object.entries(obj)
.filter(([, v]) => Array.isArray(v) ? v.length : v !== undefined)
diff --git a/packages/frontend/src/scripts/use-note-capture.ts b/packages/frontend/src/scripts/use-note-capture.ts
index 22a01e066a..d057386b13 100644
--- a/packages/frontend/src/scripts/use-note-capture.ts
+++ b/packages/frontend/src/scripts/use-note-capture.ts
@@ -93,12 +93,12 @@ export function useNoteCapture(props: {
function onStreamConnected() {
capture(false);
}
-
+
capture(true);
if (connection) {
connection.on('_connected_', onStreamConnected);
}
-
+
onUnmounted(() => {
decapture(true);
if (connection) {