Compare commits
11 Commits
1ebd75ac10
...
7627017a42
Author | SHA1 | Date |
---|---|---|
|
7627017a42 | |
|
a2e391d6e4 | |
|
1f4170c259 | |
|
62bd14ef88 | |
|
26215b7466 | |
|
17b7067f9b | |
|
0a0247a678 | |
|
c701016989 | |
|
5342b024b2 | |
|
93d17aff6c | |
|
3bc81522c6 |
|
@ -12085,6 +12085,22 @@ export interface Locale extends ILocale {
|
||||||
* 高度
|
* 高度
|
||||||
*/
|
*/
|
||||||
"advanced": string;
|
"advanced": string;
|
||||||
|
/**
|
||||||
|
* ストライプ
|
||||||
|
*/
|
||||||
|
"stripe": string;
|
||||||
|
/**
|
||||||
|
* ラインの幅
|
||||||
|
*/
|
||||||
|
"stripeWidth": string;
|
||||||
|
/**
|
||||||
|
* ラインの数
|
||||||
|
*/
|
||||||
|
"stripeFrequency": string;
|
||||||
|
/**
|
||||||
|
* 角度
|
||||||
|
*/
|
||||||
|
"angle": string;
|
||||||
};
|
};
|
||||||
"_imageEffector": {
|
"_imageEffector": {
|
||||||
/**
|
/**
|
||||||
|
@ -12140,6 +12156,10 @@ export interface Locale extends ILocale {
|
||||||
* 集中線
|
* 集中線
|
||||||
*/
|
*/
|
||||||
"zoomLines": string;
|
"zoomLines": string;
|
||||||
|
/**
|
||||||
|
* ストライプ
|
||||||
|
*/
|
||||||
|
"stripe": string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -3236,6 +3236,10 @@ _watermarkEditor:
|
||||||
type: "タイプ"
|
type: "タイプ"
|
||||||
image: "画像"
|
image: "画像"
|
||||||
advanced: "高度"
|
advanced: "高度"
|
||||||
|
stripe: "ストライプ"
|
||||||
|
stripeWidth: "ラインの幅"
|
||||||
|
stripeFrequency: "ラインの数"
|
||||||
|
angle: "角度"
|
||||||
|
|
||||||
_imageEffector:
|
_imageEffector:
|
||||||
title: "エフェクト"
|
title: "エフェクト"
|
||||||
|
@ -3253,3 +3257,4 @@ _imageEffector:
|
||||||
distort: "歪み"
|
distort: "歪み"
|
||||||
threshold: "二値化"
|
threshold: "二値化"
|
||||||
zoomLines: "集中線"
|
zoomLines: "集中線"
|
||||||
|
stripe: "ストライプ"
|
||||||
|
|
|
@ -72,7 +72,6 @@
|
||||||
"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",
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { utils, values } from '@syuilo/aiscript';
|
import { utils, values } from '@syuilo/aiscript';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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 ?? uuid();
|
const _id = id?.value ?? genId();
|
||||||
const component = ref({
|
const component = ref({
|
||||||
...getOptions(def, call),
|
...getOptions(def, call),
|
||||||
type,
|
type,
|
||||||
|
|
|
@ -64,6 +64,7 @@ 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>
|
||||||
|
|
||||||
|
@ -139,6 +140,9 @@ 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;
|
||||||
|
@ -489,6 +493,11 @@ function done(query?: string): boolean | void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function settings() {
|
||||||
|
emit('esc');
|
||||||
|
router.push('settings/emoji-palette');
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
focus();
|
focus();
|
||||||
});
|
});
|
||||||
|
@ -720,6 +729,15 @@ 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;
|
||||||
|
|
|
@ -38,7 +38,6 @@ 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';
|
||||||
|
|
|
@ -49,7 +49,6 @@ 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';
|
||||||
|
@ -61,6 +60,7 @@ 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: uuid(),
|
id: genId(),
|
||||||
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])),
|
||||||
});
|
});
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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 = uuid();
|
const viewId = genId();
|
||||||
const canvas = useTemplateRef('canvas');
|
const canvas = useTemplateRef('canvas');
|
||||||
const root = useTemplateRef('root');
|
const root = useTemplateRef('root');
|
||||||
const img = useTemplateRef('img');
|
const img = useTemplateRef('img');
|
||||||
|
|
|
@ -52,6 +52,7 @@ 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;
|
||||||
|
@ -87,7 +88,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 = Math.random().toString(); // TODO: uuid?
|
const id = genId();
|
||||||
const focused = ref(false);
|
const focused = ref(false);
|
||||||
const changed = ref(false);
|
const changed = ref(false);
|
||||||
const invalid = ref(false);
|
const invalid = ref(false);
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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 = uuid();
|
const gradientId = genId();
|
||||||
const polylinePoints = ref('');
|
const polylinePoints = ref('');
|
||||||
const polygonPoints = ref('');
|
const polygonPoints = ref('');
|
||||||
const headX = ref<number | null>(null);
|
const headX = ref<number | null>(null);
|
||||||
|
|
|
@ -7,12 +7,13 @@ 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="withOkButton && withCloseButton" :class="$style.headerButton" class="_button" @click="emit('close')"><i class="ti ti-x"></i></button>
|
<button v-if="withCloseButton" :class="$style.headerButton" class="_button" data-cy-modal-window-close @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>
|
||||||
<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>
|
<div v-if="withOkButton" style="padding: 0 16px; place-content: center;">
|
||||||
<button v-if="withOkButton" :class="$style.headerButton" class="_button" :disabled="okButtonDisabled" @click="emit('ok')"><i class="ti ti-check"></i></button>
|
<MkButton primary gradate small rounded :disabled="okButtonDisabled" @click="emit('ok')">{{ i18n.ts.done }} <i class="ti ti-check"></i></MkButton>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.body">
|
<div :class="$style.body">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
@ -26,7 +27,9 @@ 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 './MkModal.vue';
|
import MkModal from '@/components/MkModal.vue';
|
||||||
|
import MkButton from '@/components/MkButton.vue';
|
||||||
|
import { i18n } from '@/i18n';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
withOkButton?: boolean;
|
withOkButton?: boolean;
|
||||||
|
|
|
@ -57,6 +57,7 @@ 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,
|
||||||
|
@ -86,7 +87,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: Math.random().toString(),
|
id: genId(),
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
size: 0.2 + ((sizeFactor / 10) * 3),
|
size: 0.2 + ((sizeFactor / 10) * 3),
|
||||||
|
|
|
@ -29,6 +29,7 @@ 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';
|
||||||
|
@ -83,7 +84,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: Math.random().toString(),
|
id: genId(),
|
||||||
createdAt: new Date().toUTCString(),
|
createdAt: new Date().toUTCString(),
|
||||||
type: 'reaction',
|
type: 'reaction',
|
||||||
reaction: emoji,
|
reaction: emoji,
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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 = uuid();
|
const id = genId();
|
||||||
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 = {
|
||||||
|
|
|
@ -29,6 +29,16 @@ 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"
|
||||||
|
@ -66,6 +76,16 @@ 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"
|
||||||
|
@ -85,12 +105,53 @@ 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';
|
||||||
|
|
|
@ -46,6 +46,7 @@ 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">
|
||||||
|
@ -71,7 +72,6 @@ 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,16 +83,18 @@ 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: uuid(),
|
id: genId(),
|
||||||
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,
|
||||||
};
|
};
|
||||||
|
@ -100,25 +102,38 @@ function createTextLayer(): WatermarkPreset['layers'][number] {
|
||||||
|
|
||||||
function createImageLayer(): WatermarkPreset['layers'][number] {
|
function createImageLayer(): WatermarkPreset['layers'][number] {
|
||||||
return {
|
return {
|
||||||
id: uuid(),
|
id: genId(),
|
||||||
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: uuid(),
|
id: genId(),
|
||||||
name: '',
|
name: '',
|
||||||
layers: [createTextLayer()],
|
layers: [createTextLayer()],
|
||||||
});
|
});
|
||||||
|
@ -281,6 +296,11 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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: uuid(),
|
id: genId(),
|
||||||
data: {},
|
data: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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: uuid(),
|
id: genId(),
|
||||||
name,
|
name,
|
||||||
columns: [],
|
columns: [],
|
||||||
layout: [],
|
layout: [],
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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: uuid(), type: 'isRemote' };
|
if (t === 'not') v.value.value = { id: genId(), 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: uuid(), type: 'isRemote' });
|
v.value.values.push({ id: genId(), type: 'isRemote' });
|
||||||
}
|
}
|
||||||
|
|
||||||
function valuesItemUpdated(item) {
|
function valuesItemUpdated(item) {
|
||||||
|
|
|
@ -97,6 +97,7 @@ 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');
|
||||||
|
|
||||||
|
@ -117,7 +118,7 @@ watch(announcementsStatus, (to) => {
|
||||||
|
|
||||||
function add() {
|
function add() {
|
||||||
announcements.value.unshift({
|
announcements.value.unshift({
|
||||||
_id: Math.random().toString(36),
|
_id: genId(),
|
||||||
id: null,
|
id: null,
|
||||||
title: 'New announcement',
|
title: 'New announcement',
|
||||||
text: '',
|
text: '',
|
||||||
|
|
|
@ -57,6 +57,7 @@ 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'));
|
||||||
|
|
||||||
|
@ -113,7 +114,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: Math.random().toString().substring(2, 10),
|
id: genId(),
|
||||||
length: 200,
|
length: 200,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -41,6 +41,7 @@ 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'));
|
||||||
|
|
||||||
|
@ -92,7 +93,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: Math.random().toString().substring(2, 10),
|
id: genId(),
|
||||||
length: 100,
|
length: 100,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -84,6 +84,7 @@ 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);
|
||||||
|
@ -170,7 +171,7 @@ onMounted(async () => {
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
queueStatsConnection.send('requestLog', {
|
queueStatsConnection.send('requestLog', {
|
||||||
id: Math.random().toString().substring(2, 10),
|
id: genId(),
|
||||||
length: 100,
|
length: 100,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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: uuid(), type: 'isRemote' },
|
condFormula: { id: genId(), type: 'isRemote' },
|
||||||
isPublic: false,
|
isPublic: false,
|
||||||
isExplorable: false,
|
isExplorable: false,
|
||||||
asBadge: false,
|
asBadge: false,
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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 = uuid();
|
const id = genId();
|
||||||
children.value.push({ id, type });
|
children.value.push({ id, type });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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 = uuid();
|
const id = genId();
|
||||||
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 = uuid();
|
const id = genId();
|
||||||
content.value = [{
|
content.value = [{
|
||||||
id,
|
id,
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
|
|
@ -158,6 +158,7 @@ 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();
|
||||||
|
|
||||||
|
@ -273,7 +274,7 @@ function putStone(pos: number) {
|
||||||
playbackRate: 1,
|
playbackRate: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
const id = Math.random().toString(36).slice(2);
|
const id = genId();
|
||||||
props.connection!.send('putStone', {
|
props.connection!.send('putStone', {
|
||||||
pos: pos,
|
pos: pos,
|
||||||
id,
|
id,
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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: uuid(),
|
id: genId(),
|
||||||
name: '',
|
name: '',
|
||||||
emojis: [],
|
emojis: [],
|
||||||
},
|
},
|
||||||
|
|
|
@ -70,11 +70,12 @@ 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: Math.random().toString(),
|
id: genId(),
|
||||||
type: x,
|
type: x,
|
||||||
})));
|
})));
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ async function addItem() {
|
||||||
});
|
});
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
items.value = [...items.value, {
|
items.value = [...items.value, {
|
||||||
id: Math.random().toString(),
|
id: genId(),
|
||||||
type: item,
|
type: item,
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
@ -108,7 +109,7 @@ async function save() {
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
items.value = getInitialPrefValue('menu').map(x => ({
|
items.value = getInitialPrefValue('menu').map(x => ({
|
||||||
id: Math.random().toString(),
|
id: genId(),
|
||||||
type: x,
|
type: x,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -796,6 +796,7 @@ 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();
|
||||||
|
|
||||||
|
@ -1009,7 +1010,7 @@ let smashTimer: number | null = null;
|
||||||
|
|
||||||
function testNotification(): void {
|
function testNotification(): void {
|
||||||
const notification: Misskey.entities.Notification = {
|
const notification: Misskey.entities.Notification = {
|
||||||
id: Math.random().toString(),
|
id: genId(),
|
||||||
createdAt: new Date().toUTCString(),
|
createdAt: new Date().toUTCString(),
|
||||||
isRead: false,
|
isRead: false,
|
||||||
type: 'test',
|
type: 'test',
|
||||||
|
|
|
@ -171,6 +171,7 @@ 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();
|
||||||
|
|
||||||
|
@ -199,12 +200,12 @@ watch(() => profile, () => {
|
||||||
deep: true,
|
deep: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const fields = ref($i.fields.map(field => ({ id: Math.random().toString(), name: field.name, value: field.value })) ?? []);
|
const fields = ref($i.fields.map(field => ({ id: genId(), 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: Math.random().toString(),
|
id: genId(),
|
||||||
name: '',
|
name: '',
|
||||||
value: '',
|
value: '',
|
||||||
});
|
});
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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: uuid(),
|
id: genId(),
|
||||||
type: null,
|
type: null,
|
||||||
black: false,
|
black: false,
|
||||||
size: 'medium',
|
size: 'medium',
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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 = uuid();
|
theme.value.id = genId();
|
||||||
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;
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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 = uuid();
|
const installId = genId();
|
||||||
|
|
||||||
const plugin = {
|
const plugin = {
|
||||||
...realMeta,
|
...realMeta,
|
||||||
|
|
|
@ -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: uuid(),
|
id: genId(),
|
||||||
name: key,
|
name: key,
|
||||||
columns: deck.columns,
|
columns: deck.columns,
|
||||||
layout: deck.layout,
|
layout: deck.layout,
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
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';
|
||||||
|
@ -13,6 +12,7 @@ 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: uuid(), place: 'right', data: {},
|
id: genId(), place: 'right', data: {},
|
||||||
}, {
|
}, {
|
||||||
name: 'notifications',
|
name: 'notifications',
|
||||||
id: uuid(), place: 'right', data: {},
|
id: genId(), place: 'right', data: {},
|
||||||
}, {
|
}, {
|
||||||
name: 'trends',
|
name: 'trends',
|
||||||
id: uuid(), place: 'right', data: {},
|
id: genId(), 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: uuid(),
|
id: genId(),
|
||||||
name: '',
|
name: '',
|
||||||
emojis: ['👍', '❤️', '😆', '🤔', '😮', '🎉', '💢', '😥', '😇', '🍮'],
|
emojis: ['👍', '❤️', '😆', '🤔', '😮', '🎉', '💢', '😥', '😇', '🍮'],
|
||||||
}] as {
|
}] as {
|
||||||
|
|
|
@ -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: uuid(),
|
id: genId(),
|
||||||
version: version,
|
version: version,
|
||||||
type: 'main',
|
type: 'main',
|
||||||
modifiedAt: Date.now(),
|
modifiedAt: Date.now(),
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
|
|
||||||
// HMR有効時にバグか知らんけど複数回実行されるのでその対策
|
// HMR有効時にバグか知らんけど複数回実行されるのでその対策
|
||||||
export const TAB_ID = window.sessionStorage.getItem('TAB_ID') ?? uuid();
|
export const TAB_ID = window.sessionStorage.getItem('TAB_ID') ?? genId();
|
||||||
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);
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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: uuid(),
|
id: genId(),
|
||||||
name: null,
|
name: null,
|
||||||
width: 330,
|
width: 330,
|
||||||
soundSetting: { type: null, volume: 1 },
|
soundSetting: { type: null, volume: 1 },
|
||||||
|
|
|
@ -15,6 +15,7 @@ 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>;
|
||||||
|
@ -195,7 +196,7 @@ export function chooseFileFromUrl(): Promise<Misskey.entities.DriveFile> {
|
||||||
}).then(({ canceled, result: url }) => {
|
}).then(({ canceled, result: url }) => {
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
|
|
||||||
const marker = Math.random().toString(); // TODO: UUIDとか使う
|
const marker = genId();
|
||||||
|
|
||||||
// TODO: no websocketモード対応
|
// TODO: no websocketモード対応
|
||||||
const connection = useStream().useChannel('main');
|
const connection = useStream().useChannel('main');
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
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_' + uuid(); // 将来embed.jsのバージョンが上がったとき用にv1_を付けておく
|
const iframeId = 'v1_' + genId(); // 将来embed.jsのバージョンが上がったとき用にv1_を付けておく
|
||||||
|
|
||||||
let paramString = '';
|
let paramString = '';
|
||||||
if (params) {
|
if (params) {
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* 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();
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ 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';
|
||||||
|
@ -28,4 +29,5 @@ 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>[];
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
},
|
||||||
|
});
|
|
@ -8,6 +8,10 @@ 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;
|
||||||
|
@ -45,9 +49,20 @@ 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 = in_uv.x > x_offset - (x_scale / 2.0) && in_uv.x < x_offset + (x_scale / 2.0) &&
|
bool isInside = rotatedUV.x > x_offset - (x_scale / 2.0) && rotatedUV.x < x_offset + (x_scale / 2.0) &&
|
||||||
in_uv.y > y_offset - (y_scale / 2.0) && in_uv.y < y_offset + (y_scale / 2.0);
|
rotatedUV.y > y_offset - (y_scale / 2.0) && rotatedUV.y < y_offset + (y_scale / 2.0);
|
||||||
if (!isInside) {
|
if (!isInside) {
|
||||||
out_color = in_color;
|
out_color = in_color;
|
||||||
return;
|
return;
|
||||||
|
@ -55,8 +70,8 @@ void main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 watermark_color = texture(u_texture_watermark, vec2(
|
vec4 watermark_color = texture(u_texture_watermark, vec2(
|
||||||
(in_uv.x - (x_offset - (x_scale / 2.0))) / x_scale,
|
(rotatedUV.x - (x_offset - (x_scale / 2.0))) / x_scale,
|
||||||
(in_uv.y - (y_offset - (y_scale / 2.0))) / y_scale
|
(rotatedUV.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);
|
||||||
|
@ -87,6 +102,13 @@ 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' },
|
||||||
|
@ -114,8 +136,9 @@ 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, 0.0);
|
gl.uniform1f(u.angle, params.angle);
|
||||||
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);
|
||||||
|
|
|
@ -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.8,
|
default: 0.2,
|
||||||
min: 0.0,
|
min: 0.0,
|
||||||
max: 1.0,
|
max: 1.0,
|
||||||
step: 0.01,
|
step: 0.01,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
|
|
||||||
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: uuid(),
|
id: genId(),
|
||||||
name, desc, author, props, base,
|
name, desc, author, props, base,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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';
|
||||||
|
|
||||||
|
@ -16,6 +17,7 @@ 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;
|
||||||
} | {
|
} | {
|
||||||
|
@ -26,8 +28,17 @@ 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;
|
||||||
})[];
|
})[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,7 +57,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],
|
fxs: [FX_watermarkPlacement, FX_stripe],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +71,7 @@ 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: {
|
||||||
|
@ -68,7 +80,7 @@ export class WatermarkRenderer {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} else {
|
} else if (layer.type === 'image') {
|
||||||
return {
|
return {
|
||||||
fxId: 'watermarkPlacement',
|
fxId: 'watermarkPlacement',
|
||||||
id: layer.id,
|
id: layer.id,
|
||||||
|
@ -76,6 +88,7 @@ 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: {
|
||||||
|
@ -84,6 +97,18 @@ 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,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ 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';
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ const run = async () => {
|
||||||
in: aiScriptReadline,
|
in: aiScriptReadline,
|
||||||
out: (value) => {
|
out: (value) => {
|
||||||
logs.value.push({
|
logs.value.push({
|
||||||
id: Math.random().toString(),
|
id: genId(),
|
||||||
text: value.type === 'str' ? value.value : utils.valToString(value),
|
text: value.type === 'str' ? value.value : utils.valToString(value),
|
||||||
print: true,
|
print: true,
|
||||||
});
|
});
|
||||||
|
@ -81,7 +82,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: Math.random().toString(),
|
id: genId(),
|
||||||
text: utils.valToString(params.val, true),
|
text: utils.valToString(params.val, true),
|
||||||
print: false,
|
print: false,
|
||||||
}); break;
|
}); break;
|
||||||
|
|
|
@ -60,6 +60,7 @@ 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';
|
||||||
|
|
||||||
|
@ -144,7 +145,7 @@ connection.on('stats', onStats);
|
||||||
connection.on('statsLog', onStatsLog);
|
connection.on('statsLog', onStatsLog);
|
||||||
|
|
||||||
connection.send('requestLog', {
|
connection.send('requestLog', {
|
||||||
id: Math.random().toString().substring(2, 10),
|
id: genId(),
|
||||||
length: 1,
|
length: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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 { v4 as uuid } from 'uuid';
|
import { genId } from '@/utility/id.js';
|
||||||
|
|
||||||
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 = uuid();
|
const cpuGradientId = genId();
|
||||||
const cpuMaskId = uuid();
|
const cpuMaskId = genId();
|
||||||
const memGradientId = uuid();
|
const memGradientId = genId();
|
||||||
const memMaskId = uuid();
|
const memMaskId = genId();
|
||||||
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: Math.random().toString().substring(2, 10),
|
id: genId(),
|
||||||
length: 50,
|
length: 50,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -52,6 +52,7 @@ 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']>,
|
||||||
|
@ -76,7 +77,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: Math.random().toString().substring(2, 10),
|
id: genId(),
|
||||||
length: 50,
|
length: 50,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -866,9 +866,6 @@ 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))
|
||||||
|
@ -21868,7 +21865,7 @@ snapshots:
|
||||||
|
|
||||||
tsx@4.19.4:
|
tsx@4.19.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.25.4
|
esbuild: 0.25.5
|
||||||
get-tsconfig: 4.10.1
|
get-tsconfig: 4.10.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
|
Loading…
Reference in New Issue