Merge remote-tracking branch 'misskey-original/develop' into develop
# Conflicts: # package.json # packages/backend/src/server/api/stream/ChannelsService.ts # packages/frontend/src/components/MkPostForm.vue # packages/frontend/src/pages/custom-emojis-manager.vue # packages/frontend/src/pages/settings/mute-block.vue
This commit is contained in:
commit
d19a4ab8a3
208 changed files with 1404 additions and 740 deletions
|
|
@ -38,14 +38,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkDriveFileThumbnail from '@/components/MkDriveFileThumbnail.vue';
|
||||
import bytes from '@/filters/bytes.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { dateString } from '@/filters/date.js';
|
||||
|
||||
const props = defineProps<{
|
||||
pagination: Paging;
|
||||
pagination: any;
|
||||
viewMode: 'grid' | 'list';
|
||||
}>();
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ import { claimAchievement } from '@/scripts/achievements.js';
|
|||
import MkRippleEffect from '@/components/MkRippleEffect.vue';
|
||||
import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
|
||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkReactionIcon from '@/components/MkReactionIcon.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
||||
|
|
@ -333,7 +333,7 @@ const renotesPagination = computed(() => ({
|
|||
params: {
|
||||
noteId: appearNote.value.id,
|
||||
},
|
||||
} satisfies Paging));
|
||||
}));
|
||||
|
||||
const reactionsPagination = computed(() => ({
|
||||
endpoint: 'notes/reactions',
|
||||
|
|
@ -342,7 +342,7 @@ const reactionsPagination = computed(() => ({
|
|||
noteId: appearNote.value.id,
|
||||
type: reactionTabType.value,
|
||||
},
|
||||
} satisfies Paging));
|
||||
}));
|
||||
|
||||
useNoteCapture({
|
||||
rootEl: el,
|
||||
|
|
|
|||
|
|
@ -85,9 +85,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<button v-tooltip="i18n.ts.hashtags" class="_button" :class="[$style.footerButton, { [$style.footerButtonActive]: withHashtags }]" @click="withHashtags = !withHashtags"><i class="ti ti-hash"></i></button>
|
||||
<button v-if="postFormActions.length > 0" v-tooltip="i18n.ts.plugin" class="_button" :class="$style.footerButton" @click="showActions"><i class="ti ti-plug"></i></button>
|
||||
<button v-tooltip="i18n.ts.emoji" :class="['_button', $style.footerButton]" @click="insertEmoji"><i class="ti ti-mood-happy"></i></button>
|
||||
<button v-tooltip="i18n.ts.mfm" :class="['_button', $style.footerButton]" @click="insertMfm"><i class="ti ti-wand"></i></button>
|
||||
<button v-tooltip="i18n.ts.ruby" :class="['_button', $style.footerButton]" @click="insertRuby"><i class="ti ti-abc"></i></button>
|
||||
</div>
|
||||
<button v-if="showAddMfmFunction" v-tooltip="i18n.ts.addMfmFunction" :class="['_button', $style.footerButton]" @click="insertMfmFunction"><i class="ti ti-palette"></i></button>
|
||||
<button v-tooltip="i18n.ts.ruby" :class="['_button', $style.footerButton]" @click="insertRuby"><i class="ti ti-abc"></i></button>
|
||||
</div>
|
||||
<div :class="$style.footerRight">
|
||||
<button v-tooltip="i18n.ts.previewNoteText" class="_button" :class="[$style.footerButton, { [$style.previewButtonActive]: showPreview }]" @click="showPreview = !showPreview"><i class="ti ti-eye"></i></button>
|
||||
<!--<button v-tooltip="i18n.ts.more" class="_button" :class="$style.footerButton" @click="showingOptions = !showingOptions"><i class="ti ti-dots"></i></button>-->
|
||||
|
|
@ -136,8 +136,7 @@ import MkRippleEffect from '@/components/MkRippleEffect.vue';
|
|||
import { miLocalStorage } from '@/local-storage.js';
|
||||
import { claimAchievement } from '@/scripts/achievements.js';
|
||||
import { emojiPicker } from '@/scripts/emoji-picker.js';
|
||||
import MkScheduleEditor from '@/components/MkScheduleEditor.vue';
|
||||
import { listSchedulePost } from '@/os.js';
|
||||
import { mfmFunctionPicker } from '@/scripts/mfm-function-picker.js';
|
||||
|
||||
const modal = inject('modal');
|
||||
let gamingType = computed(defaultStore.makeGetterSetter('gamingType'));
|
||||
|
|
@ -200,6 +199,8 @@ let schedule = ref<{
|
|||
const useCw = ref<boolean>(!!props.initialCw);
|
||||
const showPreview = ref(defaultStore.state.showPreview);
|
||||
watch(showPreview, () => defaultStore.set('showPreview', showPreview.value));
|
||||
const showAddMfmFunction = ref(defaultStore.state.enableQuickAddMfmFunction);
|
||||
watch(showAddMfmFunction, () => defaultStore.set('enableQuickAddMfmFunction', showAddMfmFunction.value));
|
||||
const cw = ref<string | null>(props.initialCw ?? null);
|
||||
const localOnly = ref<boolean>(props.initialLocalOnly ?? defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly);
|
||||
const visibility = ref(props.initialVisibility ?? (defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility) as typeof Misskey.noteVisibilities[number]);
|
||||
|
|
@ -891,12 +892,15 @@ async function insertEmoji(ev: MouseEvent) {
|
|||
},
|
||||
);
|
||||
}
|
||||
function insertMfm(){
|
||||
insertTextAtCursor(textareaEl.value, '$');
|
||||
}
|
||||
function insertRuby() {
|
||||
insertTextAtCursor(textareaEl.value, '$[ruby 本文 上につくやつ]');
|
||||
|
||||
async function insertMfmFunction(ev: MouseEvent) {
|
||||
mfmFunctionPicker(
|
||||
ev.currentTarget ?? ev.target,
|
||||
textareaEl.value,
|
||||
text,
|
||||
);
|
||||
}
|
||||
|
||||
function showActions(ev) {
|
||||
os.popupMenu(postFormActions.map(action => ({
|
||||
text: action.title,
|
||||
|
|
|
|||
|
|
@ -224,7 +224,8 @@ if (!mock) {
|
|||
}
|
||||
|
||||
.limitWidth {
|
||||
max-width: 150px;
|
||||
max-width: 70px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.count {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkButton inline @click="enableAll">{{ i18n.ts.enableAll }}</MkButton>
|
||||
</div>
|
||||
<div class="_gaps_s">
|
||||
<MkSwitch v-for="kind in (initialPermissions || Misskey.permissions)" :key="kind" v-model="permissions[kind]">{{ i18n.t(`_permissions.${kind}`) }}</MkSwitch>
|
||||
<MkSwitch v-for="kind in Object.keys(permissions)" :key="kind" v-model="permissions[kind]">{{ i18n.t(`_permissions.${kind}`) }}</MkSwitch>
|
||||
</div>
|
||||
</div>
|
||||
</MkSpacer>
|
||||
|
|
@ -54,7 +54,7 @@ const props = withDefaults(defineProps<{
|
|||
title?: string | null;
|
||||
information?: string | null;
|
||||
initialName?: string | null;
|
||||
initialPermissions?: string[] | null;
|
||||
initialPermissions?: (typeof Misskey.permissions)[number][] | null;
|
||||
}>(), {
|
||||
title: null,
|
||||
information: null,
|
||||
|
|
@ -67,16 +67,17 @@ const emit = defineEmits<{
|
|||
(ev: 'done', result: { name: string | null, permissions: string[] }): void;
|
||||
}>();
|
||||
|
||||
const defaultPermissions = Misskey.permissions.filter(p => !p.startsWith('read:admin') && !p.startsWith('write:admin'));
|
||||
const dialog = shallowRef<InstanceType<typeof MkModalWindow>>();
|
||||
const name = ref(props.initialName);
|
||||
const permissions = ref({});
|
||||
const permissions = ref(<Record<(typeof Misskey.permissions)[number], boolean>>{});
|
||||
|
||||
if (props.initialPermissions) {
|
||||
for (const kind of props.initialPermissions) {
|
||||
permissions.value[kind] = true;
|
||||
}
|
||||
} else {
|
||||
for (const kind of Misskey.permissions) {
|
||||
for (const kind of defaultPermissions) {
|
||||
permissions.value[kind] = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,15 +37,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
import { i18n } from '@/i18n.js';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import XUser from '@/components/MkUserSetupDialog.User.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
|
||||
const pinnedUsers = { endpoint: 'pinned-users', noPaging: true } satisfies Paging;
|
||||
const pinnedUsers = { endpoint: 'pinned-users', noPaging: true };
|
||||
|
||||
const popularUsers = { endpoint: 'users', limit: 10, noPaging: true, params: {
|
||||
state: 'alive',
|
||||
origin: 'local',
|
||||
sort: '+follower',
|
||||
} } satisfies Paging;
|
||||
} };
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
|
|
|||
|
|
@ -292,13 +292,13 @@ export default function(props: MfmProps, context: SetupContext<MfmEvents>) {
|
|||
case 'fg': {
|
||||
let color = token.props.args.color;
|
||||
if (!/^[0-9a-f]{3,6}$/i.test(color)) color = 'f00';
|
||||
style = `color: #${color};`;
|
||||
style = `color: #${color}; overflow-wrap: anywhere;`;
|
||||
break;
|
||||
}
|
||||
case 'bg': {
|
||||
let color = token.props.args.color;
|
||||
if (!/^[0-9a-f]{3,6}$/i.test(color)) color = 'f00';
|
||||
style = `background-color: #${color};`;
|
||||
style = `background-color: #${color}; overflow-wrap: anywhere;`;
|
||||
break;
|
||||
}
|
||||
case 'ruby': {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<img src="https://avatars.githubusercontent.com/u/40626578?v=4" :class="$style.contributorAvatar">
|
||||
<span :class="$style.contributorUsername">@tai-cha</span>
|
||||
</a>
|
||||
<a href="https://github.com/samunohito" target="_blank" :class="$style.contributor">
|
||||
<img src="https://avatars.githubusercontent.com/u/46447427?v=4" :class="$style.contributorAvatar">
|
||||
<span :class="$style.contributorUsername">@samunohito</span>
|
||||
</a>
|
||||
<a href="https://github.com/anatawa12" target="_blank" :class="$style.contributor">
|
||||
<img src="https://avatars.githubusercontent.com/u/22656849?v=4" :class="$style.contributorAvatar">
|
||||
<span :class="$style.contributorUsername">@anatawa12</span>
|
||||
</a>
|
||||
</div>
|
||||
</FormSection>
|
||||
<FormSection>
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ const pagination = {
|
|||
state.value === 'notResponding' ? { notResponding: true } :
|
||||
{}),
|
||||
})),
|
||||
} satisfies Paging;
|
||||
} as Paging;
|
||||
|
||||
function getStatus(instance) {
|
||||
if (instance.isSuspended) return 'Suspended';
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
|
|||
import { i18n } from '@/i18n.js';
|
||||
import { iAmAdmin, $i } from '@/account.js';
|
||||
import MkRolePreview from '@/components/MkRolePreview.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
userId: string;
|
||||
|
|
@ -258,7 +258,7 @@ const announcementsPagination = {
|
|||
params: computed(() => ({
|
||||
userId: props.userId,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
const expandedRoles = ref([]);
|
||||
|
||||
function createFetcher() {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ import { computed, shallowRef, ref } from 'vue';
|
|||
|
||||
import XHeader from './_header_.vue';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import XAbuseReport from '@/components/MkAbuseReport.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
|
@ -77,7 +77,7 @@ const pagination = {
|
|||
reporterOrigin: reporterOrigin.value,
|
||||
targetUserOrigin: targetUserOrigin.value,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
function resolved(reportId) {
|
||||
reports.value.removeItem(reportId);
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ import { computed, ref } from 'vue';
|
|||
import XHeader from './_header_.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkInstanceCardMini from '@/components/MkInstanceCardMini.vue';
|
||||
import FormSplit from '@/components/form/split.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
|
@ -88,7 +88,7 @@ const pagination = {
|
|||
state.value === 'notResponding' ? { notResponding: true } :
|
||||
{}),
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
function getStatus(instance) {
|
||||
if (instance.isSuspended) return 'Suspended';
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ const pagingComponent = shallowRef<InstanceType<typeof MkPagination>>();
|
|||
const type = ref('all');
|
||||
const sort = ref('+createdAt');
|
||||
|
||||
const pagination = {
|
||||
const pagination: Paging = {
|
||||
endpoint: 'admin/invite/list' as const,
|
||||
limit: 10,
|
||||
params: computed(() => ({
|
||||
|
|
@ -81,7 +81,7 @@ const pagination = {
|
|||
sort: sort.value,
|
||||
})),
|
||||
offsetMode: true,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
const expiresAt = ref('');
|
||||
const noExpirationDate = ref(true);
|
||||
|
|
@ -97,10 +97,10 @@ async function createWithOptions() {
|
|||
os.alert({
|
||||
type: 'success',
|
||||
title: i18n.ts.inviteCodeCreated,
|
||||
text: tickets.map(x => x.code).join('\n'),
|
||||
text: tickets?.map(x => x.code).join('\n'),
|
||||
});
|
||||
|
||||
tickets.forEach(ticket => pagingComponent.value?.prepend(ticket));
|
||||
tickets?.forEach(ticket => pagingComponent.value?.prepend(ticket));
|
||||
}
|
||||
|
||||
function deleted(id: string) {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import XHeader from './_header_.vue';
|
|||
import XModLog from './modlog.ModLog.vue';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ const pagination = {
|
|||
type: type.value,
|
||||
userId: moderatorId.value === '' ? null : moderatorId.value,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
console.log(Misskey);
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ import { useRouter } from '@/router.js';
|
|||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import { infoImageUrl } from '@/instance.js';
|
||||
|
||||
const router = useRouter();
|
||||
|
|
@ -88,7 +88,7 @@ const usersPagination = {
|
|||
params: computed(() => ({
|
||||
roleId: props.id,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
const expandedItems = ref([]);
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ import { computed, shallowRef, ref } from 'vue';
|
|||
import XHeader from './_header_.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { lookupUser } from '@/scripts/lookup-user.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
|
@ -87,7 +87,7 @@ const pagination = {
|
|||
hostname: searchHost.value,
|
||||
})),
|
||||
offsetMode: true,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
function searchUser() {
|
||||
os.selectUser().then(user => {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import * as os from '@/os.js';
|
||||
|
|
@ -55,7 +55,7 @@ const paginationCurrent = {
|
|||
params: {
|
||||
isActive: true,
|
||||
},
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
const paginationPast = {
|
||||
endpoint: 'announcements' as const,
|
||||
|
|
@ -63,7 +63,7 @@ const paginationPast = {
|
|||
params: {
|
||||
isActive: false,
|
||||
},
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
const paginationEl = ref<InstanceType<typeof MkPagination>>();
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ const bannerId = ref<string | null>(null);
|
|||
const color = ref('#000');
|
||||
const isSensitive = ref(false);
|
||||
const allowRenoteToExternal = ref(true);
|
||||
const pinnedNotes = ref<Partial<Misskey.entities.Note>[]>([]);
|
||||
const pinnedNotes = ref<{ id: Misskey.entities.Note['id'] }[]>([]);
|
||||
|
||||
watch(() => bannerId.value, async () => {
|
||||
if (bannerId.value == null) {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
import { computed, onMounted, ref } from 'vue';
|
||||
import MkChannelPreview from '@/components/MkChannelPreview.vue';
|
||||
import MkChannelList from '@/components/MkChannelList.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkRadios from '@/components/MkRadios.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
|
@ -83,20 +83,20 @@ onMounted(() => {
|
|||
const featuredPagination = {
|
||||
endpoint: 'channels/featured' as const,
|
||||
noPaging: true,
|
||||
} satisfies Paging;
|
||||
};
|
||||
const favoritesPagination = {
|
||||
endpoint: 'channels/my-favorites' as const,
|
||||
limit: 100,
|
||||
noPaging: true,
|
||||
} satisfies Paging;
|
||||
};
|
||||
const followingPagination = {
|
||||
endpoint: 'channels/followed' as const,
|
||||
limit: 10,
|
||||
} satisfies Paging;
|
||||
};
|
||||
const ownedPagination = {
|
||||
endpoint: 'channels/owned' as const,
|
||||
limit: 10,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
async function search() {
|
||||
const query = searchQuery.value.toString().trim();
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkNote from '@/components/MkNote.vue';
|
||||
import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
|
@ -36,7 +36,7 @@ import { infoImageUrl } from '@/instance.js';
|
|||
const pagination = {
|
||||
endpoint: 'i/favorites' as const,
|
||||
limit: 10,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
definePageMetadata({
|
||||
title: i18n.ts.favorites,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import MkFlashPreview from '@/components/MkFlashPreview.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { useRouter } from '@/router.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
|
@ -53,15 +53,15 @@ const tab = ref('featured');
|
|||
const featuredFlashsPagination = {
|
||||
endpoint: 'flash/featured' as const,
|
||||
noPaging: true,
|
||||
} satisfies Paging;
|
||||
};
|
||||
const myFlashsPagination = {
|
||||
endpoint: 'flash/my' as const,
|
||||
limit: 5,
|
||||
} satisfies Paging;
|
||||
};
|
||||
const likedFlashsPagination = {
|
||||
endpoint: 'flash/my-likes' as const,
|
||||
limit: 5,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
function create() {
|
||||
router.push('/play/new');
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { shallowRef, computed } from 'vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { userPage, acct } from '@/filters/user.js';
|
||||
import * as os from '@/os.js';
|
||||
|
|
@ -51,7 +51,7 @@ const paginationComponent = shallowRef<InstanceType<typeof MkPagination>>();
|
|||
const pagination = {
|
||||
endpoint: 'following/requests/list' as const,
|
||||
limit: 10,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
function accept(user) {
|
||||
os.api('following/requests/accept', { userId: user.id }).then(() => {
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<script lang="ts" setup>
|
||||
import { watch, ref, computed } from 'vue';
|
||||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkGalleryPostPreview from '@/components/MkGalleryPostPreview.vue';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
|
@ -68,19 +68,19 @@ const tagsRef = ref();
|
|||
const recentPostsPagination = {
|
||||
endpoint: 'gallery/posts' as const,
|
||||
limit: 6,
|
||||
} satisfies Paging;
|
||||
};
|
||||
const popularPostsPagination = {
|
||||
endpoint: 'gallery/featured' as const,
|
||||
noPaging: true,
|
||||
} satisfies Paging;
|
||||
};
|
||||
const myPostsPagination = {
|
||||
endpoint: 'i/gallery/posts' as const,
|
||||
limit: 5,
|
||||
} satisfies Paging;
|
||||
};
|
||||
const likedPostsPagination = {
|
||||
endpoint: 'i/gallery/likes' as const,
|
||||
limit: 5,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
const tagUsersPagination = computed(() => ({
|
||||
endpoint: 'hashtags/users' as const,
|
||||
|
|
@ -90,7 +90,7 @@ const tagUsersPagination = computed(() => ({
|
|||
origin: 'combined',
|
||||
sort: '+follower',
|
||||
},
|
||||
} satisfies Paging));
|
||||
}));
|
||||
|
||||
watch(() => props.tag, () => {
|
||||
if (tagsRef.value) tagsRef.value.tags.toggleContent(props.tag == null);
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ import * as Misskey from 'misskey-js';
|
|||
import MkButton from '@/components/MkButton.vue';
|
||||
import * as os from '@/os.js';
|
||||
import MkContainer from '@/components/MkContainer.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkGalleryPostPreview from '@/components/MkGalleryPostPreview.vue';
|
||||
import MkFollowButton from '@/components/MkFollowButton.vue';
|
||||
import { url } from '@/config.js';
|
||||
|
|
@ -93,7 +93,7 @@ const otherPostsPagination = {
|
|||
params: computed(() => ({
|
||||
userId: post.value.user.id,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
function fetchPost() {
|
||||
post.value = null;
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ import { iAmModerator, iAmAdmin } from '@/account.js';
|
|||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import { getProxiedImageUrlNullable } from '@/scripts/media-proxy.js';
|
||||
import { dateString } from '@/filters/date.js';
|
||||
|
||||
|
|
@ -160,7 +160,7 @@ const usersPagination = {
|
|||
hostname: props.host,
|
||||
},
|
||||
offsetMode: true,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
async function fetch(): Promise<void> {
|
||||
if (iAmAdmin) {
|
||||
|
|
|
|||
|
|
@ -52,10 +52,10 @@ const currentInviteLimit = ref<null | number>(null);
|
|||
const inviteLimit = (($i != null && $i.policies.inviteLimit) || (($i == null && instance.policies.inviteLimit))) as number;
|
||||
const inviteLimitCycle = (($i != null && $i.policies.inviteLimitCycle) || ($i == null && instance.policies.inviteLimitCycle)) as number;
|
||||
|
||||
const pagination = {
|
||||
const pagination: Paging = {
|
||||
endpoint: 'invite/list' as const,
|
||||
limit: 10,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
const resetCycle = computed<null | string>(() => {
|
||||
if (!inviteLimitCycle) return null;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<script lang="ts" setup>
|
||||
import { watch, ref, shallowRef, computed } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkClipPreview from '@/components/MkClipPreview.vue';
|
||||
import * as os from '@/os.js';
|
||||
|
|
@ -40,7 +40,7 @@ const pagination = {
|
|||
endpoint: 'clips/list' as const,
|
||||
noPaging: true,
|
||||
limit: 10,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
const tab = ref('my');
|
||||
const favorites = ref<Misskey.entities.Clip[] | null>(null);
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ import MkInput from '@/components/MkInput.vue';
|
|||
import { userListsCache } from '@/cache.js';
|
||||
import { $i } from '@/account.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
|
||||
const {
|
||||
enableInfiniteScroll,
|
||||
|
|
@ -88,7 +88,7 @@ const membershipsPagination = {
|
|||
params: computed(() => ({
|
||||
listId: props.listId,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
function fetchList() {
|
||||
os.api('users/lists/show', {
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ import { url } from '@/config.js';
|
|||
import MkMediaImage from '@/components/MkMediaImage.vue';
|
||||
import MkFollowButton from '@/components/MkFollowButton.vue';
|
||||
import MkContainer from '@/components/MkContainer.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkPagePreview from '@/components/MkPagePreview.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
|
@ -108,7 +108,7 @@ const otherPostsPagination = {
|
|||
params: computed(() => ({
|
||||
userId: page.value.user.id,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
const path = computed(() => props.username + '/' + props.pageName);
|
||||
|
||||
function fetchPage() {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import MkPagePreview from '@/components/MkPagePreview.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { useRouter } from '@/router.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
|
@ -51,15 +51,15 @@ const tab = ref('featured');
|
|||
const featuredPagesPagination = {
|
||||
endpoint: 'pages/featured' as const,
|
||||
noPaging: true,
|
||||
} satisfies Paging;
|
||||
};
|
||||
const myPagesPagination = {
|
||||
endpoint: 'i/pages' as const,
|
||||
limit: 5,
|
||||
} satisfies Paging;
|
||||
};
|
||||
const likedPagesPagination = {
|
||||
endpoint: 'i/page-likes' as const,
|
||||
limit: 5,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
function create() {
|
||||
router.push('/pages/new');
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import FormPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import FormPagination from '@/components/MkPagination.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
|
@ -63,7 +63,7 @@ const pagination = {
|
|||
params: {
|
||||
sort: '+lastUsedAt',
|
||||
},
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
function revoke(token) {
|
||||
os.api('i/revoke-token', { tokenId: token.id }).then(() => {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
import { computed, ref, watch } from 'vue';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import * as os from '@/os.js';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkDriveFileThumbnail from '@/components/MkDriveFileThumbnail.vue';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import bytes from '@/filters/bytes.js';
|
||||
|
|
@ -64,7 +64,7 @@ const pagination = {
|
|||
endpoint: 'drive/files' as const,
|
||||
limit: 10,
|
||||
params: computed(() => ({ sort: sortMode.value })),
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
const sortOptions = [
|
||||
{ value: 'sizeDesc', displayName: i18n.ts._drivecleaner.orderBySizeDesc },
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</MkColorInput>
|
||||
<MkSwitch v-model="advancedMfm">{{ i18n.ts.enableAdvancedMfm }}</MkSwitch>
|
||||
<MkSwitch v-if="advancedMfm" v-model="animatedMfm">{{ i18n.ts.enableAnimatedMfm }}</MkSwitch>
|
||||
<MkSwitch v-if="advancedMfm" v-model="enableQuickAddMfmFunction">{{ i18n.ts.enableQuickAddMfmFunction }}</MkSwitch>
|
||||
<MkSwitch v-model="showGapBetweenNotesInTimeline">{{ i18n.ts.showGapBetweenNotesInTimeline }}</MkSwitch>
|
||||
<MkSwitch v-model="loadRawImages">{{ i18n.ts.loadRawImages }}</MkSwitch>
|
||||
<MkRadios v-model="reactionsDisplaySize">
|
||||
|
|
@ -291,6 +292,7 @@ const useBlurEffect = computed(defaultStore.makeGetterSetter('useBlurEffect'));
|
|||
const showGapBetweenNotesInTimeline = computed(defaultStore.makeGetterSetter('showGapBetweenNotesInTimeline'));
|
||||
const animatedMfm = computed(defaultStore.makeGetterSetter('animatedMfm'));
|
||||
const advancedMfm = computed(defaultStore.makeGetterSetter('advancedMfm'));
|
||||
const enableQuickAddMfmFunction = computed(defaultStore.makeGetterSetter('enableQuickAddMfmFunction'));
|
||||
const emojiStyle = computed(defaultStore.makeGetterSetter('emojiStyle'));
|
||||
const disableDrawer = computed(defaultStore.makeGetterSetter('disableDrawer'));
|
||||
const disableShowingAnimatedImages = computed(defaultStore.makeGetterSetter('disableShowingAnimatedImages'));
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
import { ref, computed } from 'vue';
|
||||
import XInstanceMute from './mute-block.instance-mute.vue';
|
||||
import XWordMute from './mute-block.word-mute.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import { userPage } from '@/filters/user.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
|
@ -142,17 +142,17 @@ import MkFolder from '@/components/MkFolder.vue';
|
|||
const renoteMutingPagination = {
|
||||
endpoint: 'renote-mute/list' as const,
|
||||
limit: 10,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
const mutingPagination = {
|
||||
endpoint: 'mute/list' as const,
|
||||
limit: 10,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
const blockingPagination = {
|
||||
endpoint: 'blocking/list' as const,
|
||||
limit: 10,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
const expandedRenoteMuteItems = ref([]);
|
||||
const expandedMuteItems = ref([]);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import X2fa from './2fa.vue';
|
|||
import FormSection from '@/components/form/section.vue';
|
||||
import FormSlot from '@/components/form/slot.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
|
@ -53,7 +53,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
|
|||
const pagination = {
|
||||
endpoint: 'i/signin-history' as const,
|
||||
limit: 5,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
async function change() {
|
||||
const { canceled: canceled2, result: newPassword } = await os.inputText({
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import FormSection from '@/components/form/section.vue';
|
||||
import FormLink from '@/components/form/link.vue';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
|
@ -44,7 +44,7 @@ const pagination = {
|
|||
endpoint: 'i/webhooks/list' as const,
|
||||
limit: 100,
|
||||
noPaging: true,
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
const headerActions = computed(() => []);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
user: Misskey.entities.User;
|
||||
|
|
@ -31,7 +31,7 @@ const pagination = {
|
|||
params: computed(() => ({
|
||||
userId: props.user.id,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
import { computed } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkFlashPreview from '@/components/MkFlashPreview.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
user: Misskey.entities.User;
|
||||
|
|
@ -27,5 +27,5 @@ const pagination = {
|
|||
params: computed(() => ({
|
||||
userId: props.user.id,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
import { computed } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkUserInfo from '@/components/MkUserInfo.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
user: Misskey.entities.User;
|
||||
|
|
@ -30,7 +30,7 @@ const followingPagination = {
|
|||
params: computed(() => ({
|
||||
userId: props.user.id,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
|
||||
const followersPagination = {
|
||||
endpoint: 'users/followers' as const,
|
||||
|
|
@ -38,7 +38,7 @@ const followersPagination = {
|
|||
params: computed(() => ({
|
||||
userId: props.user.id,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
import { computed } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkGalleryPostPreview from '@/components/MkGalleryPostPreview.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
user: Misskey.entities.User;
|
||||
|
|
@ -30,7 +30,7 @@ const pagination = {
|
|||
params: computed(() => ({
|
||||
userId: props.user.id,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<script lang="ts" setup>
|
||||
import {} from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkStickyContainer from '@/components/global/MkStickyContainer.vue';
|
||||
import MkSpacer from '@/components/global/MkSpacer.vue';
|
||||
import MkAvatars from '@/components/MkAvatars.vue';
|
||||
|
|
@ -37,7 +37,7 @@ const pagination = {
|
|||
params: {
|
||||
userId: props.user.id,
|
||||
},
|
||||
} satisfies Paging;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
import { computed } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkPagePreview from '@/components/MkPagePreview.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
user: Misskey.entities.User;
|
||||
|
|
@ -27,5 +27,5 @@ const pagination = {
|
|||
params: computed(() => ({
|
||||
userId: props.user.id,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
import MkNote from '@/components/MkNote.vue';
|
||||
import MkReactionIcon from '@/components/MkReactionIcon.vue';
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ const pagination = {
|
|||
params: computed(() => ({
|
||||
userId: props.user.id,
|
||||
})),
|
||||
} satisfies Paging;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
|
|
|||
61
packages/frontend/src/scripts/mfm-function-picker.ts
Normal file
61
packages/frontend/src/scripts/mfm-function-picker.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and other misskey contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Ref, nextTick } from 'vue';
|
||||
import * as os from '@/os.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { MFM_TAGS } from '@/const.js';
|
||||
|
||||
/**
|
||||
* MFMの装飾のリストを表示する
|
||||
*/
|
||||
export function mfmFunctionPicker(src: any, textArea: HTMLInputElement | HTMLTextAreaElement, textRef: Ref<string>) {
|
||||
return new Promise((res, rej) => {
|
||||
os.popupMenu([{
|
||||
text: i18n.ts.addMfmFunction,
|
||||
type: 'label',
|
||||
}, ...getFunctionList(textArea, textRef)], src);
|
||||
});
|
||||
}
|
||||
|
||||
function getFunctionList(textArea: HTMLInputElement | HTMLTextAreaElement, textRef: Ref<string>) : object[] {
|
||||
const ret: object[] = [];
|
||||
MFM_TAGS.forEach(tag => {
|
||||
ret.push({
|
||||
text: tag,
|
||||
icon: 'ti ti-icons',
|
||||
action: () => add(textArea, textRef, tag),
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
function add(textArea: HTMLInputElement | HTMLTextAreaElement, textRef: Ref<string>, type: string) {
|
||||
const caretStart: number = textArea.selectionStart as number;
|
||||
const caretEnd: number = textArea.selectionEnd as number;
|
||||
|
||||
MFM_TAGS.forEach(tag => {
|
||||
if (type === tag) {
|
||||
if (caretStart === caretEnd) {
|
||||
// 単純にFunctionを追加
|
||||
const trimmedText = `${textRef.value.substring(0, caretStart)}$[${type} ]${textRef.value.substring(caretEnd)}`;
|
||||
textRef.value = trimmedText;
|
||||
} else {
|
||||
// 選択範囲を囲むようにFunctionを追加
|
||||
const trimmedText = `${textRef.value.substring(0, caretStart)}$[${type} ${textRef.value.substring(caretStart, caretEnd)}]${textRef.value.substring(caretEnd)}`;
|
||||
textRef.value = trimmedText;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const nextCaretStart: number = caretStart + 3 + type.length;
|
||||
const nextCaretEnd: number = caretEnd + 3 + type.length;
|
||||
|
||||
// キャレットを戻す
|
||||
nextTick(() => {
|
||||
textArea.focus();
|
||||
textArea.setSelectionRange(nextCaretStart, nextCaretEnd);
|
||||
});
|
||||
}
|
||||
|
|
@ -226,6 +226,10 @@ export const defaultStore = markRaw(new Storage('base', {
|
|||
where: 'device',
|
||||
default: true,
|
||||
},
|
||||
enableQuickAddMfmFunction: {
|
||||
where: 'device',
|
||||
default: false,
|
||||
},
|
||||
loadRawImages: {
|
||||
where: 'device',
|
||||
default: false,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue