Merge remote-tracking branch 'misskey-original/develop' into develop
# Conflicts: # packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts
This commit is contained in:
commit
31a9670182
|
@ -22,6 +22,8 @@
|
||||||
### Client
|
### Client
|
||||||
- Enhance: MFMでルビを振れるように
|
- Enhance: MFMでルビを振れるように
|
||||||
- 例: `$[ruby 三須木 みすき]`
|
- 例: `$[ruby 三須木 みすき]`
|
||||||
|
- Enhance: MFMでUNIX時間を指定して日時を表示できるように
|
||||||
|
- 例: `$[unixtime 1701356400]`
|
||||||
- Enhance: プラグインでエラーが発生した場合のハンドリングを強化
|
- Enhance: プラグインでエラーが発生した場合のハンドリングを強化
|
||||||
- Enhance: 細かなUIのブラッシュアップ
|
- Enhance: 細かなUIのブラッシュアップ
|
||||||
- Fix: 効果音が再生されるとデバイスで再生している動画や音声が停止する問題を修正 #12339
|
- Fix: 効果音が再生されるとデバイスで再生している動画や音声が停止する問題を修正 #12339
|
||||||
|
|
9
locales/index.d.ts
vendored
9
locales/index.d.ts
vendored
|
@ -1989,6 +1989,15 @@ export interface Locale {
|
||||||
"yearsAgo": string;
|
"yearsAgo": string;
|
||||||
"invalid": string;
|
"invalid": string;
|
||||||
};
|
};
|
||||||
|
"_timeIn": {
|
||||||
|
"seconds": string;
|
||||||
|
"minutes": string;
|
||||||
|
"hours": string;
|
||||||
|
"days": string;
|
||||||
|
"weeks": string;
|
||||||
|
"months": string;
|
||||||
|
"years": string;
|
||||||
|
};
|
||||||
"_time": {
|
"_time": {
|
||||||
"second": string;
|
"second": string;
|
||||||
"minute": string;
|
"minute": string;
|
||||||
|
|
|
@ -1894,6 +1894,15 @@ _ago:
|
||||||
yearsAgo: "{n}年前"
|
yearsAgo: "{n}年前"
|
||||||
invalid: "ありません"
|
invalid: "ありません"
|
||||||
|
|
||||||
|
_timeIn:
|
||||||
|
seconds: "{n}秒後"
|
||||||
|
minutes: "{n}分後"
|
||||||
|
hours: "{n}時間後"
|
||||||
|
days: "{n}日後"
|
||||||
|
weeks: "{n}週間後"
|
||||||
|
months: "{n}ヶ月後"
|
||||||
|
years: "{n}年後"
|
||||||
|
|
||||||
_time:
|
_time:
|
||||||
second: "秒"
|
second: "秒"
|
||||||
minute: "分"
|
minute: "分"
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { VNode, h } from 'vue';
|
||||||
import * as mfm from 'mfm-js';
|
import * as mfm from 'mfm-js';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import MkUrl from '@/components/global/MkUrl.vue';
|
import MkUrl from '@/components/global/MkUrl.vue';
|
||||||
|
import MkTime from '@/components/global/MkTime.vue';
|
||||||
import MkLink from '@/components/MkLink.vue';
|
import MkLink from '@/components/MkLink.vue';
|
||||||
import MkMention from '@/components/MkMention.vue';
|
import MkMention from '@/components/MkMention.vue';
|
||||||
import MkEmoji from '@/components/global/MkEmoji.vue';
|
import MkEmoji from '@/components/global/MkEmoji.vue';
|
||||||
|
@ -322,6 +323,19 @@ export default function(props: MfmProps) {
|
||||||
url: mixedEmojiUrl
|
url: mixedEmojiUrl
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
case 'unixtime': {
|
||||||
|
const child = token.children[0];
|
||||||
|
const unixtime = parseInt(child.type === 'text' ? child.props.text : '');
|
||||||
|
return h('span', {
|
||||||
|
style: 'display: inline-block; font-size: 90%; border: solid 1px var(--divider); border-radius: 999px; padding: 4px 10px 4px 6px;',
|
||||||
|
}, [
|
||||||
|
h('i', {
|
||||||
|
class: 'ti ti-clock',
|
||||||
|
style: 'margin-right: 0.25em;',
|
||||||
|
}),
|
||||||
|
h(MkTime, { time: unixtime * 1000, mode: 'detail' }),
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (style == null) {
|
if (style == null) {
|
||||||
return h('span', {}, ['$[', token.props.name, ' ', ...genEl(token.children, scale), ']']);
|
return h('span', {}, ['$[', token.props.name, ' ', ...genEl(token.children, scale), ']']);
|
||||||
|
|
|
@ -50,7 +50,15 @@ const relative = $computed<string>(() => {
|
||||||
ago >= 60 ? i18n.t('_ago.minutesAgo', { n: (~~(ago / 60)).toString() }) :
|
ago >= 60 ? i18n.t('_ago.minutesAgo', { n: (~~(ago / 60)).toString() }) :
|
||||||
ago >= 10 ? i18n.t('_ago.secondsAgo', { n: (~~(ago % 60)).toString() }) :
|
ago >= 10 ? i18n.t('_ago.secondsAgo', { n: (~~(ago % 60)).toString() }) :
|
||||||
ago >= -1 ? i18n.ts._ago.justNow :
|
ago >= -1 ? i18n.ts._ago.justNow :
|
||||||
i18n.ts._ago.future);
|
ago < -31536000 ? i18n.t('_timeIn.years', { n: Math.round(-ago / 31536000).toString() }) :
|
||||||
|
ago < -2592000 ? i18n.t('_timeIn.months', { n: Math.round(-ago / 2592000).toString() }) :
|
||||||
|
ago < -604800 ? i18n.t('_timeIn.weeks', { n: Math.round(-ago / 604800).toString() }) :
|
||||||
|
ago < -86400 ? i18n.t('_timeIn.days', { n: Math.round(-ago / 86400).toString() }) :
|
||||||
|
ago < -3600 ? i18n.t('_timeIn.hours', { n: Math.round(-ago / 3600).toString() }) :
|
||||||
|
ago < -60 ? i18n.t('_timeIn.minutes', { n: (~~(-ago / 60)).toString() }) :
|
||||||
|
ago < -10 ? i18n.t('_timeIn.seconds', { n: (~~(-ago % 60)).toString() }) :
|
||||||
|
'?'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
let tickId: number;
|
let tickId: number;
|
||||||
|
|
|
@ -95,4 +95,4 @@ export const DEFAULT_SERVER_ERROR_IMAGE_URL = 'https://xn--931a.moe/assets/error
|
||||||
export const DEFAULT_NOT_FOUND_IMAGE_URL = 'https://xn--931a.moe/assets/not-found.jpg';
|
export const DEFAULT_NOT_FOUND_IMAGE_URL = 'https://xn--931a.moe/assets/not-found.jpg';
|
||||||
export const DEFAULT_INFO_IMAGE_URL = 'https://xn--931a.moe/assets/info.jpg';
|
export const DEFAULT_INFO_IMAGE_URL = 'https://xn--931a.moe/assets/info.jpg';
|
||||||
|
|
||||||
export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'font', 'blur', 'rainbow', 'sparkle', 'rotate', 'ruby'];
|
export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'font', 'blur', 'rainbow', 'sparkle', 'rotate', 'ruby', 'unixtime'];
|
||||||
|
|
|
@ -18,16 +18,16 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkSpacer v-else-if="tab === 'users'" :contentMax="1200">
|
<MkSpacer v-else-if="tab === 'users'" :contentMax="1200">
|
||||||
<div class="_gaps_s">
|
<div class="_gaps_s">
|
||||||
<div v-if="role">{{ role.description }}</div>
|
<div v-if="role">{{ role.description }}</div>
|
||||||
<MkUserList v-if="visiable" :pagination="users" :extractor="(item) => item.user"/>
|
<MkUserList v-if="visible" :pagination="users" :extractor="(item) => item.user"/>
|
||||||
<div v-else-if="!visiable" class="_fullinfo">
|
<div v-else-if="!visible" class="_fullinfo">
|
||||||
<img :src="infoImageUrl" class="_ghost"/>
|
<img :src="infoImageUrl" class="_ghost"/>
|
||||||
<div>{{ i18n.ts.nothing }}</div>
|
<div>{{ i18n.ts.nothing }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</MkSpacer>
|
</MkSpacer>
|
||||||
<MkSpacer v-else-if="tab === 'timeline'" :contentMax="700">
|
<MkSpacer v-else-if="tab === 'timeline'" :contentMax="700">
|
||||||
<MkTimeline v-if="visiable" ref="timeline" src="role" :role="props.role"/>
|
<MkTimeline v-if="visible" ref="timeline" src="role" :role="props.role"/>
|
||||||
<div v-else-if="!visiable" class="_fullinfo">
|
<div v-else-if="!visible" class="_fullinfo">
|
||||||
<img :src="infoImageUrl" class="_ghost"/>
|
<img :src="infoImageUrl" class="_ghost"/>
|
||||||
<div>{{ i18n.ts.nothing }}</div>
|
<div>{{ i18n.ts.nothing }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -55,7 +55,7 @@ const props = withDefaults(defineProps<{
|
||||||
let tab = $ref(props.initialTab);
|
let tab = $ref(props.initialTab);
|
||||||
let role = $ref();
|
let role = $ref();
|
||||||
let error = $ref();
|
let error = $ref();
|
||||||
let visiable = $ref(false);
|
let visible = $ref(false);
|
||||||
|
|
||||||
watch(() => props.role, () => {
|
watch(() => props.role, () => {
|
||||||
os.api('roles/show', {
|
os.api('roles/show', {
|
||||||
|
@ -63,7 +63,7 @@ watch(() => props.role, () => {
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
role = res;
|
role = res;
|
||||||
document.title = `${role?.name} | ${instanceName}`;
|
document.title = `${role?.name} | ${instanceName}`;
|
||||||
visiable = res.isExplorable && res.isPublic;
|
visible = res.isExplorable && res.isPublic;
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
if (err.code === 'NO_SUCH_ROLE') {
|
if (err.code === 'NO_SUCH_ROLE') {
|
||||||
error = i18n.ts.noRole;
|
error = i18n.ts.noRole;
|
||||||
|
|
Loading…
Reference in a new issue