Merge branch 'develop' into report

This commit is contained in:
まっちゃてぃー。 2024-01-02 20:13:54 +09:00 committed by GitHub
commit 8f73d4b567
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 704 additions and 428 deletions

View file

@ -131,6 +131,10 @@ function onMousedown(evt: MouseEvent): void {
box-sizing: border-box;
transition: background 0.1s ease;
&:hover {
text-decoration: none;
}
&:not(:disabled):hover {
background: var(--buttonHoverBg);
}

View file

@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.codeEditorScroller">
<textarea
ref="inputEl"
v-model="vModel"
v-model="v"
:class="[$style.textarea]"
:disabled="disabled"
:required="required"
@ -58,7 +58,6 @@ const emit = defineEmits<{
}>();
const { modelValue } = toRefs(props);
const vModel = ref<string>(modelValue.value ?? '');
const v = ref<string>(modelValue.value ?? '');
const focused = ref(false);
const changed = ref(false);
@ -79,15 +78,14 @@ const onKeydown = (ev: KeyboardEvent) => {
if (ev.code === 'Enter') {
const pos = inputEl.value?.selectionStart ?? 0;
const posEnd = inputEl.value?.selectionEnd ?? vModel.value.length;
const posEnd = inputEl.value?.selectionEnd ?? v.value.length;
if (pos === posEnd) {
const lines = vModel.value.slice(0, pos).split('\n');
const lines = v.value.slice(0, pos).split('\n');
const currentLine = lines[lines.length - 1];
const currentLineSpaces = currentLine.match(/^\s+/);
const posDelta = currentLineSpaces ? currentLineSpaces[0].length : 0;
ev.preventDefault();
vModel.value = vModel.value.slice(0, pos) + '\n' + (currentLineSpaces ? currentLineSpaces[0] : '') + vModel.value.slice(pos);
v.value = vModel.value;
v.value = v.value.slice(0, pos) + '\n' + (currentLineSpaces ? currentLineSpaces[0] : '') + v.value.slice(pos);
nextTick(() => {
inputEl.value?.setSelectionRange(pos + 1 + posDelta, pos + 1 + posDelta);
});
@ -97,9 +95,8 @@ const onKeydown = (ev: KeyboardEvent) => {
if (ev.key === 'Tab') {
const pos = inputEl.value?.selectionStart ?? 0;
const posEnd = inputEl.value?.selectionEnd ?? vModel.value.length;
vModel.value = vModel.value.slice(0, pos) + '\t' + vModel.value.slice(posEnd);
v.value = vModel.value;
const posEnd = inputEl.value?.selectionEnd ?? v.value.length;
v.value = v.value.slice(0, pos) + '\t' + v.value.slice(posEnd);
nextTick(() => {
inputEl.value?.setSelectionRange(pos + 1, pos + 1);
});

View file

@ -9,7 +9,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { reactive, watch } from 'vue';
import gsap from 'gsap';
import number from '@/filters/number.js';
const props = defineProps<{
@ -20,8 +19,24 @@ const tweened = reactive({
number: 0,
});
watch(() => props.value, (n) => {
gsap.to(tweened, { duration: 1, number: Number(n) || 0 });
watch(() => props.value, (to, from) => {
// requestAnimationFrame500msfromto1
let start: number | null = null;
function step(timestamp: number) {
if (start === null) {
start = timestamp;
}
const elapsed = timestamp - start;
tweened.number = (from ?? 0) + (to - (from ?? 0)) * elapsed / 500;
if (elapsed < 500) {
window.requestAnimationFrame(step);
} else {
tweened.number = to;
}
}
window.requestAnimationFrame(step);
}, {
immediate: true,
});

View file

@ -752,7 +752,17 @@ async function post(ev?: MouseEvent) {
if (withHashtags.value && hashtags.value && hashtags.value.trim() !== '') {
const hashtags_ = hashtags.value.trim().split(' ').map(x => x.startsWith('#') ? x : '#' + x).join(' ');
postData.text = postData.text ? `${postData.text} ${hashtags_}` : hashtags_;
if (!postData.text) {
postData.text = hashtags_;
} else {
const postTextLines = postData.text.split('\n');
if (postTextLines[postTextLines.length - 1].trim() === '') {
postTextLines[postTextLines.length - 1] += hashtags_;
} else {
postTextLines[postTextLines.length - 1] += ' ' + hashtags_;
}
postData.text = postTextLines.join('\n');
}
}
// plugin

View file

@ -84,7 +84,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { defineAsyncComponent, onUnmounted, ref } from 'vue';
import type { summaly } from 'summaly';
import type { summaly } from '@misskey-dev/summaly';
import { url as local } from '@/config.js';
import { i18n } from '@/i18n.js';
import * as os from '@/os.js';

View file

@ -80,6 +80,17 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #prefix><i class="ti ti-key"></i></template>
<template #label>Verifymail.io API Auth Key</template>
</MkInput>
<MkSwitch v-model="enableTruemailApi" @update:modelValue="save">
<template #label>Use TrueMail API</template>
</MkSwitch>
<MkInput v-model="truemailInstance" @update:modelValue="save">
<template #prefix><i class="ti ti-key"></i></template>
<template #label>TrueMail API Instance</template>
</MkInput>
<MkInput v-model="truemailAuthKey" @update:modelValue="save">
<template #prefix><i class="ti ti-key"></i></template>
<template #label>TrueMail API Auth Key</template>
</MkInput>
</div>
</MkFolder>
@ -153,6 +164,9 @@ const enableIpLogging = ref<boolean>(false);
const enableActiveEmailValidation = ref<boolean>(false);
const enableVerifymailApi = ref<boolean>(false);
const verifymailAuthKey = ref<string | null>(null);
const enableTruemailApi = ref<boolean>(false);
const truemailInstance = ref<string | null>(null);
const truemailAuthKey = ref<string | null>(null);
const bannedEmailDomains = ref<string>('');
async function init() {
@ -194,6 +208,9 @@ function save() {
enableActiveEmailValidation: enableActiveEmailValidation.value,
enableVerifymailApi: enableVerifymailApi.value,
verifymailAuthKey: verifymailAuthKey.value,
enableTruemailApi: enableTruemailApi.value,
truemailInstance: truemailInstance.value,
truemailAuthKey: truemailAuthKey.value,
bannedEmailDomains: bannedEmailDomains.value.split('\n'),
}).then(() => {
fetchInstance();

View file

@ -46,7 +46,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-else-if="tab === 'search'">
<div class="_gaps">
<div>
<MkInput v-model="searchQuery">
<MkInput v-model="searchQuery" @enter="search()">
<template #prefix><i class="ti ti-search"></i></template>
</MkInput>
<MkButton primary rounded style="margin-top: 8px;" @click="search()">{{ i18n.ts.search }}</MkButton>

View file

@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSpacer :contentMax="700">
<div v-if="tab === 'search'">
<div class="_gaps">
<MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search">
<MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search" @enter="search">
<template #prefix><i class="ti ti-search"></i></template>
</MkInput>
<MkRadios v-model="searchType" @update:modelValue="search()">

View file

@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div class="_gaps">
<div class="_gaps">
<MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search">
<MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search" @enter="search">
<template #prefix><i class="ti ti-search"></i></template>
</MkInput>
<MkFolder>

View file

@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div class="_gaps">
<div class="_gaps">
<MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search">
<MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search" @enter="search">
<template #prefix><i class="ti ti-search"></i></template>
</MkInput>
<MkRadios v-model="searchOrigin" @update:modelValue="search()">

View file

@ -168,7 +168,7 @@ export class Storage<T extends StateDef> {
this.reactiveState[key].value = this.state[key] = rawValue;
return this.addIdbSetJob(async () => {
if (_DEV_) console.log(`set ${key} start`);
if (_DEV_) console.log(`set ${String(key)} start`);
switch (this.def[key].where) {
case 'device': {
this.pizzaxChannel.postMessage({
@ -207,7 +207,7 @@ export class Storage<T extends StateDef> {
break;
}
}
if (_DEV_) console.log(`set ${key} complete`);
if (_DEV_) console.log(`set ${String(key)} complete`);
});
}

View file

@ -5,7 +5,7 @@
import { reactive, ref } from 'vue';
import * as Misskey from 'misskey-js';
import { readAndCompressImage } from 'browser-image-resizer';
import { readAndCompressImage } from '@misskey-dev/browser-image-resizer';
import { getCompressionConfig } from './upload/compress-config.js';
import { defaultStore } from '@/store.js';
import { apiUrl } from '@/config.js';

View file

@ -5,7 +5,7 @@
import isAnimated from 'is-file-animated';
import { isWebpSupported } from './isWebpSupported.js';
import type { BrowserImageResizerConfig } from 'browser-image-resizer';
import type { BrowserImageResizerConfigWithConvertedOutput } from '@misskey-dev/browser-image-resizer';
const compressTypeMap = {
'image/jpeg': { quality: 0.90, mimeType: 'image/webp' },
@ -21,7 +21,7 @@ const compressTypeMapFallback = {
'image/svg+xml': { quality: 1, mimeType: 'image/png' },
} as const;
export async function getCompressionConfig(file: File): Promise<BrowserImageResizerConfig | undefined> {
export async function getCompressionConfig(file: File): Promise<BrowserImageResizerConfigWithConvertedOutput | undefined> {
const imgConfig = (isWebpSupported() ? compressTypeMap : compressTypeMapFallback)[file.type];
if (!imgConfig || await isAnimated(file)) {
return;