1
0
mirror of https://git.boykissers.com/pawkey/pawkey-sk.git synced 2025-12-20 12:14:18 +00:00

Merge branch 'misskey-develop' into merge/2025-03-24

# Conflicts:
#	.github/workflows/api-misskey-js.yml
#	.github/workflows/changelog-check.yml
#	.github/workflows/check-misskey-js-autogen.yml
#	.github/workflows/get-api-diff.yml
#	.github/workflows/lint.yml
#	.github/workflows/locale.yml
#	.github/workflows/on-release-created.yml
#	.github/workflows/storybook.yml
#	.github/workflows/test-backend.yml
#	.github/workflows/test-federation.yml
#	.github/workflows/test-frontend.yml
#	.github/workflows/test-misskey-js.yml
#	.github/workflows/test-production.yml
#	.github/workflows/validate-api-json.yml
#	package.json
#	packages/backend/package.json
#	packages/backend/src/server/api/ApiCallService.ts
#	packages/backend/src/server/api/endpoints/drive/files/create.ts
#	packages/frontend-shared/js/url.ts
#	packages/frontend/package.json
#	packages/frontend/src/components/MkFileCaptionEditWindow.vue
#	packages/frontend/src/components/MkInfo.vue
#	packages/frontend/src/components/MkLink.vue
#	packages/frontend/src/components/MkNote.vue
#	packages/frontend/src/components/MkNotes.vue
#	packages/frontend/src/components/MkPageWindow.vue
#	packages/frontend/src/components/MkReactionsViewer.vue
#	packages/frontend/src/components/MkTimeline.vue
#	packages/frontend/src/components/MkUrlPreview.vue
#	packages/frontend/src/components/MkUserPopup.vue
#	packages/frontend/src/components/global/MkPageHeader.vue
#	packages/frontend/src/components/global/MkUrl.vue
#	packages/frontend/src/components/global/PageWithHeader.vue
#	packages/frontend/src/pages/about-misskey.vue
#	packages/frontend/src/pages/announcements.vue
#	packages/frontend/src/pages/antenna-timeline.vue
#	packages/frontend/src/pages/channel.vue
#	packages/frontend/src/pages/instance-info.vue
#	packages/frontend/src/pages/note.vue
#	packages/frontend/src/pages/page.vue
#	packages/frontend/src/pages/role.vue
#	packages/frontend/src/pages/tag.vue
#	packages/frontend/src/pages/timeline.vue
#	packages/frontend/src/pages/user-list-timeline.vue
#	packages/frontend/src/pages/user/followers.vue
#	packages/frontend/src/pages/user/following.vue
#	packages/frontend/src/pages/user/home.vue
#	packages/frontend/src/pages/user/index.vue
#	packages/frontend/src/ui/deck.vue
#	packages/misskey-js/generator/package.json
#	pnpm-lock.yaml
#	scripts/changelog-checker/package-lock.json
#	scripts/changelog-checker/package.json
This commit is contained in:
Hazelnoot
2025-04-29 15:37:43 -04:00
255 changed files with 4773 additions and 4085 deletions

View File

@@ -55,7 +55,7 @@ await fs.readFile(
'../../locales/ja-JP.yml',
'assets/**',
'public/**',
'../../pnpm-lock.yaml',
'package.json',
]).length
) {
return;

View File

@@ -25,7 +25,7 @@
"@rollup/plugin-replace": "6.0.2",
"@rollup/pluginutils": "5.1.4",
"@ruffle-rs/ruffle": "0.1.0-nightly.2024.10.15",
"@sentry/vue": "9.12.0",
"@sentry/vue": "9.14.0",
"@syuilo/aiscript": "0.19.0",
"@transfem-org/sfm-js": "0.24.6",
"@twemoji/parser": "15.1.1",
@@ -36,12 +36,12 @@
"broadcast-channel": "7.1.0",
"buraha": "0.0.1",
"canvas-confetti": "1.9.3",
"chart.js": "4.4.8",
"chart.js": "4.4.9",
"chartjs-adapter-date-fns": "3.0.0",
"chartjs-chart-matrix": "2.1.1",
"chartjs-plugin-gradient": "0.6.1",
"chartjs-plugin-zoom": "2.2.0",
"chromatic": "11.28.0",
"chromatic": "11.28.2",
"compare-versions": "6.1.1",
"cropperjs": "2.0.0",
"date-fns": "4.1.0",
@@ -61,13 +61,13 @@
"moment": "^2.30.1",
"photoswipe": "5.4.4",
"punycode.js": "2.3.1",
"rollup": "4.39.0",
"sanitize-html": "2.15.0",
"sass": "1.86.3",
"shiki": "3.2.2",
"rollup": "4.40.0",
"sanitize-html": "2.16.0",
"sass": "1.87.0",
"shiki": "3.3.0",
"strict-event-emitter-types": "2.0.0",
"textarea-caret": "3.1.0",
"three": "0.175.0",
"three": "0.176.0",
"throttle-debounce": "5.0.2",
"tinycolor2": "1.6.0",
"tsc-alias": "1.8.15",
@@ -75,13 +75,13 @@
"typescript": "5.8.3",
"uuid": "11.1.0",
"v-code-diff": "1.13.1",
"vite": "6.3.1",
"vite": "6.3.3",
"vue": "3.5.13",
"vuedraggable": "next",
"wanakana": "5.3.1"
},
"optionalDependencies": {
"cypress": "13.15.2"
"cypress": "14.3.2"
},
"devDependencies": {
"@misskey-dev/summaly": "5.2.1",
@@ -109,16 +109,16 @@
"@types/katex": "^0.16.7",
"@types/matter-js": "0.19.8",
"@types/micromatch": "4.0.9",
"@types/node": "22.14.0",
"@types/node": "22.15.2",
"@types/punycode.js": "npm:@types/punycode@2.1.4",
"@types/sanitize-html": "2.15.0",
"@types/seedrandom": "3.0.8",
"@types/throttle-debounce": "5.0.2",
"@types/tinycolor2": "1.4.6",
"@types/ws": "8.18.1",
"@typescript-eslint/eslint-plugin": "8.29.1",
"@typescript-eslint/parser": "8.29.1",
"@vitest/coverage-v8": "3.1.1",
"@typescript-eslint/eslint-plugin": "8.31.0",
"@typescript-eslint/parser": "8.31.0",
"@vitest/coverage-v8": "3.1.2",
"@vue/compiler-core": "3.5.13",
"@vue/runtime-core": "3.5.13",
"acorn": "8.14.1",
@@ -130,9 +130,9 @@
"intersection-observer": "0.12.2",
"micromatch": "4.0.8",
"minimatch": "10.0.1",
"msw": "2.7.3",
"msw": "2.7.5",
"msw-storybook-addon": "2.0.4",
"nodemon": "3.1.9",
"nodemon": "3.1.10",
"prettier": "3.5.3",
"react": "19.1.0",
"react-dom": "19.1.0",
@@ -141,10 +141,10 @@
"storybook": "8.6.12",
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
"vite-plugin-turbosnap": "1.0.3",
"vitest": "3.1.1",
"vitest": "3.1.2",
"vitest-fetch-mock": "0.4.5",
"vue-component-type-helpers": "2.2.8",
"vue-component-type-helpers": "2.2.10",
"vue-eslint-parser": "10.1.3",
"vue-tsc": "2.2.8"
"vue-tsc": "2.2.10"
}
}

View File

@@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
</I18n>
</template>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<div class="_gaps_m" :class="$style.root">
<div class="">
<MkTextarea v-model="comment">
@@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton primary full :disabled="comment.length === 0" @click="send">{{ i18n.ts.send }}</MkButton>
</div>
</div>
</MkSpacer>
</div>
</MkWindow>
</template>

View File

@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<MkSpacer :contentMax="700">
<div class="_spacer" style="--MI_SPACER-w: 700px;">
<div>
<div class="_gaps_m">
<MkInput v-model="name">
@@ -48,7 +48,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
</div>
</MkSpacer>
</div>
</template>
<script lang="ts" setup>

View File

@@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkModalWindow ref="dialogEl" @close="cancel()" @closed="emit('closed')">
<template #header>:{{ emoji.name }}:</template>
<template #default>
<MkSpacer>
<div class="_spacer">
<div style="display: flex; flex-direction: column; gap: 1em;">
<div :class="$style.emojiImgWrapper">
<MkCustomEmoji :name="emoji.name" :normal="true" :useOriginalSize="true" style="height: 100%;"></MkCustomEmoji>
@@ -50,7 +50,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
</MkKeyValue>
</div>
</MkSpacer>
</div>
</template>
</MkModalWindow>
</template>

View File

@@ -52,6 +52,7 @@ SPDX-License-Identifier: AGPL-3.0-only
@contextmenu.stop="onContextmenu"
>
<div ref="contents">
<MkInfo v-if="!store.r.readDriveTip.value" closable @close="closeTip()"><div v-html="i18n.ts.driveAboutTip"></div></MkInfo>
<div v-show="folders.length > 0" ref="foldersContainer" :class="$style.folders">
<XFolder
v-for="(f, i) in folders"
@@ -108,6 +109,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { nextTick, onActivated, onBeforeUnmount, onMounted, ref, useTemplateRef, watch } from 'vue';
import * as Misskey from 'misskey-js';
import MkButton from './MkButton.vue';
import MkInfo from './MkInfo.vue';
import type { MenuItem } from '@/types/menu.js';
import XNavFolder from '@/components/MkDrive.navFolder.vue';
import XFolder from '@/components/MkDrive.folder.vue';
@@ -121,6 +123,7 @@ import { uploadFile, uploads } from '@/utility/upload.js';
import { claimAchievement } from '@/utility/achievements.js';
import { prefer } from '@/preferences.js';
import { chooseFileFromPc } from '@/utility/select-file.js';
import { store } from '@/store.js';
const searchQuery = ref('');
@@ -723,6 +726,10 @@ function onContextmenu(ev: MouseEvent) {
os.contextMenu(getMenu(), ev);
}
function closeTip() {
store.set('readDriveTip', true);
}
onMounted(() => {
if (prefer.s.enableInfiniteScroll && loadMoreFiles.value) {
nextTick(() => {

View File

@@ -15,12 +15,12 @@ SPDX-License-Identifier: AGPL-3.0-only
@closed="emit('closed')"
>
<template #header>{{ i18n.ts.describeFile }}</template>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<MkDriveFileThumbnail :file="file" fit="contain" style="height: 193px; margin-bottom: 16px;"/>
<MkTextarea v-model="caption" autofocus :placeholder="i18n.ts.inputNewDescription" @keydown="onKeydown($event)">
<template #label>{{ i18n.ts.caption }}</template>
</MkTextarea>
</MkSpacer>
</div>
</MkModalWindow>
</template>

View File

@@ -31,10 +31,6 @@ SPDX-License-Identifier: AGPL-3.0-only
:leaveActiveClass="prefer.s.animation ? $style.transition_toggle_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_toggle_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_toggle_leaveTo : ''"
@enter="enter"
@afterEnter="afterEnter"
@leave="leave"
@afterLeave="afterLeave"
>
<KeepAlive>
<div v-show="opened">
@@ -45,9 +41,9 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</template>
<MkSpacer v-if="withSpacer" :marginMin="spacerMin" :marginMax="spacerMax">
<div v-if="withSpacer" class="_spacer" :style="{ '--MI_SPACER-min': props.spacerMin + 'px', '--MI_SPACER-max': props.spacerMax + 'px' }">
<slot></slot>
</MkSpacer>
</div>
<div v-else>
<slot></slot>
</div>
@@ -90,32 +86,6 @@ const bgSame = ref(false);
const opened = ref(props.defaultOpen);
const openedAtLeastOnce = ref(props.defaultOpen);
function enter(el: Element) {
if (!(el instanceof HTMLElement)) return;
const elementHeight = el.getBoundingClientRect().height;
el.style.height = '0';
el.offsetHeight; // reflow
el.style.height = `${Math.min(elementHeight, props.maxHeight ?? Infinity)}px`;
}
function afterEnter(el: Element) {
if (!(el instanceof HTMLElement)) return;
el.style.height = '';
}
function leave(el: Element) {
if (!(el instanceof HTMLElement)) return;
const elementHeight = el.getBoundingClientRect().height;
el.style.height = `${elementHeight}px`;
el.offsetHeight; // reflow
el.style.height = '0';
}
function afterLeave(el: Element) {
if (!(el instanceof HTMLElement)) return;
el.style.height = '';
}
function toggle() {
if (!opened.value) {
openedAtLeastOnce.value = true;
@@ -137,16 +107,18 @@ onMounted(() => {
<style lang="scss" module>
.transition_toggle_enterActive,
.transition_toggle_leaveActive {
overflow-y: clip;
transition: opacity 0.3s, height 0.3s, transform 0.3s !important;
overflow-y: hidden; // 子要素のmarginが突き出るため clip を使ってはいけない
transition: opacity 0.3s, height 0.3s !important;
}
.transition_toggle_enterFrom,
.transition_toggle_leaveTo {
opacity: 0;
height: 0;
}
.root {
display: block;
interpolate-size: allow-keywords; // heightのtransitionを動作させるために必要
}
.header {

View File

@@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
>
<template #header>{{ i18n.ts.forgotPassword }}</template>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<form v-if="instance.enableEmail" @submit.prevent="onSubmit">
<div class="_gaps_m">
<MkInput v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" :spellcheck="false" autofocus required>
@@ -34,7 +34,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-else>
{{ i18n.ts._forgotPassword.contactAdmin }}
</div>
</MkSpacer>
</div>
</MkModalWindow>
</template>

View File

@@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ title }}
</template>
<MkSpacer :marginMin="20" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 32px;">
<div v-if="Object.keys(form).filter(item => !form[item].hidden).length > 0" class="_gaps_m">
<template v-for="(v, k) in Object.fromEntries(Object.entries(form))">
<template v-if="typeof v.hidden == 'function' ? v.hidden(values) : v.hidden"></template>
@@ -66,7 +66,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<img :src="infoImageUrl" draggable="false"/>
<div>{{ i18n.ts.nothing }}</div>
</div>
</MkSpacer>
</div>
</MkModalWindow>
</template>

View File

@@ -39,7 +39,6 @@ function closeInfo() {
background: color-mix(in srgb, var(--MI_THEME-infoBg) 65%, transparent);
color: var(--MI_THEME-infoFg);
border-radius: var(--MI-radius);
white-space: pre-wrap;
z-index: 1;
&.warn {

View File

@@ -114,7 +114,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA>
</bdi>
</div>
<MkReactionsViewer v-if="appearNote.reactionAcceptance !== 'likeOnly'" :note="appearNote" :maxNumber="16" @click.stop @mockUpdateMyReaction="emitUpdReaction">
<MkReactionsViewer v-if="appearNote.reactionAcceptance !== 'likeOnly'" style="margin-top: 6px;" :note="appearNote" :maxNumber="16" @click.stop @mockUpdateMyReaction="emitUpdReaction">
<template #more>
<MkA :to="`/notes/${appearNote.id}/reactions`" :class="[$style.reactionOmitted]">{{ i18n.ts.more }}</MkA>
</template>

View File

@@ -133,7 +133,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkTime :time="appearNote.createdAt" mode="detail" colored/>
</MkA>
</div>
<MkReactionsViewer v-if="appearNote.reactionAcceptance !== 'likeOnly'" ref="reactionsViewer" :note="appearNote"/>
<MkReactionsViewer v-if="appearNote.reactionAcceptance !== 'likeOnly'" ref="reactionsViewer" style="margin-top: 6px;" :note="appearNote"/>
<button class="_button" :class="$style.noteFooterButton" @click="reply()">
<i class="ti ti-arrow-back-up"></i>
<p v-if="appearNote.repliesCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.repliesCount) }}</p>

View File

@@ -13,16 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<template #default="{ items: notes }">
<component
:is="prefer.s.animation ? TransitionGroup : 'div'"
:class="[$style.root, { [$style.noGap]: noGap, '_gaps': !noGap, [$style.reverse]: pagination.reversed }]"
:enterActiveClass="$style.transition_x_enterActive"
:leaveActiveClass="$style.transition_x_leaveActive"
:enterFromClass="$style.transition_x_enterFrom"
:leaveToClass="$style.transition_x_leaveTo"
:moveClass=" $style.transition_x_move"
tag="div"
>
<div :class="[$style.root, { [$style.noGap]: noGap, '_gaps': !noGap, [$style.reverse]: pagination.reversed }]">
<template v-for="(note, i) in notes" :key="note.id">
<div v-if="note._shouldInsertAd_" :class="[$style.noteWithAd, { '_gaps': !noGap }]" :data-scroll-anchor="note.id">
<DynamicNote :class="$style.note" :note="note as Misskey.entities.Note" :withHardMute="true"/>
@@ -32,20 +23,19 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<DynamicNote v-else :class="$style.note" :note="note as Misskey.entities.Note" :withHardMute="true" :data-scroll-anchor="note.id"/>
</template>
</component>
</div>
</template>
</MkPagination>
</template>
<script lang="ts" setup>
import * as Misskey from 'misskey-js';
import { useTemplateRef, TransitionGroup } from 'vue';
import { useTemplateRef } from 'vue';
import type { Paging } from '@/components/MkPagination.vue';
import DynamicNote from '@/components/DynamicNote.vue';
import MkPagination from '@/components/MkPagination.vue';
import { i18n } from '@/i18n.js';
import { infoImageUrl } from '@/instance.js';
import { prefer } from '@/preferences.js';
const props = defineProps<{
pagination: Paging;
@@ -61,20 +51,6 @@ defineExpose({
</script>
<style lang="scss" module>
.transition_x_move,
.transition_x_enterActive,
.transition_x_leaveActive {
transition: opacity 0.3s cubic-bezier(0,.5,.5,1), transform 0.3s cubic-bezier(0,.5,.5,1) !important;
}
.transition_x_enterFrom,
.transition_x_leaveTo {
opacity: 0;
transform: translateY(-50%);
}
.transition_x_leaveActive {
position: absolute;
}
.reverse {
display: flex;
flex-direction: column-reverse;

View File

@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
>
<template #header>{{ i18n.ts.notificationSetting }}</template>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<div class="_gaps_m">
<MkInfo>{{ i18n.ts.notificationSettingDesc }}</MkInfo>
<div class="_buttons">
@@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<MkSwitch v-for="ntype in notificationTypes" :key="ntype" v-model="typesMap[ntype].value">{{ i18n.ts._notification._types[ntype] }}</MkSwitch>
</div>
</MkSpacer>
</div>
</MkModalWindow>
</template>

View File

@@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
</template>
<div :class="$style.root">
<div :class="$style.root" class="_forceShrinkSpacer">
<StackingRouterView v-if="prefer.s['experimental.stackingRouterView']" :key="reloadCount" :router="windowRouter"/>
<RouterView v-else :key="reloadCount" :router="windowRouter"/>
</div>
@@ -121,7 +121,6 @@ provideMetadataReceiver((metadataGetter) => {
provideReactiveMetadata(pageMetadata);
provide('shouldOmitHeaderTitle', true);
provide('shouldHeaderThin', true);
provide(DI.forceSpacerMin, true);
provide('shouldBackButton', false);
const contextmenu = computed(() => ([{

View File

@@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
>
<template #header>{{ i18n.ts.authentication }}</template>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<div style="padding: 0 0 16px 0; text-align: center;">
<img src="/client-assets/locked_with_key_3d.png" alt="🔐" style="display: block; margin: 0 auto; width: 48px;">
<div style="margin-top: 16px;">{{ i18n.ts.authenticationRequiredToContinue }}</div>
@@ -34,7 +34,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton :disabled="(password ?? '') == '' || ($i.twoFactorEnabled && (token ?? '') == '')" type="submit" primary rounded style="margin: 0 auto;"><i class="ti ti-lock-open"></i> {{ i18n.ts.continue }}</MkButton>
</div>
</form>
</MkSpacer>
</div>
</MkModalWindow>
</template>

View File

@@ -182,7 +182,6 @@ if (!mock) {
.root {
display: inline-flex;
height: 42px;
margin: 2px;
padding: 0 6px;
font-size: 1.5em;
border-radius: var(--MI-radius-sm);

View File

@@ -106,7 +106,7 @@ watch([() => props.note.reactions, () => props.maxNumber], ([newSource, maxNumbe
display: flex;
flex-wrap: wrap;
align-items: center;
margin: 4px -2px 0 -2px;
gap: 4px;
cursor: auto; /* not clickToOpen-able */
&:empty {

View File

@@ -15,7 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #header>:{{ name }}:</template>
<div style="display: flex; flex-direction: column; min-height: 100%;">
<MkSpacer :marginMin="20" :marginMax="28" style="flex-grow: 1;">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px; flex-grow: 1;">
<div class="_gaps_m">
<div v-if="imgUrl != null" :class="$style.imgs">
<div style="background: #000;" :class="$style.imgContainer">
@@ -45,7 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #value>{{ license }}</template>
</MkKeyValue>
</div>
</MkSpacer>
</div>
<div :class="$style.footer">
<MkButton primary rounded style="margin: 0 auto;" @click="done">
<i class="ti ti-plus"></i> {{ i18n.ts.import }}

View File

@@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
@closed="emit('closed')"
>
<template #header>{{ title }}</template>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<MkLoading v-if="fetching"/>
<div v-else class="_gaps" :class="$style.root">
<div :class="$style.header">
@@ -38,7 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton @click="onCancelClicked">{{ i18n.ts.cancel }}</MkButton>
</div>
</div>
</MkSpacer>
</div>
</MkModalWindow>
</template>
@@ -51,7 +51,6 @@ import MkInfo from '@/components/MkInfo.vue';
import MkRolePreview from '@/components/MkRolePreview.vue';
import { misskeyApi } from '@/utility/misskey-api.js';
import * as os from '@/os.js';
import MkSpacer from '@/components/global/MkSpacer.vue';
import MkModalWindow from '@/components/MkModalWindow.vue';
import MkLoading from '@/components/global/MkLoading.vue';

View File

@@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only
@close="cancel()"
>
<template #header>{{ i18n.ts.schedulePostList }}</template>
<MkSpacer :marginMin="14" :marginMax="16">
<div class="_spacer" style="--MI_SPACER-min: 14px; --MI_SPACER-max: 16px;">
<MkPagination ref="paginationEl" :pagination="pagination">
<template #empty>
<div class="_fullinfo">
@@ -26,7 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</template>
</MkPagination>
</MkSpacer>
</div>
</MkModalWindow>
</template>

View File

@@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.banner">
<i class="ti ti-user-edit"></i>
</div>
<MkSpacer :marginMin="20" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 32px;">
<form class="_gaps_m" autocomplete="new-password" @submit.prevent="onSubmit">
<MkInput v-if="instance.disableRegistration" v-model="invitationCode" type="text" :spellcheck="false" required>
<template #label>{{ i18n.ts.invitationCode }}</template>
@@ -79,7 +79,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-else>{{ i18n.ts.start }}</template>
</MkButton>
</form>
</MkSpacer>
</div>
</div>
</template>

View File

@@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.banner">
<i class="ti ti-checklist"></i>
</div>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<div class="_gaps_m">
<div v-if="instance.disableRegistration || instance.federation !== 'all'" class="_gaps_s">
<MkInfo v-if="instance.disableRegistration" warn>{{ i18n.ts.invitationRequiredToRegister }}</MkInfo>
@@ -59,7 +59,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton inline primary rounded gradate :disabled="!agreed" data-cy-signup-rules-continue @click="emit('done')">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
</div>
</div>
</MkSpacer>
</div>
</div>
</template>

View File

@@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<div style="display: flex; flex-direction: column; min-height: 100%;">
<MkSpacer :marginMin="20" :marginMax="28" style="flex-grow: 1;">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px; flex-grow: 1;">
<MkLoading v-if="loading !== 0"/>
<div v-else :class="$style.root" class="_gaps_m">
<MkInput v-model="title">
@@ -79,7 +79,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts.enable }}</template>
</MkSwitch>
</div>
</MkSpacer>
</div>
<div :class="$style.footer" class="_buttonsCenter">
<MkButton primary rounded :disabled="disableSubmitButton" @click="onSubmitClicked">
<i class="ti ti-check"></i>

View File

@@ -5,29 +5,55 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<MkPullToRefresh ref="prComponent" :refresher="() => reloadTimeline()">
<MkNotes
v-if="paginationQuery"
ref="tlComponent"
:pagination="paginationQuery"
:noGap="!prefer.s.showGapBetweenNotesInTimeline"
@queue="emit('queue', $event)"
@status="prComponent?.setDisabled($event)"
/>
<MkPagination v-if="paginationQuery" ref="pagingComponent" :pagination="paginationQuery" @queue="emit('queue', $event)" @status="prComponent?.setDisabled($event)">
<template #empty>
<div class="_fullinfo">
<img :src="infoImageUrl" draggable="false"/>
<div>{{ i18n.ts.noNotes }}</div>
</div>
</template>
<template #default="{ items: notes }">
<component
:is="prefer.s.animation ? TransitionGroup : 'div'"
:class="[$style.root, { [$style.noGap]: noGap, '_gaps': !noGap, [$style.reverse]: paginationQuery.reversed }]"
:enterActiveClass="$style.transition_x_enterActive"
:leaveActiveClass="$style.transition_x_leaveActive"
:enterFromClass="$style.transition_x_enterFrom"
:leaveToClass="$style.transition_x_leaveTo"
:moveClass=" $style.transition_x_move"
tag="div"
>
<template v-for="(note, i) in notes" :key="note.id">
<div v-if="note._shouldInsertAd_" :class="[$style.noteWithAd, { '_gaps': !noGap }]" :data-scroll-anchor="note.id">
<MkNote :class="$style.note" :note="note" :withHardMute="true"/>
<div :class="$style.ad">
<MkAd :preferForms="['horizontal', 'horizontal-big']"/>
</div>
</div>
<MkNote v-else :class="$style.note" :note="note" :withHardMute="true" :data-scroll-anchor="note.id"/>
</template>
</component>
</template>
</MkPagination>
</MkPullToRefresh>
</template>
<script lang="ts" setup>
import { computed, watch, onUnmounted, provide, useTemplateRef } from 'vue';
import { computed, watch, onUnmounted, provide, useTemplateRef, TransitionGroup } from 'vue';
import * as Misskey from 'misskey-js';
import type { BasicTimelineType } from '@/timelines.js';
import type { Paging } from '@/components/MkPagination.vue';
import MkNotes from '@/components/MkNotes.vue';
import MkPullToRefresh from '@/components/MkPullToRefresh.vue';
import { useStream } from '@/stream.js';
import * as sound from '@/utility/sound.js';
import { $i } from '@/i.js';
import { instance } from '@/instance.js';
import { prefer } from '@/preferences.js';
import MkNote from '@/components/MkNote.vue';
import MkPagination from '@/components/MkPagination.vue';
import { i18n } from '@/i18n.js';
import { infoImageUrl } from '@/instance.js';
const props = withDefaults(defineProps<{
src: BasicTimelineType | 'mentions' | 'directs' | 'list' | 'antenna' | 'channel' | 'role';
@@ -71,12 +97,12 @@ type TimelineQueryType = {
};
const prComponent = useTemplateRef('prComponent');
const tlComponent = useTemplateRef('tlComponent');
const pagingComponent = useTemplateRef('pagingComponent');
let tlNotesCount = 0;
function prepend(note: Misskey.entities.Note) {
if (tlComponent.value == null) return;
if (pagingComponent.value == null) return;
tlNotesCount++;
@@ -84,7 +110,7 @@ function prepend(note: Misskey.entities.Note) {
note._shouldInsertAd_ = true;
}
tlComponent.value.pagingComponent?.prepend(note);
pagingComponent.value.prepend(note);
emit('note');
@@ -96,6 +122,7 @@ function prepend(note: Misskey.entities.Note) {
let connection: Misskey.ChannelConnection | null = null;
let connection2: Misskey.ChannelConnection | null = null;
let paginationQuery: Paging | null = null;
const noGap = !prefer.s.showGapBetweenNotesInTimeline;
const stream = useStream();
@@ -290,11 +317,11 @@ onUnmounted(() => {
function reloadTimeline() {
return new Promise<void>((res) => {
if (tlComponent.value == null) return;
if (pagingComponent.value == null) return;
tlNotesCount = 0;
tlComponent.value.pagingComponent?.reload().then(() => {
pagingComponent.value.reload().then(() => {
res();
});
});
@@ -304,3 +331,56 @@ defineExpose({
reloadTimeline,
});
</script>
<style lang="scss" module>
.transition_x_move,
.transition_x_enterActive,
.transition_x_leaveActive {
transition: opacity 0.3s cubic-bezier(0,.5,.5,1), transform 0.3s cubic-bezier(0,.5,.5,1) !important;
}
.transition_x_enterFrom,
.transition_x_leaveTo {
opacity: 0;
transform: translateY(-50%);
}
.transition_x_leaveActive {
position: absolute;
}
.reverse {
display: flex;
flex-direction: column-reverse;
}
.root {
container-type: inline-size;
&.noGap {
background: var(--MI_THEME-panel);
.note {
border-bottom: solid 0.5px var(--MI_THEME-divider);
}
.ad {
padding: 8px;
background-size: auto auto;
background-image: repeating-linear-gradient(45deg, transparent, transparent 8px, var(--MI_THEME-bg) 8px, var(--MI_THEME-bg) 14px);
border-bottom: solid 0.5px var(--MI_THEME-divider);
}
}
&:not(.noGap) {
background: var(--MI_THEME-bg);
.note {
background: var(--MI_THEME-panel);
border-radius: var(--MI-radius);
}
}
}
.ad:empty {
display: none;
}
</style>

View File

@@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
>
<template #header>{{ title || i18n.ts.generateAccessToken }}</template>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<div class="_gaps_m">
<div v-if="information">
<MkInfo warn>{{ information }}</MkInfo>
@@ -42,7 +42,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
</div>
</MkSpacer>
</div>
</MkModalWindow>
</template>

View File

@@ -29,7 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-if="page === 0">
<div :class="$style.centerPage">
<MkAnimBg style="position: absolute; top: 0;" :scale="1.5"/>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<div class="_gaps" style="text-align: center;">
<i class="ti ti-confetti" style="display: block; margin: auto; font-size: 3em; color: var(--MI_THEME-accent);"></i>
<div style="font-size: 120%;">{{ i18n.ts._initialTutorial._landing.title }}</div>
@@ -37,15 +37,15 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton primary rounded gradate style="margin: 16px auto 0 auto;" @click="page++">{{ i18n.ts._initialTutorial.launchTutorial }} <i class="ti ti-arrow-right"></i></MkButton>
<MkButton style="margin: 0 auto;" transparent rounded @click="close(true)">{{ i18n.ts.close }}</MkButton>
</div>
</MkSpacer>
</div>
</div>
</template>
<template v-else-if="page === 1">
<div style="height: 100cqh; overflow: auto;">
<div :class="$style.pageRoot">
<MkSpacer :marginMin="20" :marginMax="28" :class="$style.pageMain">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;" :class="$style.pageMain">
<XNote phase="aboutNote"/>
</MkSpacer>
</div>
<div :class="$style.pageFooter">
<div class="_buttonsCenter">
<MkButton v-if="initialPage !== 1" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
@@ -58,12 +58,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-else-if="page === 2">
<div style="height: 100cqh; overflow: auto;">
<div :class="$style.pageRoot">
<MkSpacer :marginMin="20" :marginMax="28" :class="$style.pageMain">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;" :class="$style.pageMain">
<div class="_gaps">
<XNote phase="howToReact" @reacted="isReactionTutorialPushed = true"/>
<div v-if="!isReactionTutorialPushed">{{ i18n.ts._initialTutorial._reaction.reactToContinue }}</div>
</div>
</MkSpacer>
</div>
<div :class="$style.pageFooter">
<div class="_buttonsCenter">
<MkButton v-if="initialPage !== 2" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
@@ -76,9 +76,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-else-if="page === 3">
<div style="height: 100cqh; overflow: auto;">
<div :class="$style.pageRoot">
<MkSpacer :marginMin="20" :marginMax="28" :class="$style.pageMain">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;" :class="$style.pageMain">
<XTimeline/>
</MkSpacer>
</div>
<div :class="$style.pageFooter">
<div class="_buttonsCenter">
<MkButton v-if="initialPage !== 3" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
@@ -91,9 +91,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-else-if="page === 4">
<div style="height: 100cqh; overflow: auto;">
<div :class="$style.pageRoot">
<MkSpacer :marginMin="20" :marginMax="28" :class="$style.pageMain">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;" :class="$style.pageMain">
<XPostNote/>
</MkSpacer>
</div>
<div :class="$style.pageFooter">
<div class="_buttonsCenter">
<MkButton v-if="initialPage !== 3" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
@@ -106,12 +106,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-else-if="page === 5">
<div style="height: 100cqh; overflow: auto;">
<div :class="$style.pageRoot">
<MkSpacer :marginMin="20" :marginMax="28" :class="$style.pageMain">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;" :class="$style.pageMain">
<div class="_gaps">
<XSensitive @succeeded="isSensitiveTutorialSucceeded = true"/>
<div v-if="!isSensitiveTutorialSucceeded">{{ i18n.ts._initialTutorial._howToMakeAttachmentsSensitive.doItToContinue }}</div>
</div>
</MkSpacer>
</div>
<div :class="$style.pageFooter">
<div class="_buttonsCenter">
<MkButton v-if="initialPage !== 2" rounded @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
@@ -124,7 +124,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-else-if="page === 6">
<div :class="$style.centerPage">
<MkAnimBg style="position: absolute; top: 0;" :scale="1.5"/>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<div class="_gaps" style="text-align: center;">
<i class="ti ti-check" style="display: block; margin: auto; font-size: 3em; color: var(--MI_THEME-accent);"></i>
<div style="font-size: 120%;">{{ i18n.ts._initialTutorial._done.title }}</div>
@@ -139,7 +139,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton rounded primary gradate @click="close(false)">{{ i18n.ts.close }}</MkButton>
</div>
</div>
</MkSpacer>
</div>
</div>
</template>
</Transition>

View File

@@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-else #header>New announcement</template>
<div>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<div class="_gaps_m">
<MkInput v-model="title">
<template #label>{{ i18n.ts.title }}</template>
@@ -41,7 +41,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkSwitch>
<MkButton v-if="announcement" danger @click="del()"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
</div>
</MkSpacer>
</div>
<div :class="$style.footer">
<MkButton primary rounded style="margin: 0 auto;" @click="done"><i class="ti ti-check"></i> {{ props.announcement ? i18n.ts.update : i18n.ts.create }}</MkButton>
</div>

View File

@@ -33,7 +33,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-if="page === 0">
<div :class="$style.centerPage">
<MkAnimBg style="position: absolute; top: 0;" :scale="1.5"/>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<div class="_gaps" style="text-align: center;">
<i class="ti ti-confetti" style="display: block; margin: auto; font-size: 3em; color: var(--MI_THEME-accent);"></i>
<div style="font-size: 120%;">{{ i18n.ts._initialAccountSetting.accountCreated }}</div>
@@ -41,15 +41,15 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton primary rounded gradate style="margin: 16px auto 0 auto;" data-cy-user-setup-continue @click="page++">{{ i18n.ts._initialAccountSetting.profileSetting }} <i class="ti ti-arrow-right"></i></MkButton>
<MkButton style="margin: 0 auto;" transparent rounded @click="later(true)">{{ i18n.ts.later }}</MkButton>
</div>
</MkSpacer>
</div>
</div>
</template>
<template v-else-if="page === 1">
<div style="height: 100cqh; overflow: auto;">
<div :class="$style.pageRoot">
<MkSpacer :marginMin="20" :marginMax="28" :class="$style.pageMain">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;" :class="$style.pageMain">
<XProfile/>
</MkSpacer>
</div>
<div :class="$style.pageFooter">
<div class="_buttonsCenter">
<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
@@ -62,9 +62,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-else-if="page === 2">
<div style="height: 100cqh; overflow: auto;">
<div :class="$style.pageRoot">
<MkSpacer :marginMin="20" :marginMax="28" :class="$style.pageMain">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;" :class="$style.pageMain">
<XPrivacy/>
</MkSpacer>
</div>
<div :class="$style.pageFooter">
<div class="_buttonsCenter">
<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
@@ -76,9 +76,9 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<template v-else-if="page === 3">
<div style="height: 100cqh; overflow: auto;">
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<XFollow/>
</MkSpacer>
</div>
<div :class="$style.pageFooter">
<div class="_buttonsCenter">
<MkButton rounded data-cy-user-setup-back @click="page--"><i class="ti ti-arrow-left"></i> {{ i18n.ts.goBack }}</MkButton>
@@ -89,7 +89,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<template v-else-if="page === 4">
<div :class="$style.centerPage">
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<div class="_gaps" style="text-align: center;">
<i class="ti ti-bell-ringing-2" style="display: block; margin: auto; font-size: 3em; color: var(--MI_THEME-accent);"></i>
<div style="font-size: 120%;">{{ i18n.ts.pushNotification }}</div>
@@ -100,13 +100,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton primary rounded gradate data-cy-user-setup-continue @click="page++">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
</div>
</div>
</MkSpacer>
</div>
</div>
</template>
<template v-else-if="page === 5">
<div :class="$style.centerPage">
<MkAnimBg style="position: absolute; top: 0;" :scale="1.5"/>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px;">
<div class="_gaps" style="text-align: center;">
<i class="ti ti-check" style="display: block; margin: auto; font-size: 3em; color: var(--MI_THEME-accent);"></i>
<div style="font-size: 120%;">{{ i18n.ts._initialAccountSetting.initialAccountSettingCompleted }}</div>
@@ -119,7 +119,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton rounded primary data-cy-user-setup-continue @click="setupComplete()">{{ i18n.ts.close }}</MkButton>
</div>
</div>
</MkSpacer>
</div>
</div>
</template>
</Transition>
@@ -147,7 +147,7 @@ const emit = defineEmits<{
}>();
const dialog = useTemplateRef('dialog');
const page = ref(store.s.accountSetupWizard);
watch(page, () => {

View File

@@ -15,7 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only
MFM Cheatsheet
</template>
<MkStickyContainer>
<MkSpacer :contentMax="800">
<div class="_spacer" style="--MI_SPACER-w: 800px;">
<div class="mfm-cheat-sheet">
<div>{{ i18n.ts._mfm.intro }}</div>
<br/>
@@ -402,7 +402,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
</div>
</MkSpacer>
</div>
</MkStickyContainer>
</MkWindow>
</template>

View File

@@ -49,19 +49,12 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref, inject, useTemplateRef, computed } from 'vue';
import { scrollToTop } from '@@/js/scroll.js';
import XTabs from './MkPageHeader.tabs.vue';
import type { Tab } from './MkPageHeader.tabs.vue';
<script lang="ts">
import type { PageHeaderItem } from '@/types/page-header.js';
import type { PageMetadata } from '@/page.js';
import { globalEvents } from '@/events.js';
import { openAccountMenu as openAccountMenu_ } from '@/accounts.js';
import { $i } from '@/i.js';
import { DI } from '@/di.js';
import type { Tab } from './MkPageHeader.tabs.vue';
const props = withDefaults(defineProps<{
export type PageHeaderProps = {
overridePageMetadata?: PageMetadata;
tabs?: Tab[];
tab?: string;
@@ -70,7 +63,19 @@ const props = withDefaults(defineProps<{
hideTitle?: boolean;
displayMyAvatar?: boolean;
displayBackButton?: boolean;
}>(), {
};
</script>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref, inject, useTemplateRef, computed } from 'vue';
import { scrollToTop } from '@@/js/scroll.js';
import XTabs from './MkPageHeader.tabs.vue';
import { globalEvents } from '@/events.js';
import { openAccountMenu as openAccountMenu_ } from '@/accounts.js';
import { $i } from '@/i.js';
import { DI } from '@/di.js';
const props = withDefaults(defineProps<PageHeaderProps>(), {
tabs: () => ([] as Tab[]),
});

View File

@@ -1,58 +0,0 @@
<!--
SPDX-FileCopyrightText: syuilo and misskey-project
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div :class="[$style.root, { [$style.rootMin]: forceSpacerMin }]">
<div :class="$style.content">
<slot></slot>
</div>
</div>
</template>
<script lang="ts" setup>
import { inject } from 'vue';
import { deviceKind } from '@/utility/device-kind.js';
import { DI } from '@/di.js';
const props = withDefaults(defineProps<{
contentMax?: number | null;
marginMin?: number;
marginMax?: number;
}>(), {
contentMax: null,
marginMin: 12,
marginMax: 24,
});
const forceSpacerMin = inject(DI.forceSpacerMin, false) || deviceKind === 'smartphone';
</script>
<style lang="scss" module>
.root {
box-sizing: border-box;
width: 100%;
}
.rootMin {
padding: v-bind('props.marginMin + "px"') !important;
}
.content {
margin: 0 auto;
max-width: v-bind('props.contentMax + "px"');
container-type: inline-size;
}
@container (max-width: 450px) {
.root {
padding: v-bind('props.marginMin + "px"');
}
}
@container (min-width: 451px) {
.root {
padding: v-bind('props.marginMax + "px"');
}
}
</style>

View File

@@ -6,9 +6,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div ref="rootEl" :class="[$style.root, reversed ? '_pageScrollableReversed' : '_pageScrollable']">
<MkStickyContainer>
<template #header><MkPageHeader v-model:tab="tab" :actions="actions" :tabs="tabs" :displayBackButton="displayBackButton"/></template>
<template #header><MkPageHeader v-model:tab="tab" v-bind="pageHeaderProps"/></template>
<div :class="$style.body">
<slot></slot>
<MkSwiper v-if="swipable && (props.tabs?.length ?? 1) > 1" v-model:tab="tab" :class="$style.swiper" :tabs="props.tabs">
<slot></slot>
</MkSwiper>
<slot v-else></slot>
</div>
<template #footer><slot name="footer"></slot></template>
</MkStickyContainer>
@@ -16,22 +19,24 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
import { useTemplateRef } from 'vue';
import { computed, useTemplateRef } from 'vue';
import { scrollInContainer } from '@@/js/scroll.js';
import type { PageHeaderItem } from '@/types/page-header.js';
import type { Tab } from './MkPageHeader.tabs.vue';
import type { PageHeaderProps } from './MkPageHeader.vue';
import { useScrollPositionKeeper } from '@/use/use-scroll-position-keeper.js';
import MkSwiper from '@/components/MkSwiper.vue';
import { useRouter } from '@/router.js';
const props = withDefaults(defineProps<{
tabs?: Tab[];
actions?: PageHeaderItem[] | null;
thin?: boolean;
hideTitle?: boolean;
displayMyAvatar?: boolean;
const props = withDefaults(defineProps<PageHeaderProps & {
reversed?: boolean;
displayBackButton?: boolean;
swipable?: boolean;
}>(), {
tabs: () => ([] as Tab[]),
reversed: false,
swipable: true,
});
const pageHeaderProps = computed(() => {
const { reversed, ...rest } = props;
return rest;
});
const tab = defineModel<string>('tab');
@@ -39,10 +44,18 @@ const rootEl = useTemplateRef('rootEl');
useScrollPositionKeeper(rootEl);
const router = useRouter();
router.useListener('same', () => {
scrollToTop();
});
function scrollToTop() {
if (rootEl.value) scrollInContainer(rootEl.value, { top: 0, behavior: 'smooth' });
}
defineExpose({
scrollToTop: () => {
if (rootEl.value) scrollInContainer(rootEl.value, { top: 0, behavior: 'smooth' });
},
scrollToTop,
});
</script>
@@ -51,7 +64,7 @@ defineExpose({
}
.body {
.body, .swiper {
min-height: calc(100cqh - (var(--MI-stickyTop, 0px) + var(--MI-stickyBottom, 0px)));
}
</style>

View File

@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div ref="rootEl" class="_pageContainer" :class="$style.root">
<div class="_pageContainer" :class="$style.root">
<KeepAlive :max="prefer.s.numberOfPageCache">
<Suspense :timeout="0">
<component :is="currentPageComponent" :key="key" v-bind="Object.fromEntries(currentPageProps)"/>
@@ -42,37 +42,6 @@ provide(DI.viewId, viewId);
const currentDepth = inject(DI.routerCurrentDepth, 0);
provide(DI.routerCurrentDepth, currentDepth + 1);
const rootEl = useTemplateRef('rootEl');
onMounted(() => {
if (prefer.s.animation) {
rootEl.value.style.viewTransitionName = viewId; // view-transition-nameにcss varが使えないっぽいため直接代入
}
});
// view-transition-newなどの<pt-name-selector>にはcss varが使えず、v-bindできないため直接スタイルを生成
const viewTransitionStylesTag = window.document.createElement('style');
viewTransitionStylesTag.textContent = `
@keyframes ${viewId}-old {
to { transform: scale(0.95); opacity: 0; }
}
@keyframes ${viewId}-new {
from { transform: scale(0.95); opacity: 0; }
}
::view-transition-old(${viewId}) {
animation-duration: 0.2s;
animation-name: ${viewId}-old;
}
::view-transition-new(${viewId}) {
animation-duration: 0.2s;
animation-name: ${viewId}-new;
}
`;
window.document.head.appendChild(viewTransitionStylesTag);
const current = router.current!;
const currentPageComponent = shallowRef('component' in current.route ? current.route.component : MkLoadingPage);
const currentPageProps = ref(current.props);
@@ -90,18 +59,7 @@ router.useListener('change', ({ resolved }) => {
currentRoutePath = resolved.route.path;
}
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (prefer.s.animation && window.document.startViewTransition) {
window.document.startViewTransition(() => new Promise((res) => {
_();
nextTick(() => {
res();
//setTimeout(res, 100);
});
}));
} else {
_();
}
_();
});
</script>

View File

@@ -38,7 +38,6 @@ SPDX-License-Identifier: AGPL-3.0-only
:setting="rowSetting"
:bus="bus"
:using="row.using"
:class="[lastLine === row.index ? 'last_row' : '']"
@operation:beginEdit="onCellEditBegin"
@operation:endEdit="onCellEditEnd"
@change:value="onChangeCellValue"
@@ -1301,8 +1300,6 @@ onMounted(() => {
</style>
<style lang="scss">
$borderSetting: solid 0.5px var(--MI_THEME-divider);
// 配下コンポーネントを含めて一括してコントロールするため、scopedもmoduleも使用できない
.mk_grid_border {
--rootBorderSetting: none;
@@ -1310,66 +1307,39 @@ $borderSetting: solid 0.5px var(--MI_THEME-divider);
border-spacing: 0;
&.mk_grid_root_border {
--rootBorderSetting: #{$borderSetting};
}
&.mk_grid_root_rounded {
--borderRadius: var(--MI-radius);
}
.mk_grid_thead {
position: sticky;
z-index: 1;
left: 0;
top: 0;
-webkit-backdrop-filter: var(--MI-blur, blur(8px));
backdrop-filter: var(--MI-blur, blur(20px));
background: color(from var(--MI_THEME-bg) srgb r g b / 0.5);
.mk_grid_tr {
.mk_grid_th {
border-left: $borderSetting;
border-top: var(--rootBorderSetting);
&:first-child {
// 左上セル
border-left: var(--rootBorderSetting);
border-top-left-radius: var(--borderRadius);
}
&:last-child {
// 右上セル
border-top-right-radius: var(--borderRadius);
border-right: var(--rootBorderSetting);
}
}
}
}
.mk_grid_tbody {
.mk_grid_tr {
.mk_grid_td, .mk_grid_th {
border-left: $borderSetting;
border-top: $borderSetting;
&:first-child {
// 左端の列
border-left: var(--rootBorderSetting);
}
&:last-child {
// 一番右端の列
border-right: var(--rootBorderSetting);
}
&:nth-child(odd) {
background: var(--MI_THEME-panel);
}
&:nth-child(even) {
background: var(--MI_THEME-bg);
}
}
.last_row {
.mk_grid_td, .mk_grid_th {
// 一番下の行
border-bottom: var(--rootBorderSetting);
&:first-child {
// 左下セル
border-bottom-left-radius: var(--borderRadius);
}
&:last-child {
// 右下セル
border-bottom-right-radius: var(--borderRadius);
&:hover {
box-shadow: 0 0 0 1px var(--MI_THEME-divider) inset;
}
}
}

View File

@@ -22,7 +22,6 @@ import MkLoading from './global/MkLoading.vue';
import MkError from './global/MkError.vue';
import MkAd from './global/MkAd.vue';
import MkPageHeader from './global/MkPageHeader.vue';
import MkSpacer from './global/MkSpacer.vue';
import MkStickyContainer from './global/MkStickyContainer.vue';
import MkLazy from './global/MkLazy.vue';
import PageWithHeader from './global/PageWithHeader.vue';
@@ -60,7 +59,6 @@ export const components = {
MkError: MkError,
MkAd: MkAd,
MkPageHeader: MkPageHeader,
MkSpacer: MkSpacer,
MkStickyContainer: MkStickyContainer,
MkLazy: MkLazy,
PageWithHeader: PageWithHeader,
@@ -92,7 +90,6 @@ declare module '@vue/runtime-core' {
MkError: typeof MkError;
MkAd: typeof MkAd;
MkPageHeader: typeof MkPageHeader;
MkSpacer: typeof MkSpacer;
MkStickyContainer: typeof MkStickyContainer;
MkLazy: typeof MkLazy;
PageWithHeader: typeof PageWithHeader;

View File

@@ -17,5 +17,4 @@ export const DI = {
mfmEmojiReactCallback: Symbol() as InjectionKey<(emoji: string) => void>,
inModal: Symbol() as InjectionKey<boolean>,
inAppSearchMarkerId: Symbol() as InjectionKey<Ref<string | null>>,
forceSpacerMin: Symbol() as InjectionKey<boolean>,
};

View File

@@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkStickyContainer>
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
<div style="overflow: clip;">
<MkSpacer :contentMax="600" :marginMin="20">
<div class="_spacer" style="--MI_SPACER-w: 600px; --MI_SPACER-min: 20px;">
<div class="_gaps_m znqjceqz">
<div v-panel class="about">
<div ref="containerEl" class="container" :class="{ playing: easterEggEngine != null }">
@@ -85,7 +85,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-if="section.link" #description><MkLink :url="section.link.url">{{ section.link.label }}</MkLink></template>
</FormSection>
</div>
</MkSpacer>
</div>
</div>
</MkStickyContainer>
</template>

View File

@@ -4,21 +4,19 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
<MkSwiper v-model:tab="tab" :tabs="headerTabs">
<MkSpacer v-if="tab === 'overview'" :contentMax="600" :marginMin="20">
<XOverview/>
</MkSpacer>
<MkSpacer v-else-if="tab === 'emojis'" :contentMax="1000" :marginMin="20">
<XEmojis/>
</MkSpacer>
<MkSpacer v-else-if="instance.federation !== 'none' && tab === 'federation'" :contentMax="1000" :marginMin="20">
<XFederation/>
</MkSpacer>
<MkSpacer v-else-if="tab === 'charts'" :contentMax="1000" :marginMin="20">
<MkInstanceStats/>
</MkSpacer>
</MkSwiper>
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<div v-if="tab === 'overview'" class="_spacer" style="--MI_SPACER-w: 600px; --MI_SPACER-min: 20px;">
<XOverview/>
</div>
<div v-else-if="tab === 'emojis'" class="_spacer" style="--MI_SPACER-w: 1000px; --MI_SPACER-min: 20px;">
<XEmojis/>
</div>
<div v-else-if="instance.federation !== 'none' && tab === 'federation'" class="_spacer" style="--MI_SPACER-w: 1000px; --MI_SPACER-min: 20px;">
<XFederation/>
</div>
<div v-else-if="tab === 'charts'" class="_spacer" style="--MI_SPACER-w: 1000px; --MI_SPACER-min: 20px;">
<MkInstanceStats/>
</div>
</PageWithHeader>
</template>
@@ -28,7 +26,6 @@ import { instance } from '@/instance.js';
import { i18n } from '@/i18n.js';
import { claimAchievement } from '@/utility/achievements.js';
import { definePage } from '@/page.js';
import MkSwiper from '@/components/MkSwiper.vue';
const XOverview = defineAsyncComponent(() => import('@/pages/about.overview.vue'));
const XEmojis = defineAsyncComponent(() => import('@/pages/about.emojis.vue'));

View File

@@ -5,9 +5,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader>
<MkSpacer :contentMax="1200">
<div class="_spacer" style="--MI_SPACER-w: 1200px;">
<MkAchievements :user="$i"/>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
<MkSpacer v-if="file" :contentMax="600" :marginMin="16" :marginMax="32">
<div v-if="file" class="_spacer" style="--MI_SPACER-w: 600px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<div v-if="tab === 'overview'" class="cxqhhsmd _gaps_m">
<a class="thumbnail" :href="file.url" target="_blank">
<MkDriveFileThumbnail class="thumbnail" :file="file" fit="contain"/>
@@ -65,7 +65,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkObjectView v-if="info" tall :value="info">
</MkObjectView>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="600" :marginMin="16" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-w: 600px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<FormSuspense :p="init">
<div v-if="tab === 'overview'" class="_gaps_m">
<div class="aeakzknw">
@@ -201,7 +201,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkObjectView>
</div>
</FormSuspense>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ mode === 'create' ? i18n.ts._abuseReport._notificationRecipient.createRecipient : i18n.ts._abuseReport._notificationRecipient.modifyRecipient }}
</template>
<div v-if="loading === 0" style="display: flex; flex-direction: column; min-height: 100%;">
<MkSpacer :marginMin="20" :marginMax="28" style="flex-grow: 1;">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px; flex-grow: 1;">
<div :class="$style.root" class="_gaps_m">
<MkInput v-model="title">
<template #label>{{ i18n.ts.title }}</template>
@@ -57,7 +57,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts.enable }}</template>
</MkSwitch>
</div>
</MkSpacer>
</div>
<div :class="$style.footer" class="_buttonsCenter">
<MkButton primary rounded :disabled="disableSubmitButton" @click="onSubmitClicked"><i class="ti ti-check"></i> {{ i18n.ts.ok }}</MkButton>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="900">
<div class="_spacer" style="--MI_SPACER-w: 900px;">
<div :class="$style.root" class="_gaps_m">
<div :class="$style.addButton">
<MkButton primary @click="onAddButtonClicked">
@@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
/>
</div>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="900">
<div class="_spacer" style="--MI_SPACER-w: 900px;">
<div :class="$style.root" class="_gaps">
<div :class="$style.subMenus" class="_gaps">
<MkButton link to="/admin/abuse-report-notification-recipient" primary>{{ i18n.ts.notificationSetting }}</MkButton>
@@ -53,7 +53,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</MkPagination>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="900">
<div class="_spacer" style="--MI_SPACER-w: 900px;">
<MkSelect v-model="filterType" :class="$style.input" @update:modelValue="filterItems">
<template #label>{{ i18n.ts.state }}</template>
<option value="all">{{ i18n.ts.all }}</option>
@@ -77,7 +77,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<i class="ti ti-reload"></i>{{ i18n.ts.more }}
</MkButton>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="900">
<div class="_spacer" style="--MI_SPACER-w: 900px;">
<div class="_gaps">
<MkInfo>{{ i18n.ts._announcement.shouldNotBeUsedToPresentPermanentInfo }}</MkInfo>
<MkInfo v-if="announcements.length > 5" warn>{{ i18n.ts._announcement.tooManyActiveAnnouncementDescription }}</MkInfo>
@@ -79,7 +79,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkButton>
</template>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div>
<PageWithHeader :tabs="headerTabs">
<MkSpacer :contentMax="900">
<div class="_spacer" style="--MI_SPACER-w: 900px;">
<div class="_gaps_m">
<MkPagination ref="paginationComponent" :pagination="pagination" :displayLimit="50">
<template #default="{ items }">
@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
</MkPagination>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</div>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :tabs="headerTabs">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<FormSuspense :p="init">
<div class="_gaps_m">
<MkInput v-model="iconUrl" type="url">
@@ -105,12 +105,12 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkTextarea>
</div>
</FormSuspense>
</MkSpacer>
</div>
<template #footer>
<div :class="$style.footer">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="16">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px; --MI_SPACER-max: 16px;">
<MkButton primary rounded @click="save"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
</MkSpacer>
</div>
</div>
</template>
</PageWithHeader>

View File

@@ -14,9 +14,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #header>
<i class="ti ti-notes" style="margin-right: 0.5em;"></i> {{ i18n.ts._customEmojisManager._gridCommon.registrationLogs }}
</template>
<MkSpacer>
<div class="_spacer">
<XRegisterLogs :logs="logs"/>
</MkSpacer>
</div>
</MkWindow>
</template>

View File

@@ -15,7 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<i class="ti ti-search" style="margin-right: 0.5em;"></i> {{ i18n.ts.search }}
</template>
<div :class="$style.root">
<MkSpacer>
<div class="_spacer">
<div class="_gaps">
<div class="_gaps_s">
<MkInput
@@ -107,7 +107,7 @@ SPDX-License-Identifier: AGPL-3.0-only
/>
</MkFolder>
</div>
</MkSpacer>
</div>
<div :class="$style.footerActions">
<MkButton primary @click="onSearchRequest">
{{ i18n.ts.search }}

View File

@@ -285,7 +285,7 @@ const searchQuery = ref<EmojiSearchQuery>({
localOnly: null,
roles: [],
sortOrders: [],
limit: 25,
limit: 100,
});
let searchWindowOpening = false;

View File

@@ -1,35 +0,0 @@
<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<MkStickyContainer>
<template #header>
<MkPageHeader v-model:tab="headerTab" :tabs="headerTabs" hideTitle thin/>
</template>
<XListComponent v-if="headerTab === 'list'" key="localList"/>
<MkSpacer v-else key="localRegister">
<XRegisterComponent/>
</MkSpacer>
</MkStickyContainer>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import { i18n } from '@/i18n.js';
import XListComponent from '@/pages/admin/custom-emojis-manager.local.list.vue';
import XRegisterComponent from '@/pages/admin/custom-emojis-manager.local.register.vue';
type PageMode = 'list' | 'register';
const headerTab = ref<PageMode>('list');
const headerTabs = computed(() => [{
key: 'list',
title: i18n.ts._customEmojisManager._local.tabTitleList,
}, {
key: 'register',
title: i18n.ts._customEmojisManager._local.tabTitleRegister,
}]);
</script>

View File

@@ -4,67 +4,69 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div class="_gaps">
<MkFolder>
<template #icon><i class="ti ti-settings"></i></template>
<template #label>{{ i18n.ts._customEmojisManager._local._register.uploadSettingTitle }}</template>
<template #caption>{{ i18n.ts._customEmojisManager._local._register.uploadSettingDescription }}</template>
<div class="_spacer">
<div class="_gaps">
<MkFolder>
<template #icon><i class="ti ti-settings"></i></template>
<template #label>{{ i18n.ts._customEmojisManager._local._register.uploadSettingTitle }}</template>
<template #caption>{{ i18n.ts._customEmojisManager._local._register.uploadSettingDescription }}</template>
<div class="_gaps">
<MkSelect v-model="selectedFolderId">
<template #label>{{ i18n.ts.uploadFolder }}</template>
<option v-for="folder in uploadFolders" :key="folder.id" :value="folder.id">
{{ folder.name }}
</option>
</MkSelect>
<div class="_gaps">
<MkSelect v-model="selectedFolderId">
<template #label>{{ i18n.ts.uploadFolder }}</template>
<option v-for="folder in uploadFolders" :key="folder.id" :value="folder.id">
{{ folder.name }}
</option>
</MkSelect>
<MkSwitch v-model="directoryToCategory">
<template #label>{{ i18n.ts._customEmojisManager._local._register.directoryToCategoryLabel }}</template>
<template #caption>{{ i18n.ts._customEmojisManager._local._register.directoryToCategoryCaption }}</template>
</MkSwitch>
<MkSwitch v-model="directoryToCategory">
<template #label>{{ i18n.ts._customEmojisManager._local._register.directoryToCategoryLabel }}</template>
<template #caption>{{ i18n.ts._customEmojisManager._local._register.directoryToCategoryCaption }}</template>
</MkSwitch>
</div>
</MkFolder>
<MkFolder>
<template #icon><i class="ti ti-notes"></i></template>
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.registrationLogs }}</template>
<template #caption>
{{ i18n.ts._customEmojisManager._gridCommon.registrationLogsCaption }}
</template>
<XRegisterLogs :logs="requestLogs"/>
</MkFolder>
<div
:class="[$style.uploadBox, [isDragOver ? $style.dragOver : {}]]"
@dragover.prevent="isDragOver = true"
@dragleave.prevent="isDragOver = false"
@drop.prevent.stop="onDrop"
>
<div style="margin-top: 1em">
{{ i18n.ts._customEmojisManager._local._register.emojiInputAreaCaption }}
</div>
<ul>
<li>{{ i18n.ts._customEmojisManager._local._register.emojiInputAreaList1 }}</li>
<li><a @click.prevent="onFileSelectClicked">{{ i18n.ts._customEmojisManager._local._register.emojiInputAreaList2 }}</a></li>
<li><a @click.prevent="onDriveSelectClicked">{{ i18n.ts._customEmojisManager._local._register.emojiInputAreaList3 }}</a></li>
</ul>
</div>
</MkFolder>
<MkFolder>
<template #icon><i class="ti ti-notes"></i></template>
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.registrationLogs }}</template>
<template #caption>
{{ i18n.ts._customEmojisManager._gridCommon.registrationLogsCaption }}
</template>
<XRegisterLogs :logs="requestLogs"/>
</MkFolder>
<div
:class="[$style.uploadBox, [isDragOver ? $style.dragOver : {}]]"
@dragover.prevent="isDragOver = true"
@dragleave.prevent="isDragOver = false"
@drop.prevent.stop="onDrop"
>
<div style="margin-top: 1em">
{{ i18n.ts._customEmojisManager._local._register.emojiInputAreaCaption }}
<div v-if="gridItems.length > 0" :class="$style.gridArea">
<MkGrid
:data="gridItems"
:settings="setupGrid()"
@event="onGridEvent"
/>
</div>
<ul>
<li>{{ i18n.ts._customEmojisManager._local._register.emojiInputAreaList1 }}</li>
<li><a @click.prevent="onFileSelectClicked">{{ i18n.ts._customEmojisManager._local._register.emojiInputAreaList2 }}</a></li>
<li><a @click.prevent="onDriveSelectClicked">{{ i18n.ts._customEmojisManager._local._register.emojiInputAreaList3 }}</a></li>
</ul>
</div>
<div v-if="gridItems.length > 0" :class="$style.gridArea">
<MkGrid
:data="gridItems"
:settings="setupGrid()"
@event="onGridEvent"
/>
</div>
<div v-if="gridItems.length > 0" :class="$style.footer">
<MkButton primary :disabled="registerButtonDisabled" @click="onRegistryClicked">
{{ i18n.ts.registration }}
</MkButton>
<MkButton @click="onClearClicked">
{{ i18n.ts.clear }}
</MkButton>
<div v-if="gridItems.length > 0" :class="$style.footer">
<MkButton primary :disabled="registerButtonDisabled" @click="onRegistryClicked">
{{ i18n.ts.registration }}
</MkButton>
<MkButton @click="onClearClicked">
{{ i18n.ts.clear }}
</MkButton>
</div>
</div>
</div>
</template>
@@ -407,7 +409,7 @@ function fromDriveFile(it: Misskey.entities.DriveFile): GridItem {
return {
fileId: it.id,
url: it.url,
name: it.name.replace(/(\.[a-zA-Z0-9]+)+$/, ''),
name: it.name.replace(/(\.[a-zA-Z0-9]+)+$/, '').replaceAll('-', '_').replaceAll(' ', '_'),
host: '',
category: '',
aliases: '',

View File

@@ -142,6 +142,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<script setup lang="ts">
import { computed, onMounted, ref, useCssModule } from 'vue';
import * as Misskey from 'misskey-js';
import type { GridSortOrderKey, RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
import type { GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
import type { GridSetting } from '@/components/grid/grid.js';
import type { SortOrder } from '@/components/MkSortOrderEditor.define.js';
import MkRemoteEmojiEditDialog from '@/components/MkRemoteEmojiEditDialog.vue';
import { misskeyApi } from '@/utility/misskey-api.js';
import { i18n } from '@/i18n.js';
@@ -157,11 +161,6 @@ import MkPagingButtons from '@/components/MkPagingButtons.vue';
import MkSortOrderEditor from '@/components/MkSortOrderEditor.vue';
import { useLoading } from '@/components/hook/useLoading.js';
import type { GridSortOrderKey, RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
import type { GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
import type { GridSetting } from '@/components/grid/grid.js';
import type { SortOrder } from '@/components/MkSortOrderEditor.define.js';
type GridItem = {
checked: boolean;
id: string;
@@ -260,7 +259,7 @@ const queryHost = ref<string | null>(null);
const queryLicense = ref<string | null>(null);
const queryUri = ref<string | null>(null);
const queryPublicUrl = ref<string | null>(null);
const queryLimit = ref<number>(25);
const queryLimit = ref<number>(100);
const previousQuery = ref<string | undefined>(undefined);
const sortOrders = ref<SortOrder<GridSortOrderKey>[]>([]);
const requestLogs = ref<RequestLogItem[]>([]);

View File

@@ -4,25 +4,20 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div>
<MkStickyContainer>
<template #header>
<MkPageHeader v-model:tab="headerTab" :tabs="headerTabs"/>
</template>
<XGridLocalComponent v-if="headerTab === 'local'" :class="$style.local"/>
<XGridRemoteComponent v-else/>
</MkStickyContainer>
</div>
<PageWithHeader v-model:tab="headerTab" :tabs="headerTabs">
<XGridLocalComponent v-if="headerTab === 'local'" :class="$style.local"/>
<XGridRemoteComponent v-else-if="headerTab === 'remote'" :class="$style.remote"/>
<XRegisterComponent v-else-if="headerTab === 'register'" :class="$style.register"/>
</PageWithHeader>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
import XGridLocalComponent from '@/pages/admin/custom-emojis-manager.local.vue';
import XGridLocalComponent from '@/pages/admin/custom-emojis-manager.local.list.vue';
import XGridRemoteComponent from '@/pages/admin/custom-emojis-manager.remote.vue';
import MkPageHeader from '@/components/global/MkPageHeader.vue';
import MkStickyContainer from '@/components/global/MkStickyContainer.vue';
import XRegisterComponent from '@/pages/admin/custom-emojis-manager.register.vue';
type PageMode = 'local' | 'remote';
@@ -34,6 +29,9 @@ const headerTabs = computed(() => [{
}, {
key: 'remote',
title: i18n.ts.remote,
}, {
key: 'register',
title: i18n.ts._customEmojisManager._local.tabTitleRegister,
}]);
definePage(computed(() => ({

View File

@@ -5,14 +5,14 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="800" :marginMin="16" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-w: 800px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<FormSuspense v-slot="{ result: database }" :p="databasePromiseFactory">
<MkKeyValue v-for="table in database" :key="table[0]" oneline style="margin: 1em 0;">
<template #key>{{ table[0] }}</template>
<template #value>{{ bytes(table[1].size) }} ({{ number(table[1].count) }} recs)</template>
</MkKeyValue>
</FormSuspense>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :tabs="headerTabs">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<FormSuspense :p="init">
<div class="_gaps_m">
<MkSwitch v-model="enableEmail">
@@ -48,15 +48,15 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
</div>
</FormSuspense>
</MkSpacer>
</div>
<template #footer>
<div :class="$style.footer">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="16">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px; --MI_SPACER-max: 16px;">
<div class="_buttons">
<MkButton primary rounded @click="save"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
<MkButton rounded @click="testEmail"><i class="ti ti-send"></i> {{ i18n.ts.testEmail }}</MkButton>
</div>
</MkSpacer>
</div>
</div>
</template>
</PageWithHeader>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<FormSuspense :p="init">
<div class="_gaps_m">
<MkFolder>
@@ -52,7 +52,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFolder>
</div>
</FormSuspense>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="800">
<div class="_spacer" style="--MI_SPACER-w: 800px;">
<XQueue v-if="tab === 'deliver'" domain="deliver"/>
<XQueue v-else-if="tab === 'inbox'" domain="inbox"/>
<br>
@@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton @click="promoteAllQueues"><i class="ti ti-reload"></i> {{ i18n.ts.retryAllQueuesNow }}</MkButton>
<MkButton danger @click="clear"><i class="ti ti-trash"></i> {{ i18n.ts.clearQueue }}</MkButton>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="900">
<div class="_spacer" style="--MI_SPACER-w: 900px;">
<div class="_gaps">
<div>
<MkInput v-model="host" :debounce="true" class="">
@@ -52,7 +52,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</MkPagination>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="900">
<div class="_spacer" style="--MI_SPACER-w: 900px;">
<div class="_gaps">
<div class="inputs" style="display: flex; gap: var(--MI-margin); flex-wrap: wrap;">
<MkSelect v-model="origin" style="margin: 0; flex: 1;">
@@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<MkFileListForAdmin :pagination="pagination" :viewMode="viewMode"/>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div ref="el" class="hiyeyicy" :class="{ wide: !narrow }">
<div v-if="!narrow || currentPage?.route.name == null" class="nav">
<MkSpacer :contentMax="700" :marginMin="16">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px;">
<div class="lxpfedzu _gaps">
<div class="banner">
<img :src="instance.iconUrl || '/favicon.ico'" alt="" class="icon"/>
@@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSuperMenu :def="menuDef" :grid="narrow"></MkSuperMenu>
</div>
</MkSpacer>
</div>
</div>
<div v-if="!(narrow && currentPage?.route.name == null)" class="main _pageContainer" style="height: 100%;">
<NestedRouterView/>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="800">
<div class="_spacer" style="--MI_SPACER-w: 800px;">
<div class="_gaps_m">
<MkFolder :expanded="false">
<template #icon><i class="ti ti-plus"></i></template>
@@ -49,7 +49,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
</MkPagination>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
<MkSpacer>
<div class="_spacer">
<div v-if="tab === '-'" class="_gaps">
<div :class="$style.queues">
<div v-for="q in queueInfos" :key="q.name" :class="$style.queue" @click="tab = q.name">
@@ -139,7 +139,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</template>
<MkSpacer>
<div class="_spacer">
<MkInput
v-model="searchQuery"
:placeholder="i18n.ts.search"
@@ -163,10 +163,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<XJob :job="job" :queueType="tab" style="margin: 4px 0;" @needRefresh="refreshJob(job.id)"/>
</template>
</MkTl>
</MkSpacer>
</div>
</MkFolder>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :tabs="headerTabs">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<FormSuspense :p="init">
<div class="_gaps_m">
<MkSwitch :modelValue="enableRegistration" @update:modelValue="onChange_enableRegistration">
@@ -148,7 +148,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFolder>
</div>
</FormSuspense>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="900">
<div class="_spacer" style="--MI_SPACER-w: 900px;">
<div class="_gaps">
<div style="display: flex; gap: var(--MI-margin); flex-wrap: wrap;">
<MkSelect v-model="type" style="margin: 0; flex: 1;">
@@ -33,7 +33,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton primary rounded style="margin: 0 auto;" @click="fetchMore">{{ i18n.ts.loadMore }}</MkButton>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :tabs="headerTabs">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<FormSuspense :p="init">
<div class="_gaps_m">
<MkSwitch v-model="useObjectStorage">{{ i18n.ts.useObjectStorage }}</MkSwitch>
@@ -70,12 +70,12 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
</div>
</FormSuspense>
</MkSpacer>
</div>
<template #footer>
<div :class="$style.footer">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="16">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px; --MI_SPACER-max: 16px;">
<MkButton primary rounded @click="save"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
</MkSpacer>
</div>
</div>
</template>
</PageWithHeader>

View File

@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<MkSpacer :contentMax="1000">
<div class="_spacer" style="--MI_SPACER-w: 1000px;">
<div ref="rootEl" :class="$style.root">
<MkFoldableSection class="item">
<template #header>Stats</template>
@@ -61,7 +61,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<XQueue domain="inbox"/>
</MkFoldableSection>
</div>
</MkSpacer>
</div>
</template>
<script lang="ts" setup>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<div class="_gaps">
<div class="_panel" style="padding: 16px;">
<MkSwitch v-model="enableServerMachineStats" @change="onChange_enableServerMachineStats">
@@ -102,7 +102,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</MkFolder>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="800">
<div class="_spacer" style="--MI_SPACER-w: 800px;">
<div class="_gaps">
<div v-for="relay in relays" :key="relay.inbox" class="relaycxt _panel" style="padding: 16px;">
<div>{{ relay.inbox }}</div>
@@ -18,7 +18,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton class="button" inline danger @click="remove(relay.inbox)"><i class="ti ti-trash"></i> {{ i18n.ts.remove }}</MkButton>
</div>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,14 +5,14 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :tabs="headerTabs">
<MkSpacer :contentMax="600" :marginMin="16" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-w: 600px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<XEditor v-if="data" v-model="data"/>
</MkSpacer>
</div>
<template #footer>
<div :class="$style.footer">
<MkSpacer :contentMax="600" :marginMin="16" :marginMax="16">
<div class="_spacer" style="--MI_SPACER-w: 600px; --MI_SPACER-min: 16px; --MI_SPACER-max: 16px;">
<MkButton primary rounded @click="save"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
</MkSpacer>
</div>
</div>
</template>
</PageWithHeader>

View File

@@ -445,6 +445,26 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</MkFolder>
<MkFolder v-if="matchQuery([i18n.ts._role._options.maxFileSize, 'maxFileSizeMb'])">
<template #label>{{ i18n.ts._role._options.maxFileSize }}</template>
<template #suffix>
<span v-if="role.policies.maxFileSizeMb.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
<span v-else>{{ role.policies.maxFileSizeMb.value + 'MB' }}</span>
<span :class="$style.priorityIndicator"><i :class="getPriorityIcon(role.policies.maxFileSizeMb)"></i></span>
</template>
<div class="_gaps">
<MkSwitch v-model="role.policies.maxFileSizeMb.useDefault" :readonly="readonly">
<template #label>{{ i18n.ts._role.useBaseValue }}</template>
</MkSwitch>
<MkInput v-model="role.policies.maxFileSizeMb.value" :disabled="role.policies.maxFileSizeMb.useDefault" type="number" :readonly="readonly">
<template #suffix>MB</template>
</MkInput>
<MkRange v-model="role.policies.maxFileSizeMb.priority" :min="0" :max="2" :step="1" easing :textConverter="(v) => v === 0 ? i18n.ts._role._priority.low : v === 1 ? i18n.ts._role._priority.middle : v === 2 ? i18n.ts._role._priority.high : ''">
<template #label>{{ i18n.ts._role.priority }}</template>
</MkRange>
</div>
</MkFolder>
<MkFolder v-if="matchQuery([i18n.ts._role._options.alwaysMarkNsfw, 'alwaysMarkNsfw'])">
<template #label>{{ i18n.ts._role._options.alwaysMarkNsfw }}</template>
<template #suffix>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="700">
<div class="_spacer" style="--MI_SPACER-w: 700px;">
<div class="_gaps">
<div class="_buttons">
<MkButton primary rounded @click="edit"><i class="ti ti-pencil"></i> {{ i18n.ts.edit }}</MkButton>
@@ -54,7 +54,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFolder>
<MkInfo v-else>{{ i18n.ts._role.isConditionalRole }}</MkInfo>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="700">
<div class="_spacer" style="--MI_SPACER-w: 700px;">
<div class="_gaps">
<MkFolder>
<template #label>{{ i18n.ts._role.baseRole }}</template>
@@ -165,6 +165,14 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkInput>
</MkFolder>
<MkFolder v-if="matchQuery([i18n.ts._role._options.maxFileSize, 'maxFileSizeMb'])">
<template #label>{{ i18n.ts._role._options.maxFileSize }}</template>
<template #suffix>{{ policies.maxFileSizeMb }}MB</template>
<MkInput v-model="policies.maxFileSizeMb" type="number">
<template #suffix>MB</template>
</MkInput>
</MkFolder>
<MkFolder v-if="matchQuery([i18n.ts._role._options.alwaysMarkNsfw, 'alwaysMarkNsfw'])">
<template #label>{{ i18n.ts._role._options.alwaysMarkNsfw }}</template>
<template #suffix>{{ policies.alwaysMarkNsfw ? i18n.ts.yes : i18n.ts.no }}</template>
@@ -310,7 +318,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFoldableSection>
</div>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<div class="_gaps_m">
<MkFolder v-if="meta.federation !== 'none'">
<template #label>{{ i18n.ts.authorizedFetchSection }}</template>
@@ -87,7 +87,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</MkFolder>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :tabs="headerTabs">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<div class="_gaps_m">
<div>{{ i18n.ts._serverRules.description }}</div>
<Sortable
@@ -33,7 +33,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton primary rounded @click="save"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
</div>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :tabs="headerTabs">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<div class="_gaps_m">
<MkFolder :defaultOpen="true">
<template #icon><i class="ti ti-info-circle"></i></template>
@@ -282,7 +282,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</MkFolder>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="900">
<div class="_spacer" style="--MI_SPACER-w: 900px;">
<div class="_gaps_m">
<MkButton primary @click="onCreateWebhookClicked">
<i class="ti ti-plus"></i> {{ i18n.ts._webhookSettings.createWebhook }}
@@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</FormSection>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="900">
<div class="_spacer" style="--MI_SPACER-w: 900px;">
<div class="_gaps">
<div :class="$style.inputs">
<MkButton style="margin-left: auto" @click="resetQuery">{{ i18n.ts.reset }}</MkButton>
@@ -53,7 +53,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</MkPagination>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,11 +5,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader>
<MkSpacer :contentMax="500">
<div class="_spacer" style="--MI_SPACER-w: 500px;">
<div class="_gaps">
<MkAd v-for="ad in instance.ads" :key="ad.id" :specify="ad"/>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="800">
<div class="_spacer" style="--MI_SPACER-w: 800px;">
<Transition
:enterActiveClass="prefer.s.animation ? $style.fadeEnterActive : ''"
:leaveActiveClass="prefer.s.animation ? $style.fadeLeaveActive : ''"
@@ -42,7 +42,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkError v-else-if="error" @retry="fetch()"/>
<MkLoading v-else/>
</Transition>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -4,8 +4,8 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="800">
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<div class="_spacer" style="--MI_SPACER-w: 800px;">
<MkSwiper v-model:tab="tab" :tabs="headerTabs">
<div class="_gaps">
<MkInfo v-if="$i && $i.hasUnreadAnnouncement && tab === 'current'" warn>{{ i18n.ts.youHaveUnreadAnnouncements }}</MkInfo>
@@ -41,7 +41,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkPagination>
</div>
</MkSwiper>
</MkSpacer>
</div>
</PageWithHeader>
</template>
@@ -50,7 +50,6 @@ import { ref, computed } from 'vue';
import MkPagination from '@/components/MkPagination.vue';
import MkButton from '@/components/MkButton.vue';
import MkInfo from '@/components/MkInfo.vue';
import MkSwiper from '@/components/MkSwiper.vue';
import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import { i18n } from '@/i18n.js';

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :displayBackButton="true" :tabs="headerTabs">
<MkSpacer :contentMax="800">
<div class="_spacer" style="--MI_SPACER-w: 800px;">
<div ref="rootEl">
<div v-if="queue > 0" :class="$style.new"><button class="_buttonPrimary" :class="$style.newButton" @click="top()">{{ i18n.ts.newNoteRecived }}</button></div>
<div :class="$style.tl">
@@ -18,7 +18,7 @@ SPDX-License-Identifier: AGPL-3.0-only
/>
</div>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="700">
<div class="_spacer" style="--MI_SPACER-w: 700px;">
<div class="_gaps_m">
<div class="_gaps_m">
<MkInput v-model="endpoint" :datalist="endpoints" debounce @update:modelValue="onEndpointChange()">
@@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkTextarea>
</div>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="500">
<div class="_spacer" style="--MI_SPACER-w: 500px;">
<div v-if="state == 'fetch-session-error'">
<p>{{ i18n.ts.somethingHappened }}</p>
</div>
@@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<p :class="$style.loginMessage">{{ i18n.ts._auth.pleaseLogin }}</p>
<MkSignin @login="onLogin"/>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-else #header>New decoration</template>
<div style="display: flex; flex-direction: column; min-height: 100%;">
<MkSpacer :marginMin="20" :marginMax="28" style="flex-grow: 1;">
<div class="_spacer" style="--MI_SPACER-min: 20px; --MI_SPACER-max: 28px; flex-grow: 1;">
<div class="_gaps_m">
<div :class="$style.preview">
<div :class="[$style.previewItem, $style.light]">
@@ -51,7 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFolder>
<MkButton v-if="avatarDecoration" danger @click="del()"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
</div>
</MkSpacer>
</div>
<div :class="$style.footer">
<MkButton primary rounded style="margin: 0 auto;" @click="done"><i class="ti ti-check"></i> {{ props.avatarDecoration ? i18n.ts.update : i18n.ts.create }}</MkButton>
</div>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="900">
<div class="_spacer" style="--MI_SPACER-w: 900px;">
<div class="_gaps">
<div :class="$style.decorations">
<div
@@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="700">
<div class="_spacer" style="--MI_SPACER-w: 700px;">
<div v-if="channelId == null || channel != null" class="_gaps_m">
<MkInput v-model="name">
<template #label>{{ i18n.ts.name }}</template>
@@ -63,7 +63,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton v-if="channelId" danger @click="archive()"><i class="ti ti-trash"></i> {{ i18n.ts.archive }}</MkButton>
</div>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -4,8 +4,8 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="700">
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<div class="_spacer" style="--MI_SPACER-w: 700px;">
<MkSwiper v-model:tab="tab" :tabs="headerTabs">
<div v-if="channel && tab === 'overview'" class="_gaps">
<div class="_panel" :class="$style.bannerContainer">
@@ -58,14 +58,14 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
</MkSwiper>
</MkSpacer>
</div>
<template #footer>
<div :class="$style.footer">
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="16">
<div class="_spacer" style="--MI_SPACER-w: 700px; --MI_SPACER-min: 16px; --MI_SPACER-max: 16px;">
<div class="_buttonsCenter">
<MkButton inline rounded primary gradate @click="openPostForm()"><i class="ti ti-pencil"></i> {{ i18n.ts.postToTheChannel }}</MkButton>
</div>
</MkSpacer>
</div>
</div>
</template>
</PageWithHeader>
@@ -93,7 +93,6 @@ import { prefer } from '@/preferences.js';
import MkNote from '@/components/MkNote.vue';
import MkInfo from '@/components/MkInfo.vue';
import MkFoldableSection from '@/components/MkFoldableSection.vue';
import MkSwiper from '@/components/MkSwiper.vue';
import { isSupportShare } from '@/utility/navigator.js';
import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
import { notesSearchAvailable } from '@/utility/check-permissions.js';

View File

@@ -4,57 +4,55 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="1200">
<MkSwiper v-model:tab="tab" :tabs="headerTabs">
<div v-if="tab === 'search'" :class="$style.searchRoot">
<div class="_gaps">
<MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search" @enter="search">
<template #prefix><i class="ti ti-search"></i></template>
</MkInput>
<MkRadios v-model="searchType" @update:modelValue="search()">
<option value="nameAndDescription">{{ i18n.ts._channel.nameAndDescription }}</option>
<option value="nameOnly">{{ i18n.ts._channel.nameOnly }}</option>
</MkRadios>
<MkButton large primary gradate rounded @click="search">{{ i18n.ts.search }}</MkButton>
</div>
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<div class="_spacer" style="--MI_SPACER-w: 1200px;">
<div v-if="tab === 'search'" :class="$style.searchRoot">
<div class="_gaps">
<MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search" @enter="search">
<template #prefix><i class="ti ti-search"></i></template>
</MkInput>
<MkRadios v-model="searchType" @update:modelValue="search()">
<option value="nameAndDescription">{{ i18n.ts._channel.nameAndDescription }}</option>
<option value="nameOnly">{{ i18n.ts._channel.nameOnly }}</option>
</MkRadios>
<MkButton large primary gradate rounded @click="search">{{ i18n.ts.search }}</MkButton>
</div>
<MkFoldableSection v-if="channelPagination">
<template #header>{{ i18n.ts.searchResult }}</template>
<MkChannelList :key="key" :pagination="channelPagination"/>
</MkFoldableSection>
</div>
<div v-if="tab === 'featured'">
<MkPagination v-slot="{items}" :pagination="featuredPagination">
<div :class="$style.root">
<MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
</div>
</MkPagination>
</div>
<div v-else-if="tab === 'favorites'">
<MkPagination v-slot="{items}" :pagination="favoritesPagination">
<div :class="$style.root">
<MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
</div>
</MkPagination>
</div>
<div v-else-if="tab === 'following'">
<MkPagination v-slot="{items}" :pagination="followingPagination">
<div :class="$style.root">
<MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
</div>
</MkPagination>
</div>
<div v-else-if="tab === 'owned'">
<MkButton class="new" @click="create()"><i class="ti ti-plus"></i></MkButton>
<MkPagination v-slot="{items}" :pagination="ownedPagination">
<div :class="$style.root">
<MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
</div>
</MkPagination>
</div>
</MkSwiper>
</MkSpacer>
<MkFoldableSection v-if="channelPagination">
<template #header>{{ i18n.ts.searchResult }}</template>
<MkChannelList :key="key" :pagination="channelPagination"/>
</MkFoldableSection>
</div>
<div v-if="tab === 'featured'">
<MkPagination v-slot="{items}" :pagination="featuredPagination">
<div :class="$style.root">
<MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
</div>
</MkPagination>
</div>
<div v-else-if="tab === 'favorites'">
<MkPagination v-slot="{items}" :pagination="favoritesPagination">
<div :class="$style.root">
<MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
</div>
</MkPagination>
</div>
<div v-else-if="tab === 'following'">
<MkPagination v-slot="{items}" :pagination="followingPagination">
<div :class="$style.root">
<MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
</div>
</MkPagination>
</div>
<div v-else-if="tab === 'owned'">
<MkButton class="new" @click="create()"><i class="ti ti-plus"></i></MkButton>
<MkPagination v-slot="{items}" :pagination="ownedPagination">
<div :class="$style.root">
<MkChannelPreview v-for="channel in items" :key="channel.id" :channel="channel"/>
</div>
</MkPagination>
</div>
</div>
</PageWithHeader>
</template>
@@ -67,7 +65,6 @@ import MkInput from '@/components/MkInput.vue';
import MkRadios from '@/components/MkRadios.vue';
import MkButton from '@/components/MkButton.vue';
import MkFoldableSection from '@/components/MkFoldableSection.vue';
import MkSwiper from '@/components/MkSwiper.vue';
import { definePage } from '@/page.js';
import { i18n } from '@/i18n.js';
import { useRouter } from '@/router.js';

View File

@@ -4,16 +4,14 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<MkPolkadots v-if="tab === 'home'" accented/>
<MkSpacer :contentMax="700">
<MkSwiper v-model:tab="tab" :tabs="headerTabs">
<XHome v-if="tab === 'home'"/>
<XInvitations v-else-if="tab === 'invitations'"/>
<XJoiningRooms v-else-if="tab === 'joiningRooms'"/>
<XOwnedRooms v-else-if="tab === 'ownedRooms'"/>
</MkSwiper>
</MkSpacer>
<div class="_spacer" style="--MI_SPACER-w: 700px;">
<XHome v-if="tab === 'home'"/>
<XInvitations v-else-if="tab === 'invitations'"/>
<XJoiningRooms v-else-if="tab === 'joiningRooms'"/>
<XOwnedRooms v-else-if="tab === 'ownedRooms'"/>
</div>
</PageWithHeader>
</template>
@@ -25,7 +23,6 @@ import XJoiningRooms from './home.joiningRooms.vue';
import XOwnedRooms from './home.ownedRooms.vue';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
import MkSwiper from '@/components/MkSwiper.vue';
import MkPolkadots from '@/components/MkPolkadots.vue';
const tab = ref('home');

View File

@@ -5,14 +5,14 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader>
<MkSpacer :contentMax="700">
<div class="_spacer" style="--MI_SPACER-w: 700px;">
<div v-if="initializing || message == null">
<MkLoading/>
</div>
<div v-else>
<XMessage :message="message" :isSearchResult="true"/>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader v-model:tab="tab" :reversed="tab === 'chat'" :tabs="headerTabs" :actions="headerActions">
<MkSpacer v-if="tab === 'chat'" :contentMax="700">
<div v-if="tab === 'chat'" class="_spacer" style="--MI_SPACER-w: 700px;">
<div class="_gaps">
<div v-if="initializing">
<MkLoading/>
@@ -56,19 +56,19 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkInfo v-if="$i.policies.chatAvailability !== 'available'" warn>{{ $i.policies.chatAvailability === 'readonly' ? i18n.ts._chat.chatIsReadOnlyForThisAccountOrServer : i18n.ts._chat.chatNotAvailableForThisAccountOrServer }}</MkInfo>
</div>
</MkSpacer>
</div>
<MkSpacer v-else-if="tab === 'search'" :contentMax="700">
<div v-else-if="tab === 'search'" class="_spacer" style="--MI_SPACER-w: 700px;">
<XSearch :userId="userId" :roomId="roomId"/>
</MkSpacer>
</div>
<MkSpacer v-else-if="tab === 'members'" :contentMax="700">
<div v-else-if="tab === 'members'" class="_spacer" style="--MI_SPACER-w: 700px;">
<XMembers v-if="room != null" :room="room" @inviteUser="inviteUser"/>
</MkSpacer>
</div>
<MkSpacer v-else-if="tab === 'info'" :contentMax="700">
<div v-else-if="tab === 'info'" class="_spacer" style="--MI_SPACER-w: 700px;">
<XInfo v-if="room != null" :room="room"/>
</MkSpacer>
</div>
<template #footer>
<div v-if="tab === 'chat'" :class="$style.footer">

View File

@@ -5,9 +5,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader>
<MkSpacer :contentMax="800">
<div class="_spacer" style="--MI_SPACER-w: 800px;">
<MkClickerGame/>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions">
<MkSpacer :contentMax="800">
<div class="_spacer" style="--MI_SPACER-w: 800px;">
<div v-if="clip" class="_gaps">
<div class="_panel">
<div class="_gaps_s" :class="$style.description">
@@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkNotes :pagination="pagination" :detail="true"/>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader>
<MkSpacer :contentMax="600" :marginMin="20">
<div class="_spacer" style="--MI_SPACER-w: 600px; --MI_SPACER-min: 20px;">
<div class="_gaps_m">
<MkKeyValue :copy="instance.maintainerName">
<template #key>{{ i18n.ts.administrator }}</template>
@@ -29,7 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
</MkKeyValue>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="900">
<div class="_spacer" style="--MI_SPACER-w: 900px;">
<div class="ogwlenmc">
<div v-if="tab === 'local'" class="local">
<MkInput v-model="query" :debounce="true" type="search" autocapitalize="off">
@@ -66,7 +66,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkPagination>
</div>
</div>
</MkSpacer>
</div>
</PageWithHeader>
</template>

View File

@@ -10,13 +10,13 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<MkSwiper v-model:tab="tab" :tabs="headerTabs">
<MkSpacer v-if="tab === 'info'" :contentMax="800">
<div v-if="tab === 'info'" class="_spacer" style="--MI_SPACER-w: 800px;">
<XFileInfo :fileId="fileId"/>
</MkSpacer>
</div>
<MkSpacer v-else-if="tab === 'notes'" :contentMax="800">
<div v-else-if="tab === 'notes'" class="_spacer" style="--MI_SPACER-w: 800px;">
<XNotes :fileId="fileId"/>
</MkSpacer>
</div>
</MkSwiper>
</MkStickyContainer>
</template>

Some files were not shown because too many files have changed in this diff Show More