43c0ffe7f8
We use MfM in all sorts of places, and only some of them are actual blocks. We can now tell the `Mfm` component to make the top-level `<bdi>` a block when we need to (mostly note bodies, user descriptions, announcements) and leave it inline in all other places. This should still rendener inline rtl content embedded in ltr text in a sensible way, while providing right-alignment for fully rtl blocks.
105 lines
2.6 KiB
Vue
105 lines
2.6 KiB
Vue
<!--
|
|
SPDX-FileCopyrightText: syuilo and misskey-project
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
-->
|
|
|
|
<template>
|
|
<MkModal ref="modal" :zPriority="'middle'" @closed="$emit('closed')" @click="onBgClick">
|
|
<div ref="rootEl" :class="$style.root">
|
|
<div :class="$style.header">
|
|
<span :class="$style.icon">
|
|
<i v-if="announcement.icon === 'info'" class="ph-info ph-bold ph-lg"></i>
|
|
<i v-else-if="announcement.icon === 'warning'" class="ph-warning-circle ph-bold ph-lg" style="color: var(--warn);"></i>
|
|
<i v-else-if="announcement.icon === 'error'" class="ph-seal-warning ph-bold ph-lg" style="color: var(--error);"></i>
|
|
<i v-else-if="announcement.icon === 'success'" class="ph-check-circle ph-bold ph-lg" style="color: var(--success);"></i>
|
|
</span>
|
|
<span :class="$style.title">{{ announcement.title }}</span>
|
|
</div>
|
|
<div :class="$style.text"><Mfm :text="announcement.text" :isBlock="true" /></div>
|
|
<MkButton primary full @click="ok">{{ i18n.ts.ok }}</MkButton>
|
|
</div>
|
|
</MkModal>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { onMounted, shallowRef } from 'vue';
|
|
import * as Misskey from 'misskey-js';
|
|
import * as os from '@/os.js';
|
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
|
import MkModal from '@/components/MkModal.vue';
|
|
import MkButton from '@/components/MkButton.vue';
|
|
import { i18n } from '@/i18n.js';
|
|
import { $i, updateAccount } from '@/account.js';
|
|
|
|
const props = withDefaults(defineProps<{
|
|
announcement: Misskey.entities.Announcement;
|
|
}>(), {
|
|
});
|
|
|
|
const rootEl = shallowRef<HTMLDivElement>();
|
|
const modal = shallowRef<InstanceType<typeof MkModal>>();
|
|
|
|
async function ok() {
|
|
if (props.announcement.needConfirmationToRead) {
|
|
const confirm = await os.confirm({
|
|
type: 'question',
|
|
title: i18n.ts._announcement.readConfirmTitle,
|
|
text: i18n.tsx._announcement.readConfirmText({ title: props.announcement.title }),
|
|
});
|
|
if (confirm.canceled) return;
|
|
}
|
|
|
|
modal.value?.close();
|
|
misskeyApi('i/read-announcement', { announcementId: props.announcement.id });
|
|
updateAccount({
|
|
unreadAnnouncements: $i!.unreadAnnouncements.filter(a => a.id !== props.announcement.id),
|
|
});
|
|
}
|
|
|
|
function onBgClick() {
|
|
rootEl.value?.animate([{
|
|
offset: 0,
|
|
transform: 'scale(1)',
|
|
}, {
|
|
offset: 0.5,
|
|
transform: 'scale(1.1)',
|
|
}, {
|
|
offset: 1,
|
|
transform: 'scale(1)',
|
|
}], {
|
|
duration: 100,
|
|
});
|
|
}
|
|
|
|
onMounted(() => {
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" module>
|
|
.root {
|
|
margin: auto;
|
|
position: relative;
|
|
padding: 32px;
|
|
min-width: 320px;
|
|
max-width: 480px;
|
|
box-sizing: border-box;
|
|
background: var(--panel);
|
|
border-radius: var(--radius);
|
|
}
|
|
|
|
.header {
|
|
font-size: 120%;
|
|
}
|
|
|
|
.icon {
|
|
margin-right: 0.5em;
|
|
}
|
|
|
|
.title {
|
|
font-weight: bold;
|
|
}
|
|
|
|
.text {
|
|
margin: 1em 0;
|
|
}
|
|
</style>
|