Compare commits

..

No commits in common. "7627017a42ea78f89da1aac2f7740b68961052eb" and "1ebd75ac10a0992cb7190c1d0fc3313dccfc0691" have entirely different histories.

53 changed files with 98 additions and 404 deletions

20
locales/index.d.ts vendored
View File

@ -12085,22 +12085,6 @@ export interface Locale extends ILocale {
* *
*/ */
"advanced": string; "advanced": string;
/**
*
*/
"stripe": string;
/**
*
*/
"stripeWidth": string;
/**
*
*/
"stripeFrequency": string;
/**
*
*/
"angle": string;
}; };
"_imageEffector": { "_imageEffector": {
/** /**
@ -12156,10 +12140,6 @@ export interface Locale extends ILocale {
* *
*/ */
"zoomLines": string; "zoomLines": string;
/**
*
*/
"stripe": string;
}; };
}; };
} }

View File

@ -3236,10 +3236,6 @@ _watermarkEditor:
type: "タイプ" type: "タイプ"
image: "画像" image: "画像"
advanced: "高度" advanced: "高度"
stripe: "ストライプ"
stripeWidth: "ラインの幅"
stripeFrequency: "ラインの数"
angle: "角度"
_imageEffector: _imageEffector:
title: "エフェクト" title: "エフェクト"
@ -3257,4 +3253,3 @@ _imageEffector:
distort: "歪み" distort: "歪み"
threshold: "二値化" threshold: "二値化"
zoomLines: "集中線" zoomLines: "集中線"
stripe: "ストライプ"

View File

@ -72,6 +72,7 @@
"tsc-alias": "1.8.16", "tsc-alias": "1.8.16",
"tsconfig-paths": "4.2.0", "tsconfig-paths": "4.2.0",
"typescript": "5.8.3", "typescript": "5.8.3",
"uuid": "11.1.0",
"v-code-diff": "1.13.1", "v-code-diff": "1.13.1",
"vite": "6.3.5", "vite": "6.3.5",
"vue": "3.5.16", "vue": "3.5.16",

View File

@ -4,7 +4,7 @@
*/ */
import { utils, values } from '@syuilo/aiscript'; import { utils, values } from '@syuilo/aiscript';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import { ref } from 'vue'; import { ref } from 'vue';
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
@ -543,7 +543,7 @@ export function registerAsUiLib(components: Ref<AsUiComponent>[], done: (root: R
call: C, call: C,
) { ) {
if (id) utils.assertString(id); if (id) utils.assertString(id);
const _id = id?.value ?? genId(); const _id = id?.value ?? uuid();
const component = ref({ const component = ref({
...getOptions(def, call), ...getOptions(def, call),
type, type,

View File

@ -64,7 +64,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkCustomEmoji v-if="!emoji.hasOwnProperty('char')" class="emoji" :name="getKey(emoji)" :normal="true"/> <MkCustomEmoji v-if="!emoji.hasOwnProperty('char')" class="emoji" :name="getKey(emoji)" :normal="true"/>
<MkEmoji v-else class="emoji" :emoji="getKey(emoji)" :normal="true"/> <MkEmoji v-else class="emoji" :emoji="getKey(emoji)" :normal="true"/>
</button> </button>
<button v-tooltip="i18n.ts.settings" class="_button config" @click="settings"><i class="ti ti-settings"></i></button>
</div> </div>
</section> </section>
@ -140,9 +139,6 @@ import { customEmojiCategories, customEmojis, customEmojisMap } from '@/custom-e
import { $i } from '@/i.js'; import { $i } from '@/i.js';
import { checkReactionPermissions } from '@/utility/check-reaction-permissions.js'; import { checkReactionPermissions } from '@/utility/check-reaction-permissions.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
import { useRouter } from '@/router.js';
const router = useRouter();
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
showPinned?: boolean; showPinned?: boolean;
@ -493,11 +489,6 @@ function done(query?: string): boolean | void {
} }
} }
function settings() {
emit('esc');
router.push('settings/emoji-palette');
}
onMounted(() => { onMounted(() => {
focus(); focus();
}); });
@ -729,15 +720,6 @@ defineExpose({
position: relative; position: relative;
padding: $pad; padding: $pad;
> .config {
position: relative;
padding: 0 3px;
width: var(--eachSize);
height: var(--eachSize);
contain: strict;
opacity: 0.5;
}
> .item { > .item {
position: relative; position: relative;
padding: 0 3px; padding: 0 3px;

View File

@ -38,6 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script setup lang="ts"> <script setup lang="ts">
import { ref, useTemplateRef, watch, onMounted, onUnmounted } from 'vue'; import { ref, useTemplateRef, watch, onMounted, onUnmounted } from 'vue';
import { v4 as uuid } from 'uuid';
import type { ImageEffectorLayer } from '@/utility/image-effector/ImageEffector.js'; import type { ImageEffectorLayer } from '@/utility/image-effector/ImageEffector.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { ImageEffector } from '@/utility/image-effector/ImageEffector.js'; import { ImageEffector } from '@/utility/image-effector/ImageEffector.js';

View File

@ -49,6 +49,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script setup lang="ts"> <script setup lang="ts">
import { ref, useTemplateRef, watch, onMounted, onUnmounted, reactive, nextTick } from 'vue'; import { ref, useTemplateRef, watch, onMounted, onUnmounted, reactive, nextTick } from 'vue';
import { v4 as uuid } from 'uuid';
import type { ImageEffectorLayer } from '@/utility/image-effector/ImageEffector.js'; import type { ImageEffectorLayer } from '@/utility/image-effector/ImageEffector.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { ImageEffector } from '@/utility/image-effector/ImageEffector.js'; import { ImageEffector } from '@/utility/image-effector/ImageEffector.js';
@ -60,7 +61,6 @@ import XLayer from '@/components/MkImageEffectorDialog.Layer.vue';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { deepClone } from '@/utility/clone.js'; import { deepClone } from '@/utility/clone.js';
import { FXS } from '@/utility/image-effector/fxs.js'; import { FXS } from '@/utility/image-effector/fxs.js';
import { genId } from '@/utility/id.js';
const props = defineProps<{ const props = defineProps<{
image: File; image: File;
@ -99,7 +99,7 @@ function addEffect(ev: MouseEvent) {
text: fx.name, text: fx.name,
action: () => { action: () => {
layers.push({ layers.push({
id: genId(), id: uuid(),
fxId: fx.id, fxId: fx.id,
params: Object.fromEntries(Object.entries(fx.params).map(([k, v]) => [k, v.default])), params: Object.fromEntries(Object.entries(fx.params).map(([k, v]) => [k, v.default])),
}); });

View File

@ -82,7 +82,7 @@ const canvasPromise = new Promise<WorkerMultiDispatch | HTMLCanvasElement>(resol
<script lang="ts" setup> <script lang="ts" setup>
import { computed, nextTick, onMounted, onUnmounted, useTemplateRef, watch, ref } from 'vue'; import { computed, nextTick, onMounted, onUnmounted, useTemplateRef, watch, ref } from 'vue';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import { render } from 'buraha'; import { render } from 'buraha';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
@ -117,7 +117,7 @@ const props = withDefaults(defineProps<{
onlyAvgColor: false, onlyAvgColor: false,
}); });
const viewId = genId(); const viewId = uuid();
const canvas = useTemplateRef('canvas'); const canvas = useTemplateRef('canvas');
const root = useTemplateRef('root'); const root = useTemplateRef('root');
const img = useTemplateRef('img'); const img = useTemplateRef('img');

View File

@ -52,7 +52,6 @@ import type { SuggestionType } from '@/utility/autocomplete.js';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { Autocomplete } from '@/utility/autocomplete.js'; import { Autocomplete } from '@/utility/autocomplete.js';
import { genId } from '@/utility/id.js';
const props = defineProps<{ const props = defineProps<{
modelValue: string | number | null; modelValue: string | number | null;
@ -88,7 +87,7 @@ const emit = defineEmits<{
const { modelValue, type, autofocus } = toRefs(props); const { modelValue, type, autofocus } = toRefs(props);
const v = ref(modelValue.value); const v = ref(modelValue.value);
const id = genId(); const id = Math.random().toString(); // TODO: uuid?
const focused = ref(false); const focused = ref(false);
const changed = ref(false); const changed = ref(false);
const invalid = ref(false); const invalid = ref(false);

View File

@ -32,7 +32,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { watch, ref } from 'vue'; import { watch, ref } from 'vue';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { useInterval } from '@@/js/use-interval.js'; import { useInterval } from '@@/js/use-interval.js';
@ -42,7 +42,7 @@ const props = defineProps<{
const viewBoxX = 50; const viewBoxX = 50;
const viewBoxY = 50; const viewBoxY = 50;
const gradientId = genId(); const gradientId = uuid();
const polylinePoints = ref(''); const polylinePoints = ref('');
const polygonPoints = ref(''); const polygonPoints = ref('');
const headX = ref<number | null>(null); const headX = ref<number | null>(null);

View File

@ -7,13 +7,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkModal ref="modal" :preferType="'dialog'" @click="onBgClick" @closed="emit('closed')" @esc="emit('esc')"> <MkModal ref="modal" :preferType="'dialog'" @click="onBgClick" @closed="emit('closed')" @esc="emit('esc')">
<div ref="rootEl" :class="$style.root" :style="{ width: `${width}px`, height: `min(${height}px, 100%)` }"> <div ref="rootEl" :class="$style.root" :style="{ width: `${width}px`, height: `min(${height}px, 100%)` }">
<div :class="$style.header"> <div :class="$style.header">
<button v-if="withCloseButton" :class="$style.headerButton" class="_button" data-cy-modal-window-close @click="emit('close')"><i class="ti ti-x"></i></button> <button v-if="withOkButton && withCloseButton" :class="$style.headerButton" class="_button" @click="emit('close')"><i class="ti ti-x"></i></button>
<span :class="$style.title"> <span :class="$style.title">
<slot name="header"></slot> <slot name="header"></slot>
</span> </span>
<div v-if="withOkButton" style="padding: 0 16px; place-content: center;"> <button v-if="!withOkButton && withCloseButton" :class="$style.headerButton" class="_button" data-cy-modal-window-close @click="emit('close')"><i class="ti ti-x"></i></button>
<MkButton primary gradate small rounded :disabled="okButtonDisabled" @click="emit('ok')">{{ i18n.ts.done }} <i class="ti ti-check"></i></MkButton> <button v-if="withOkButton" :class="$style.headerButton" class="_button" :disabled="okButtonDisabled" @click="emit('ok')"><i class="ti ti-check"></i></button>
</div>
</div> </div>
<div :class="$style.body"> <div :class="$style.body">
<slot></slot> <slot></slot>
@ -27,9 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, onUnmounted, useTemplateRef, ref } from 'vue'; import { onMounted, onUnmounted, useTemplateRef, ref } from 'vue';
import MkModal from '@/components/MkModal.vue'; import MkModal from './MkModal.vue';
import MkButton from '@/components/MkButton.vue';
import { i18n } from '@/i18n';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
withOkButton?: boolean; withOkButton?: boolean;

View File

@ -57,7 +57,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, onUnmounted, ref, useTemplateRef } from 'vue'; import { onMounted, onUnmounted, ref, useTemplateRef } from 'vue';
import { genId } from '@/utility/id.js';
const particles = ref<{ const particles = ref<{
id: string, id: string,
@ -87,7 +86,7 @@ onMounted(() => {
const y = (Math.random() * (height.value - 64)); const y = (Math.random() * (height.value - 64));
const sizeFactor = Math.random(); const sizeFactor = Math.random();
const particle = { const particle = {
id: genId(), id: Math.random().toString(),
x, x,
y, y,
size: 0.2 + ((sizeFactor / 10) * 3), size: 0.2 + ((sizeFactor / 10) * 3),

View File

@ -29,7 +29,6 @@ import { i18n } from '@/i18n.js';
import { globalEvents } from '@/events.js'; import { globalEvents } from '@/events.js';
import { $i } from '@/i.js'; import { $i } from '@/i.js';
import MkNote from '@/components/MkNote.vue'; import MkNote from '@/components/MkNote.vue';
import { genId } from '@/utility/id.js';
const props = defineProps<{ const props = defineProps<{
phase: 'aboutNote' | 'howToReact'; phase: 'aboutNote' | 'howToReact';
@ -84,7 +83,7 @@ function doNotification(emoji: string): void {
if (!$i || !emoji) return; if (!$i || !emoji) return;
const notification: Misskey.entities.Notification = { const notification: Misskey.entities.Notification = {
id: genId(), id: Math.random().toString(),
createdAt: new Date().toUTCString(), createdAt: new Date().toUTCString(),
type: 'reaction', type: 'reaction',
reaction: emoji, reaction: emoji,

View File

@ -82,7 +82,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { computed, defineAsyncComponent, markRaw, onMounted, onUnmounted, ref, triggerRef, useTemplateRef, watch } from 'vue'; import { computed, defineAsyncComponent, markRaw, onMounted, onUnmounted, ref, triggerRef, useTemplateRef, watch } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import { readAndCompressImage } from '@misskey-dev/browser-image-resizer'; import { readAndCompressImage } from '@misskey-dev/browser-image-resizer';
import isAnimated from 'is-file-animated'; import isAnimated from 'is-file-animated';
import type { MenuItem } from '@/types/menu.js'; import type { MenuItem } from '@/types/menu.js';
@ -576,7 +576,7 @@ async function preprocess(item: (typeof items)['value'][number]): Promise<void>
} }
function initializeFile(file: File) { function initializeFile(file: File) {
const id = genId(); const id = uuid();
const filename = file.name ?? 'untitled'; const filename = file.name ?? 'untitled';
const extension = filename.split('.').length > 1 ? '.' + filename.split('.').pop() : ''; const extension = filename.split('.').length > 1 ? '.' + filename.split('.').pop() : '';
const item = { const item = {

View File

@ -29,16 +29,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts._watermarkEditor.scale }}</template> <template #label>{{ i18n.ts._watermarkEditor.scale }}</template>
</MkRange> </MkRange>
<MkRange
v-model="layer.angle"
:min="-1"
:max="1"
:step="0.01"
continuousUpdate
>
<template #label>{{ i18n.ts._watermarkEditor.angle }}</template>
</MkRange>
<MkRange <MkRange
v-model="layer.opacity" v-model="layer.opacity"
:min="0" :min="0"
@ -76,16 +66,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts._watermarkEditor.scale }}</template> <template #label>{{ i18n.ts._watermarkEditor.scale }}</template>
</MkRange> </MkRange>
<MkRange
v-model="layer.angle"
:min="-1"
:max="1"
:step="0.01"
continuousUpdate
>
<template #label>{{ i18n.ts._watermarkEditor.angle }}</template>
</MkRange>
<MkRange <MkRange
v-model="layer.opacity" v-model="layer.opacity"
:min="0" :min="0"
@ -105,53 +85,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts._watermarkEditor.cover }}</template> <template #label>{{ i18n.ts._watermarkEditor.cover }}</template>
</MkSwitch> </MkSwitch>
</template> </template>
<template v-else-if="layer.type === 'stripe'">
<MkRange
v-model="layer.frequency"
:min="1"
:max="30"
:step="0.01"
continuousUpdate
>
<template #label>{{ i18n.ts._watermarkEditor.stripeFrequency }}</template>
</MkRange>
<MkRange
v-model="layer.threshold"
:min="0"
:max="1"
:step="0.01"
continuousUpdate
>
<template #label>{{ i18n.ts._watermarkEditor.stripeWidth }}</template>
</MkRange>
<MkRange
v-model="layer.angle"
:min="-1"
:max="1"
:step="0.01"
continuousUpdate
>
<template #label>{{ i18n.ts._watermarkEditor.angle }}</template>
</MkRange>
<MkRange
v-model="layer.opacity"
:min="0"
:max="1"
:step="0.01"
:textConverter="(v) => (v * 100).toFixed(1) + '%'"
continuousUpdate
>
<template #label>{{ i18n.ts._watermarkEditor.opacity }}</template>
</MkRange>
</template>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, useTemplateRef, watch, onMounted, onUnmounted } from 'vue'; import { ref, useTemplateRef, watch, onMounted, onUnmounted } from 'vue';
import { v4 as uuid } from 'uuid';
import type { ImageEffectorLayer } from '@/utility/image-effector/ImageEffector.js'; import type { ImageEffectorLayer } from '@/utility/image-effector/ImageEffector.js';
import type { WatermarkPreset } from '@/utility/watermark.js'; import type { WatermarkPreset } from '@/utility/watermark.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';

View File

@ -46,7 +46,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label> <template #label>
<div v-if="layer.type === 'text'">{{ i18n.ts._watermarkEditor.text }}</div> <div v-if="layer.type === 'text'">{{ i18n.ts._watermarkEditor.text }}</div>
<div v-if="layer.type === 'image'">{{ i18n.ts._watermarkEditor.image }}</div> <div v-if="layer.type === 'image'">{{ i18n.ts._watermarkEditor.image }}</div>
<div v-if="layer.type === 'stripe'">{{ i18n.ts._watermarkEditor.stripe }}</div>
</template> </template>
<template #footer> <template #footer>
<div class="_buttons"> <div class="_buttons">
@ -72,6 +71,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script setup lang="ts"> <script setup lang="ts">
import { ref, useTemplateRef, watch, onMounted, onUnmounted, reactive, nextTick } from 'vue'; import { ref, useTemplateRef, watch, onMounted, onUnmounted, reactive, nextTick } from 'vue';
import { v4 as uuid } from 'uuid';
import type { WatermarkPreset } from '@/utility/watermark.js'; import type { WatermarkPreset } from '@/utility/watermark.js';
import { WatermarkRenderer } from '@/utility/watermark.js'; import { WatermarkRenderer } from '@/utility/watermark.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
@ -83,18 +83,16 @@ import XLayer from '@/components/MkWatermarkEditorDialog.Layer.vue';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { deepClone } from '@/utility/clone.js'; import { deepClone } from '@/utility/clone.js';
import { ensureSignin } from '@/i.js'; import { ensureSignin } from '@/i.js';
import { genId } from '@/utility/id.js';
const $i = ensureSignin(); const $i = ensureSignin();
function createTextLayer(): WatermarkPreset['layers'][number] { function createTextLayer(): WatermarkPreset['layers'][number] {
return { return {
id: genId(), id: uuid(),
type: 'text', type: 'text',
text: `(c) @${$i.username}`, text: `(c) @${$i.username}`,
align: { x: 'right', y: 'bottom' }, align: { x: 'right', y: 'bottom' },
scale: 0.3, scale: 0.3,
angle: 0,
opacity: 0.75, opacity: 0.75,
repeat: false, repeat: false,
}; };
@ -102,38 +100,25 @@ function createTextLayer(): WatermarkPreset['layers'][number] {
function createImageLayer(): WatermarkPreset['layers'][number] { function createImageLayer(): WatermarkPreset['layers'][number] {
return { return {
id: genId(), id: uuid(),
type: 'image', type: 'image',
imageId: null, imageId: null,
imageUrl: null, imageUrl: null,
align: { x: 'right', y: 'bottom' }, align: { x: 'right', y: 'bottom' },
scale: 0.3, scale: 0.3,
angle: 0,
opacity: 0.75, opacity: 0.75,
repeat: false, repeat: false,
cover: false, cover: false,
}; };
} }
function createStripeLayer(): WatermarkPreset['layers'][number] {
return {
id: genId(),
type: 'stripe',
angle: 0.5,
frequency: 10,
threshold: 0.1,
black: false,
opacity: 0.75,
};
}
const props = defineProps<{ const props = defineProps<{
preset?: WatermarkPreset | null; preset?: WatermarkPreset | null;
image?: File | null; image?: File | null;
}>(); }>();
const preset = reactive<WatermarkPreset>(deepClone(props.preset) ?? { const preset = reactive<WatermarkPreset>(deepClone(props.preset) ?? {
id: genId(), id: uuid(),
name: '', name: '',
layers: [createTextLayer()], layers: [createTextLayer()],
}); });
@ -296,11 +281,6 @@ function addLayer(ev: MouseEvent) {
action: () => { action: () => {
preset.layers.push(createImageLayer()); preset.layers.push(createImageLayer());
}, },
}, {
text: i18n.ts._watermarkEditor.stripe,
action: () => {
preset.layers.push(createStripeLayer());
},
}], ev.currentTarget ?? ev.target); }], ev.currentTarget ?? ev.target);
} }

View File

@ -51,7 +51,7 @@ export type DefaultStoredWidget = {
<script lang="ts" setup> <script lang="ts" setup>
import { defineAsyncComponent, ref, computed } from 'vue'; import { defineAsyncComponent, ref, computed } from 'vue';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import MkSelect from '@/components/MkSelect.vue'; import MkSelect from '@/components/MkSelect.vue';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
import { widgets as widgetDefs, federationWidgets } from '@/widgets/index.js'; import { widgets as widgetDefs, federationWidgets } from '@/widgets/index.js';
@ -95,7 +95,7 @@ const addWidget = () => {
emit('addWidget', { emit('addWidget', {
name: widgetAdderSelected.value, name: widgetAdderSelected.value,
id: genId(), id: uuid(),
data: {}, data: {},
}); });

View File

@ -5,11 +5,11 @@
import { notificationTypes } from 'misskey-js'; import { notificationTypes } from 'misskey-js';
import { ref } from 'vue'; import { ref } from 'vue';
import { v4 as uuid } from 'uuid';
import { i18n } from './i18n.js'; import { i18n } from './i18n.js';
import type { BasicTimelineType } from '@/timelines.js'; import type { BasicTimelineType } from '@/timelines.js';
import type { SoundStore } from '@/preferences/def.js'; import type { SoundStore } from '@/preferences/def.js';
import type { MenuItem } from '@/types/menu.js'; import type { MenuItem } from '@/types/menu.js';
import { genId } from '@/utility/id.js';
import { deepClone } from '@/utility/clone.js'; import { deepClone } from '@/utility/clone.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
@ -103,7 +103,7 @@ function addProfile(name: string) {
if (prefer.s['deck.profiles'].find(p => p.name === name)) return; if (prefer.s['deck.profiles'].find(p => p.name === name)) return;
const newProfile: DeckProfile = { const newProfile: DeckProfile = {
id: genId(), id: uuid(),
name, name,
columns: [], columns: [],
layout: [], layout: [],

View File

@ -66,7 +66,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { computed, defineAsyncComponent, ref, watch } from 'vue'; import { computed, defineAsyncComponent, ref, watch } from 'vue';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import MkInput from '@/components/MkInput.vue'; import MkInput from '@/components/MkInput.vue';
import MkSelect from '@/components/MkSelect.vue'; import MkSelect from '@/components/MkSelect.vue';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
@ -104,7 +104,7 @@ const type = computed({
set: (t) => { set: (t) => {
if (t === 'and') v.value.values = []; if (t === 'and') v.value.values = [];
if (t === 'or') v.value.values = []; if (t === 'or') v.value.values = [];
if (t === 'not') v.value.value = { id: genId(), type: 'isRemote' }; if (t === 'not') v.value.value = { id: uuid(), type: 'isRemote' };
if (t === 'roleAssignedTo') v.value.roleId = ''; if (t === 'roleAssignedTo') v.value.roleId = '';
if (t === 'createdLessThan') v.value.sec = 86400; if (t === 'createdLessThan') v.value.sec = 86400;
if (t === 'createdMoreThan') v.value.sec = 86400; if (t === 'createdMoreThan') v.value.sec = 86400;
@ -119,7 +119,7 @@ const type = computed({
}); });
function addValue() { function addValue() {
v.value.values.push({ id: genId(), type: 'isRemote' }); v.value.values.push({ id: uuid(), type: 'isRemote' });
} }
function valuesItemUpdated(item) { function valuesItemUpdated(item) {

View File

@ -97,7 +97,6 @@ import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js'; import { definePage } from '@/page.js';
import MkFolder from '@/components/MkFolder.vue'; import MkFolder from '@/components/MkFolder.vue';
import MkTextarea from '@/components/MkTextarea.vue'; import MkTextarea from '@/components/MkTextarea.vue';
import { genId } from '@/utility/id.js';
const announcementsStatus = ref<'active' | 'archived'>('active'); const announcementsStatus = ref<'active' | 'archived'>('active');
@ -118,7 +117,7 @@ watch(announcementsStatus, (to) => {
function add() { function add() {
announcements.value.unshift({ announcements.value.unshift({
_id: genId(), _id: Math.random().toString(36),
id: null, id: null,
title: 'New announcement', title: 'New announcement',
text: '', text: '',

View File

@ -57,7 +57,6 @@ import { misskeyApi } from '@/utility/misskey-api.js';
import { useStream } from '@/stream.js'; import { useStream } from '@/stream.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import MkFolder from '@/components/MkFolder.vue'; import MkFolder from '@/components/MkFolder.vue';
import { genId } from '@/utility/id.js';
const connection = markRaw(useStream().useChannel('queueStats')); const connection = markRaw(useStream().useChannel('queueStats'));
@ -114,7 +113,7 @@ onMounted(() => {
connection.on('stats', onStats); connection.on('stats', onStats);
connection.on('statsLog', onStatsLog); connection.on('statsLog', onStatsLog);
connection.send('requestLog', { connection.send('requestLog', {
id: genId(), id: Math.random().toString().substring(2, 10),
length: 200, length: 200,
}); });
}); });

View File

@ -41,7 +41,6 @@ import XChart from './overview.queue.chart.vue';
import type { ApQueueDomain } from '@/pages/admin/queue.vue'; import type { ApQueueDomain } from '@/pages/admin/queue.vue';
import number from '@/filters/number.js'; import number from '@/filters/number.js';
import { useStream } from '@/stream.js'; import { useStream } from '@/stream.js';
import { genId } from '@/utility/id.js';
const connection = markRaw(useStream().useChannel('queueStats')); const connection = markRaw(useStream().useChannel('queueStats'));
@ -93,7 +92,7 @@ onMounted(() => {
connection.on('stats', onStats); connection.on('stats', onStats);
connection.on('statsLog', onStatsLog); connection.on('statsLog', onStatsLog);
connection.send('requestLog', { connection.send('requestLog', {
id: genId(), id: Math.random().toString().substring(2, 10),
length: 100, length: 100,
}); });
}); });

View File

@ -84,7 +84,6 @@ import { useStream } from '@/stream.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js'; import { definePage } from '@/page.js';
import MkFoldableSection from '@/components/MkFoldableSection.vue'; import MkFoldableSection from '@/components/MkFoldableSection.vue';
import { genId } from '@/utility/id.js';
const rootEl = useTemplateRef('rootEl'); const rootEl = useTemplateRef('rootEl');
const serverInfo = ref<Misskey.entities.ServerInfoResponse | null>(null); const serverInfo = ref<Misskey.entities.ServerInfoResponse | null>(null);
@ -171,7 +170,7 @@ onMounted(async () => {
nextTick(() => { nextTick(() => {
queueStatsConnection.send('requestLog', { queueStatsConnection.send('requestLog', {
id: genId(), id: Math.random().toString().substring(2, 10),
length: 100, length: 100,
}); });
}); });

View File

@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import XEditor from './roles.editor.vue'; import XEditor from './roles.editor.vue';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js'; import { misskeyApi } from '@/utility/misskey-api.js';
@ -55,7 +55,7 @@ if (props.id) {
color: null, color: null,
iconUrl: null, iconUrl: null,
target: 'manual', target: 'manual',
condFormula: { id: genId(), type: 'isRemote' }, condFormula: { id: uuid(), type: 'isRemote' },
isPublic: false, isPublic: false,
isExplorable: false, isExplorable: false,
asBadge: false, asBadge: false,

View File

@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { defineAsyncComponent, inject, onMounted, watch, ref } from 'vue'; import { defineAsyncComponent, inject, onMounted, watch, ref } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import XContainer from '../page-editor.container.vue'; import XContainer from '../page-editor.container.vue';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
@ -73,7 +73,7 @@ async function add() {
}); });
if (canceled) return; if (canceled) return;
const id = genId(); const id = uuid();
children.value.push({ id, type }); children.value.push({ id, type });
} }

View File

@ -62,7 +62,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { computed, provide, watch, ref } from 'vue'; import { computed, provide, watch, ref } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import { url } from '@@/js/config.js'; import { url } from '@@/js/config.js';
import XBlocks from './page-editor.blocks.vue'; import XBlocks from './page-editor.blocks.vue';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
@ -200,7 +200,7 @@ async function add() {
}); });
if (canceled) return; if (canceled) return;
const id = genId(); const id = uuid();
content.value.push({ id, type }); content.value.push({ id, type });
} }
@ -240,7 +240,7 @@ async function init() {
content.value = page.value.content; content.value = page.value.content;
eyeCatchingImageId.value = page.value.eyeCatchingImageId; eyeCatchingImageId.value = page.value.eyeCatchingImageId;
} else { } else {
const id = genId(); const id = uuid();
content.value = [{ content.value = [{
id, id,
type: 'text', type: 'text',

View File

@ -158,7 +158,6 @@ import { userPage } from '@/filters/user.js';
import * as sound from '@/utility/sound.js'; import * as sound from '@/utility/sound.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { confetti } from '@/utility/confetti.js'; import { confetti } from '@/utility/confetti.js';
import { genId } from '@/utility/id.js';
const $i = ensureSignin(); const $i = ensureSignin();
@ -274,7 +273,7 @@ function putStone(pos: number) {
playbackRate: 1, playbackRate: 1,
}); });
const id = genId(); const id = Math.random().toString(36).slice(2);
props.connection!.send('putStone', { props.connection!.send('putStone', {
pos: pos, pos: pos,
id, id,

View File

@ -119,7 +119,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import XPalette from './emoji-palette.palette.vue'; import XPalette from './emoji-palette.palette.vue';
import MkRadios from '@/components/MkRadios.vue'; import MkRadios from '@/components/MkRadios.vue';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
@ -159,7 +159,7 @@ function addPalette() {
prefer.commit('emojiPalettes', [ prefer.commit('emojiPalettes', [
...prefer.s.emojiPalettes, ...prefer.s.emojiPalettes,
{ {
id: genId(), id: uuid(),
name: '', name: '',
emojis: [], emojis: [],
}, },

View File

@ -70,12 +70,11 @@ import { definePage } from '@/page.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
import { PREF_DEF } from '@/preferences/def.js'; import { PREF_DEF } from '@/preferences/def.js';
import { getInitialPrefValue } from '@/preferences/manager.js'; import { getInitialPrefValue } from '@/preferences/manager.js';
import { genId } from '@/utility/id.js';
const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default)); const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default));
const items = ref(prefer.s.menu.map(x => ({ const items = ref(prefer.s.menu.map(x => ({
id: genId(), id: Math.random().toString(),
type: x, type: x,
}))); })));
@ -94,7 +93,7 @@ async function addItem() {
}); });
if (canceled) return; if (canceled) return;
items.value = [...items.value, { items.value = [...items.value, {
id: genId(), id: Math.random().toString(),
type: item, type: item,
}]; }];
} }
@ -109,7 +108,7 @@ async function save() {
function reset() { function reset() {
items.value = getInitialPrefValue('menu').map(x => ({ items.value = getInitialPrefValue('menu').map(x => ({
id: genId(), id: Math.random().toString(),
type: x, type: x,
})); }));
} }

View File

@ -796,7 +796,6 @@ import { globalEvents } from '@/events.js';
import { claimAchievement } from '@/utility/achievements.js'; import { claimAchievement } from '@/utility/achievements.js';
import { instance } from '@/instance.js'; import { instance } from '@/instance.js';
import { ensureSignin } from '@/i.js'; import { ensureSignin } from '@/i.js';
import { genId } from '@/utility/id.js';
const $i = ensureSignin(); const $i = ensureSignin();
@ -1010,7 +1009,7 @@ let smashTimer: number | null = null;
function testNotification(): void { function testNotification(): void {
const notification: Misskey.entities.Notification = { const notification: Misskey.entities.Notification = {
id: genId(), id: Math.random().toString(),
createdAt: new Date().toUTCString(), createdAt: new Date().toUTCString(),
isRead: false, isRead: false,
type: 'test', type: 'test',

View File

@ -171,7 +171,6 @@ import { claimAchievement } from '@/utility/achievements.js';
import { store } from '@/store.js'; import { store } from '@/store.js';
import MkInfo from '@/components/MkInfo.vue'; import MkInfo from '@/components/MkInfo.vue';
import MkTextarea from '@/components/MkTextarea.vue'; import MkTextarea from '@/components/MkTextarea.vue';
import { genId } from '@/utility/id.js';
const $i = ensureSignin(); const $i = ensureSignin();
@ -200,12 +199,12 @@ watch(() => profile, () => {
deep: true, deep: true,
}); });
const fields = ref($i.fields.map(field => ({ id: genId(), name: field.name, value: field.value })) ?? []); const fields = ref($i.fields.map(field => ({ id: Math.random().toString(), name: field.name, value: field.value })) ?? []);
const fieldEditMode = ref(false); const fieldEditMode = ref(false);
function addField() { function addField() {
fields.value.push({ fields.value.push({
id: genId(), id: Math.random().toString(),
name: '', name: '',
value: '', value: '',
}); });

View File

@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, ref, computed } from 'vue'; import { onMounted, ref, computed } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import XStatusbar from './statusbar.statusbar.vue'; import XStatusbar from './statusbar.statusbar.vue';
import MkFolder from '@/components/MkFolder.vue'; import MkFolder from '@/components/MkFolder.vue';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
@ -38,7 +38,7 @@ onMounted(() => {
async function add() { async function add() {
prefer.commit('statusbars', [...statusbars.value, { prefer.commit('statusbars', [...statusbars.value, {
id: genId(), id: uuid(),
type: null, type: null,
black: false, black: false,
size: 'medium', size: 'medium',

View File

@ -75,7 +75,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { watch, ref, computed } from 'vue'; import { watch, ref, computed } from 'vue';
import { toUnicode } from 'punycode.js'; import { toUnicode } from 'punycode.js';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import JSON5 from 'json5'; import JSON5 from 'json5';
import lightTheme from '@@/themes/_light.json5'; import lightTheme from '@@/themes/_light.json5';
import darkTheme from '@@/themes/_dark.json5'; import darkTheme from '@@/themes/_dark.json5';
@ -192,7 +192,7 @@ async function saveAs() {
}); });
if (canceled) return; if (canceled) return;
theme.value.id = genId(); theme.value.id = uuid();
theme.value.name = name; theme.value.name = name;
theme.value.author = `@${$i.username}@${toUnicode(host)}`; theme.value.author = `@${$i.username}@${toUnicode(host)}`;
if (description.value) theme.value.desc = description.value; if (description.value) theme.value.desc = description.value;

View File

@ -6,7 +6,7 @@
import { ref, defineAsyncComponent } from 'vue'; import { ref, defineAsyncComponent } from 'vue';
import { Interpreter, Parser, utils, values } from '@syuilo/aiscript'; import { Interpreter, Parser, utils, values } from '@syuilo/aiscript';
import { compareVersions } from 'compare-versions'; import { compareVersions } from 'compare-versions';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js'; import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js';
import { store } from '@/store.js'; import { store } from '@/store.js';
@ -135,7 +135,7 @@ export async function installPlugin(code: string, meta?: AiScriptPluginMeta) {
throw new Error('Plugin already installed'); throw new Error('Plugin already installed');
} }
const installId = genId(); const installId = uuid();
const plugin = { const plugin = {
...realMeta, ...realMeta,

View File

@ -3,8 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { v4 as uuid } from 'uuid';
import type { DeckProfile } from '@/deck.js'; import type { DeckProfile } from '@/deck.js';
import { genId } from '@/utility/id.js';
import { ColdDeviceStorage, store } from '@/store.js'; import { ColdDeviceStorage, store } from '@/store.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
import { misskeyApi } from '@/utility/misskey-api.js'; import { misskeyApi } from '@/utility/misskey-api.js';
@ -42,7 +42,7 @@ export function migrateOldSettings() {
key: key, key: key,
}); });
profiles.push({ profiles.push({
id: genId(), id: uuid(),
name: key, name: key,
columns: deck.columns, columns: deck.columns,
layout: deck.layout, layout: deck.layout,

View File

@ -5,6 +5,7 @@
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { hemisphere } from '@@/js/intl-const.js'; import { hemisphere } from '@@/js/intl-const.js';
import { v4 as uuid } from 'uuid';
import { definePreferences } from './manager.js'; import { definePreferences } from './manager.js';
import type { Theme } from '@/theme.js'; import type { Theme } from '@/theme.js';
import type { SoundType } from '@/utility/sound.js'; import type { SoundType } from '@/utility/sound.js';
@ -12,7 +13,6 @@ import type { Plugin } from '@/plugin.js';
import type { DeviceKind } from '@/utility/device-kind.js'; import type { DeviceKind } from '@/utility/device-kind.js';
import type { DeckProfile } from '@/deck.js'; import type { DeckProfile } from '@/deck.js';
import type { WatermarkPreset } from '@/utility/watermark.js'; import type { WatermarkPreset } from '@/utility/watermark.js';
import { genId } from '@/utility/id.js';
import { DEFAULT_DEVICE_KIND } from '@/utility/device-kind.js'; import { DEFAULT_DEVICE_KIND } from '@/utility/device-kind.js';
import { deepEqual } from '@/utility/deep-equal.js'; import { deepEqual } from '@/utility/deep-equal.js';
@ -54,13 +54,13 @@ export const PREF_DEF = definePreferences({
accountDependent: true, accountDependent: true,
default: () => [{ default: () => [{
name: 'calendar', name: 'calendar',
id: genId(), place: 'right', data: {}, id: uuid(), place: 'right', data: {},
}, { }, {
name: 'notifications', name: 'notifications',
id: genId(), place: 'right', data: {}, id: uuid(), place: 'right', data: {},
}, { }, {
name: 'trends', name: 'trends',
id: genId(), place: 'right', data: {}, id: uuid(), place: 'right', data: {},
}] as { }] as {
name: string; name: string;
id: string; id: string;
@ -80,7 +80,7 @@ export const PREF_DEF = definePreferences({
emojiPalettes: { emojiPalettes: {
serverDependent: true, serverDependent: true,
default: () => [{ default: () => [{
id: genId(), id: uuid(),
name: '', name: '',
emojis: ['👍', '❤️', '😆', '🤔', '😮', '🎉', '💢', '😥', '😇', '🍮'], emojis: ['👍', '❤️', '😆', '🤔', '😮', '🎉', '💢', '😥', '😇', '🍮'],
}] as { }] as {

View File

@ -4,11 +4,11 @@
*/ */
import { computed, onUnmounted, ref, watch } from 'vue'; import { computed, onUnmounted, ref, watch } from 'vue';
import { v4 as uuid } from 'uuid';
import { host, version } from '@@/js/config.js'; import { host, version } from '@@/js/config.js';
import { PREF_DEF } from './def.js'; import { PREF_DEF } from './def.js';
import type { Ref, WritableComputedRef } from 'vue'; import type { Ref, WritableComputedRef } from 'vue';
import type { MenuItem } from '@/types/menu.js'; import type { MenuItem } from '@/types/menu.js';
import { genId } from '@/utility/id.js';
import { $i } from '@/i.js'; import { $i } from '@/i.js';
import { copyToClipboard } from '@/utility/copy-to-clipboard.js'; import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
@ -301,7 +301,7 @@ export class PreferencesManager {
} }
} }
return { return {
id: genId(), id: uuid(),
version: version, version: version,
type: 'main', type: 'main',
modifiedAt: Date.now(), modifiedAt: Date.now(),

View File

@ -3,9 +3,9 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
// HMR有効時にバグか知らんけど複数回実行されるのでその対策 // HMR有効時にバグか知らんけど複数回実行されるのでその対策
export const TAB_ID = window.sessionStorage.getItem('TAB_ID') ?? genId(); export const TAB_ID = window.sessionStorage.getItem('TAB_ID') ?? uuid();
window.sessionStorage.setItem('TAB_ID', TAB_ID); window.sessionStorage.setItem('TAB_ID', TAB_ID);
if (_DEV_) console.log('TAB_ID', TAB_ID); if (_DEV_) console.log('TAB_ID', TAB_ID);

View File

@ -81,7 +81,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { defineAsyncComponent, ref, useTemplateRef } from 'vue'; import { defineAsyncComponent, ref, useTemplateRef } from 'vue';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import XCommon from './_common_/common.vue'; import XCommon from './_common_/common.vue';
import XSidebar from '@/ui/_common_/navbar.vue'; import XSidebar from '@/ui/_common_/navbar.vue';
import XNavbarH from '@/ui/_common_/navbar-h.vue'; import XNavbarH from '@/ui/_common_/navbar-h.vue';
@ -169,7 +169,7 @@ const addColumn = async (ev) => {
addColumnToStore({ addColumnToStore({
type: column, type: column,
id: genId(), id: uuid(),
name: null, name: null,
width: 330, width: 330,
soundSetting: { type: null, volume: 1 }, soundSetting: { type: null, volume: 1 },

View File

@ -15,7 +15,6 @@ import { $i } from '@/i.js';
import { instance } from '@/instance.js'; import { instance } from '@/instance.js';
import { globalEvents } from '@/events.js'; import { globalEvents } from '@/events.js';
import { getProxiedImageUrl } from '@/utility/media-proxy.js'; import { getProxiedImageUrl } from '@/utility/media-proxy.js';
import { genId } from '@/utility/id.js';
type UploadReturnType = { type UploadReturnType = {
filePromise: Promise<Misskey.entities.DriveFile>; filePromise: Promise<Misskey.entities.DriveFile>;
@ -196,7 +195,7 @@ export function chooseFileFromUrl(): Promise<Misskey.entities.DriveFile> {
}).then(({ canceled, result: url }) => { }).then(({ canceled, result: url }) => {
if (canceled) return; if (canceled) return;
const marker = genId(); const marker = Math.random().toString(); // TODO: UUIDとか使う
// TODO: no websocketモード対応 // TODO: no websocketモード対応
const connection = useStream().useChannel('main'); const connection = useStream().useChannel('main');

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { defineAsyncComponent } from 'vue'; import { defineAsyncComponent } from 'vue';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import { url } from '@@/js/config.js'; import { url } from '@@/js/config.js';
import { defaultEmbedParams, embedRouteWithScrollbar } from '@@/js/embed-page.js'; import { defaultEmbedParams, embedRouteWithScrollbar } from '@@/js/embed-page.js';
import type { EmbedParams, EmbeddableEntity } from '@@/js/embed-page.js'; import type { EmbedParams, EmbeddableEntity } from '@@/js/embed-page.js';
@ -44,7 +44,7 @@ export function normalizeEmbedParams(params: EmbedParams): Record<string, string
* iframe IDの発番もやる * iframe IDの発番もやる
*/ */
export function getEmbedCode(path: string, params?: EmbedParams): string { export function getEmbedCode(path: string, params?: EmbedParams): string {
const iframeId = 'v1_' + genId(); // 将来embed.jsのバージョンが上がったとき用にv1_を付けておく const iframeId = 'v1_' + uuid(); // 将来embed.jsのバージョンが上がったとき用にv1_を付けておく
let paramString = ''; let paramString = '';
if (params) { if (params) {

View File

@ -1,25 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
// ランダムな文字列が生成できればなんでも良い(時系列でソートできるなら尚良)が、とりあえずaidの実装を拝借
const TIME2000 = 946684800000;
let counter = Math.floor(Math.random() * 10000);
function getTime(time: number): string {
time = time - TIME2000;
if (time < 0) time = 0;
return time.toString(36).padStart(8, '0');
}
function getNoise(): string {
return counter.toString(36).padStart(2, '0').slice(-2);
}
export function genId(): string {
counter++;
return getTime(Date.now()) + getNoise();
}

View File

@ -11,7 +11,6 @@ import { FX_glitch } from './fxs/glitch.js';
import { FX_grayscale } from './fxs/grayscale.js'; import { FX_grayscale } from './fxs/grayscale.js';
import { FX_invert } from './fxs/invert.js'; import { FX_invert } from './fxs/invert.js';
import { FX_mirror } from './fxs/mirror.js'; import { FX_mirror } from './fxs/mirror.js';
import { FX_stripe } from './fxs/stripe.js';
import { FX_threshold } from './fxs/threshold.js'; import { FX_threshold } from './fxs/threshold.js';
import { FX_watermarkPlacement } from './fxs/watermarkPlacement.js'; import { FX_watermarkPlacement } from './fxs/watermarkPlacement.js';
import { FX_zoomLines } from './fxs/zoomLines.js'; import { FX_zoomLines } from './fxs/zoomLines.js';
@ -29,5 +28,4 @@ export const FXS = [
FX_distort, FX_distort,
FX_threshold, FX_threshold,
FX_zoomLines, FX_zoomLines,
FX_stripe,
] as const satisfies ImageEffectorFx<string, any>[]; ] as const satisfies ImageEffectorFx<string, any>[];

View File

@ -1,94 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { defineImageEffectorFx } from '../ImageEffector.js';
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;
uniform float u_angle;
uniform float u_frequency;
uniform float u_phase;
uniform float u_threshold;
uniform bool u_black;
uniform float u_opacity;
out vec4 out_color;
void main() {
vec4 in_color = texture(in_texture, in_uv);
float x_ratio = max(in_resolution.x / in_resolution.y, 1.0);
float y_ratio = max(in_resolution.y / in_resolution.x, 1.0);
float angle = u_angle * PI;
mat2 rotationMatrix = mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
vec2 rotatedUV = rotationMatrix * (vec2(in_uv.x * x_ratio, in_uv.y * y_ratio) - 0.5);
float phase = u_phase * TWO_PI;
float value = (1.0 + sin((rotatedUV.x * u_frequency - HALF_PI) + phase)) / 2.0;
value = value < u_threshold ? 1.0 : 0.0;
out_color = vec4(
mix(in_color.r, u_black ? 0.0 : 1.0, value * u_opacity),
mix(in_color.g, u_black ? 0.0 : 1.0, value * u_opacity),
mix(in_color.b, u_black ? 0.0 : 1.0, value * u_opacity),
in_color.a
);
}
`;
export const FX_stripe = defineImageEffectorFx({
id: 'stripe' as const,
name: i18n.ts._imageEffector._fxs.stripe,
shader,
uniforms: ['angle', 'frequency', 'phase', 'threshold', 'black', 'opacity'] as const,
params: {
angle: {
type: 'number' as const,
default: 0.5,
min: -1.0,
max: 1.0,
step: 0.01,
},
frequency: {
type: 'number' as const,
default: 10.0,
min: 1.0,
max: 30.0,
step: 0.1,
},
threshold: {
type: 'number' as const,
default: 0.1,
min: 0.0,
max: 1.0,
step: 0.01,
},
black: {
type: 'boolean' as const,
default: false,
},
opacity: {
type: 'number' as const,
default: 0.5,
min: 0.0,
max: 1.0,
step: 0.01,
},
},
main: ({ gl, u, params }) => {
gl.uniform1f(u.angle, params.angle / 2);
gl.uniform1f(u.frequency, params.frequency * params.frequency);
gl.uniform1f(u.phase, 0.0);
gl.uniform1f(u.threshold, params.threshold);
gl.uniform1i(u.black, params.black ? 1 : 0);
gl.uniform1f(u.opacity, params.opacity);
},
});

View File

@ -8,10 +8,6 @@ import { defineImageEffectorFx } from '../ImageEffector.js';
const shader = `#version 300 es const shader = `#version 300 es
precision mediump float; precision mediump float;
const float PI = 3.141592653589793;
const float TWO_PI = 6.283185307179586;
const float HALF_PI = 1.5707963267948966;
in vec2 in_uv; in vec2 in_uv;
uniform sampler2D in_texture; uniform sampler2D in_texture;
uniform vec2 in_resolution; uniform vec2 in_resolution;
@ -49,20 +45,9 @@ void main() {
float x_offset = u_alignX == 0 ? x_scale / 2.0 : u_alignX == 2 ? 1.0 - (x_scale / 2.0) : 0.5; float x_offset = u_alignX == 0 ? x_scale / 2.0 : u_alignX == 2 ? 1.0 - (x_scale / 2.0) : 0.5;
float y_offset = u_alignY == 0 ? y_scale / 2.0 : u_alignY == 2 ? 1.0 - (y_scale / 2.0) : 0.5; float y_offset = u_alignY == 0 ? y_scale / 2.0 : u_alignY == 2 ? 1.0 - (y_scale / 2.0) : 0.5;
float angle = -(u_angle * PI);
vec2 center = vec2(x_offset, y_offset);
vec2 centeredUv = in_uv - center;
float cosAngle = cos(angle);
float sinAngle = sin(angle);
vec2 rotatedUV = vec2(
centeredUv.x * cosAngle - centeredUv.y * sinAngle,
centeredUv.x * sinAngle + centeredUv.y * cosAngle
) + center;
// trim
if (!u_repeat) { if (!u_repeat) {
bool isInside = rotatedUV.x > x_offset - (x_scale / 2.0) && rotatedUV.x < x_offset + (x_scale / 2.0) && bool isInside = in_uv.x > x_offset - (x_scale / 2.0) && in_uv.x < x_offset + (x_scale / 2.0) &&
rotatedUV.y > y_offset - (y_scale / 2.0) && rotatedUV.y < y_offset + (y_scale / 2.0); in_uv.y > y_offset - (y_scale / 2.0) && in_uv.y < y_offset + (y_scale / 2.0);
if (!isInside) { if (!isInside) {
out_color = in_color; out_color = in_color;
return; return;
@ -70,8 +55,8 @@ void main() {
} }
vec4 watermark_color = texture(u_texture_watermark, vec2( vec4 watermark_color = texture(u_texture_watermark, vec2(
(rotatedUV.x - (x_offset - (x_scale / 2.0))) / x_scale, (in_uv.x - (x_offset - (x_scale / 2.0))) / x_scale,
(rotatedUV.y - (y_offset - (y_scale / 2.0))) / y_scale (in_uv.y - (y_offset - (y_scale / 2.0))) / y_scale
)); ));
out_color.r = mix(in_color.r, watermark_color.r, u_opacity * watermark_color.a); out_color.r = mix(in_color.r, watermark_color.r, u_opacity * watermark_color.a);
@ -102,13 +87,6 @@ export const FX_watermarkPlacement = defineImageEffectorFx({
max: 1.0, max: 1.0,
step: 0.01, step: 0.01,
}, },
angle: {
type: 'number' as const,
default: 0,
min: -1.0,
max: 1.0,
step: 0.01,
},
align: { align: {
type: 'align' as const, type: 'align' as const,
default: { x: 'right', y: 'bottom' }, default: { x: 'right', y: 'bottom' },
@ -136,9 +114,8 @@ export const FX_watermarkPlacement = defineImageEffectorFx({
gl.uniform2fv(u.resolution_watermark, [textures.watermark.width, textures.watermark.height]); gl.uniform2fv(u.resolution_watermark, [textures.watermark.width, textures.watermark.height]);
gl.uniform1f(u.scale, params.scale); gl.uniform1f(u.scale, params.scale);
gl.uniform1f(u.opacity, params.opacity); gl.uniform1f(u.opacity, params.opacity);
gl.uniform1f(u.angle, params.angle); gl.uniform1f(u.angle, 0.0);
gl.uniform1i(u.repeat, params.repeat ? 1 : 0); gl.uniform1i(u.repeat, params.repeat ? 1 : 0);
gl.uniform1i(u.alignX, params.align.x === 'left' ? 0 : params.align.x === 'right' ? 2 : 1); gl.uniform1i(u.alignX, params.align.x === 'left' ? 0 : params.align.x === 'right' ? 2 : 1);
gl.uniform1i(u.alignY, params.align.y === 'top' ? 0 : params.align.y === 'bottom' ? 2 : 1); gl.uniform1i(u.alignY, params.align.y === 'top' ? 0 : params.align.y === 'bottom' ? 2 : 1);

View File

@ -24,7 +24,7 @@ void main() {
vec4 in_color = texture(in_texture, in_uv); vec4 in_color = texture(in_texture, in_uv);
float angle = atan(-u_pos.y + (in_uv.y), -u_pos.x + (in_uv.x)); float angle = atan(-u_pos.y + (in_uv.y), -u_pos.x + (in_uv.x));
float t = (1.0 + sin(angle * u_frequency)) / 2.0; float t = (1.0 + sin(angle * u_frequency)) / 2.0;
if (u_thresholdEnabled) t = t < u_threshold ? 1.0 : 0.0; if (u_thresholdEnabled) t = t > u_threshold ? 1.0 : 0.0;
float d = distance(in_uv * vec2(2.0, 2.0), u_pos * vec2(2.0, 2.0)); float d = distance(in_uv * vec2(2.0, 2.0), u_pos * vec2(2.0, 2.0));
float mask = d < u_maskSize ? 0.0 : ((d - u_maskSize) * (1.0 + (u_maskSize * 2.0))); float mask = d < u_maskSize ? 0.0 : ((d - u_maskSize) * (1.0 + (u_maskSize * 2.0)));
out_color = vec4( out_color = vec4(
@ -69,7 +69,7 @@ export const FX_zoomLines = defineImageEffectorFx({
}, },
threshold: { threshold: {
type: 'number' as const, type: 'number' as const,
default: 0.2, default: 0.8,
min: 0.0, min: 0.0,
max: 1.0, max: 1.0,
step: 0.01, step: 0.01,

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
import type { Theme } from '@/theme.js'; import type { Theme } from '@/theme.js';
import { themeProps } from '@/theme.js'; import { themeProps } from '@/theme.js';
@ -66,7 +66,7 @@ export const convertToMisskeyTheme = (vm: ThemeViewModel, name: string, desc: st
} }
return { return {
id: genId(), id: uuid(),
name, desc, author, props, base, name, desc, author, props, base,
}; };
}; };

View File

@ -4,7 +4,6 @@
*/ */
import { FX_watermarkPlacement } from './image-effector/fxs/watermarkPlacement.js'; import { FX_watermarkPlacement } from './image-effector/fxs/watermarkPlacement.js';
import { FX_stripe } from './image-effector/fxs/stripe.js';
import type { ImageEffectorLayer } from '@/utility/image-effector/ImageEffector.js'; import type { ImageEffectorLayer } from '@/utility/image-effector/ImageEffector.js';
import { ImageEffector } from '@/utility/image-effector/ImageEffector.js'; import { ImageEffector } from '@/utility/image-effector/ImageEffector.js';
@ -17,7 +16,6 @@ export type WatermarkPreset = {
text: string; text: string;
repeat: boolean; repeat: boolean;
scale: number; scale: number;
angle: number;
align: { x: 'left' | 'center' | 'right'; y: 'top' | 'center' | 'bottom' }; align: { x: 'left' | 'center' | 'right'; y: 'top' | 'center' | 'bottom' };
opacity: number; opacity: number;
} | { } | {
@ -28,17 +26,8 @@ export type WatermarkPreset = {
cover: boolean; cover: boolean;
repeat: boolean; repeat: boolean;
scale: number; scale: number;
angle: number;
align: { x: 'left' | 'center' | 'right'; y: 'top' | 'center' | 'bottom' }; align: { x: 'left' | 'center' | 'right'; y: 'top' | 'center' | 'bottom' };
opacity: number; opacity: number;
} | {
id: string;
type: 'stripe';
angle: number;
frequency: number;
threshold: number;
black: boolean;
opacity: number;
})[]; })[];
}; };
@ -57,7 +46,7 @@ export class WatermarkRenderer {
renderWidth: options.renderWidth, renderWidth: options.renderWidth,
renderHeight: options.renderHeight, renderHeight: options.renderHeight,
image: options.image, image: options.image,
fxs: [FX_watermarkPlacement, FX_stripe], fxs: [FX_watermarkPlacement],
}); });
} }
@ -71,7 +60,6 @@ export class WatermarkRenderer {
repeat: layer.repeat, repeat: layer.repeat,
scale: layer.scale, scale: layer.scale,
align: layer.align, align: layer.align,
angle: layer.angle,
opacity: layer.opacity, opacity: layer.opacity,
cover: false, cover: false,
watermark: { watermark: {
@ -80,7 +68,7 @@ export class WatermarkRenderer {
}, },
}, },
}; };
} else if (layer.type === 'image') { } else {
return { return {
fxId: 'watermarkPlacement', fxId: 'watermarkPlacement',
id: layer.id, id: layer.id,
@ -88,7 +76,6 @@ export class WatermarkRenderer {
repeat: layer.repeat, repeat: layer.repeat,
scale: layer.scale, scale: layer.scale,
align: layer.align, align: layer.align,
angle: layer.angle,
opacity: layer.opacity, opacity: layer.opacity,
cover: layer.cover, cover: layer.cover,
watermark: { watermark: {
@ -97,18 +84,6 @@ export class WatermarkRenderer {
}, },
}, },
}; };
} else if (layer.type === 'stripe') {
return {
fxId: 'stripe',
id: layer.id,
params: {
angle: layer.angle,
frequency: layer.frequency,
threshold: layer.threshold,
black: layer.black,
opacity: layer.opacity,
},
};
} }
}); });
} }

View File

@ -29,7 +29,6 @@ import MkContainer from '@/components/MkContainer.vue';
import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js'; import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js';
import { $i } from '@/i.js'; import { $i } from '@/i.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { genId } from '@/utility/id.js';
const name = 'aiscript'; const name = 'aiscript';
@ -74,7 +73,7 @@ const run = async () => {
in: aiScriptReadline, in: aiScriptReadline,
out: (value) => { out: (value) => {
logs.value.push({ logs.value.push({
id: genId(), id: Math.random().toString(),
text: value.type === 'str' ? value.value : utils.valToString(value), text: value.type === 'str' ? value.value : utils.valToString(value),
print: true, print: true,
}); });
@ -82,7 +81,7 @@ const run = async () => {
log: (type, params) => { log: (type, params) => {
switch (type) { switch (type) {
case 'end': logs.value.push({ case 'end': logs.value.push({
id: genId(), id: Math.random().toString(),
text: utils.valToString(params.val, true), text: utils.valToString(params.val, true),
print: false, print: false,
}); break; }); break;

View File

@ -60,7 +60,6 @@ import kmg from '@/filters/kmg.js';
import * as sound from '@/utility/sound.js'; import * as sound from '@/utility/sound.js';
import { deepClone } from '@/utility/clone.js'; import { deepClone } from '@/utility/clone.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
import { genId } from '@/utility/id.js';
const name = 'jobQueue'; const name = 'jobQueue';
@ -145,7 +144,7 @@ connection.on('stats', onStats);
connection.on('statsLog', onStatsLog); connection.on('statsLog', onStatsLog);
connection.send('requestLog', { connection.send('requestLog', {
id: genId(), id: Math.random().toString().substring(2, 10),
length: 1, length: 1,
}); });

View File

@ -77,7 +77,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, onBeforeUnmount, ref } from 'vue'; import { onMounted, onBeforeUnmount, ref } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { genId } from '@/utility/id.js'; import { v4 as uuid } from 'uuid';
const props = defineProps<{ const props = defineProps<{
connection: Misskey.ChannelConnection<Misskey.Channels['serverStats']>, connection: Misskey.ChannelConnection<Misskey.Channels['serverStats']>,
@ -87,10 +87,10 @@ const props = defineProps<{
const viewBoxX = ref<number>(50); const viewBoxX = ref<number>(50);
const viewBoxY = ref<number>(30); const viewBoxY = ref<number>(30);
const stats = ref<Misskey.entities.ServerStats[]>([]); const stats = ref<Misskey.entities.ServerStats[]>([]);
const cpuGradientId = genId(); const cpuGradientId = uuid();
const cpuMaskId = genId(); const cpuMaskId = uuid();
const memGradientId = genId(); const memGradientId = uuid();
const memMaskId = genId(); const memMaskId = uuid();
const cpuPolylinePoints = ref<string>(''); const cpuPolylinePoints = ref<string>('');
const memPolylinePoints = ref<string>(''); const memPolylinePoints = ref<string>('');
const cpuPolygonPoints = ref<string>(''); const cpuPolygonPoints = ref<string>('');
@ -106,7 +106,7 @@ onMounted(() => {
props.connection.on('stats', onStats); props.connection.on('stats', onStats);
props.connection.on('statsLog', onStatsLog); props.connection.on('statsLog', onStatsLog);
props.connection.send('requestLog', { props.connection.send('requestLog', {
id: genId(), id: Math.random().toString().substring(2, 10),
length: 50, length: 50,
}); });
}); });

View File

@ -52,7 +52,6 @@ SPDX-License-Identifier: AGPL-3.0-only
import { onMounted, onBeforeUnmount, ref } from 'vue'; import { onMounted, onBeforeUnmount, ref } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import bytes from '@/filters/bytes.js'; import bytes from '@/filters/bytes.js';
import { genId } from '@/utility/id.js';
const props = defineProps<{ const props = defineProps<{
connection: Misskey.ChannelConnection<Misskey.Channels['serverStats']>, connection: Misskey.ChannelConnection<Misskey.Channels['serverStats']>,
@ -77,7 +76,7 @@ onMounted(() => {
props.connection.on('stats', onStats); props.connection.on('stats', onStats);
props.connection.on('statsLog', onStatsLog); props.connection.on('statsLog', onStatsLog);
props.connection.send('requestLog', { props.connection.send('requestLog', {
id: genId(), id: Math.random().toString().substring(2, 10),
length: 50, length: 50,
}); });
}); });

View File

@ -866,6 +866,9 @@ importers:
typescript: typescript:
specifier: 5.8.3 specifier: 5.8.3
version: 5.8.3 version: 5.8.3
uuid:
specifier: 11.1.0
version: 11.1.0
v-code-diff: v-code-diff:
specifier: 1.13.1 specifier: 1.13.1
version: 1.13.1(vue@3.5.16(typescript@5.8.3)) version: 1.13.1(vue@3.5.16(typescript@5.8.3))
@ -21865,7 +21868,7 @@ snapshots:
tsx@4.19.4: tsx@4.19.4:
dependencies: dependencies:
esbuild: 0.25.5 esbuild: 0.25.4
get-tsconfig: 4.10.1 get-tsconfig: 4.10.1
optionalDependencies: optionalDependencies:
fsevents: 2.3.3 fsevents: 2.3.3