Merge remote-tracking branch 'misskey-original/develop' into develop

# Conflicts:
#	packages/frontend/src/components/MkEmojiPicker.vue
#	packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts
#	packages/frontend/src/pages/timeline.vue
This commit is contained in:
mattyatea 2023-12-14 21:08:18 +09:00
commit 7313e13397
102 changed files with 2914 additions and 1291 deletions

View file

@ -57,7 +57,7 @@ function onContextmenu(ev) {
action: () => {
router.push(props.to, 'forcePage');
},
}, null, {
}, { type: 'divider' }, {
icon: 'ti ti-external-link',
text: i18n.ts.openInNewTab,
action: () => {

View file

@ -23,16 +23,19 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
</div>
<img
v-if="showDecoration && (decoration || user.avatarDecorations.length > 0)"
:class="[$style.decoration]"
:src="decoration?.url ?? user.avatarDecorations[0].url"
:style="{
rotate: getDecorationAngle(),
scale: getDecorationScale(),
}"
alt=""
>
<template v-if="showDecoration">
<img
v-for="decoration in decorations ?? user.avatarDecorations"
:class="[$style.decoration]"
:src="decoration.url"
:style="{
rotate: getDecorationAngle(decoration),
scale: getDecorationScale(decoration),
translate: getDecorationOffset(decoration),
}"
alt=""
>
</template>
</component>
</template>
@ -57,19 +60,14 @@ const props = withDefaults(defineProps<{
link?: boolean;
preview?: boolean;
indicator?: boolean;
decoration?: {
url: string;
angle?: number;
flipH?: boolean;
flipV?: boolean;
};
decorations?: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>[];
forceShowDecoration?: boolean;
}>(), {
target: null,
link: false,
preview: false,
indicator: false,
decoration: undefined,
decorations: undefined,
forceShowDecoration: false,
});
@ -92,30 +90,22 @@ function onClick(ev: MouseEvent): void {
emit('click', ev);
}
function getDecorationAngle() {
let angle;
if (props.decoration) {
angle = props.decoration.angle ?? 0;
} else if (props.user.avatarDecorations.length > 0) {
angle = props.user.avatarDecorations[0].angle ?? 0;
} else {
angle = 0;
}
function getDecorationAngle(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
const angle = decoration.angle ?? 0;
return angle === 0 ? undefined : `${angle * 360}deg`;
}
function getDecorationScale() {
let scaleX;
if (props.decoration) {
scaleX = props.decoration.flipH ? -1 : 1;
} else if (props.user.avatarDecorations.length > 0) {
scaleX = props.user.avatarDecorations[0].flipH ? -1 : 1;
} else {
scaleX = 1;
}
function getDecorationScale(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
const scaleX = decoration.flipH ? -1 : 1;
return scaleX === 1 ? undefined : `${scaleX} 1`;
}
function getDecorationOffset(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) {
const offsetX = decoration.offsetX ?? 0;
const offsetY = decoration.offsetY ?? 0;
return offsetX === 0 && offsetY === 0 ? undefined : `${offsetX * 100}% ${offsetY * 100}%`;
}
const color = ref<string | undefined>();
watch(() => props.user.avatarBlurhash, () => {

View file

@ -25,6 +25,7 @@ import { defaultStore } from '@/store.js';
import { customEmojisMap } from '@/custom-emojis.js';
import * as os from '@/os.js';
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
import * as sound from '@/scripts/sound.js';
import { i18n } from '@/i18n.js';
const props = defineProps<{
@ -98,6 +99,7 @@ function onClick(ev: MouseEvent) {
icon: 'ti ti-plus',
action: () => {
react(`:${props.name}:`);
sound.play('reaction');
},
}] : [])], ev.currentTarget ?? ev.target);
}

View file

@ -16,6 +16,7 @@ import { defaultStore } from '@/store.js';
import { getEmojiName } from '@/scripts/emojilist.js';
import * as os from '@/os.js';
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
import * as sound from '@/scripts/sound.js';
import { i18n } from '@/i18n.js';
const props = defineProps<{
@ -56,6 +57,7 @@ function onClick(ev: MouseEvent) {
icon: 'ti ti-plus',
action: () => {
react(props.emoji);
sound.play('reaction');
},
}] : [])], ev.currentTarget ?? ev.target);
}

View file

@ -70,7 +70,7 @@ type MfmProps = {
isNote?: boolean;
emojiUrls?: string[];
rootScale?: number;
nyaize: boolean | 'respect';
nyaize?: boolean | 'respect';
uhoize: boolean | 'respect';
parsedNodes?: mfm.MfmNode[] | null;
enableEmojiMenu?: boolean;
@ -144,22 +144,26 @@ export default function(props: MfmProps) {
switch (token.props.name) {
case 'tada': {
const speed = validTime(token.props.args.speed) ?? '1s';
style = 'font-size: 150%;' + (useAnim ? `animation: tada ${speed} linear infinite both;` : '');
const delay = validTime(token.props.args.delay) ?? '0s';
style = 'font-size: 150%;' + (useAnim ? `animation: tada ${speed} linear infinite both; animation-delay: ${delay};` : '');
break;
}
case 'jelly': {
const speed = validTime(token.props.args.speed) ?? '1s';
style = (useAnim ? `animation: mfm-rubberBand ${speed} linear infinite both;` : '');
const delay = validTime(token.props.args.delay) ?? '0s';
style = (useAnim ? `animation: mfm-rubberBand ${speed} linear infinite both; animation-delay: ${delay};` : '');
break;
}
case 'twitch': {
const speed = validTime(token.props.args.speed) ?? '0.5s';
style = useAnim ? `animation: mfm-twitch ${speed} ease infinite;` : '';
const delay = validTime(token.props.args.delay) ?? '0s';
style = useAnim ? `animation: mfm-twitch ${speed} ease infinite; animation-delay: ${delay};` : '';
break;
}
case 'shake': {
const speed = validTime(token.props.args.speed) ?? '0.5s';
style = useAnim ? `animation: mfm-shake ${speed} ease infinite;` : '';
const delay = validTime(token.props.args.delay) ?? '0s';
style = useAnim ? `animation: mfm-shake ${speed} ease infinite; animation-delay: ${delay};` : '';
break;
}
case 'spin': {
@ -172,17 +176,20 @@ export default function(props: MfmProps) {
token.props.args.y ? 'mfm-spinY' :
'mfm-spin';
const speed = validTime(token.props.args.speed) ?? '1.5s';
style = useAnim ? `animation: ${anime} ${speed} linear infinite; animation-direction: ${direction};` : '';
const delay = validTime(token.props.args.delay) ?? '0s';
style = useAnim ? `animation: ${anime} ${speed} linear infinite; animation-direction: ${direction}; animation-delay: ${delay};` : '';
break;
}
case 'jump': {
const speed = validTime(token.props.args.speed) ?? '0.75s';
style = useAnim ? `animation: mfm-jump ${speed} linear infinite;` : '';
const delay = validTime(token.props.args.delay) ?? '0s';
style = useAnim ? `animation: mfm-jump ${speed} linear infinite; animation-delay: ${delay};` : '';
break;
}
case 'bounce': {
const speed = validTime(token.props.args.speed) ?? '0.75s';
style = useAnim ? `animation: mfm-bounce ${speed} linear infinite; transform-origin: center bottom;` : '';
const delay = validTime(token.props.args.delay) ?? '0s';
style = useAnim ? `animation: mfm-bounce ${speed} linear infinite; transform-origin: center bottom; animation-delay: ${delay};` : '';
break;
}
case 'flip': {
@ -229,7 +236,8 @@ export default function(props: MfmProps) {
}
case 'rainbow': {
const speed = validTime(token.props.args.speed) ?? '1s';
style = useAnim ? `animation: mfm-rainbow ${speed} linear infinite;` : '';
const delay = validTime(token.props.args.delay) ?? '0s';
style = useAnim ? `animation: mfm-rainbow ${speed} linear infinite; animation-delay: ${delay};` : '';
break;
}
case 'sparkle': {