mirror of
https://activitypub.software/TransFem-org/Sharkey
synced 2024-12-22 08:20:10 +00:00
Merge branch 'develop' into future-2024-05-31
This commit is contained in:
commit
b2cbd507fe
44 changed files with 223 additions and 79 deletions
|
@ -760,6 +760,10 @@ noCrawleDescription: "Ask search engines to not index your profile page, notes,
|
||||||
lockedAccountInfo: "Unless you set your note visiblity to \"Followers only\", your notes will be visible to anyone, even if you require followers to be manually approved."
|
lockedAccountInfo: "Unless you set your note visiblity to \"Followers only\", your notes will be visible to anyone, even if you require followers to be manually approved."
|
||||||
alwaysMarkSensitive: "Mark as sensitive by default"
|
alwaysMarkSensitive: "Mark as sensitive by default"
|
||||||
loadRawImages: "Load original images instead of showing thumbnails"
|
loadRawImages: "Load original images instead of showing thumbnails"
|
||||||
|
searchEngine: "Search Engine For Search MFM"
|
||||||
|
searchEngineOther: "Other"
|
||||||
|
searchEngineCustomURIDescription: "The custom URI must be input in the format like \"https://www.google.com/search?q=\\{query}\" or \"https://www.google.com/search?q=%s\"."
|
||||||
|
searchEngineCusomURI: "Custom URI"
|
||||||
disableShowingAnimatedImages: "Don't play animated images"
|
disableShowingAnimatedImages: "Don't play animated images"
|
||||||
highlightSensitiveMedia: "Highlight sensitive media"
|
highlightSensitiveMedia: "Highlight sensitive media"
|
||||||
verificationEmailSent: "A verification email has been sent. Please follow the included link to complete verification."
|
verificationEmailSent: "A verification email has been sent. Please follow the included link to complete verification."
|
||||||
|
@ -1880,6 +1884,7 @@ _aboutMisskey:
|
||||||
morePatrons: "We also appreciate the support of many other helpers not listed here. Thank you! 🥰"
|
morePatrons: "We also appreciate the support of many other helpers not listed here. Thank you! 🥰"
|
||||||
patrons: "Patrons"
|
patrons: "Patrons"
|
||||||
projectMembers: "Project members"
|
projectMembers: "Project members"
|
||||||
|
testers: "Testers"
|
||||||
_displayOfSensitiveMedia:
|
_displayOfSensitiveMedia:
|
||||||
respect: "Hide media marked as sensitive"
|
respect: "Hide media marked as sensitive"
|
||||||
ignore: "Display media marked as sensitive"
|
ignore: "Display media marked as sensitive"
|
||||||
|
|
|
@ -6,7 +6,10 @@ import ts from 'typescript';
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = dirname(__filename);
|
const __dirname = dirname(__filename);
|
||||||
const parameterRegExp = /\{(\w+)\}/g;
|
// braces preceded by backslashes are literal, they don't represent
|
||||||
|
// parameters; they get cleaned up by `locales/index.js` before
|
||||||
|
// getting shipped to the browser
|
||||||
|
const parameterRegExp = /(?<!\\)\{(\w+)\}/g;
|
||||||
|
|
||||||
function createMemberType(item) {
|
function createMemberType(item) {
|
||||||
if (typeof item !== 'string') {
|
if (typeof item !== 'string') {
|
||||||
|
|
20
locales/index.d.ts
vendored
20
locales/index.d.ts
vendored
|
@ -3052,6 +3052,22 @@ export interface Locale extends ILocale {
|
||||||
* 添付画像のサムネイルをオリジナル画質にする
|
* 添付画像のサムネイルをオリジナル画質にする
|
||||||
*/
|
*/
|
||||||
"loadRawImages": string;
|
"loadRawImages": string;
|
||||||
|
/**
|
||||||
|
* 検索MFMの検索エンジン
|
||||||
|
*/
|
||||||
|
"searchEngine": string;
|
||||||
|
/**
|
||||||
|
* 他
|
||||||
|
*/
|
||||||
|
"searchEngineOther": string;
|
||||||
|
/**
|
||||||
|
* カスタム URI は、"https://www.google.com/search?q=\{query}" や "https://www.google.com/search?q=%s" のような形式で入力する必要があります。
|
||||||
|
*/
|
||||||
|
"searchEngineCustomURIDescription": string;
|
||||||
|
/**
|
||||||
|
* カスタム URI
|
||||||
|
*/
|
||||||
|
"searchEngineCusomURI": string;
|
||||||
/**
|
/**
|
||||||
* アニメーション画像を再生しない
|
* アニメーション画像を再生しない
|
||||||
*/
|
*/
|
||||||
|
@ -7304,6 +7320,10 @@ export interface Locale extends ILocale {
|
||||||
* プロジェクトメンバー
|
* プロジェクトメンバー
|
||||||
*/
|
*/
|
||||||
"projectMembers": string;
|
"projectMembers": string;
|
||||||
|
/**
|
||||||
|
* テスター
|
||||||
|
*/
|
||||||
|
"testers": string;
|
||||||
};
|
};
|
||||||
"_displayOfSensitiveMedia": {
|
"_displayOfSensitiveMedia": {
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -49,7 +49,11 @@ const primaries = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 何故か文字列にバックスペース文字が混入することがあり、YAMLが壊れるので取り除く
|
// 何故か文字列にバックスペース文字が混入することがあり、YAMLが壊れるので取り除く
|
||||||
const clean = (text) => text.replace(new RegExp(String.fromCodePoint(0x08), 'g'), '');
|
//
|
||||||
|
// also, we remove the backslashes in front of open braces (the
|
||||||
|
// backslashes are only needed to tell `generateDTS.js` that the
|
||||||
|
// braces do not represent parameters)
|
||||||
|
const clean = (text) => text.replace(new RegExp(String.fromCodePoint(0x08), 'g'), '').replaceAll(new RegExp(/\\+\{/,'g'), '{');
|
||||||
|
|
||||||
export function build() {
|
export function build() {
|
||||||
const locales = languages.reduce((a, c) => (a[c] = yaml.load(clean(fs.readFileSync(new URL(`${c}.yml`, import.meta.url), 'utf-8'))) || {}, a), {});
|
const locales = languages.reduce((a, c) => (a[c] = yaml.load(clean(fs.readFileSync(new URL(`${c}.yml`, import.meta.url), 'utf-8'))) || {}, a), {});
|
||||||
|
|
|
@ -759,6 +759,10 @@ noCrawleDescription: "外部の検索エンジンにあなたのユーザーペ
|
||||||
lockedAccountInfo: "フォローを承認制にしても、ノートの公開範囲を「フォロワー」にしない限り、誰でもあなたのノートを見ることができます。"
|
lockedAccountInfo: "フォローを承認制にしても、ノートの公開範囲を「フォロワー」にしない限り、誰でもあなたのノートを見ることができます。"
|
||||||
alwaysMarkSensitive: "デフォルトでメディアをセンシティブ設定にする"
|
alwaysMarkSensitive: "デフォルトでメディアをセンシティブ設定にする"
|
||||||
loadRawImages: "添付画像のサムネイルをオリジナル画質にする"
|
loadRawImages: "添付画像のサムネイルをオリジナル画質にする"
|
||||||
|
searchEngine: "検索MFMの検索エンジン"
|
||||||
|
searchEngineOther: "他"
|
||||||
|
searchEngineCustomURIDescription: "カスタム URI は、\"https://www.google.com/search?q=\\{query}\" や \"https://www.google.com/search?q=%s\" のような形式で入力する必要があります。"
|
||||||
|
searchEngineCusomURI: "カスタム URI"
|
||||||
disableShowingAnimatedImages: "アニメーション画像を再生しない"
|
disableShowingAnimatedImages: "アニメーション画像を再生しない"
|
||||||
highlightSensitiveMedia: "メディアがセンシティブであることを分かりやすく表示"
|
highlightSensitiveMedia: "メディアがセンシティブであることを分かりやすく表示"
|
||||||
verificationEmailSent: "確認のメールを送信しました。メールに記載されたリンクにアクセスして、設定を完了してください。"
|
verificationEmailSent: "確認のメールを送信しました。メールに記載されたリンクにアクセスして、設定を完了してください。"
|
||||||
|
@ -1903,6 +1907,7 @@ _aboutMisskey:
|
||||||
morePatrons: "他にも多くの方が支援してくれています。ありがとうございます🥰"
|
morePatrons: "他にも多くの方が支援してくれています。ありがとうございます🥰"
|
||||||
patrons: "支援者"
|
patrons: "支援者"
|
||||||
projectMembers: "プロジェクトメンバー"
|
projectMembers: "プロジェクトメンバー"
|
||||||
|
testers: "テスター"
|
||||||
|
|
||||||
_displayOfSensitiveMedia:
|
_displayOfSensitiveMedia:
|
||||||
respect: "センシティブ設定されたメディアを隠す"
|
respect: "センシティブ設定されたメディアを隠す"
|
||||||
|
|
|
@ -132,9 +132,18 @@ export class MfmService {
|
||||||
|
|
||||||
case 'h1':
|
case 'h1':
|
||||||
{
|
{
|
||||||
text += '【';
|
text += '**【';
|
||||||
appendChildren(node.childNodes);
|
appendChildren(node.childNodes);
|
||||||
text += '】\n';
|
text += '】**\n';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'h2':
|
||||||
|
case 'h3':
|
||||||
|
{
|
||||||
|
text += '**';
|
||||||
|
appendChildren(node.childNodes);
|
||||||
|
text += '**\n';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,8 +212,6 @@ export class MfmService {
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
case 'h2':
|
|
||||||
case 'h3':
|
|
||||||
case 'h4':
|
case 'h4':
|
||||||
case 'h5':
|
case 'h5':
|
||||||
case 'h6':
|
case 'h6':
|
||||||
|
|
|
@ -30,8 +30,9 @@ export const meta = {
|
||||||
prohibitMoved: true,
|
prohibitMoved: true,
|
||||||
|
|
||||||
limit: {
|
limit: {
|
||||||
duration: ms('1minute'),
|
duration: ms('1hour'),
|
||||||
max: 5,
|
max: 300,
|
||||||
|
minInterval: ms('1sec'),
|
||||||
},
|
},
|
||||||
|
|
||||||
kind: 'write:notes',
|
kind: 'write:notes',
|
||||||
|
|
|
@ -236,7 +236,7 @@ export async function mainBoot() {
|
||||||
if (Date.now() - lastUsedDate > 1000 * 60 * 60 * 2) {
|
if (Date.now() - lastUsedDate > 1000 * 60 * 60 * 2) {
|
||||||
toast(i18n.tsx.welcomeBackWithName({
|
toast(i18n.tsx.welcomeBackWithName({
|
||||||
name: $i.name || $i.username,
|
name: $i.name || $i.username,
|
||||||
}));
|
}), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
miLocalStorage.setItem('lastUsed', Date.now().toString());
|
miLocalStorage.setItem('lastUsed', Date.now().toString());
|
||||||
|
|
|
@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
<div class="detail">
|
<div class="detail">
|
||||||
<div>
|
<div>
|
||||||
<Mfm :text="report.comment" :linkNavigationBehavior="'window'"/>
|
<Mfm :text="report.comment" :isBlock="true" :linkNavigationBehavior="'window'"/>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div>{{ i18n.ts.reporter }}: <MkA :to="`/admin/user/${report.reporter.id}`" class="_link" :behavior="'window'">@{{ report.reporter.username }}</MkA></div>
|
<div>{{ i18n.ts.reporter }}: <MkA :to="`/admin/user/${report.reporter.id}`" class="_link" :behavior="'window'">@{{ report.reporter.username }}</MkA></div>
|
||||||
|
|
|
@ -15,7 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</span>
|
</span>
|
||||||
<span :class="$style.title">{{ announcement.title }}</span>
|
<span :class="$style.title">{{ announcement.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.text"><Mfm :text="announcement.text"/></div>
|
<div :class="$style.text"><Mfm :text="announcement.text" :isBlock="true" /></div>
|
||||||
<MkButton primary full @click="ok">{{ i18n.ts.ok }}</MkButton>
|
<MkButton primary full @click="ok">{{ i18n.ts.ok }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</MkModal>
|
</MkModal>
|
||||||
|
|
|
@ -26,7 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkLoading v-else-if="type === 'waiting'" :class="$style.iconInner" :em="true"/>
|
<MkLoading v-else-if="type === 'waiting'" :class="$style.iconInner" :em="true"/>
|
||||||
</div>
|
</div>
|
||||||
<header v-if="title" :class="$style.title"><Mfm :text="title"/></header>
|
<header v-if="title" :class="$style.title"><Mfm :text="title"/></header>
|
||||||
<div v-if="text" :class="$style.text"><Mfm :text="text"/></div>
|
<div v-if="text" :class="$style.text"><Mfm :text="text" :isBlock="true" /></div>
|
||||||
<MkInput v-if="input" v-model="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder || undefined" :autocomplete="input.autocomplete" @keydown="onInputKeydown">
|
<MkInput v-if="input" v-model="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder || undefined" :autocomplete="input.autocomplete" @keydown="onInputKeydown">
|
||||||
<template v-if="input.type === 'password'" #prefix><i class="ph-lock ph-bold ph-lg"></i></template>
|
<template v-if="input.type === 'password'" #prefix><i class="ph-lock ph-bold ph-lg"></i></template>
|
||||||
<template #caption>
|
<template #caption>
|
||||||
|
|
|
@ -13,6 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
|
import { defaultStore } from '@/store';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
q: string;
|
q: string;
|
||||||
|
@ -21,9 +22,10 @@ const props = defineProps<{
|
||||||
const query = ref(props.q);
|
const query = ref(props.q);
|
||||||
|
|
||||||
const search = () => {
|
const search = () => {
|
||||||
const sp = new URLSearchParams();
|
const searchQuery = encodeURIComponent(query.value);
|
||||||
sp.append('q', query.value);
|
const searchUrl = defaultStore.state.searchEngine.replace(/{query}|%s\b/g, searchQuery);
|
||||||
window.open(`https://www.google.com/search?${sp.toString()}`, '_blank', 'noopener');
|
|
||||||
|
window.open(searchUrl, '_blank', 'noopener');
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
<div v-if="renoteCollapsed" :class="$style.collapsedRenoteTarget">
|
<div v-if="renoteCollapsed" :class="$style.collapsedRenoteTarget">
|
||||||
<MkAvatar :class="$style.collapsedRenoteTargetAvatar" :user="appearNote.user" link preview/>
|
<MkAvatar :class="$style.collapsedRenoteTargetAvatar" :user="appearNote.user" link preview/>
|
||||||
<Mfm :text="getNoteSummary(appearNote)" :plain="true" :nowrap="true" :author="appearNote.user" :nyaize="'respect'" :class="$style.collapsedRenoteTargetText" @click="renoteCollapsed = false"/>
|
<Mfm :text="getNoteSummary(appearNote)" :isBlock="true" :plain="true" :nowrap="true" :author="appearNote.user" :nyaize="'respect'" :class="$style.collapsedRenoteTargetText" @click="renoteCollapsed = false"/>
|
||||||
</div>
|
</div>
|
||||||
<article v-else :class="$style.article" @contextmenu.stop="onContextmenu">
|
<article v-else :class="$style.article" @contextmenu.stop="onContextmenu">
|
||||||
<div v-if="appearNote.channel" :class="$style.colorBar" :style="{ background: appearNote.channel.color }"></div>
|
<div v-if="appearNote.channel" :class="$style.colorBar" :style="{ background: appearNote.channel.color }"></div>
|
||||||
|
@ -53,8 +53,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkNoteHeader :note="appearNote" :mini="true" @click.stop/>
|
<MkNoteHeader :note="appearNote" :mini="true" @click.stop/>
|
||||||
<MkInstanceTicker v-if="showTicker" :instance="appearNote.user.instance"/>
|
<MkInstanceTicker v-if="showTicker" :instance="appearNote.user.instance"/>
|
||||||
<div style="container-type: inline-size;">
|
<div style="container-type: inline-size;">
|
||||||
|
<bdi>
|
||||||
<p v-if="appearNote.cw != null" :class="$style.cw">
|
<p v-if="appearNote.cw != null" :class="$style.cw">
|
||||||
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :nyaize="'respect'"/>
|
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :isBlock="true" :author="appearNote.user" :nyaize="'respect'"/>
|
||||||
<MkCwButton v-model="showContent" :text="appearNote.text" :renote="appearNote.renote" :files="appearNote.files" :poll="appearNote.poll" style="margin: 4px 0;" @click.stop/>
|
<MkCwButton v-model="showContent" :text="appearNote.text" :renote="appearNote.renote" :files="appearNote.files" :poll="appearNote.poll" style="margin: 4px 0;" @click.stop/>
|
||||||
</p>
|
</p>
|
||||||
<div v-show="appearNote.cw == null || showContent" :class="[{ [$style.contentCollapsed]: collapsed }]">
|
<div v-show="appearNote.cw == null || showContent" :class="[{ [$style.contentCollapsed]: collapsed }]">
|
||||||
|
@ -71,12 +72,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
:enableEmojiMenu="true"
|
:enableEmojiMenu="true"
|
||||||
:enableEmojiMenuReaction="true"
|
:enableEmojiMenuReaction="true"
|
||||||
:isAnim="allowAnim"
|
:isAnim="allowAnim"
|
||||||
|
:isBlock="true"
|
||||||
/>
|
/>
|
||||||
<div v-if="translating || translation" :class="$style.translation">
|
<div v-if="translating || translation" :class="$style.translation">
|
||||||
<MkLoading v-if="translating" mini/>
|
<MkLoading v-if="translating" mini/>
|
||||||
<div v-else-if="translation">
|
<div v-else-if="translation">
|
||||||
<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
|
<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
|
||||||
<Mfm :text="translation.text" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis"/>
|
<Mfm :text="translation.text" :isBlock="true" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MkButton v-if="!allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
|
<MkButton v-if="!allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
|
||||||
|
@ -98,6 +100,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ph-television ph-bold ph-lg"></i> {{ appearNote.channel.name }}</MkA>
|
<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ph-television ph-bold ph-lg"></i> {{ appearNote.channel.name }}</MkA>
|
||||||
|
</bdi>
|
||||||
</div>
|
</div>
|
||||||
<MkReactionsViewer v-if="appearNote.reactionAcceptance !== 'likeOnly'" :note="appearNote" :maxNumber="16" @click.stop @mockUpdateMyReaction="emitUpdReaction">
|
<MkReactionsViewer v-if="appearNote.reactionAcceptance !== 'likeOnly'" :note="appearNote" :maxNumber="16" @click.stop @mockUpdateMyReaction="emitUpdReaction">
|
||||||
<template #more>
|
<template #more>
|
||||||
|
@ -339,7 +342,7 @@ let renoting = false;
|
||||||
const keymap = {
|
const keymap = {
|
||||||
'r': () => reply(true),
|
'r': () => reply(true),
|
||||||
'e|a|plus': () => react(true),
|
'e|a|plus': () => react(true),
|
||||||
'(q)': () => { if (canRenote.value && !renoted.value && !renoting) { renoting = true; renote(appearNote.value.visibility); } },
|
'(q)': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); },
|
||||||
'up|k|shift+tab': focusBefore,
|
'up|k|shift+tab': focusBefore,
|
||||||
'down|j|tab': focusAfter,
|
'down|j|tab': focusAfter,
|
||||||
'esc': blur,
|
'esc': blur,
|
||||||
|
@ -439,6 +442,8 @@ if (!props.mock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function boostVisibility() {
|
function boostVisibility() {
|
||||||
|
if (renoting) return;
|
||||||
|
|
||||||
if (!defaultStore.state.showVisibilitySelectorOnBoost) {
|
if (!defaultStore.state.showVisibilitySelectorOnBoost) {
|
||||||
renote(defaultStore.state.visibilityOnBoost);
|
renote(defaultStore.state.visibilityOnBoost);
|
||||||
} else {
|
} else {
|
||||||
|
@ -450,6 +455,8 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
||||||
pleaseLogin();
|
pleaseLogin();
|
||||||
showMovedDialog();
|
showMovedDialog();
|
||||||
|
|
||||||
|
renoting = true;
|
||||||
|
|
||||||
if (appearNote.value.channel) {
|
if (appearNote.value.channel) {
|
||||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||||
if (el) {
|
if (el) {
|
||||||
|
|
|
@ -68,7 +68,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</header>
|
</header>
|
||||||
<div :class="$style.noteContent">
|
<div :class="$style.noteContent">
|
||||||
<p v-if="appearNote.cw != null" :class="$style.cw">
|
<p v-if="appearNote.cw != null" :class="$style.cw">
|
||||||
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :nyaize="'respect'"/>
|
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :isBlock="true" :author="appearNote.user" :nyaize="'respect'"/>
|
||||||
<MkCwButton v-model="showContent" :text="appearNote.text" :renote="appearNote.renote" :files="appearNote.files" :poll="appearNote.poll"/>
|
<MkCwButton v-model="showContent" :text="appearNote.text" :renote="appearNote.renote" :files="appearNote.files" :poll="appearNote.poll"/>
|
||||||
</p>
|
</p>
|
||||||
<div v-show="appearNote.cw == null || showContent">
|
<div v-show="appearNote.cw == null || showContent">
|
||||||
|
@ -84,13 +84,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
:enableEmojiMenu="true"
|
:enableEmojiMenu="true"
|
||||||
:enableEmojiMenuReaction="true"
|
:enableEmojiMenuReaction="true"
|
||||||
:isAnim="allowAnim"
|
:isAnim="allowAnim"
|
||||||
|
:isBlock="true"
|
||||||
/>
|
/>
|
||||||
<a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
|
<a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
|
||||||
<div v-if="translating || translation" :class="$style.translation">
|
<div v-if="translating || translation" :class="$style.translation">
|
||||||
<MkLoading v-if="translating" mini/>
|
<MkLoading v-if="translating" mini/>
|
||||||
<div v-else-if="translation">
|
<div v-else-if="translation">
|
||||||
<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
|
<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
|
||||||
<Mfm :text="translation.text" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis"/>
|
<Mfm :text="translation.text" :isBlock="true" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MkButton v-if="!allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
|
<MkButton v-if="!allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
|
||||||
|
@ -351,7 +352,7 @@ let renoting = false;
|
||||||
const keymap = {
|
const keymap = {
|
||||||
'r': () => reply(true),
|
'r': () => reply(true),
|
||||||
'e|a|plus': () => react(true),
|
'e|a|plus': () => react(true),
|
||||||
'(q)': () => { if (canRenote.value && !renoted.value && !renoting) { renoting = true; renote(appearNote.value.visibility); } },
|
'(q)': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); },
|
||||||
'esc': blur,
|
'esc': blur,
|
||||||
'm|o': () => showMenu(true),
|
'm|o': () => showMenu(true),
|
||||||
's': () => showContent.value !== showContent.value,
|
's': () => showContent.value !== showContent.value,
|
||||||
|
@ -443,6 +444,8 @@ useTooltip(quoteButton, async (showing) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function boostVisibility() {
|
function boostVisibility() {
|
||||||
|
if (renoting) return;
|
||||||
|
|
||||||
if (!defaultStore.state.showVisibilitySelectorOnBoost) {
|
if (!defaultStore.state.showVisibilitySelectorOnBoost) {
|
||||||
renote(defaultStore.state.visibilityOnBoost);
|
renote(defaultStore.state.visibilityOnBoost);
|
||||||
} else {
|
} else {
|
||||||
|
@ -476,6 +479,8 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
||||||
pleaseLogin();
|
pleaseLogin();
|
||||||
showMovedDialog();
|
showMovedDialog();
|
||||||
|
|
||||||
|
renoting = true;
|
||||||
|
|
||||||
if (appearNote.value.channel) {
|
if (appearNote.value.channel) {
|
||||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||||
if (el) {
|
if (el) {
|
||||||
|
|
|
@ -12,11 +12,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p v-if="useCw" :class="$style.cw">
|
<p v-if="useCw" :class="$style.cw">
|
||||||
<Mfm v-if="cw != null && cw != ''" :text="cw" :author="user" :nyaize="'respect'" :i="user" style="margin-right: 8px;"/>
|
<Mfm v-if="cw != null && cw != ''" :text="cw" :isBlock="true" :author="user" :nyaize="'respect'" :i="user" style="margin-right: 8px;"/>
|
||||||
<MkCwButton v-model="showContent" :text="text.trim()" :files="files" :poll="poll" style="margin: 4px 0;"/>
|
<MkCwButton v-model="showContent" :text="text.trim()" :files="files" :poll="poll" style="margin: 4px 0;"/>
|
||||||
</p>
|
</p>
|
||||||
<div v-show="!useCw || showContent">
|
<div v-show="!useCw || showContent">
|
||||||
<Mfm :text="text.trim()" :author="user" :nyaize="'respect'" :i="user"/>
|
<Mfm :text="text.trim()" :isBlock="true" :author="user" :nyaize="'respect'" :i="user"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkNoteHeader :class="$style.header" :note="note" :mini="true"/>
|
<MkNoteHeader :class="$style.header" :note="note" :mini="true"/>
|
||||||
<div>
|
<div>
|
||||||
<p v-if="note.cw != null" :class="$style.cw">
|
<p v-if="note.cw != null" :class="$style.cw">
|
||||||
<Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :author="note.user" :nyaize="'respect'" :emojiUrls="note.emojis"/>
|
<Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :isBlock="true" :author="note.user" :nyaize="'respect'" :emojiUrls="note.emojis"/>
|
||||||
<MkCwButton v-model="showContent" :text="note.text" :files="note.files" :poll="note.poll" @click.stop/>
|
<MkCwButton v-model="showContent" :text="note.text" :files="note.files" :poll="note.poll" @click.stop/>
|
||||||
</p>
|
</p>
|
||||||
<div v-show="note.cw == null || showContent">
|
<div v-show="note.cw == null || showContent">
|
||||||
|
|
|
@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkNoteHeader :class="$style.header" :note="note" :mini="true"/>
|
<MkNoteHeader :class="$style.header" :note="note" :mini="true"/>
|
||||||
<div :class="$style.content">
|
<div :class="$style.content">
|
||||||
<p v-if="note.cw != null" :class="$style.cw">
|
<p v-if="note.cw != null" :class="$style.cw">
|
||||||
<Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :author="note.user" :nyaize="'respect'"/>
|
<Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :isBlock="true" :author="note.user" :nyaize="'respect'"/>
|
||||||
<MkCwButton v-model="showContent" :text="note.text" :files="note.files" :poll="note.poll"/>
|
<MkCwButton v-model="showContent" :text="note.text" :files="note.files" :poll="note.poll"/>
|
||||||
</p>
|
</p>
|
||||||
<div v-show="note.cw == null || showContent">
|
<div v-show="note.cw == null || showContent">
|
||||||
|
|
|
@ -71,29 +71,29 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<div>
|
<div>
|
||||||
<MkA v-if="notification.type === 'reaction' || notification.type === 'reaction:grouped'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
<MkA v-if="notification.type === 'reaction' || notification.type === 'reaction:grouped'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||||
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
||||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
<Mfm :text="getNoteSummary(notification.note)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
||||||
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
||||||
</MkA>
|
</MkA>
|
||||||
<MkA v-else-if="notification.type === 'renote' || notification.type === 'renote:grouped'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note.renote)">
|
<MkA v-else-if="notification.type === 'renote' || notification.type === 'renote:grouped'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note.renote)">
|
||||||
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
||||||
<Mfm :text="getNoteSummary(notification.note.renote)" :plain="true" :nowrap="true" :author="notification.note.renote?.user"/>
|
<Mfm :text="getNoteSummary(notification.note.renote)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.renote?.user"/>
|
||||||
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
||||||
</MkA>
|
</MkA>
|
||||||
<MkA v-else-if="notification.type === 'reply'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
<MkA v-else-if="notification.type === 'reply'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
<Mfm :text="getNoteSummary(notification.note)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
||||||
</MkA>
|
</MkA>
|
||||||
<MkA v-else-if="notification.type === 'mention'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
<MkA v-else-if="notification.type === 'mention'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
<Mfm :text="getNoteSummary(notification.note)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
||||||
</MkA>
|
</MkA>
|
||||||
<MkA v-else-if="notification.type === 'quote'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
<MkA v-else-if="notification.type === 'quote'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
<Mfm :text="getNoteSummary(notification.note)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
||||||
</MkA>
|
</MkA>
|
||||||
<MkA v-else-if="notification.type === 'note'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
<MkA v-else-if="notification.type === 'note'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
<Mfm :text="getNoteSummary(notification.note)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
||||||
</MkA>
|
</MkA>
|
||||||
<MkA v-else-if="notification.type === 'pollEnded'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
<MkA v-else-if="notification.type === 'pollEnded'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||||
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
||||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
<Mfm :text="getNoteSummary(notification.note)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
||||||
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
||||||
</MkA>
|
</MkA>
|
||||||
<div v-else-if="notification.type === 'roleAssigned'" :class="$style.text">
|
<div v-else-if="notification.type === 'roleAssigned'" :class="$style.text">
|
||||||
|
@ -139,7 +139,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<MkA v-else-if="notification.type === 'edited'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
<MkA v-else-if="notification.type === 'edited'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||||
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
||||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
<Mfm :text="getNoteSummary(notification.note)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.user"/>
|
||||||
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
<i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i>
|
||||||
</MkA>
|
</MkA>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,14 +9,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<span v-if="note.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
|
<span v-if="note.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
|
||||||
<span v-if="note.deletedAt" style="opacity: 0.5">({{ i18n.ts.deletedNote }})</span>
|
<span v-if="note.deletedAt" style="opacity: 0.5">({{ i18n.ts.deletedNote }})</span>
|
||||||
<MkA v-if="note.replyId" :class="$style.reply" :to="`/notes/${note.replyId}`" @click.stop><i class="ph-arrow-bend-left-up ph-bold ph-lg"></i></MkA>
|
<MkA v-if="note.replyId" :class="$style.reply" :to="`/notes/${note.replyId}`" @click.stop><i class="ph-arrow-bend-left-up ph-bold ph-lg"></i></MkA>
|
||||||
<Mfm v-if="note.text" :text="note.text" :author="note.user" :nyaize="'respect'" :isAnim="allowAnim" :emojiUrls="note.emojis"/>
|
<Mfm v-if="note.text" :text="note.text" :isBlock="true" :author="note.user" :nyaize="'respect'" :isAnim="allowAnim" :emojiUrls="note.emojis"/>
|
||||||
<MkButton v-if="!allowAnim && animated && !hideFiles" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
|
<MkButton v-if="!allowAnim && animated && !hideFiles" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
|
||||||
<MkButton v-else-if="!defaultStore.state.animatedMfm && allowAnim && animated && !hideFiles" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-stop ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.stop }}</MkButton>
|
<MkButton v-else-if="!defaultStore.state.animatedMfm && allowAnim && animated && !hideFiles" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-stop ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.stop }}</MkButton>
|
||||||
<div v-if="note.text && translating || note.text && translation" :class="$style.translation">
|
<div v-if="note.text && translating || note.text && translation" :class="$style.translation">
|
||||||
<MkLoading v-if="translating" mini/>
|
<MkLoading v-if="translating" mini/>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
|
<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
|
||||||
<Mfm :text="translation.text" :author="note.user" :nyaize="'respect'" :emojiUrls="note.emojis"/>
|
<Mfm :text="translation.text" :isBlock="true" :author="note.user" :nyaize="'respect'" :emojiUrls="note.emojis"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MkA v-if="note.renoteId" :class="$style.rp" :to="`/notes/${note.renoteId}`" @click.stop>RN: ...</MkA>
|
<MkA v-if="note.renoteId" :class="$style.rp" :to="`/notes/${note.renoteId}`" @click.stop>RN: ...</MkA>
|
||||||
|
|
|
@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<div :class="$style.caption"><slot name="caption"></slot></div>
|
<div :class="$style.caption"><slot name="caption"></slot></div>
|
||||||
<button v-if="mfmPreview" style="font-size: 0.85em;" class="_textButton" type="button" @click="preview = !preview">{{ i18n.ts.preview }}</button>
|
<button v-if="mfmPreview" style="font-size: 0.85em;" class="_textButton" type="button" @click="preview = !preview">{{ i18n.ts.preview }}</button>
|
||||||
<div v-if="mfmPreview" v-show="preview" v-panel :class="$style.mfmPreview">
|
<div v-if="mfmPreview" v-show="preview" v-panel :class="$style.mfmPreview">
|
||||||
<Mfm :text="v"/>
|
<Mfm :text="v" :isBlock="true" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MkButton v-if="manualSave && changed" primary :class="$style.save" @click="updated"><i class="ph-floppy-disk ph-bold ph-lg"></i> {{ i18n.ts.save }}</MkButton>
|
<MkButton v-if="manualSave && changed" primary :class="$style.save" @click="updated"><i class="ph-floppy-disk ph-bold ph-lg"></i> {{ i18n.ts.save }}</MkButton>
|
||||||
|
|
|
@ -14,7 +14,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
>
|
>
|
||||||
<div v-if="showing" class="_acrylic" :class="$style.root" :style="{ zIndex }">
|
<div v-if="showing" class="_acrylic" :class="$style.root" :style="{ zIndex }">
|
||||||
<div style="padding: 16px 24px;">
|
<div style="padding: 16px 24px;">
|
||||||
{{ message }}
|
<Mfm v-if="renderMfm" :text="message" plain/>
|
||||||
|
<template v-else>{{ message }}</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
@ -26,9 +27,12 @@ import { onMounted, ref } from 'vue';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
|
|
||||||
defineProps<{
|
withDefaults(defineProps<{
|
||||||
message: string;
|
message: string;
|
||||||
}>();
|
renderMfm: boolean;
|
||||||
|
}>(), {
|
||||||
|
renderMfm: false,
|
||||||
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'closed'): void;
|
(ev: 'closed'): void;
|
||||||
|
|
|
@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<span v-if="$i && $i.id !== user.id && user.isFollowed" :class="$style.followed">{{ i18n.ts.followsYou }}</span>
|
<span v-if="$i && $i.id !== user.id && user.isFollowed" :class="$style.followed">{{ i18n.ts.followsYou }}</span>
|
||||||
<div :class="$style.description">
|
<div :class="$style.description">
|
||||||
<div v-if="user.description" :class="$style.mfm">
|
<div v-if="user.description" :class="$style.mfm">
|
||||||
<Mfm :text="user.description" :author="user"/>
|
<Mfm :text="user.description" :isBlock="true" :author="user"/>
|
||||||
</div>
|
</div>
|
||||||
<span v-else style="opacity: 0.7;">{{ i18n.ts.noAccountDescription }}</span>
|
<span v-else style="opacity: 0.7;">{{ i18n.ts.noAccountDescription }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<div :class="$style.username"><MkAcct :user="user"/></div>
|
<div :class="$style.username"><MkAcct :user="user"/></div>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.description">
|
<div :class="$style.description">
|
||||||
<Mfm v-if="user.description" :nyaize="false" :class="$style.mfm" :text="user.description" :author="user"/>
|
<Mfm v-if="user.description" :nyaize="false" :class="$style.mfm" :text="user.description" :isBlock="true" :author="user"/>
|
||||||
<div v-else style="opacity: 0.7;">{{ i18n.ts.noAccountDescription }}</div>
|
<div v-else style="opacity: 0.7;">{{ i18n.ts.noAccountDescription }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="user.fields.length > 0" :class="$style.fields">
|
<div v-if="user.fields.length > 0" :class="$style.fields">
|
||||||
|
|
|
@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.description">
|
<div :class="$style.description">
|
||||||
<div v-if="user.description" :class="$style.mfm">
|
<div v-if="user.description" :class="$style.mfm">
|
||||||
<Mfm :text="user.description" :author="user"/>
|
<Mfm :text="user.description" :isBlock="true" :author="user"/>
|
||||||
</div>
|
</div>
|
||||||
<span v-else style="opacity: 0.7;">{{ i18n.ts.noAccountDescription }}</span>
|
<span v-else style="opacity: 0.7;">{{ i18n.ts.noAccountDescription }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -44,7 +44,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
<div v-if="renoteCollapsed" :class="$style.collapsedRenoteTarget">
|
<div v-if="renoteCollapsed" :class="$style.collapsedRenoteTarget">
|
||||||
<MkAvatar :class="$style.collapsedRenoteTargetAvatar" :user="appearNote.user" link preview/>
|
<MkAvatar :class="$style.collapsedRenoteTargetAvatar" :user="appearNote.user" link preview/>
|
||||||
<Mfm :text="getNoteSummary(appearNote)" :plain="true" :nowrap="true" :author="appearNote.user" :nyaize="'respect'" :class="$style.collapsedRenoteTargetText" @click="renoteCollapsed = false"/>
|
<Mfm :text="getNoteSummary(appearNote)" :isBlock="true" :plain="true" :nowrap="true" :author="appearNote.user" :nyaize="'respect'" :class="$style.collapsedRenoteTargetText" @click="renoteCollapsed = false"/>
|
||||||
</div>
|
</div>
|
||||||
<article v-else :class="$style.article" @contextmenu.stop="onContextmenu">
|
<article v-else :class="$style.article" @contextmenu.stop="onContextmenu">
|
||||||
<div style="display: flex; padding-bottom: 10px;">
|
<div style="display: flex; padding-bottom: 10px;">
|
||||||
|
@ -57,7 +57,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<div :class="[{ [$style.clickToOpen]: defaultStore.state.clickToOpen }]" @click.stop="defaultStore.state.clickToOpen ? noteclick(appearNote.id) : undefined">
|
<div :class="[{ [$style.clickToOpen]: defaultStore.state.clickToOpen }]" @click.stop="defaultStore.state.clickToOpen ? noteclick(appearNote.id) : undefined">
|
||||||
<div style="container-type: inline-size;">
|
<div style="container-type: inline-size;">
|
||||||
<p v-if="appearNote.cw != null" :class="$style.cw">
|
<p v-if="appearNote.cw != null" :class="$style.cw">
|
||||||
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :nyaize="'respect'"/>
|
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :isBlock="true" :author="appearNote.user" :nyaize="'respect'"/>
|
||||||
<MkCwButton v-model="showContent" :text="appearNote.text" :renote="appearNote.renote" :files="appearNote.files" :poll="appearNote.poll" style="margin: 4px 0;" @click.stop/>
|
<MkCwButton v-model="showContent" :text="appearNote.text" :renote="appearNote.renote" :files="appearNote.files" :poll="appearNote.poll" style="margin: 4px 0;" @click.stop/>
|
||||||
</p>
|
</p>
|
||||||
<div v-show="appearNote.cw == null || showContent" :class="[{ [$style.contentCollapsed]: collapsed }]">
|
<div v-show="appearNote.cw == null || showContent" :class="[{ [$style.contentCollapsed]: collapsed }]">
|
||||||
|
@ -73,12 +73,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
:enableEmojiMenu="true"
|
:enableEmojiMenu="true"
|
||||||
:enableEmojiMenuReaction="true"
|
:enableEmojiMenuReaction="true"
|
||||||
:isAnim="allowAnim"
|
:isAnim="allowAnim"
|
||||||
|
:isBlock="true"
|
||||||
/>
|
/>
|
||||||
<div v-if="translating || translation" :class="$style.translation">
|
<div v-if="translating || translation" :class="$style.translation">
|
||||||
<MkLoading v-if="translating" mini/>
|
<MkLoading v-if="translating" mini/>
|
||||||
<div v-else-if="translation">
|
<div v-else-if="translation">
|
||||||
<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
|
<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
|
||||||
<Mfm :text="translation.text" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis"/>
|
<Mfm :text="translation.text" :isBlock="true" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MkButton v-if="!allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
|
<MkButton v-if="!allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
|
||||||
|
@ -340,7 +341,7 @@ let renoting = false;
|
||||||
const keymap = {
|
const keymap = {
|
||||||
'r': () => reply(true),
|
'r': () => reply(true),
|
||||||
'e|a|plus': () => react(true),
|
'e|a|plus': () => react(true),
|
||||||
'(q)': () => { if (canRenote.value && !renoted.value && !renoting) { renoting = true; renote(appearNote.value.visibility); } },
|
'(q)': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); },
|
||||||
'up|k|shift+tab': focusBefore,
|
'up|k|shift+tab': focusBefore,
|
||||||
'down|j|tab': focusAfter,
|
'down|j|tab': focusAfter,
|
||||||
'esc': blur,
|
'esc': blur,
|
||||||
|
@ -440,6 +441,8 @@ if (!props.mock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function boostVisibility() {
|
function boostVisibility() {
|
||||||
|
if (renoting) return;
|
||||||
|
|
||||||
if (!defaultStore.state.showVisibilitySelectorOnBoost) {
|
if (!defaultStore.state.showVisibilitySelectorOnBoost) {
|
||||||
renote(defaultStore.state.visibilityOnBoost);
|
renote(defaultStore.state.visibilityOnBoost);
|
||||||
} else {
|
} else {
|
||||||
|
@ -451,6 +454,8 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
||||||
pleaseLogin();
|
pleaseLogin();
|
||||||
showMovedDialog();
|
showMovedDialog();
|
||||||
|
|
||||||
|
renoting = true;
|
||||||
|
|
||||||
if (appearNote.value.channel) {
|
if (appearNote.value.channel) {
|
||||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||||
if (el) {
|
if (el) {
|
||||||
|
|
|
@ -77,7 +77,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</header>
|
</header>
|
||||||
<div :class="$style.noteContent">
|
<div :class="$style.noteContent">
|
||||||
<p v-if="appearNote.cw != null" :class="$style.cw">
|
<p v-if="appearNote.cw != null" :class="$style.cw">
|
||||||
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :nyaize="'respect'"/>
|
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :isBlock="true" :author="appearNote.user" :nyaize="'respect'"/>
|
||||||
<MkCwButton v-model="showContent" :text="appearNote.text" :renote="appearNote.renote" :files="appearNote.files" :poll="appearNote.poll"/>
|
<MkCwButton v-model="showContent" :text="appearNote.text" :renote="appearNote.renote" :files="appearNote.files" :poll="appearNote.poll"/>
|
||||||
</p>
|
</p>
|
||||||
<div v-show="appearNote.cw == null || showContent">
|
<div v-show="appearNote.cw == null || showContent">
|
||||||
|
@ -92,13 +92,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
:enableEmojiMenu="true"
|
:enableEmojiMenu="true"
|
||||||
:enableEmojiMenuReaction="true"
|
:enableEmojiMenuReaction="true"
|
||||||
:isAnim="allowAnim"
|
:isAnim="allowAnim"
|
||||||
|
:isBlock="true"
|
||||||
/>
|
/>
|
||||||
<a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
|
<a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
|
||||||
<div v-if="translating || translation" :class="$style.translation">
|
<div v-if="translating || translation" :class="$style.translation">
|
||||||
<MkLoading v-if="translating" mini/>
|
<MkLoading v-if="translating" mini/>
|
||||||
<div v-else-if="translation">
|
<div v-else-if="translation">
|
||||||
<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
|
<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
|
||||||
<Mfm :text="translation.text" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis"/>
|
<Mfm :text="translation.text" :isBlock="true" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MkButton v-if="!allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
|
<MkButton v-if="!allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
|
||||||
|
@ -360,7 +361,7 @@ let renoting = false;
|
||||||
const keymap = {
|
const keymap = {
|
||||||
'r': () => reply(true),
|
'r': () => reply(true),
|
||||||
'e|a|plus': () => react(true),
|
'e|a|plus': () => react(true),
|
||||||
'(q)': () => { if (canRenote.value && !renoted.value && !renoting) { renoting = true; renote(appearNote.value.visibility); } },
|
'(q)': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); },
|
||||||
'esc': blur,
|
'esc': blur,
|
||||||
'm|o': () => showMenu(true),
|
'm|o': () => showMenu(true),
|
||||||
's': () => showContent.value !== showContent.value,
|
's': () => showContent.value !== showContent.value,
|
||||||
|
@ -452,6 +453,8 @@ useTooltip(quoteButton, async (showing) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function boostVisibility() {
|
function boostVisibility() {
|
||||||
|
if (renoting) return;
|
||||||
|
|
||||||
if (!defaultStore.state.showVisibilitySelectorOnBoost) {
|
if (!defaultStore.state.showVisibilitySelectorOnBoost) {
|
||||||
renote(defaultStore.state.visibilityOnBoost);
|
renote(defaultStore.state.visibilityOnBoost);
|
||||||
} else {
|
} else {
|
||||||
|
@ -485,6 +488,8 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
||||||
pleaseLogin();
|
pleaseLogin();
|
||||||
showMovedDialog();
|
showMovedDialog();
|
||||||
|
|
||||||
|
renoting = true;
|
||||||
|
|
||||||
if (appearNote.value.channel) {
|
if (appearNote.value.channel) {
|
||||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||||
if (el) {
|
if (el) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkNoteHeader :class="$style.header" :classic="true" :note="note" :mini="true"/>
|
<MkNoteHeader :class="$style.header" :classic="true" :note="note" :mini="true"/>
|
||||||
<div>
|
<div>
|
||||||
<p v-if="note.cw != null" :class="$style.cw">
|
<p v-if="note.cw != null" :class="$style.cw">
|
||||||
<Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :author="note.user" :nyaize="'respect'" :emojiUrls="note.emojis"/>
|
<Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :isBlock="true" :author="note.user" :nyaize="'respect'" :emojiUrls="note.emojis"/>
|
||||||
<MkCwButton v-model="showContent" :text="note.text" :files="note.files" :poll="note.poll" @click.stop/>
|
<MkCwButton v-model="showContent" :text="note.text" :files="note.files" :poll="note.poll" @click.stop/>
|
||||||
</p>
|
</p>
|
||||||
<div v-show="note.cw == null || showContent">
|
<div v-show="note.cw == null || showContent">
|
||||||
|
|
|
@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<SkNoteHeader :class="$style.header" :note="note" :classic="true" :mini="true"/>
|
<SkNoteHeader :class="$style.header" :note="note" :classic="true" :mini="true"/>
|
||||||
<div :class="$style.content">
|
<div :class="$style.content">
|
||||||
<p v-if="note.cw != null" :class="$style.cw">
|
<p v-if="note.cw != null" :class="$style.cw">
|
||||||
<Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :author="note.user" :nyaize="'respect'"/>
|
<Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :isBlock="true" :author="note.user" :nyaize="'respect'"/>
|
||||||
<MkCwButton v-model="showContent" :text="note.text" :files="note.files" :poll="note.poll"/>
|
<MkCwButton v-model="showContent" :text="note.text" :files="note.files" :poll="note.poll"/>
|
||||||
</p>
|
</p>
|
||||||
<div v-show="note.cw == null || showContent">
|
<div v-show="note.cw == null || showContent">
|
||||||
|
|
|
@ -29,19 +29,19 @@
|
||||||
</header>
|
</header>
|
||||||
<div :class="$style.noteContent">
|
<div :class="$style.noteContent">
|
||||||
<p v-if="appearNote.cw != null" :class="$style.cw">
|
<p v-if="appearNote.cw != null" :class="$style.cw">
|
||||||
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :nyaize="'account'"/>
|
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :isBlock="true" :author="appearNote.user" :nyaize="'account'"/>
|
||||||
<MkCwButton v-model="showContent" :text="appearNote.text" :files="appearNote.files" :poll="appearNote.poll"/>
|
<MkCwButton v-model="showContent" :text="appearNote.text" :files="appearNote.files" :poll="appearNote.poll"/>
|
||||||
</p>
|
</p>
|
||||||
<div v-show="appearNote.cw == null || showContent">
|
<div v-show="appearNote.cw == null || showContent">
|
||||||
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
|
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
|
||||||
<MkA v-if="appearNote.replyId" :class="$style.noteReplyTarget" :to="`/notes/${appearNote.replyId}`"><i class="ph-arrow-bend-left-up ph-bold ph-lg"></i></MkA>
|
<MkA v-if="appearNote.replyId" :class="$style.noteReplyTarget" :to="`/notes/${appearNote.replyId}`"><i class="ph-arrow-bend-left-up ph-bold ph-lg"></i></MkA>
|
||||||
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :nyaize="'account'" :emojiUrls="appearNote.emojis"/>
|
<Mfm v-if="appearNote.text" :text="appearNote.text" :isBlock="true" :author="appearNote.user" :nyaize="'account'" :emojiUrls="appearNote.emojis"/>
|
||||||
<a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
|
<a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
|
||||||
<div v-if="translating || translation" :class="$style.translation">
|
<div v-if="translating || translation" :class="$style.translation">
|
||||||
<MkLoading v-if="translating" mini/>
|
<MkLoading v-if="translating" mini/>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<b>{{ i18n.t('translatedFrom', { x: translation.sourceLang }) }}: </b>
|
<b>{{ i18n.t('translatedFrom', { x: translation.sourceLang }) }}: </b>
|
||||||
<Mfm :text="translation.text" :author="appearNote.user" :nyaize="'account'" :emojiUrls="appearNote.emojis"/>
|
<Mfm :text="translation.text" :isBlock="true" :author="appearNote.user" :nyaize="'account'" :emojiUrls="appearNote.emojis"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="appearNote.files.length > 0">
|
<div v-if="appearNote.files.length > 0">
|
||||||
|
|
|
@ -46,6 +46,7 @@ type MfmProps = {
|
||||||
enableEmojiMenuReaction?: boolean;
|
enableEmojiMenuReaction?: boolean;
|
||||||
isAnim?: boolean;
|
isAnim?: boolean;
|
||||||
linkNavigationBehavior?: MkABehavior;
|
linkNavigationBehavior?: MkABehavior;
|
||||||
|
isBlock?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type MfmEvents = {
|
type MfmEvents = {
|
||||||
|
@ -77,6 +78,8 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
|
||||||
return c.match(/^[0-9a-f]{3,6}$/i) ? c : null;
|
return c.match(/^[0-9a-f]{3,6}$/i) ? c : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isBlock = props.isBlock ?? false;
|
||||||
|
|
||||||
const MkFormula = defineAsyncComponent(() => import('@/components/MkFormula.vue'));
|
const MkFormula = defineAsyncComponent(() => import('@/components/MkFormula.vue'));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -393,9 +396,9 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'center': {
|
case 'center': {
|
||||||
return [h('bdi', h('div', {
|
return [h('div', {
|
||||||
style: 'text-align:center;',
|
style: 'text-align:center;',
|
||||||
}, genEl(token.children, scale)))];
|
}, h('bdi', genEl(token.children, scale)))];
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'url': {
|
case 'url': {
|
||||||
|
@ -431,7 +434,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'blockCode': {
|
case 'blockCode': {
|
||||||
return [h('bdi', h(MkCode, {
|
return [h('bdi', { class: 'block' }, h(MkCode, {
|
||||||
key: Math.random(),
|
key: Math.random(),
|
||||||
code: token.props.code,
|
code: token.props.code,
|
||||||
lang: token.props.lang ?? undefined,
|
lang: token.props.lang ?? undefined,
|
||||||
|
@ -447,13 +450,13 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
|
||||||
|
|
||||||
case 'quote': {
|
case 'quote': {
|
||||||
if (!props.nowrap) {
|
if (!props.nowrap) {
|
||||||
return [h('bdi', h('div', {
|
return [h('bdi', { class: 'block' }, h('div', {
|
||||||
style: QUOTE_STYLE,
|
style: QUOTE_STYLE,
|
||||||
}, genEl(token.children, scale, true)))];
|
}, h('bdi',genEl(token.children, scale, true))))];
|
||||||
} else {
|
} else {
|
||||||
return [h('bdi', h('span', {
|
return [h('span', {
|
||||||
style: QUOTE_STYLE,
|
style: QUOTE_STYLE,
|
||||||
}, genEl(token.children, scale, true)))];
|
}, h('bdi',genEl(token.children, scale, true)))];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,7 +507,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'mathBlock': {
|
case 'mathBlock': {
|
||||||
return [h('bdi', h(MkFormula, {
|
return [h('bdi', { class: 'block' }, h(MkFormula, {
|
||||||
formula: token.props.formula,
|
formula: token.props.formula,
|
||||||
block: true,
|
block: true,
|
||||||
}))];
|
}))];
|
||||||
|
@ -518,7 +521,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'plain': {
|
case 'plain': {
|
||||||
return [h('span', genEl(token.children, scale, true))];
|
return [h('bdi', h('span', genEl(token.children, scale, true)))];
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
|
@ -530,7 +533,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
|
||||||
}
|
}
|
||||||
}).flat(Infinity) as (VNode | string)[];
|
}).flat(Infinity) as (VNode | string)[];
|
||||||
|
|
||||||
return h('bdi', h('span', {
|
return h('bdi', { ...( isBlock ? { class: 'block' } : {}) }, h('span', {
|
||||||
// https://codeday.me/jp/qa/20190424/690106.html
|
// https://codeday.me/jp/qa/20190424/690106.html
|
||||||
style: props.nowrap ? 'white-space: pre; word-wrap: normal; overflow: hidden; text-overflow: ellipsis;' : 'white-space: pre-wrap;',
|
style: props.nowrap ? 'white-space: pre; word-wrap: normal; overflow: hidden; text-overflow: ellipsis;' : 'white-space: pre-wrap;',
|
||||||
}, genEl(rootAst, props.rootScale ?? 1)));
|
}, genEl(rootAst, props.rootScale ?? 1)));
|
||||||
|
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="_gaps" :class="$style.textRoot">
|
<div class="_gaps" :class="$style.textRoot">
|
||||||
<Mfm :text="block.text ?? ''" :isNote="false"/>
|
<Mfm :text="block.text ?? ''" :isBlock="true" :isNote="false"/>
|
||||||
<div v-if="isEnabledUrlPreview" class="_gaps_s">
|
<div v-if="isEnabledUrlPreview" class="_gaps_s">
|
||||||
<MkUrlPreview v-for="url in urls" :key="url" :url="url"/>
|
<MkUrlPreview v-for="url in urls" :key="url" :url="url"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -211,9 +211,10 @@ export function pageWindow(path: string) {
|
||||||
}, {}, 'closed');
|
}, {}, 'closed');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toast(message: string) {
|
export function toast(message: string, renderMfm = false) {
|
||||||
popup(MkToast, {
|
popup(MkToast, {
|
||||||
message,
|
message,
|
||||||
|
renderMfm,
|
||||||
}, {}, 'closed');
|
}, {}, 'closed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,8 +105,29 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<img src="https://secure.gravatar.com/avatar/ea0ea6451fdb74311efad369bdce018e?s=80&d=identicon" :class="$style.contributorAvatar">
|
<img src="https://secure.gravatar.com/avatar/ea0ea6451fdb74311efad369bdce018e?s=80&d=identicon" :class="$style.contributorAvatar">
|
||||||
<span :class="$style.contributorUsername">@fEmber</span>
|
<span :class="$style.contributorUsername">@fEmber</span>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="https://activitypub.software/tess" target="_blank" :class="$style.contributor">
|
||||||
|
<img src="https://activitypub.software/uploads/-/system/user/avatar/132/avatar.png?width=128" :class="$style.contributorAvatar">
|
||||||
|
<span :class="$style.contributorUsername">@tess</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<template #description><MkLink url="https://activitypub.software/TransFem-org/Sharkey/-/graphs/develop">{{ i18n.ts._aboutMisskey.allContributors }}</MkLink></template>
|
||||||
|
</FormSection>
|
||||||
|
<FormSection>
|
||||||
|
<template #label>{{ i18n.ts._aboutMisskey.testers }}</template>
|
||||||
|
<div :class="$style.contributors" style="margin-bottom: 8px;">
|
||||||
|
<a href="https://antani.cyou/@lucent" target="_blank" :class="$style.contributor">
|
||||||
|
<img src="https://antani.cyou/proxy/avatar.webp?url=https%3A%2F%2Fantani.cyou%2Ffiles%2Fa2944119-024c-4abd-86e5-64bf0d30b26f&avatar=1" :class="$style.contributorAvatar">
|
||||||
|
<span :class="$style.contributorUsername">@lucent</span>
|
||||||
|
</a>
|
||||||
|
<a href="https://karilaa.app/@karilaa" target="_blank" :class="$style.contributor">
|
||||||
|
<img src="https://karilaa.app/proxy/avatar.webp?url=https%3A%2F%2Fkarilaa.app%2Ffiles%2Fc366e6f9-96d8-4d3b-b996-30e0a7cb3c5a&avatar=1" :class="$style.contributorAvatar">
|
||||||
|
<span :class="$style.contributorUsername">@karilaa</span>
|
||||||
|
</a>
|
||||||
|
<a href="https://thetransagenda.gay/@phoenix_fairy" target="_blank" :class="$style.contributor">
|
||||||
|
<img src="https://thetransagenda.gay/proxy/avatar.webp?url=https%3A%2F%2Fs3.us-east-005.backblazeb2.com%2Ftranssharkey%2Fnull%2Fd93ac6dc-2020-4b5a-bce7-84b41e97a0ac.png&avatar=1" :class="$style.contributorAvatar">
|
||||||
|
<span :class="$style.contributorUsername">@phoenix_fairy</span>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<template #caption><MkLink url="https://activitypub.software/TransFem-org/Sharkey/-/graphs/develop">{{ i18n.ts._aboutMisskey.allContributors }}</MkLink></template>
|
|
||||||
</FormSection>
|
</FormSection>
|
||||||
<FormSection>
|
<FormSection>
|
||||||
<template #label>Misskey Contributors</template>
|
<template #label>Misskey Contributors</template>
|
||||||
|
|
|
@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkA :to="`/announcements/${announcement.id}`"><span>{{ announcement.title }}</span></MkA>
|
<MkA :to="`/announcements/${announcement.id}`"><span>{{ announcement.title }}</span></MkA>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.content">
|
<div :class="$style.content">
|
||||||
<Mfm :text="announcement.text"/>
|
<Mfm :text="announcement.text" :isBlock="true" />
|
||||||
<img v-if="announcement.imageUrl" :src="announcement.imageUrl"/>
|
<img v-if="announcement.imageUrl" :src="announcement.imageUrl"/>
|
||||||
<MkA :to="`/announcements/${announcement.id}`">
|
<MkA :to="`/announcements/${announcement.id}`">
|
||||||
<div style="margin-top: 8px; opacity: 0.7; font-size: 85%;">
|
<div style="margin-top: 8px; opacity: 0.7; font-size: 85%;">
|
||||||
|
|
|
@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<div :class="$style.bannerFade"></div>
|
<div :class="$style.bannerFade"></div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="channel.description" :class="$style.description">
|
<div v-if="channel.description" :class="$style.description">
|
||||||
<Mfm :text="channel.description" :isNote="false"/>
|
<Mfm :text="channel.description" :isBlock="true" :isNote="false"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<div class="_panel">
|
<div class="_panel">
|
||||||
<div class="_gaps_s" :class="$style.description">
|
<div class="_gaps_s" :class="$style.description">
|
||||||
<div v-if="clip.description">
|
<div v-if="clip.description">
|
||||||
<Mfm :text="clip.description" :isNote="false"/>
|
<Mfm :text="clip.description" :isBlock="true" :isNote="false"/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>({{ i18n.ts.noDescription }})</div>
|
<div v-else>({{ i18n.ts.noDescription }})</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -29,7 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<div v-else :class="$style.ready">
|
<div v-else :class="$style.ready">
|
||||||
<div class="_panel main">
|
<div class="_panel main">
|
||||||
<div class="title">{{ flash.title }}</div>
|
<div class="title">{{ flash.title }}</div>
|
||||||
<div class="summary"><Mfm :text="flash.summary"/></div>
|
<div class="summary"><Mfm :text="flash.summary" :isBlock="true"/></div>
|
||||||
<MkButton class="start" gradate rounded large @click="start">Play</MkButton>
|
<MkButton class="start" gradate rounded large @click="start">Play</MkButton>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<span v-tooltip="i18n.ts.numberOfLikes"><i class="ph-heart ph-bold ph-lg"></i> {{ flash.likedCount }}</span>
|
<span v-tooltip="i18n.ts.numberOfLikes"><i class="ph-heart ph-bold ph-lg"></i> {{ flash.likedCount }}</span>
|
||||||
|
|
|
@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div class="title">{{ post.title }}</div>
|
<div class="title">{{ post.title }}</div>
|
||||||
<div class="description"><Mfm :text="post.description"/></div>
|
<div class="description"><Mfm :text="post.description" :isBlock="true"/></div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<i class="ph-clock ph-bold ph-lg"></i> <MkTime :time="post.createdAt" mode="detail"/>
|
<i class="ph-clock ph-bold ph-lg"></i> <MkTime :time="post.createdAt" mode="detail"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -67,6 +67,28 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkSwitch v-model="showGapBetweenNotesInTimeline">{{ i18n.ts.showGapBetweenNotesInTimeline }}</MkSwitch>
|
<MkSwitch v-model="showGapBetweenNotesInTimeline">{{ i18n.ts.showGapBetweenNotesInTimeline }}</MkSwitch>
|
||||||
<MkSwitch v-model="loadRawImages">{{ i18n.ts.loadRawImages }}</MkSwitch>
|
<MkSwitch v-model="loadRawImages">{{ i18n.ts.loadRawImages }}</MkSwitch>
|
||||||
<MkSwitch v-model="showTickerOnReplies">Show instance ticker on replies</MkSwitch>
|
<MkSwitch v-model="showTickerOnReplies">Show instance ticker on replies</MkSwitch>
|
||||||
|
<MkSelect v-model="searchEngine" placeholder="Other">
|
||||||
|
<template #label>{{ i18n.ts.searchEngine }}</template>
|
||||||
|
<option
|
||||||
|
v-for="[key, value] in Object.entries(searchEngineMap)" :key="key" :value="key"
|
||||||
|
>
|
||||||
|
{{ value }}
|
||||||
|
</option>
|
||||||
|
<!-- If the user is on Other and enters a domain add this one so that the dropdown doesnt go blank -->
|
||||||
|
<option v-if="useCustomSearchEngine" :value="searchEngine">
|
||||||
|
{{ i18n.ts.searchEngineOther }}
|
||||||
|
</option>
|
||||||
|
<!-- If one of the other options is selected show this as a blank other -->
|
||||||
|
<option v-if="!useCustomSearchEngine" value="">{{ i18n.ts.searchEngineOther }}</option>
|
||||||
|
</MkSelect>
|
||||||
|
|
||||||
|
<div v-if="useCustomSearchEngine">
|
||||||
|
<MkInput v-model="searchEngine" :max="300">
|
||||||
|
<template #label>{{ i18n.ts.searchEngineCusomURI }}</template>
|
||||||
|
<template #caption>{{ i18n.ts.searchEngineCustomURIDescription }}</template>
|
||||||
|
</MkInput>
|
||||||
|
</div>
|
||||||
|
|
||||||
<MkRadios v-model="reactionsDisplaySize">
|
<MkRadios v-model="reactionsDisplaySize">
|
||||||
<template #label>{{ i18n.ts.reactionsDisplaySize }}</template>
|
<template #label>{{ i18n.ts.reactionsDisplaySize }}</template>
|
||||||
<option value="small">{{ i18n.ts.small }}</option>
|
<option value="small">{{ i18n.ts.small }}</option>
|
||||||
|
@ -279,11 +301,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, reactive, ref, watch } from 'vue';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import MkSwitch from '@/components/MkSwitch.vue';
|
import MkSwitch from '@/components/MkSwitch.vue';
|
||||||
import MkSelect from '@/components/MkSelect.vue';
|
import MkSelect from '@/components/MkSelect.vue';
|
||||||
import MkRadios from '@/components/MkRadios.vue';
|
import MkRadios from '@/components/MkRadios.vue';
|
||||||
|
import MkInput from '@/components/MkInput.vue';
|
||||||
import MkRange from '@/components/MkRange.vue';
|
import MkRange from '@/components/MkRange.vue';
|
||||||
import MkFolder from '@/components/MkFolder.vue';
|
import MkFolder from '@/components/MkFolder.vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
|
@ -292,6 +315,7 @@ import FormLink from '@/components/form/link.vue';
|
||||||
import MkLink from '@/components/MkLink.vue';
|
import MkLink from '@/components/MkLink.vue';
|
||||||
import MkInfo from '@/components/MkInfo.vue';
|
import MkInfo from '@/components/MkInfo.vue';
|
||||||
import { langs } from '@/config.js';
|
import { langs } from '@/config.js';
|
||||||
|
import { searchEngineMap } from '@/scripts/search-engine-map.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
|
@ -373,6 +397,9 @@ const keepScreenOn = computed(defaultStore.makeGetterSetter('keepScreenOn'));
|
||||||
const disableStreamingTimeline = computed(defaultStore.makeGetterSetter('disableStreamingTimeline'));
|
const disableStreamingTimeline = computed(defaultStore.makeGetterSetter('disableStreamingTimeline'));
|
||||||
const useGroupedNotifications = computed(defaultStore.makeGetterSetter('useGroupedNotifications'));
|
const useGroupedNotifications = computed(defaultStore.makeGetterSetter('useGroupedNotifications'));
|
||||||
const showTickerOnReplies = computed(defaultStore.makeGetterSetter('showTickerOnReplies'));
|
const showTickerOnReplies = computed(defaultStore.makeGetterSetter('showTickerOnReplies'));
|
||||||
|
//const searchEngine = computed(defaultStore.makeGetterSetter('searchEngine'));
|
||||||
|
const searchEngine = computed(defaultStore.makeGetterSetter('searchEngine'));
|
||||||
|
|
||||||
const noteDesign = computed(defaultStore.makeGetterSetter('noteDesign'));
|
const noteDesign = computed(defaultStore.makeGetterSetter('noteDesign'));
|
||||||
const uncollapseCW = computed(defaultStore.makeGetterSetter('uncollapseCW'));
|
const uncollapseCW = computed(defaultStore.makeGetterSetter('uncollapseCW'));
|
||||||
const expandLongNote = computed(defaultStore.makeGetterSetter('expandLongNote'));
|
const expandLongNote = computed(defaultStore.makeGetterSetter('expandLongNote'));
|
||||||
|
@ -563,4 +590,6 @@ definePageMetadata(() => ({
|
||||||
title: i18n.ts.general,
|
title: i18n.ts.general,
|
||||||
icon: 'ph-faders ph-bold ph-lg',
|
icon: 'ph-faders ph-bold ph-lg',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const useCustomSearchEngine = computed(() => !Object.keys(searchEngineMap).includes(searchEngine.value));
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -74,7 +74,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<Mfm v-if="user.description" :text="user.description" :isNote="false" :author="user"/>
|
<Mfm v-if="user.description" :text="user.description" :isBlock="true" :isNote="false" :author="user"/>
|
||||||
<p v-else class="empty">{{ i18n.ts.noAccountDescription }}</p>
|
<p v-else class="empty">{{ i18n.ts.noAccountDescription }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="fields system">
|
<div class="fields system">
|
||||||
|
|
|
@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<div class="_panel" :class="$style.content">
|
<div class="_panel" :class="$style.content">
|
||||||
<div>
|
<div>
|
||||||
<MkA v-if="note.replyId" class="reply" :to="`/notes/${note.replyId}`"><i class="ph-arrow-u-up-left ph-bold ph-lg"></i></MkA>
|
<MkA v-if="note.replyId" class="reply" :to="`/notes/${note.replyId}`"><i class="ph-arrow-u-up-left ph-bold ph-lg"></i></MkA>
|
||||||
<Mfm v-if="note.text" :text="note.text" :author="note.user"/>
|
<Mfm v-if="note.text" :text="note.text" :isBlock="true" :author="note.user"/>
|
||||||
<MkA v-if="note.renoteId" class="rp" :to="`/notes/${note.renoteId}`">RN: ...</MkA>
|
<MkA v-if="note.renoteId" class="rp" :to="`/notes/${note.renoteId}`">RN: ...</MkA>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="note.files.length > 0" :class="$style.richcontent">
|
<div v-if="note.files.length > 0" :class="$style.richcontent">
|
||||||
|
|
12
packages/frontend/src/scripts/search-engine-map.ts
Normal file
12
packages/frontend/src/scripts/search-engine-map.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
//store the URL and if its none of these its a custom one
|
||||||
|
export const searchEngineMap = {
|
||||||
|
//The first one is the default search engine
|
||||||
|
'https://www.google.com/search?q={query}': 'Google',
|
||||||
|
'https://duckduckgo.com/?q={query}': 'Duckduckgo',
|
||||||
|
'https://www.bing.com/search?q={query}': 'Bing',
|
||||||
|
'https://search.yahoo.com/search?p={query}': 'Yahoo',
|
||||||
|
'https://www.ecosia.org/search?q={query}': 'Ecosia',
|
||||||
|
'https://www.qwant.com/?q={query}': 'Qwant',
|
||||||
|
'https://search.aol.com/aol/search?q={query}': 'AOL',
|
||||||
|
'https://yandex.com/search?text={query}': 'Yandex',
|
||||||
|
};
|
|
@ -6,6 +6,7 @@
|
||||||
import { markRaw, ref } from 'vue';
|
import { markRaw, ref } from 'vue';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import { miLocalStorage } from './local-storage.js';
|
import { miLocalStorage } from './local-storage.js';
|
||||||
|
import { searchEngineMap } from './scripts/search-engine-map.js';
|
||||||
import type { SoundType } from '@/scripts/sound.js';
|
import type { SoundType } from '@/scripts/sound.js';
|
||||||
import { Storage } from '@/pizzax.js';
|
import { Storage } from '@/pizzax.js';
|
||||||
import { hemisphere } from '@/scripts/intl-const.js';
|
import { hemisphere } from '@/scripts/intl-const.js';
|
||||||
|
@ -311,6 +312,10 @@ export const defaultStore = markRaw(new Storage('base', {
|
||||||
where: 'device',
|
where: 'device',
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
searchEngine: {
|
||||||
|
where: 'account',
|
||||||
|
default: Object.keys(searchEngineMap)[0],
|
||||||
|
},
|
||||||
noteDesign: {
|
noteDesign: {
|
||||||
where: 'device',
|
where: 'device',
|
||||||
default: 'sharkey' as 'sharkey' | 'misskey',
|
default: 'sharkey' as 'sharkey' | 'misskey',
|
||||||
|
|
|
@ -565,7 +565,7 @@ html[data-color-mode=dark] ._woodenFrame {
|
||||||
|
|
||||||
// MFM -----------------------------
|
// MFM -----------------------------
|
||||||
|
|
||||||
div > bdi, p > bdi { display: block }
|
bdi.block { display: block }
|
||||||
|
|
||||||
._mfm_blur_ {
|
._mfm_blur_ {
|
||||||
filter: blur(6px);
|
filter: blur(6px);
|
||||||
|
|
Loading…
Reference in a new issue