Merge branch 'develop'
This commit is contained in:
commit
24705a7e39
|
@ -9,6 +9,14 @@
|
||||||
You should also include the user name that made the change.
|
You should also include the user name that made the change.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
## 13.3.1 (2023/02/04)
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
- Client: カスタム絵文字にアニメーション画像を再生しない設定が適用されていない問題を修正
|
||||||
|
- Client: オートコンプリートでUnicode絵文字がカスタム絵文字として表示されてしまうのを修正
|
||||||
|
- Client: Fix Vue-plyr CORS issue
|
||||||
|
- Client: validate urls to improve security
|
||||||
|
|
||||||
## 13.3.0 (2023/02/03)
|
## 13.3.0 (2023/02/03)
|
||||||
### Changes
|
### Changes
|
||||||
- twitter/github/discord連携機能が削除されました
|
- twitter/github/discord連携機能が削除されました
|
||||||
|
|
|
@ -68,7 +68,7 @@ export: "Export"
|
||||||
files: "Dateien"
|
files: "Dateien"
|
||||||
download: "Herunterladen"
|
download: "Herunterladen"
|
||||||
driveFileDeleteConfirm: "Möchtest du die Datei „{name}“ wirklich löschen? Notizen mit dieser Datei werden ebenso verschwinden."
|
driveFileDeleteConfirm: "Möchtest du die Datei „{name}“ wirklich löschen? Notizen mit dieser Datei werden ebenso verschwinden."
|
||||||
unfollowConfirm: "Möchtest du {name} nicht mehr folgen?"
|
unfollowConfirm: "Möchtest du {name} wirklich nicht mehr folgen?"
|
||||||
exportRequested: "Du hast einen Export angefragt. Dies kann etwas Zeit in Anspruch nehmen. Sobald der Export abgeschlossen ist, wird er deiner Drive hinzugefügt."
|
exportRequested: "Du hast einen Export angefragt. Dies kann etwas Zeit in Anspruch nehmen. Sobald der Export abgeschlossen ist, wird er deiner Drive hinzugefügt."
|
||||||
importRequested: "Du hast einen Import angefragt. Dies kann etwas Zeit in Anspruch nehmen."
|
importRequested: "Du hast einen Import angefragt. Dies kann etwas Zeit in Anspruch nehmen."
|
||||||
lists: "Listen"
|
lists: "Listen"
|
||||||
|
@ -94,7 +94,7 @@ defaultNoteVisibility: "Standardsichtbarkeit"
|
||||||
follow: "Folgen"
|
follow: "Folgen"
|
||||||
followRequest: "Follow-Anfrage senden"
|
followRequest: "Follow-Anfrage senden"
|
||||||
followRequests: "Follow-Anfragen"
|
followRequests: "Follow-Anfragen"
|
||||||
unfollow: "Nicht mehr folgen"
|
unfollow: "Entfolgen"
|
||||||
followRequestPending: "Follow-Anfrage ausstehend"
|
followRequestPending: "Follow-Anfrage ausstehend"
|
||||||
enterEmoji: "Gib ein Emoji ein"
|
enterEmoji: "Gib ein Emoji ein"
|
||||||
renote: "Renote"
|
renote: "Renote"
|
||||||
|
|
|
@ -68,7 +68,7 @@ export: "Export"
|
||||||
files: "Files"
|
files: "Files"
|
||||||
download: "Download"
|
download: "Download"
|
||||||
driveFileDeleteConfirm: "Are you sure you want to delete the file \"{name}\"? Notes with this file attached will also be deleted."
|
driveFileDeleteConfirm: "Are you sure you want to delete the file \"{name}\"? Notes with this file attached will also be deleted."
|
||||||
unfollowConfirm: "Are you sure that you want to unfollow {name}?"
|
unfollowConfirm: "Are you sure you want to unfollow {name}?"
|
||||||
exportRequested: "You've requested an export. This may take a while. It will be added to your Drive once completed."
|
exportRequested: "You've requested an export. This may take a while. It will be added to your Drive once completed."
|
||||||
importRequested: "You've requested an import. This may take a while."
|
importRequested: "You've requested an import. This may take a while."
|
||||||
lists: "Lists"
|
lists: "Lists"
|
||||||
|
|
|
@ -943,8 +943,8 @@ _achievements:
|
||||||
earnedAt: "Desbloqueado el"
|
earnedAt: "Desbloqueado el"
|
||||||
_types:
|
_types:
|
||||||
_notes1:
|
_notes1:
|
||||||
title: "Configurando mis espacio"
|
title: "¡Hola Misskey!"
|
||||||
description: "Publicar tu primera nota"
|
description: "Publicaste tu primera nota"
|
||||||
flavor: "¡Pasándola bien con Misskey!"
|
flavor: "¡Pasándola bien con Misskey!"
|
||||||
_notes10:
|
_notes10:
|
||||||
title: "Algunas notas"
|
title: "Algunas notas"
|
||||||
|
@ -1233,8 +1233,8 @@ _role:
|
||||||
or: "Condicional OR"
|
or: "Condicional OR"
|
||||||
not: "Condicional NOT"
|
not: "Condicional NOT"
|
||||||
_sensitiveMediaDetection:
|
_sensitiveMediaDetection:
|
||||||
description: "Reduce el esfuerzo de la moderación el el servidor a través del reconocimiento automático de contenido NSFW usando 'Machine Learning'. Esto puede incrementar ligeramente la carga en el servidor."
|
description: "Reduce el esfuerzo de la moderación en el servidor a través del reconocimiento automático de contenido NSFW usando 'Machine Learning'. Esto puede incrementar ligeramente la carga en el servidor."
|
||||||
sensitivity: "Sensibilidad de detección"
|
sensitivity: "Sensibilidad de la detección"
|
||||||
sensitivityDescription: "Reducir la sensibilidad puede acarrear a varios falsos positivos, mientras que incrementarla puede reducir las detecciones (falsos negativos)."
|
sensitivityDescription: "Reducir la sensibilidad puede acarrear a varios falsos positivos, mientras que incrementarla puede reducir las detecciones (falsos negativos)."
|
||||||
setSensitiveFlagAutomatically: "Marcar como NSFW"
|
setSensitiveFlagAutomatically: "Marcar como NSFW"
|
||||||
setSensitiveFlagAutomaticallyDescription: "Los resultados de la detección interna pueden ser retenidos incluso si la opción está desactivada."
|
setSensitiveFlagAutomaticallyDescription: "Los resultados de la detección interna pueden ser retenidos incluso si la opción está desactivada."
|
||||||
|
|
|
@ -1072,19 +1072,21 @@ _achievements:
|
||||||
description: "第一次被关注"
|
description: "第一次被关注"
|
||||||
_followers10:
|
_followers10:
|
||||||
title: "关注我吧!"
|
title: "关注我吧!"
|
||||||
description: "关注者超过10人"
|
description: "拥有超过10名关注者"
|
||||||
_followers50:
|
_followers50:
|
||||||
title: "三五成群"
|
title: "三五成群"
|
||||||
description: "关注者超过50人"
|
description: "拥有超过50名关注者"
|
||||||
_followers100:
|
_followers100:
|
||||||
title: "胜友如云"
|
title: "胜友如云"
|
||||||
description: "关注者超过100人"
|
description: "拥有超过100名关注者"
|
||||||
_followers300:
|
_followers300:
|
||||||
title: "排列成行"
|
title: "排列成行"
|
||||||
description: "关注者超过300人"
|
description: "拥有超过300名关注者"
|
||||||
_followers500:
|
_followers500:
|
||||||
title: "信号塔"
|
title: "信号塔"
|
||||||
description: "关注者超过500人"
|
description: "拥有超过500名关注者"
|
||||||
|
_followers1000:
|
||||||
|
description: "拥有超过1000名关注者"
|
||||||
_collectAchievements30:
|
_collectAchievements30:
|
||||||
title: "成就收藏家"
|
title: "成就收藏家"
|
||||||
description: "获得超过30个成就"
|
description: "获得超过30个成就"
|
||||||
|
@ -1096,6 +1098,7 @@ _achievements:
|
||||||
description: "发布\"I ❤ #Misskey\"帖子"
|
description: "发布\"I ❤ #Misskey\"帖子"
|
||||||
flavor: "感谢您使用 Misskey ! by 开发团队"
|
flavor: "感谢您使用 Misskey ! by 开发团队"
|
||||||
_foundTreasure:
|
_foundTreasure:
|
||||||
|
title: "寻宝"
|
||||||
description: "发现了隐藏的宝藏"
|
description: "发现了隐藏的宝藏"
|
||||||
_client30min:
|
_client30min:
|
||||||
title: "休息一下!"
|
title: "休息一下!"
|
||||||
|
@ -1122,11 +1125,13 @@ _achievements:
|
||||||
description: "查看了实例信息中的图表"
|
description: "查看了实例信息中的图表"
|
||||||
_outputHelloWorldOnScratchpad:
|
_outputHelloWorldOnScratchpad:
|
||||||
title: "Hello, world!"
|
title: "Hello, world!"
|
||||||
|
description: "在AiScript控制台中输出 hello world"
|
||||||
_open3windows:
|
_open3windows:
|
||||||
title: "多窗口"
|
title: "多窗口"
|
||||||
description: "打开了三个或更多的窗口"
|
description: "打开了三个或更多的窗口"
|
||||||
_driveFolderCircularReference:
|
_driveFolderCircularReference:
|
||||||
title: "循环引用"
|
title: "循环引用"
|
||||||
|
description: "试图对网盘中的文件夹进行循环嵌套"
|
||||||
_reactWithoutRead:
|
_reactWithoutRead:
|
||||||
title: "有好好读过吗?"
|
title: "有好好读过吗?"
|
||||||
description: "在含有100字以上的帖子被发出三秒内做出回应"
|
description: "在含有100字以上的帖子被发出三秒内做出回应"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"version": "13.3.0",
|
"version": "13.3.1",
|
||||||
"codename": "nasubi",
|
"codename": "nasubi",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
</ol>
|
</ol>
|
||||||
<ol v-else-if="emojis.length > 0" ref="suggests" :class="$style.list">
|
<ol v-else-if="emojis.length > 0" ref="suggests" :class="$style.list">
|
||||||
<li v-for="emoji in emojis" :key="emoji.emoji" :class="$style.item" tabindex="-1" @click="complete(type, emoji.emoji)" @keydown="onKeydown">
|
<li v-for="emoji in emojis" :key="emoji.emoji" :class="$style.item" tabindex="-1" @click="complete(type, emoji.emoji)" @keydown="onKeydown">
|
||||||
<MkCustomEmoji :name="emoji.emoji" :class="$style.emoji"/>
|
<MkCustomEmoji v-if="'isCustomEmoji' in emoji && emoji.isCustomEmoji" :name="emoji.emoji" :class="$style.emoji"/>
|
||||||
|
<MkEmoji v-else :emoji="emoji.emoji" :class="$style.emoji"/>
|
||||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
<span v-if="q" :class="$style.emojiName" v-html="sanitizeHtml(emoji.name.replace(q, `<b>${q}</b>`))"></span>
|
<span v-if="q" :class="$style.emojiName" v-html="sanitizeHtml(emoji.name.replace(q, `<b>${q}</b>`))"></span>
|
||||||
<span v-else v-text="emoji.name"></span>
|
<span v-else v-text="emoji.name"></span>
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
<vue-plyr>
|
<vue-plyr>
|
||||||
<video
|
<video
|
||||||
controls
|
controls
|
||||||
crossorigin
|
|
||||||
playsinline
|
|
||||||
:data-poster="video.thumbnailUrl"
|
:data-poster="video.thumbnailUrl"
|
||||||
>
|
>
|
||||||
<source
|
<source
|
||||||
|
|
|
@ -56,8 +56,6 @@ async function renderChart() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
fetching = false;
|
fetching = false;
|
||||||
|
|
||||||
await nextTick();
|
await nextTick();
|
||||||
|
|
|
@ -154,7 +154,6 @@ function queryKey() {
|
||||||
|
|
||||||
function onSubmit() {
|
function onSubmit() {
|
||||||
signing = true;
|
signing = true;
|
||||||
console.log('submit');
|
|
||||||
if (!totpLogin && user && user.twoFactorEnabled) {
|
if (!totpLogin && user && user.twoFactorEnabled) {
|
||||||
if (window.PublicKeyCredential && user.securityKeys) {
|
if (window.PublicKeyCredential && user.securityKeys) {
|
||||||
os.api('signin', {
|
os.api('signin', {
|
||||||
|
|
|
@ -86,6 +86,7 @@ let tweetHeight = $ref(150);
|
||||||
let unknownUrl = $ref(false);
|
let unknownUrl = $ref(false);
|
||||||
|
|
||||||
const requestUrl = new URL(props.url);
|
const requestUrl = new URL(props.url);
|
||||||
|
if (!['http:', 'https:'].includes(requestUrl.protocol)) throw new Error('invalid url');
|
||||||
|
|
||||||
if (requestUrl.hostname === 'twitter.com' || requestUrl.hostname === 'mobile.twitter.com') {
|
if (requestUrl.hostname === 'twitter.com' || requestUrl.hostname === 'mobile.twitter.com') {
|
||||||
const m = requestUrl.pathname.match(/^\/.+\/status(?:es)?\/(\d+)/);
|
const m = requestUrl.pathname.match(/^\/.+\/status(?:es)?\/(\d+)/);
|
||||||
|
|
|
@ -26,6 +26,7 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const requestUrl = new URL(props.url);
|
const requestUrl = new URL(props.url);
|
||||||
|
if (!['http:', 'https:'].includes(requestUrl.protocol)) throw new Error('invalid url');
|
||||||
|
|
||||||
let fetching = $ref(true);
|
let fetching = $ref(true);
|
||||||
let title = $ref<string | null>(null);
|
let title = $ref<string | null>(null);
|
||||||
|
|
|
@ -18,19 +18,23 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const customEmojiName = computed(() => (props.name[0] === ':' ? props.name.substr(1, props.name.length - 2) : props.name).replace('@.', ''));
|
const customEmojiName = computed(() => (props.name[0] === ':' ? props.name.substr(1, props.name.length - 2) : props.name).replace('@.', ''));
|
||||||
const url = computed(() => {
|
|
||||||
|
const rawUrl = computed(() => {
|
||||||
if (props.url) {
|
if (props.url) {
|
||||||
return props.url;
|
return props.url;
|
||||||
} else if (props.host == null && !customEmojiName.value.includes('@')) {
|
|
||||||
const found = customEmojis.value.find(x => x.name === customEmojiName.value);
|
|
||||||
return found ? defaultStore.state.disableShowingAnimatedImages ? getStaticImageUrl(found.url) : found.url : null;
|
|
||||||
} else {
|
|
||||||
const rawUrl = props.host ? `/emoji/${customEmojiName.value}@${props.host}.webp` : `/emoji/${customEmojiName.value}.webp`;
|
|
||||||
return defaultStore.state.disableShowingAnimatedImages
|
|
||||||
? getStaticImageUrl(rawUrl)
|
|
||||||
: rawUrl;
|
|
||||||
}
|
}
|
||||||
|
if (props.host == null && !customEmojiName.value.includes('@')) {
|
||||||
|
return customEmojis.value.find(x => x.name === customEmojiName.value)?.url || null;
|
||||||
|
}
|
||||||
|
return props.host ? `/emoji/${customEmojiName.value}@${props.host}.webp` : `/emoji/${customEmojiName.value}.webp`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const url = computed(() =>
|
||||||
|
defaultStore.reactiveState.disableShowingAnimatedImages.value && rawUrl.value
|
||||||
|
? getStaticImageUrl(rawUrl.value)
|
||||||
|
: rawUrl.value
|
||||||
|
);
|
||||||
|
|
||||||
const alt = computed(() => `:${customEmojiName.value}:`);
|
const alt = computed(() => `:${customEmojiName.value}:`);
|
||||||
let errored = $ref(url.value == null);
|
let errored = $ref(url.value == null);
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -33,6 +33,7 @@ const props = defineProps<{
|
||||||
|
|
||||||
const self = props.url.startsWith(local);
|
const self = props.url.startsWith(local);
|
||||||
const url = new URL(props.url);
|
const url = new URL(props.url);
|
||||||
|
if (!['http:', 'https:'].includes(url.protocol)) throw new Error('invalid url');
|
||||||
const el = ref();
|
const el = ref();
|
||||||
|
|
||||||
useTooltip(el, (showing) => {
|
useTooltip(el, (showing) => {
|
||||||
|
|
|
@ -70,6 +70,7 @@ async function accept(): Promise<void> {
|
||||||
state = 'accepted';
|
state = 'accepted';
|
||||||
if (props.callback) {
|
if (props.callback) {
|
||||||
const cbUrl = new URL(props.callback);
|
const cbUrl = new URL(props.callback);
|
||||||
|
if (!['http:', 'https:'].includes(cbUrl.protocol)) throw new Error('invalid url');
|
||||||
cbUrl.searchParams.set('session', props.session);
|
cbUrl.searchParams.set('session', props.session);
|
||||||
location.href = cbUrl.href;
|
location.href = cbUrl.href;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,14 +38,11 @@ const init = async () => {
|
||||||
getAccounts().then(accounts => {
|
getAccounts().then(accounts => {
|
||||||
storedAccounts.value = accounts.filter(x => x.id !== $i!.id);
|
storedAccounts.value = accounts.filter(x => x.id !== $i!.id);
|
||||||
|
|
||||||
console.log(storedAccounts.value);
|
|
||||||
|
|
||||||
return os.api('users/show', {
|
return os.api('users/show', {
|
||||||
userIds: storedAccounts.value.map(x => x.id),
|
userIds: storedAccounts.value.map(x => x.id),
|
||||||
});
|
});
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
accounts.value = response;
|
accounts.value = response;
|
||||||
console.log(accounts.value);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,14 +8,15 @@ import {
|
||||||
|
|
||||||
const fallbackName = (key: string) => `idbfallback::${key}`;
|
const fallbackName = (key: string) => `idbfallback::${key}`;
|
||||||
|
|
||||||
let idbAvailable = typeof window !== 'undefined' ? !!window.indexedDB : true;
|
let idbAvailable = typeof window !== 'undefined' ? !!(window.indexedDB && window.indexedDB.open) : true;
|
||||||
|
|
||||||
if (idbAvailable) {
|
if (idbAvailable) {
|
||||||
iset('idb-test', 'test').catch(err => {
|
await iset('idb-test', 'test')
|
||||||
console.error('idb error', err);
|
.catch(err => {
|
||||||
console.error('indexedDB is unavailable. It will use localStorage.');
|
console.error('idb error', err);
|
||||||
idbAvailable = false;
|
console.error('indexedDB is unavailable. It will use localStorage.');
|
||||||
});
|
idbAvailable = false;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
console.error('indexedDB is unavailable. It will use localStorage.');
|
console.error('indexedDB is unavailable. It will use localStorage.');
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue