merge: Ported firefish crop and fade mfm (!525)

View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/525

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Amelia Yukii <amelia.yukii@shourai.de>
This commit is contained in:
Amelia Yukii 2024-05-23 21:40:27 +00:00
commit 47963f323b
5 changed files with 73 additions and 2 deletions

View file

@ -2543,12 +2543,16 @@ _mfm:
rotateDescription: "Turns content by a specified angle." rotateDescription: "Turns content by a specified angle."
position: "Position" position: "Position"
positionDescription: "Move content by a specified amount." positionDescription: "Move content by a specified amount."
crop: "Crop"
cropDescription: "Crop content."
followMouse: "Follow Mouse" followMouse: "Follow Mouse"
followMouseDescription: "Content will follow the mouse. On mobile it will follow wherever the user taps." followMouseDescription: "Content will follow the mouse. On mobile it will follow wherever the user taps."
scale: "Scale" scale: "Scale"
scaleDescription: "Scale content by a specified amount." scaleDescription: "Scale content by a specified amount."
foreground: "Foreground color" foreground: "Foreground color"
foregroundDescription: "Change the foreground color of text." foregroundDescription: "Change the foreground color of text."
fade: 'Fade'
fadeDescription: 'Fade text in and out.'
background: "Background color" background: "Background color"
backgroundDescription: "Change the background color of text." backgroundDescription: "Change the background color of text."
plain: "Plain" plain: "Plain"

View file

@ -304,6 +304,16 @@
</div> </div>
</div> </div>
</div> </div>
<div class="section _block">
<div class="title">{{ i18n.ts._mfm.crop }}</div>
<div class="content">
<p>{{ i18n.ts._mfm.cropDescription }}</p>
<div class="preview">
<Mfm :text="preview_crop" />
<MkTextarea v-model="preview_crop"><span>MFM</span></MkTextarea>
</div>
</div>
</div>
<div class="section _block"> <div class="section _block">
<div class="title">{{ i18n.ts._mfm.position }}</div> <div class="title">{{ i18n.ts._mfm.position }}</div>
<div class="content"> <div class="content">
@ -336,6 +346,16 @@
</div> </div>
</div> </div>
</div> </div>
<div class="section _block">
<div class="title">{{ i18n.ts._mfm.fade }}</div>
<div class="content">
<p>{{ i18n.ts._mfm.fadeDescription }}</p>
<div class="preview">
<Mfm :text="preview_fade" />
<MkTextarea v-model="preview_fade"><span>MFM</span></MkTextarea>
</div>
</div>
</div>
<div class="section _block"> <div class="section _block">
<div class="title">{{ i18n.ts._mfm.foreground }}</div> <div class="title">{{ i18n.ts._mfm.foreground }}</div>
<div class="content"> <div class="content">
@ -445,6 +465,9 @@ const preview_rotate = ref(
'$[rotate 🍮]\n$[rotate.deg=45 🍮]\n$[rotate.x,deg=45 Hello, world!]', '$[rotate 🍮]\n$[rotate.deg=45 🍮]\n$[rotate.x,deg=45 Hello, world!]',
); );
const preview_position = ref('$[position.y=-1 🍮]\n$[position.x=-1 🍮]'); const preview_position = ref('$[position.y=-1 🍮]\n$[position.x=-1 🍮]');
const preview_crop = ref(
"$[crop.top=50 🍮] $[crop.right=50 🍮] $[crop.bottom=50 🍮] $[crop.left=50 🍮]",
);
const preview_followmouse = ref('$[followmouse.x 🍮]\n$[followmouse.x,y,rotateByVelocity,speed=0.4 🍮]'); const preview_followmouse = ref('$[followmouse.x 🍮]\n$[followmouse.x,y,rotateByVelocity,speed=0.4 🍮]');
const preview_scale = ref( const preview_scale = ref(
'$[scale.x=1.3 🍮]\n$[scale.x=1.5,y=3 🍮]\n$[scale.y=0.3 🍮]', '$[scale.x=1.3 🍮]\n$[scale.x=1.5,y=3 🍮]\n$[scale.y=0.3 🍮]',
@ -454,6 +477,7 @@ const preview_bg = ref('$[bg.color=31748f Background color]');
const preview_plain = ref( const preview_plain = ref(
'<plain>**bold** @mention #hashtag `code` $[x2 🍮]</plain>', '<plain>**bold** @mention #hashtag `code` $[x2 🍮]</plain>',
); );
const preview_fade = ref(`$[fade 🍮] $[fade.out 🍮] $[fade.speed=3s 🍮] $[fade.delay=3s 🍮]`);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View file

@ -228,6 +228,22 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
} }
return h(MkSparkle, {}, genEl(token.children, scale)); return h(MkSparkle, {}, genEl(token.children, scale));
} }
case 'fade': {
// Dont run with reduced motion on
if (!defaultStore.state.animation) {
style = '';
break;
}
const direction = token.props.args.out
? 'alternate-reverse'
: 'alternate';
const speed = validTime(token.props.args.speed) ?? '1.5s';
const delay = validTime(token.props.args.delay) ?? '0s';
const loop = safeParseFloat(token.props.args.loop) ?? 'infinite';
style = `animation: mfm-fade ${speed} ${delay} linear ${loop}; animation-direction: ${direction};`;
break;
}
case 'rotate': { case 'rotate': {
const degrees = safeParseFloat(token.props.args.deg) ?? 90; const degrees = safeParseFloat(token.props.args.deg) ?? 90;
style = `transform: rotate(${degrees}deg); transform-origin: center center;`; style = `transform: rotate(${degrees}deg); transform-origin: center center;`;
@ -262,6 +278,22 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
style = `transform: translateX(${x}em) translateY(${y}em);`; style = `transform: translateX(${x}em) translateY(${y}em);`;
break; break;
} }
case 'crop': {
const top = Number.parseFloat(
(token.props.args.top ?? '0').toString(),
);
const right = Number.parseFloat(
(token.props.args.right ?? '0').toString(),
);
const bottom = Number.parseFloat(
(token.props.args.bottom ?? '0').toString(),
);
const left = Number.parseFloat(
(token.props.args.left ?? '0').toString(),
);
style = `clip-path: inset(${top}% ${right}% ${bottom}% ${left}%);`;
break;
}
case 'scale': { case 'scale': {
if (!defaultStore.state.advancedMfm) { if (!defaultStore.state.advancedMfm) {
style = ''; style = '';

View file

@ -162,7 +162,7 @@ export const DEFAULT_SERVER_ERROR_IMAGE_URL = 'https://launcher.moe/error.png';
export const DEFAULT_NOT_FOUND_IMAGE_URL = 'https://launcher.moe/missingpage.webp'; export const DEFAULT_NOT_FOUND_IMAGE_URL = 'https://launcher.moe/missingpage.webp';
export const DEFAULT_INFO_IMAGE_URL = 'https://launcher.moe/nothinghere.png'; export const DEFAULT_INFO_IMAGE_URL = 'https://launcher.moe/nothinghere.png';
export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'border', 'font', 'blur', 'rainbow', 'sparkle', 'rotate', 'ruby', 'unixtime', 'followmouse']; export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'border', 'font', 'blur', 'rainbow', 'sparkle', 'rotate', 'ruby', 'unixtime', 'crop', 'fade', 'followmouse'];
export const MFM_PARAMS: Record<typeof MFM_TAGS[number], string[]> = { export const MFM_PARAMS: Record<typeof MFM_TAGS[number], string[]> = {
tada: ['speed=', 'delay='], tada: ['speed=', 'delay='],
jelly: ['speed=', 'delay='], jelly: ['speed=', 'delay='],
@ -186,5 +186,7 @@ export const MFM_PARAMS: Record<typeof MFM_TAGS[number], string[]> = {
rotate: ['deg='], rotate: ['deg='],
ruby: [], ruby: [],
unixtime: [], unixtime: [],
fade: ['speed=', 'delay=', 'loop=', 'out'],
crop: ['top=', 'bottom=', 'left=', 'right='],
followmouse: ['x', 'y', 'rotateByVelocity', 'speed='], followmouse: ['x', 'y', 'rotateByVelocity', 'speed='],
}; };

View file

@ -698,3 +698,12 @@ rt {
0% { filter: hue-rotate(0deg) contrast(150%) saturate(150%); } 0% { filter: hue-rotate(0deg) contrast(150%) saturate(150%); }
100% { filter: hue-rotate(360deg) contrast(150%) saturate(150%); } 100% { filter: hue-rotate(360deg) contrast(150%) saturate(150%); }
} }
@keyframes mfm-fade {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}