Merge tag '2023.11.0' into merge-upstream
This commit is contained in:
commit
2bc887a6c5
301 changed files with 9351 additions and 3283 deletions
|
@ -74,7 +74,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkInfo v-if="files.length > 0" warn :class="$style.guidelineInfo" :rounded="false"><Mfm :text="i18n.t('_postForm.guidelineInfo', { tosUrl: instance.tosUrl, nsfwGuideUrl })"/></MkInfo>
|
||||
<XPostFormAttaches v-model="files" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName" @replaceFile="replaceFile"/>
|
||||
<MkPollEditor v-if="poll" v-model="poll" @destroyed="poll = null"/>
|
||||
<MkNotePreview v-if="showPreview" :class="$style.preview" :text="text"/>
|
||||
<MkNotePreview v-if="showPreview" :class="$style.preview" :text="text" :user="postAccount ?? $i"/>
|
||||
<div v-if="showingOptions" style="padding: 8px 16px;">
|
||||
</div>
|
||||
<footer :class="$style.footer">
|
||||
|
@ -99,7 +99,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject, watch, nextTick, onMounted, defineAsyncComponent } from 'vue';
|
||||
import { inject, watch, nextTick, onMounted, defineAsyncComponent, provide } from 'vue';
|
||||
import * as mfm from 'mfm-js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||
|
@ -144,15 +144,22 @@ const props = withDefaults(defineProps<{
|
|||
fixed?: boolean;
|
||||
autofocus?: boolean;
|
||||
freezeAfterPosted?: boolean;
|
||||
mock?: boolean;
|
||||
}>(), {
|
||||
initialVisibleUsers: () => [],
|
||||
autofocus: true,
|
||||
mock: false,
|
||||
});
|
||||
|
||||
provide('mock', props.mock);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'posted'): void;
|
||||
(ev: 'cancel'): void;
|
||||
(ev: 'esc'): void;
|
||||
|
||||
// Mock用
|
||||
(ev: 'fileChangeSensitive', fileId: string, to: boolean): void;
|
||||
}>();
|
||||
|
||||
const textareaEl = $shallowRef<HTMLTextAreaElement | null>(null);
|
||||
|
@ -242,7 +249,7 @@ const maxTextLength = $computed((): number => {
|
|||
});
|
||||
|
||||
const canPost = $computed((): boolean => {
|
||||
return !posting && !posted &&
|
||||
return !props.mock && !posting && !posted &&
|
||||
(1 <= textLength || 1 <= files.length || !!poll || !!props.renote) &&
|
||||
(textLength <= maxTextLength) &&
|
||||
(!poll || poll.choices.length >= 2);
|
||||
|
@ -295,6 +302,10 @@ if (props.reply && props.reply.text != null) {
|
|||
}
|
||||
}
|
||||
|
||||
if ($i?.isSilenced && visibility === 'public') {
|
||||
visibility = 'home';
|
||||
}
|
||||
|
||||
if (props.channel) {
|
||||
visibility = 'public';
|
||||
localOnly = true; // TODO: チャンネルが連合するようになった折には消す
|
||||
|
@ -399,6 +410,8 @@ function focus() {
|
|||
}
|
||||
|
||||
function chooseFileFrom(ev) {
|
||||
if (props.mock) return;
|
||||
|
||||
selectFiles(ev.currentTarget ?? ev.target, i18n.ts.attachFile).then(files_ => {
|
||||
for (const file of files_) {
|
||||
files.push(file);
|
||||
|
@ -411,6 +424,9 @@ function detachFile(id) {
|
|||
}
|
||||
|
||||
function updateFileSensitive(file, sensitive) {
|
||||
if (props.mock) {
|
||||
emit('fileChangeSensitive', file.id, sensitive);
|
||||
}
|
||||
files[files.findIndex(x => x.id === file.id)].isSensitive = sensitive;
|
||||
}
|
||||
|
||||
|
@ -423,6 +439,8 @@ function replaceFile(file: Misskey.entities.DriveFile, newFile: Misskey.entities
|
|||
}
|
||||
|
||||
function upload(file: File, name?: string): void {
|
||||
if (props.mock) return;
|
||||
|
||||
uploadFile(file, defaultStore.state.uploadFolder, name).then(res => {
|
||||
files.push(res);
|
||||
});
|
||||
|
@ -437,6 +455,7 @@ function setVisibility() {
|
|||
|
||||
os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), {
|
||||
currentVisibility: visibility,
|
||||
isSilenced: $i?.isSilenced,
|
||||
localOnly: localOnly,
|
||||
src: visibilityButton,
|
||||
}, {
|
||||
|
@ -548,6 +567,8 @@ function onCompositionEnd(ev: CompositionEvent) {
|
|||
}
|
||||
|
||||
async function onPaste(ev: ClipboardEvent) {
|
||||
if (props.mock) return;
|
||||
|
||||
for (const { item, i } of Array.from(ev.clipboardData.items, (item, i) => ({ item, i }))) {
|
||||
if (item.kind === 'file') {
|
||||
const file = item.getAsFile();
|
||||
|
@ -632,7 +653,7 @@ function onDrop(ev): void {
|
|||
}
|
||||
|
||||
function saveDraft() {
|
||||
if (props.instant) return;
|
||||
if (props.instant || props.mock) return;
|
||||
|
||||
const draftData = JSON.parse(miLocalStorage.getItem('drafts') ?? '{}');
|
||||
|
||||
|
@ -661,6 +682,14 @@ function deleteDraft() {
|
|||
}
|
||||
|
||||
async function post(ev?: MouseEvent) {
|
||||
if (useCw && (cw == null || cw.trim() === '')) {
|
||||
os.alert({
|
||||
type: 'error',
|
||||
text: i18n.ts.cwNotationRequired,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (ev) {
|
||||
const el = ev.currentTarget ?? ev.target;
|
||||
const rect = el.getBoundingClientRect();
|
||||
|
@ -669,6 +698,8 @@ async function post(ev?: MouseEvent) {
|
|||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
||||
}
|
||||
|
||||
if (props.mock) return;
|
||||
|
||||
const annoying =
|
||||
text.includes('$[x2') ||
|
||||
text.includes('$[x3') ||
|
||||
|
@ -834,6 +865,8 @@ function showActions(ev) {
|
|||
let postAccount = $ref<Misskey.entities.UserDetailed | null>(null);
|
||||
|
||||
function openAccountMenu(ev: MouseEvent) {
|
||||
if (props.mock) return;
|
||||
|
||||
openAccountMenu_({
|
||||
withExtraOperation: false,
|
||||
includeCurrentAccount: true,
|
||||
|
@ -864,7 +897,7 @@ onMounted(() => {
|
|||
|
||||
nextTick(() => {
|
||||
// 書きかけの投稿を復元
|
||||
if (!props.instant && !props.mention && !props.specified) {
|
||||
if (!props.instant && !props.mention && !props.specified && !props.mock) {
|
||||
const draft = JSON.parse(miLocalStorage.getItem('drafts') ?? '{}')[draftKey];
|
||||
if (draft) {
|
||||
text = draft.data.text;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue