Feat: クリックイベントを発生させるMFM構文を追加 (#12798)

* Update MkMisskeyFlavoredMarkdown.ts

* fix MkMisskeyFlavoredMarkdown.ts

* Update MkAsUi.vue

* Update ui.ts

* Fix MkMisskeyFlavoredMarkdown.ts

* Update CHANGELOG.md

* fix ui.ts

* revert CHANGELOG.md

* Update CHANGELOG.md
This commit is contained in:
FineArchs 2023-12-25 18:03:06 +09:00 committed by Marie
parent adf13f79bd
commit 9c17e0f976
No known key found for this signature in database
GPG key ID: 56569BBE47D2C828
4 changed files with 21 additions and 3 deletions

View file

@ -20,6 +20,7 @@
### Client
- Fix: 一部のモデログ(logYellowでの表示対象)について、表示の色が変わらない問題を修正
- Feat: AiScript専用のMFM構文`$[clickable.ev=EVENTNAME ...]`を追加。`Mk:C:mfm`のオプション`onClickEv`に関数を渡すと、クリック時に`EVENTNAME`を引数にして呼び出す
### Server
- Enhance: センシティブワードの設定がハッシュタグトレンドにも適用されるようになりました

View file

@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
</div>
<span v-else-if="c.type === 'text'" :class="{ [$style.fontSerif]: c.font === 'serif', [$style.fontMonospace]: c.font === 'monospace' }" :style="{ fontSize: c.size ? `${c.size * 100}%` : null, fontWeight: c.bold ? 'bold' : null, color: c.color ?? null }">{{ c.text }}</span>
<Mfm v-else-if="c.type === 'mfm'" :class="{ [$style.fontSerif]: c.font === 'serif', [$style.fontMonospace]: c.font === 'monospace' }" :style="{ fontSize: c.size ? `${c.size * 100}%` : null, fontWeight: c.bold ? 'bold' : null, color: c.color ?? null }" :text="c.text"/>
<Mfm v-else-if="c.type === 'mfm'" :class="{ [$style.fontSerif]: c.font === 'serif', [$style.fontMonospace]: c.font === 'monospace' }" :style="{ fontSize: c.size ? `${c.size * 100}%` : null, fontWeight: c.bold ? 'bold' : null, color: c.color ?? null }" :text="c.text" @clickEv="c.onClickEv"/>
<MkButton v-else-if="c.type === 'button'" :primary="c.primary" :rounded="c.rounded" :disabled="c.disabled" :small="size === 'small'" inline @click="c.onClick">{{ c.text }}</MkButton>
<div v-else-if="c.type === 'buttons'" class="_buttons" :style="{ justifyContent: align }">
<MkButton v-for="button in c.buttons" :primary="button.primary" :rounded="button.rounded" :disabled="button.disabled" inline :small="size === 'small'" @click="button.onClick">{{ button.text }}</MkButton>

View file

@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { VNode, h, defineAsyncComponent } from 'vue';
import { VNode, h, defineAsyncComponent, SetupContext } from 'vue';
import * as mfm from '@sharkey/sfm-js';
import * as Misskey from 'misskey-js';
import MkUrl from '@/components/global/MkUrl.vue';
@ -44,8 +44,12 @@ type MfmProps = {
isAnim?: boolean;
};
type MfmEvents = {
clickEv(id: string): void;
};
// eslint-disable-next-line import/no-default-export
export default function(props: MfmProps) {
export default function(props: MfmProps, context: SetupContext<MfmEvents>) {
const isNote = props.isNote ?? true;
const shouldNyaize = props.nyaize ? props.nyaize === 'respect' ? props.author?.isCat ? props.author?.speakAsCat : false : false : false;
@ -290,6 +294,13 @@ export default function(props: MfmProps) {
}),
]);
}
case 'clickable': {
return h('span', { onClick(ev: MouseEvent): void {
ev.stopPropagation();
ev.preventDefault();
context.emit('clickEv', token.props.args.ev ?? '');
} }, genEl(token.children, scale));
}
}
if (style === undefined) {
return h('span', {}, ['$[', token.props.name, ' ', ...genEl(token.children, scale), ']']);

View file

@ -47,6 +47,7 @@ export type AsUiMfm = AsUiComponentBase & {
bold?: boolean;
color?: string;
font?: 'serif' | 'sans-serif' | 'monospace';
onClickEv?: (evId: string) => void
};
export type AsUiButton = AsUiComponentBase & {
@ -230,6 +231,8 @@ function getMfmOptions(def: values.Value | undefined): Omit<AsUiMfm, 'id' | 'typ
if (color) utils.assertString(color);
const font = def.value.get('font');
if (font) utils.assertString(font);
const onClickEv = def.value.get('onClickEv');
if (onClickEv) utils.assertFunction(onClickEv);
return {
text: text?.value,
@ -237,6 +240,9 @@ function getMfmOptions(def: values.Value | undefined): Omit<AsUiMfm, 'id' | 'typ
bold: bold?.value,
color: color?.value,
font: font?.value,
onClickEv: (evId: string) => {
if (onClickEv) call(onClickEv, values.STR(evId));
},
};
}