refactor
This commit is contained in:
		
							parent
							
								
									8524e9d735
								
							
						
					
					
						commit
						e633c3b84b
					
				
					 22 changed files with 453 additions and 450 deletions
				
			
		|  | @ -33,12 +33,12 @@ | ||||||
| 		<option v-for="item in c.items" :key="item.value" :value="item.value">{{ item.text }}</option> | 		<option v-for="item in c.items" :key="item.value" :value="item.value">{{ item.text }}</option> | ||||||
| 	</MkSelect> | 	</MkSelect> | ||||||
| 	<MkButton v-else-if="c.type === 'postFormButton'" :primary="c.primary" :rounded="c.rounded" :small="size === 'small'" @click="openPostForm">{{ c.text }}</MkButton> | 	<MkButton v-else-if="c.type === 'postFormButton'" :primary="c.primary" :rounded="c.rounded" :small="size === 'small'" @click="openPostForm">{{ c.text }}</MkButton> | ||||||
| 	<FormFolder v-else-if="c.type === 'folder'" :default-open="c.opened"> | 	<MkFolder v-else-if="c.type === 'folder'" :default-open="c.opened"> | ||||||
| 		<template #label>{{ c.title }}</template> | 		<template #label>{{ c.title }}</template> | ||||||
| 		<template v-for="child in c.children" :key="child"> | 		<template v-for="child in c.children" :key="child"> | ||||||
| 			<MkAsUi v-if="!g(child).hidden" :component="g(child)" :components="props.components" :size="size"/> | 			<MkAsUi v-if="!g(child).hidden" :component="g(child)" :components="props.components" :size="size"/> | ||||||
| 		</template> | 		</template> | ||||||
| 	</FormFolder> | 	</MkFolder> | ||||||
| 	<div v-else-if="c.type === 'container'" :class="[$style.container, { [$style.fontSerif]: c.font === 'serif', [$style.fontMonospace]: c.font === 'monospace', [$style.containerCenter]: c.align === 'center' }]" :style="{ backgroundColor: c.bgColor ?? null, color: c.fgColor ?? null, borderWidth: c.borderWidth ? `${c.borderWidth}px` : 0, borderColor: c.borderColor ?? 'var(--divider)', padding: c.padding ? `${c.padding}px` : 0, borderRadius: c.rounded ? '8px' : 0 }"> | 	<div v-else-if="c.type === 'container'" :class="[$style.container, { [$style.fontSerif]: c.font === 'serif', [$style.fontMonospace]: c.font === 'monospace', [$style.containerCenter]: c.align === 'center' }]" :style="{ backgroundColor: c.bgColor ?? null, color: c.fgColor ?? null, borderWidth: c.borderWidth ? `${c.borderWidth}px` : 0, borderColor: c.borderColor ?? 'var(--divider)', padding: c.padding ? `${c.padding}px` : 0, borderRadius: c.rounded ? '8px' : 0 }"> | ||||||
| 		<template v-for="child in c.children" :key="child"> | 		<template v-for="child in c.children" :key="child"> | ||||||
| 			<MkAsUi v-if="!g(child).hidden" :component="g(child)" :components="props.components" :size="size"/> | 			<MkAsUi v-if="!g(child).hidden" :component="g(child)" :components="props.components" :size="size"/> | ||||||
|  | @ -56,7 +56,7 @@ import MkSwitch from '@/components/MkSwitch.vue'; | ||||||
| import MkTextarea from '@/components/MkTextarea.vue'; | import MkTextarea from '@/components/MkTextarea.vue'; | ||||||
| import MkSelect from '@/components/MkSelect.vue'; | import MkSelect from '@/components/MkSelect.vue'; | ||||||
| import { AsUiComponent } from '@/scripts/aiscript/ui'; | import { AsUiComponent } from '@/scripts/aiscript/ui'; | ||||||
| import FormFolder from '@/components/form/folder.vue'; | import MkFolder from '@/components/MkFolder.vue'; | ||||||
| 
 | 
 | ||||||
| const props = withDefaults(defineProps<{ | const props = withDefaults(defineProps<{ | ||||||
| 	component: AsUiComponent; | 	component: AsUiComponent; | ||||||
|  |  | ||||||
							
								
								
									
										154
									
								
								packages/frontend/src/components/MkFoldableSection.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								packages/frontend/src/components/MkFoldableSection.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,154 @@ | ||||||
|  | <template> | ||||||
|  | <div class="ssazuxis"> | ||||||
|  | 	<header class="_button" :style="{ background: bg }" @click="showBody = !showBody"> | ||||||
|  | 		<div class="title"><div><slot name="header"></slot></div></div> | ||||||
|  | 		<div class="divider"></div> | ||||||
|  | 		<button class="_button"> | ||||||
|  | 			<template v-if="showBody"><i class="ti ti-chevron-up"></i></template> | ||||||
|  | 			<template v-else><i class="ti ti-chevron-down"></i></template> | ||||||
|  | 		</button> | ||||||
|  | 	</header> | ||||||
|  | 	<Transition | ||||||
|  | 		:name="$store.state.animation ? 'folder-toggle' : ''" | ||||||
|  | 		@enter="enter" | ||||||
|  | 		@after-enter="afterEnter" | ||||||
|  | 		@leave="leave" | ||||||
|  | 		@after-leave="afterLeave" | ||||||
|  | 	> | ||||||
|  | 		<div v-show="showBody"> | ||||||
|  | 			<slot></slot> | ||||||
|  | 		</div> | ||||||
|  | 	</Transition> | ||||||
|  | </div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script lang="ts"> | ||||||
|  | import { defineComponent } from 'vue'; | ||||||
|  | import tinycolor from 'tinycolor2'; | ||||||
|  | import { miLocalStorage } from '@/local-storage'; | ||||||
|  | 
 | ||||||
|  | const miLocalStoragePrefix = 'ui:folder:' as const; | ||||||
|  | 
 | ||||||
|  | export default defineComponent({ | ||||||
|  | 	props: { | ||||||
|  | 		expanded: { | ||||||
|  | 			type: Boolean, | ||||||
|  | 			required: false, | ||||||
|  | 			default: true, | ||||||
|  | 		}, | ||||||
|  | 		persistKey: { | ||||||
|  | 			type: String, | ||||||
|  | 			required: false, | ||||||
|  | 			default: null, | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 	data() { | ||||||
|  | 		return { | ||||||
|  | 			bg: null, | ||||||
|  | 			showBody: (this.persistKey && miLocalStorage.getItem(`${miLocalStoragePrefix}${this.persistKey}`)) ? (miLocalStorage.getItem(`${miLocalStoragePrefix}${this.persistKey}`) === 't') : this.expanded, | ||||||
|  | 		}; | ||||||
|  | 	}, | ||||||
|  | 	watch: { | ||||||
|  | 		showBody() { | ||||||
|  | 			if (this.persistKey) { | ||||||
|  | 				miLocalStorage.setItem(`${miLocalStoragePrefix}${this.persistKey}`, this.showBody ? 't' : 'f'); | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 	mounted() { | ||||||
|  | 		function getParentBg(el: Element | null): string { | ||||||
|  | 			if (el == null || el.tagName === 'BODY') return 'var(--bg)'; | ||||||
|  | 			const bg = el.style.background || el.style.backgroundColor; | ||||||
|  | 			if (bg) { | ||||||
|  | 				return bg; | ||||||
|  | 			} else { | ||||||
|  | 				return getParentBg(el.parentElement); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		const rawBg = getParentBg(this.$el); | ||||||
|  | 		const bg = tinycolor(rawBg.startsWith('var(') ? getComputedStyle(document.documentElement).getPropertyValue(rawBg.slice(4, -1)) : rawBg); | ||||||
|  | 		bg.setAlpha(0.85); | ||||||
|  | 		this.bg = bg.toRgbString(); | ||||||
|  | 	}, | ||||||
|  | 	methods: { | ||||||
|  | 		toggleContent(show: boolean) { | ||||||
|  | 			this.showBody = show; | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		enter(el) { | ||||||
|  | 			const elementHeight = el.getBoundingClientRect().height; | ||||||
|  | 			el.style.height = 0; | ||||||
|  | 			el.offsetHeight; // reflow | ||||||
|  | 			el.style.height = elementHeight + 'px'; | ||||||
|  | 		}, | ||||||
|  | 		afterEnter(el) { | ||||||
|  | 			el.style.height = null; | ||||||
|  | 		}, | ||||||
|  | 		leave(el) { | ||||||
|  | 			const elementHeight = el.getBoundingClientRect().height; | ||||||
|  | 			el.style.height = elementHeight + 'px'; | ||||||
|  | 			el.offsetHeight; // reflow | ||||||
|  | 			el.style.height = 0; | ||||||
|  | 		}, | ||||||
|  | 		afterLeave(el) { | ||||||
|  | 			el.style.height = null; | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | .folder-toggle-enter-active, .folder-toggle-leave-active { | ||||||
|  | 	overflow-y: clip; | ||||||
|  | 	transition: opacity 0.5s, height 0.5s !important; | ||||||
|  | } | ||||||
|  | .folder-toggle-enter-from { | ||||||
|  | 	opacity: 0; | ||||||
|  | } | ||||||
|  | .folder-toggle-leave-to { | ||||||
|  | 	opacity: 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .ssazuxis { | ||||||
|  | 	position: relative; | ||||||
|  | 
 | ||||||
|  | 	> header { | ||||||
|  | 		display: flex; | ||||||
|  | 		position: relative; | ||||||
|  | 		z-index: 10; | ||||||
|  | 		position: sticky; | ||||||
|  | 		top: var(--stickyTop, 0px); | ||||||
|  | 		padding: var(--x-padding); | ||||||
|  | 		-webkit-backdrop-filter: var(--blur, blur(8px)); | ||||||
|  | 		backdrop-filter: var(--blur, blur(20px)); | ||||||
|  | 
 | ||||||
|  | 		> .title { | ||||||
|  | 			display: grid; | ||||||
|  | 			place-content: center; | ||||||
|  | 			margin: 0; | ||||||
|  | 			padding: 12px 16px 12px 0; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		> .divider { | ||||||
|  | 			flex: 1; | ||||||
|  | 			margin: auto; | ||||||
|  | 			height: 1px; | ||||||
|  | 			background: var(--divider); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		> button { | ||||||
|  | 			padding: 12px 0 12px 16px; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @container (max-width: 500px) { | ||||||
|  | 	.ssazuxis { | ||||||
|  | 		> header { | ||||||
|  | 			> .title { | ||||||
|  | 				padding: 8px 10px 8px 0; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | @ -1,13 +1,15 @@ | ||||||
| <template> | <template> | ||||||
| <div class="ssazuxis"> | <div ref="rootEl" class="dwzlatin" :class="{ opened }"> | ||||||
| 	<header class="_button" :style="{ background: bg }" @click="showBody = !showBody"> | 	<div class="header _button" @click="toggle"> | ||||||
| 		<div class="title"><div><slot name="header"></slot></div></div> | 		<span class="icon"><slot name="icon"></slot></span> | ||||||
| 		<div class="divider"></div> | 		<span class="text"><slot name="label"></slot></span> | ||||||
| 		<button class="_button"> | 		<span class="right"> | ||||||
| 			<template v-if="showBody"><i class="ti ti-chevron-up"></i></template> | 			<span class="text"><slot name="suffix"></slot></span> | ||||||
| 			<template v-else><i class="ti ti-chevron-down"></i></template> | 			<i v-if="opened" class="ti ti-chevron-up icon"></i> | ||||||
| 		</button> | 			<i v-else class="ti ti-chevron-down icon"></i> | ||||||
| 	</header> | 		</span> | ||||||
|  | 	</div> | ||||||
|  | 	<div v-if="openedAtLeastOnce" class="body" :class="{ bgSame }" :style="{ maxHeight: maxHeight ? `${maxHeight}px` : null }"> | ||||||
| 		<Transition | 		<Transition | ||||||
| 			:name="$store.state.animation ? 'folder-toggle' : ''" | 			:name="$store.state.animation ? 'folder-toggle' : ''" | ||||||
| 			@enter="enter" | 			@enter="enter" | ||||||
|  | @ -15,139 +17,161 @@ | ||||||
| 			@leave="leave" | 			@leave="leave" | ||||||
| 			@after-leave="afterLeave" | 			@after-leave="afterLeave" | ||||||
| 		> | 		> | ||||||
| 		<div v-show="showBody"> | 			<KeepAlive> | ||||||
|  | 				<div v-show="opened"> | ||||||
|  | 					<MkSpacer :margin-min="14" :margin-max="22"> | ||||||
| 						<slot></slot> | 						<slot></slot> | ||||||
|  | 					</MkSpacer> | ||||||
| 				</div> | 				</div> | ||||||
|  | 			</KeepAlive> | ||||||
| 		</Transition> | 		</Transition> | ||||||
| 	</div> | 	</div> | ||||||
|  | </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script lang="ts"> | <script lang="ts" setup> | ||||||
| import { defineComponent } from 'vue'; | import { nextTick, onMounted } from 'vue'; | ||||||
| import tinycolor from 'tinycolor2'; |  | ||||||
| import { miLocalStorage } from '@/local-storage'; |  | ||||||
| 
 | 
 | ||||||
| const miLocalStoragePrefix = 'ui:folder:' as const; | const props = withDefaults(defineProps<{ | ||||||
|  | 	defaultOpen: boolean; | ||||||
|  | 	maxHeight: number | null; | ||||||
|  | }>(), { | ||||||
|  | 	defaultOpen: false, | ||||||
|  | 	maxHeight: null, | ||||||
|  | }); | ||||||
| 
 | 
 | ||||||
| export default defineComponent({ | const getBgColor = (el: HTMLElement) => { | ||||||
| 	props: { | 	const style = window.getComputedStyle(el); | ||||||
| 		expanded: { | 	if (style.backgroundColor && !['rgba(0, 0, 0, 0)', 'rgba(0,0,0,0)', 'transparent'].includes(style.backgroundColor)) { | ||||||
| 			type: Boolean, | 		return style.backgroundColor; | ||||||
| 			required: false, |  | ||||||
| 			default: true, |  | ||||||
| 		}, |  | ||||||
| 		persistKey: { |  | ||||||
| 			type: String, |  | ||||||
| 			required: false, |  | ||||||
| 			default: null, |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| 	data() { |  | ||||||
| 		return { |  | ||||||
| 			bg: null, |  | ||||||
| 			showBody: (this.persistKey && miLocalStorage.getItem(`${miLocalStoragePrefix}${this.persistKey}`)) ? (miLocalStorage.getItem(`${miLocalStoragePrefix}${this.persistKey}`) === 't') : this.expanded, |  | ||||||
| 		}; |  | ||||||
| 	}, |  | ||||||
| 	watch: { |  | ||||||
| 		showBody() { |  | ||||||
| 			if (this.persistKey) { |  | ||||||
| 				miLocalStorage.setItem(`${miLocalStoragePrefix}${this.persistKey}`, this.showBody ? 't' : 'f'); |  | ||||||
| 			} |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| 	mounted() { |  | ||||||
| 		function getParentBg(el: Element | null): string { |  | ||||||
| 			if (el == null || el.tagName === 'BODY') return 'var(--bg)'; |  | ||||||
| 			const bg = el.style.background || el.style.backgroundColor; |  | ||||||
| 			if (bg) { |  | ||||||
| 				return bg; |  | ||||||
| 	} else { | 	} else { | ||||||
| 				return getParentBg(el.parentElement); | 		return el.parentElement ? getBgColor(el.parentElement) : 'transparent'; | ||||||
| 	} | 	} | ||||||
| 		} | }; | ||||||
| 		const rawBg = getParentBg(this.$el); |  | ||||||
| 		const bg = tinycolor(rawBg.startsWith('var(') ? getComputedStyle(document.documentElement).getPropertyValue(rawBg.slice(4, -1)) : rawBg); |  | ||||||
| 		bg.setAlpha(0.85); |  | ||||||
| 		this.bg = bg.toRgbString(); |  | ||||||
| 	}, |  | ||||||
| 	methods: { |  | ||||||
| 		toggleContent(show: boolean) { |  | ||||||
| 			this.showBody = show; |  | ||||||
| 		}, |  | ||||||
| 
 | 
 | ||||||
| 		enter(el) { | let rootEl = $ref<HTMLElement>(); | ||||||
|  | let bgSame = $ref(false); | ||||||
|  | let opened = $ref(props.defaultOpen); | ||||||
|  | let openedAtLeastOnce = $ref(props.defaultOpen); | ||||||
|  | 
 | ||||||
|  | function enter(el) { | ||||||
| 	const elementHeight = el.getBoundingClientRect().height; | 	const elementHeight = el.getBoundingClientRect().height; | ||||||
| 	el.style.height = 0; | 	el.style.height = 0; | ||||||
| 	el.offsetHeight; // reflow | 	el.offsetHeight; // reflow | ||||||
| 			el.style.height = elementHeight + 'px'; | 	el.style.height = Math.min(elementHeight, props.maxHeight ?? Infinity) + 'px'; | ||||||
| 		}, | } | ||||||
| 		afterEnter(el) { | 
 | ||||||
|  | function afterEnter(el) { | ||||||
| 	el.style.height = null; | 	el.style.height = null; | ||||||
| 		}, | } | ||||||
| 		leave(el) { | 
 | ||||||
|  | function leave(el) { | ||||||
| 	const elementHeight = el.getBoundingClientRect().height; | 	const elementHeight = el.getBoundingClientRect().height; | ||||||
| 	el.style.height = elementHeight + 'px'; | 	el.style.height = elementHeight + 'px'; | ||||||
| 	el.offsetHeight; // reflow | 	el.offsetHeight; // reflow | ||||||
| 	el.style.height = 0; | 	el.style.height = 0; | ||||||
| 		}, | } | ||||||
| 		afterLeave(el) { | 
 | ||||||
|  | function afterLeave(el) { | ||||||
| 	el.style.height = null; | 	el.style.height = null; | ||||||
| 		}, | } | ||||||
| 	}, | 
 | ||||||
|  | function toggle() { | ||||||
|  | 	if (!opened) { | ||||||
|  | 		openedAtLeastOnce = true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	nextTick(() => { | ||||||
|  | 		opened = !opened; | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | onMounted(() => { | ||||||
|  | 	const computedStyle = getComputedStyle(document.documentElement); | ||||||
|  | 	const parentBg = getBgColor(rootEl.parentElement); | ||||||
|  | 	const myBg = computedStyle.getPropertyValue('--panel'); | ||||||
|  | 	bgSame = parentBg === myBg; | ||||||
| }); | }); | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <style lang="scss" scoped> | <style lang="scss" scoped> | ||||||
| .folder-toggle-enter-active, .folder-toggle-leave-active { | .folder-toggle-enter-active, .folder-toggle-leave-active { | ||||||
| 	overflow-y: clip; | 	overflow-y: clip; | ||||||
| 	transition: opacity 0.5s, height 0.5s !important; | 	transition: opacity 0.3s, height 0.3s, transform 0.3s !important; | ||||||
| } | } | ||||||
| .folder-toggle-enter-from { | .folder-toggle-enter-from, .folder-toggle-leave-to { | ||||||
| 	opacity: 0; |  | ||||||
| } |  | ||||||
| .folder-toggle-leave-to { |  | ||||||
| 	opacity: 0; | 	opacity: 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .ssazuxis { | .dwzlatin { | ||||||
| 	position: relative; | 	display: block; | ||||||
| 
 | 
 | ||||||
| 	> header { | 	> .header { | ||||||
| 		display: flex; | 		display: flex; | ||||||
| 		position: relative; | 		align-items: center; | ||||||
| 		z-index: 10; | 		width: 100%; | ||||||
| 		position: sticky; | 		box-sizing: border-box; | ||||||
| 		top: var(--stickyTop, 0px); | 		padding: 10px 14px 10px 14px; | ||||||
| 		padding: var(--x-padding); | 		background: var(--buttonBg); | ||||||
| 		-webkit-backdrop-filter: var(--blur, blur(8px)); | 		border-radius: 6px; | ||||||
| 		backdrop-filter: var(--blur, blur(20px)); |  | ||||||
| 
 | 
 | ||||||
| 		> .title { | 		&:hover { | ||||||
| 			display: grid; | 			text-decoration: none; | ||||||
| 			place-content: center; | 			background: var(--buttonHoverBg); | ||||||
| 			margin: 0; |  | ||||||
| 			padding: 12px 16px 12px 0; |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		> .divider { | 		&.active { | ||||||
| 			flex: 1; | 			color: var(--accent); | ||||||
| 			margin: auto; | 			background: var(--buttonHoverBg); | ||||||
| 			height: 1px; |  | ||||||
| 			background: var(--divider); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		> button { | 		> .icon { | ||||||
| 			padding: 12px 0 12px 16px; | 			margin-right: 0.75em; | ||||||
|  | 			flex-shrink: 0; | ||||||
|  | 			text-align: center; | ||||||
|  | 			opacity: 0.8; | ||||||
|  | 
 | ||||||
|  | 			&:empty { | ||||||
|  | 				display: none; | ||||||
|  | 
 | ||||||
|  | 				& + .text { | ||||||
|  | 					padding-left: 4px; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @container (max-width: 500px) { | 		> .text { | ||||||
| 	.ssazuxis { | 			white-space: nowrap; | ||||||
| 		> header { | 			text-overflow: ellipsis; | ||||||
| 			> .title { | 			overflow: hidden; | ||||||
| 				padding: 8px 10px 8px 0; | 			padding-right: 12px; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		> .right { | ||||||
|  | 			margin-left: auto; | ||||||
|  | 			opacity: 0.7; | ||||||
|  | 			white-space: nowrap; | ||||||
|  | 
 | ||||||
|  | 			> .text:not(:empty) { | ||||||
|  | 				margin-right: 0.75em; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	> .body { | ||||||
|  | 		background: var(--panel); | ||||||
|  | 		border-radius: 0 0 6px 6px; | ||||||
|  | 		container-type: inline-size; | ||||||
|  | 		overflow: auto; | ||||||
|  | 
 | ||||||
|  | 		&.bgSame { | ||||||
|  | 			background: var(--bg); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	&.opened { | ||||||
|  | 		> .header { | ||||||
|  | 			border-radius: 6px 6px 0 0; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <template> | <template> | ||||||
| <div :class="$style.root"> | <div :class="$style.root"> | ||||||
| 	<MkFolder class="item"> | 	<MkFoldableSection class="item"> | ||||||
| 		<template #header>Chart</template> | 		<template #header>Chart</template> | ||||||
| 		<div :class="$style.chart"> | 		<div :class="$style.chart"> | ||||||
| 			<div class="selects"> | 			<div class="selects"> | ||||||
|  | @ -34,9 +34,9 @@ | ||||||
| 				<MkChart :src="chartSrc" :span="chartSpan" :limit="chartLimit" :detailed="true"></MkChart> | 				<MkChart :src="chartSrc" :span="chartSpan" :limit="chartLimit" :detailed="true"></MkChart> | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 	</MkFolder> | 	</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 	<MkFolder class="item"> | 	<MkFoldableSection class="item"> | ||||||
| 		<template #header>Active users heatmap</template> | 		<template #header>Active users heatmap</template> | ||||||
| 		<MkSelect v-model="heatmapSrc" style="margin: 0 0 12px 0;"> | 		<MkSelect v-model="heatmapSrc" style="margin: 0 0 12px 0;"> | ||||||
| 			<option value="active-users">Active users</option> | 			<option value="active-users">Active users</option> | ||||||
|  | @ -48,16 +48,16 @@ | ||||||
| 		<div class="_panel" :class="$style.heatmap"> | 		<div class="_panel" :class="$style.heatmap"> | ||||||
| 			<MkHeatmap :src="heatmapSrc"/> | 			<MkHeatmap :src="heatmapSrc"/> | ||||||
| 		</div> | 		</div> | ||||||
| 	</MkFolder> | 	</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 	<MkFolder class="item"> | 	<MkFoldableSection class="item"> | ||||||
| 		<template #header>Retention rate</template> | 		<template #header>Retention rate</template> | ||||||
| 		<div class="_panel" :class="$style.retention"> | 		<div class="_panel" :class="$style.retention"> | ||||||
| 			<MkRetentionHeatmap/> | 			<MkRetentionHeatmap/> | ||||||
| 		</div> | 		</div> | ||||||
| 	</MkFolder> | 	</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 	<MkFolder class="item"> | 	<MkFoldableSection class="item"> | ||||||
| 		<template #header>Federation</template> | 		<template #header>Federation</template> | ||||||
| 		<div :class="$style.federation"> | 		<div :class="$style.federation"> | ||||||
| 			<div class="pies"> | 			<div class="pies"> | ||||||
|  | @ -71,7 +71,7 @@ | ||||||
| 				</div> | 				</div> | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 	</MkFolder> | 	</MkFoldableSection> | ||||||
| </div> | </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
|  | @ -84,7 +84,7 @@ import { useChartTooltip } from '@/scripts/use-chart-tooltip'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
| import { i18n } from '@/i18n'; | import { i18n } from '@/i18n'; | ||||||
| import MkHeatmap from '@/components/MkHeatmap.vue'; | import MkHeatmap from '@/components/MkHeatmap.vue'; | ||||||
| import MkFolder from '@/components/MkFolder.vue'; | import MkFoldableSection from '@/components/MkFoldableSection.vue'; | ||||||
| import MkRetentionHeatmap from '@/components/MkRetentionHeatmap.vue'; | import MkRetentionHeatmap from '@/components/MkRetentionHeatmap.vue'; | ||||||
| import { initChart } from '@/scripts/init-chart'; | import { initChart } from '@/scripts/init-chart'; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,175 +0,0 @@ | ||||||
| <template> |  | ||||||
| <div ref="rootEl" class="dwzlatin" :class="{ opened }"> |  | ||||||
| 	<div class="header _button" @click="toggle"> |  | ||||||
| 		<span class="icon"><slot name="icon"></slot></span> |  | ||||||
| 		<span class="text"><slot name="label"></slot></span> |  | ||||||
| 		<span class="right"> |  | ||||||
| 			<span class="text"><slot name="suffix"></slot></span> |  | ||||||
| 			<i v-if="opened" class="ti ti-chevron-up icon"></i> |  | ||||||
| 			<i v-else class="ti ti-chevron-down icon"></i> |  | ||||||
| 		</span> |  | ||||||
| 	</div> |  | ||||||
| 	<div v-if="openedAtLeastOnce" class="body" :class="{ bgSame }"> |  | ||||||
| 		<Transition |  | ||||||
| 			:name="$store.state.animation ? 'folder-toggle' : ''" |  | ||||||
| 			@enter="enter" |  | ||||||
| 			@after-enter="afterEnter" |  | ||||||
| 			@leave="leave" |  | ||||||
| 			@after-leave="afterLeave" |  | ||||||
| 		> |  | ||||||
| 			<KeepAlive> |  | ||||||
| 				<div v-show="opened"> |  | ||||||
| 					<MkSpacer :margin-min="14" :margin-max="22"> |  | ||||||
| 						<slot></slot> |  | ||||||
| 					</MkSpacer> |  | ||||||
| 				</div> |  | ||||||
| 			</KeepAlive> |  | ||||||
| 		</Transition> |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script lang="ts" setup> |  | ||||||
| import { nextTick, onMounted } from 'vue'; |  | ||||||
| 
 |  | ||||||
| const props = withDefaults(defineProps<{ |  | ||||||
| 	defaultOpen: boolean; |  | ||||||
| }>(), { |  | ||||||
| 	defaultOpen: false, |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| const getBgColor = (el: HTMLElement) => { |  | ||||||
| 	const style = window.getComputedStyle(el); |  | ||||||
| 	if (style.backgroundColor && !['rgba(0, 0, 0, 0)', 'rgba(0,0,0,0)', 'transparent'].includes(style.backgroundColor)) { |  | ||||||
| 		return style.backgroundColor; |  | ||||||
| 	} else { |  | ||||||
| 		return el.parentElement ? getBgColor(el.parentElement) : 'transparent'; |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| let rootEl = $ref<HTMLElement>(); |  | ||||||
| let bgSame = $ref(false); |  | ||||||
| let opened = $ref(props.defaultOpen); |  | ||||||
| let openedAtLeastOnce = $ref(props.defaultOpen); |  | ||||||
| 
 |  | ||||||
| function enter(el) { |  | ||||||
| 	const elementHeight = el.getBoundingClientRect().height; |  | ||||||
| 	el.style.height = 0; |  | ||||||
| 	el.offsetHeight; // reflow |  | ||||||
| 	el.style.height = elementHeight + 'px'; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function afterEnter(el) { |  | ||||||
| 	el.style.height = null; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function leave(el) { |  | ||||||
| 	const elementHeight = el.getBoundingClientRect().height; |  | ||||||
| 	el.style.height = elementHeight + 'px'; |  | ||||||
| 	el.offsetHeight; // reflow |  | ||||||
| 	el.style.height = 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function afterLeave(el) { |  | ||||||
| 	el.style.height = null; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function toggle() { |  | ||||||
| 	if (!opened) { |  | ||||||
| 		openedAtLeastOnce = true; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	nextTick(() => { |  | ||||||
| 		opened = !opened; |  | ||||||
| 	}); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| onMounted(() => { |  | ||||||
| 	const computedStyle = getComputedStyle(document.documentElement); |  | ||||||
| 	const parentBg = getBgColor(rootEl.parentElement); |  | ||||||
| 	const myBg = computedStyle.getPropertyValue('--panel'); |  | ||||||
| 	bgSame = parentBg === myBg; |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .folder-toggle-enter-active, .folder-toggle-leave-active { |  | ||||||
| 	overflow-y: clip; |  | ||||||
| 	transition: opacity 0.3s, height 0.3s, transform 0.3s !important; |  | ||||||
| } |  | ||||||
| .folder-toggle-enter-from, .folder-toggle-leave-to { |  | ||||||
| 	opacity: 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .dwzlatin { |  | ||||||
| 	display: block; |  | ||||||
| 
 |  | ||||||
| 	> .header { |  | ||||||
| 		display: flex; |  | ||||||
| 		align-items: center; |  | ||||||
| 		width: 100%; |  | ||||||
| 		box-sizing: border-box; |  | ||||||
| 		padding: 10px 14px 10px 14px; |  | ||||||
| 		background: var(--buttonBg); |  | ||||||
| 		border-radius: 6px; |  | ||||||
| 
 |  | ||||||
| 		&:hover { |  | ||||||
| 			text-decoration: none; |  | ||||||
| 			background: var(--buttonHoverBg); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		&.active { |  | ||||||
| 			color: var(--accent); |  | ||||||
| 			background: var(--buttonHoverBg); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> .icon { |  | ||||||
| 			margin-right: 0.75em; |  | ||||||
| 			flex-shrink: 0; |  | ||||||
| 			text-align: center; |  | ||||||
| 			opacity: 0.8; |  | ||||||
| 
 |  | ||||||
| 			&:empty { |  | ||||||
| 				display: none; |  | ||||||
| 
 |  | ||||||
| 				& + .text { |  | ||||||
| 					padding-left: 4px; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> .text { |  | ||||||
| 			white-space: nowrap; |  | ||||||
| 			text-overflow: ellipsis; |  | ||||||
| 			overflow: hidden; |  | ||||||
| 			padding-right: 12px; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> .right { |  | ||||||
| 			margin-left: auto; |  | ||||||
| 			opacity: 0.7; |  | ||||||
| 			white-space: nowrap; |  | ||||||
| 
 |  | ||||||
| 			> .text:not(:empty) { |  | ||||||
| 				margin-right: 0.75em; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	> .body { |  | ||||||
| 		background: var(--panel); |  | ||||||
| 		border-radius: 0 0 6px 6px; |  | ||||||
| 		container-type: inline-size; |  | ||||||
| 
 |  | ||||||
| 		&.bgSame { |  | ||||||
| 			background: var(--bg); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	&.opened { |  | ||||||
| 		> .header { |  | ||||||
| 			border-radius: 6px 6px 0 0; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | @ -12,19 +12,19 @@ | ||||||
| 		--> | 		--> | ||||||
| 	</div> | 	</div> | ||||||
| 
 | 
 | ||||||
| 	<MkFolder v-if="searchEmojis" class="emojis"> | 	<MkFoldableSection v-if="searchEmojis" class="emojis"> | ||||||
| 		<template #header>{{ $ts.searchResult }}</template> | 		<template #header>{{ $ts.searchResult }}</template> | ||||||
| 		<div class="zuvgdzyt"> | 		<div class="zuvgdzyt"> | ||||||
| 			<XEmoji v-for="emoji in searchEmojis" :key="emoji.name" class="emoji" :emoji="emoji"/> | 			<XEmoji v-for="emoji in searchEmojis" :key="emoji.name" class="emoji" :emoji="emoji"/> | ||||||
| 		</div> | 		</div> | ||||||
| 	</MkFolder> | 	</MkFoldableSection> | ||||||
| 	 | 	 | ||||||
| 	<MkFolder v-for="category in customEmojiCategories" v-once :key="category" class="emojis"> | 	<MkFoldableSection v-for="category in customEmojiCategories" v-once :key="category" class="emojis"> | ||||||
| 		<template #header>{{ category || $ts.other }}</template> | 		<template #header>{{ category || $ts.other }}</template> | ||||||
| 		<div class="zuvgdzyt"> | 		<div class="zuvgdzyt"> | ||||||
| 			<XEmoji v-for="emoji in customEmojis.filter(e => e.category === category)" :key="emoji.name" class="emoji" :emoji="emoji"/> | 			<XEmoji v-for="emoji in customEmojis.filter(e => e.category === category)" :key="emoji.name" class="emoji" :emoji="emoji"/> | ||||||
| 		</div> | 		</div> | ||||||
| 	</MkFolder> | 	</MkFoldableSection> | ||||||
| </div> | </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
|  | @ -34,7 +34,7 @@ import XEmoji from './emojis.emoji.vue'; | ||||||
| import MkButton from '@/components/MkButton.vue'; | import MkButton from '@/components/MkButton.vue'; | ||||||
| import MkInput from '@/components/MkInput.vue'; | import MkInput from '@/components/MkInput.vue'; | ||||||
| import MkSelect from '@/components/MkSelect.vue'; | import MkSelect from '@/components/MkSelect.vue'; | ||||||
| import MkFolder from '@/components/MkFolder.vue'; | import MkFoldableSection from '@/components/MkFoldableSection.vue'; | ||||||
| import MkTab from '@/components/MkTab.vue'; | import MkTab from '@/components/MkTab.vue'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
| import { emojiCategories, emojiTags } from '@/instance'; | import { emojiCategories, emojiTags } from '@/instance'; | ||||||
|  | @ -44,7 +44,7 @@ export default defineComponent({ | ||||||
| 		MkButton, | 		MkButton, | ||||||
| 		MkInput, | 		MkInput, | ||||||
| 		MkSelect, | 		MkSelect, | ||||||
| 		MkFolder, | 		MkFoldableSection, | ||||||
| 		MkTab, | 		MkTab, | ||||||
| 		XEmoji, | 		XEmoji, | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
|  | @ -4,24 +4,24 @@ | ||||||
| 	<MkSpacer :content-max="700" :margin-min="16" :margin-max="32"> | 	<MkSpacer :content-max="700" :margin-min="16" :margin-max="32"> | ||||||
| 		<FormSuspense :p="init"> | 		<FormSuspense :p="init"> | ||||||
| 			<div class="_gaps_m"> | 			<div class="_gaps_m"> | ||||||
| 				<FormFolder> | 				<MkFolder> | ||||||
| 					<template #icon><i class="ti ti-brand-twitter"></i></template> | 					<template #icon><i class="ti ti-brand-twitter"></i></template> | ||||||
| 					<template #label>Twitter</template> | 					<template #label>Twitter</template> | ||||||
| 					<template #suffix>{{ enableTwitterIntegration ? i18n.ts.enabled : i18n.ts.disabled }}</template> | 					<template #suffix>{{ enableTwitterIntegration ? i18n.ts.enabled : i18n.ts.disabled }}</template> | ||||||
| 					<XTwitter/> | 					<XTwitter/> | ||||||
| 				</FormFolder> | 				</MkFolder> | ||||||
| 				<FormFolder> | 				<MkFolder> | ||||||
| 					<template #icon><i class="ti ti-brand-github"></i></template> | 					<template #icon><i class="ti ti-brand-github"></i></template> | ||||||
| 					<template #label>GitHub</template> | 					<template #label>GitHub</template> | ||||||
| 					<template #suffix>{{ enableGithubIntegration ? i18n.ts.enabled : i18n.ts.disabled }}</template> | 					<template #suffix>{{ enableGithubIntegration ? i18n.ts.enabled : i18n.ts.disabled }}</template> | ||||||
| 					<XGithub/> | 					<XGithub/> | ||||||
| 				</FormFolder> | 				</MkFolder> | ||||||
| 				<FormFolder> | 				<MkFolder> | ||||||
| 					<template #icon><i class="ti ti-brand-discord"></i></template> | 					<template #icon><i class="ti ti-brand-discord"></i></template> | ||||||
| 					<template #label>Discord</template> | 					<template #label>Discord</template> | ||||||
| 					<template #suffix>{{ enableDiscordIntegration ? i18n.ts.enabled : i18n.ts.disabled }}</template> | 					<template #suffix>{{ enableDiscordIntegration ? i18n.ts.enabled : i18n.ts.disabled }}</template> | ||||||
| 					<XDiscord/> | 					<XDiscord/> | ||||||
| 				</FormFolder> | 				</MkFolder> | ||||||
| 			</div> | 			</div> | ||||||
| 		</FormSuspense> | 		</FormSuspense> | ||||||
| 	</MkSpacer> | 	</MkSpacer> | ||||||
|  | @ -34,7 +34,7 @@ import XTwitter from './integrations.twitter.vue'; | ||||||
| import XGithub from './integrations.github.vue'; | import XGithub from './integrations.github.vue'; | ||||||
| import XDiscord from './integrations.discord.vue'; | import XDiscord from './integrations.discord.vue'; | ||||||
| import FormSuspense from '@/components/form/suspense.vue'; | import FormSuspense from '@/components/form/suspense.vue'; | ||||||
| import FormFolder from '@/components/form/folder.vue'; | import MkFolder from '@/components/MkFolder.vue'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
| import { i18n } from '@/i18n'; | import { i18n } from '@/i18n'; | ||||||
| import { definePageMetadata } from '@/scripts/page-metadata'; | import { definePageMetadata } from '@/scripts/page-metadata'; | ||||||
|  |  | ||||||
|  | @ -1,60 +1,60 @@ | ||||||
| <template> | <template> | ||||||
| <MkSpacer :content-max="1000"> | <MkSpacer :content-max="1000"> | ||||||
| 	<div ref="rootEl" class="edbbcaef"> | 	<div ref="rootEl" class="edbbcaef"> | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header>Stats</template> | 			<template #header>Stats</template> | ||||||
| 			<XStats/> | 			<XStats/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header>Active users</template> | 			<template #header>Active users</template> | ||||||
| 			<XActiveUsers/> | 			<XActiveUsers/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header>Heatmap</template> | 			<template #header>Heatmap</template> | ||||||
| 			<XHeatmap/> | 			<XHeatmap/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header>Retention rate</template> | 			<template #header>Retention rate</template> | ||||||
| 			<XRetention/> | 			<XRetention/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header>Moderators</template> | 			<template #header>Moderators</template> | ||||||
| 			<XModerators/> | 			<XModerators/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header>Federation</template> | 			<template #header>Federation</template> | ||||||
| 			<XFederation/> | 			<XFederation/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 		 | 		 | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header>Instances</template> | 			<template #header>Instances</template> | ||||||
| 			<XInstances/> | 			<XInstances/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header>Ap requests</template> | 			<template #header>Ap requests</template> | ||||||
| 			<XApRequests/> | 			<XApRequests/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header>New users</template> | 			<template #header>New users</template> | ||||||
| 			<XUsers/> | 			<XUsers/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header>Deliver queue</template> | 			<template #header>Deliver queue</template> | ||||||
| 			<XQueue domain="deliver"/> | 			<XQueue domain="deliver"/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header>Inbox queue</template> | 			<template #header>Inbox queue</template> | ||||||
| 			<XQueue domain="inbox"/> | 			<XQueue domain="inbox"/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 	</div> | 	</div> | ||||||
| </MkSpacer> | </MkSpacer> | ||||||
| </template> | </template> | ||||||
|  | @ -79,7 +79,7 @@ import { i18n } from '@/i18n'; | ||||||
| import { definePageMetadata } from '@/scripts/page-metadata'; | import { definePageMetadata } from '@/scripts/page-metadata'; | ||||||
| import { defaultStore } from '@/store'; | import { defaultStore } from '@/store'; | ||||||
| import MkFileListForAdmin from '@/components/MkFileListForAdmin.vue'; | import MkFileListForAdmin from '@/components/MkFileListForAdmin.vue'; | ||||||
| import MkFolder from '@/components/MkFolder.vue'; | import MkFoldableSection from '@/components/MkFoldableSection.vue'; | ||||||
| 
 | 
 | ||||||
| const rootEl = $shallowRef<HTMLElement>(); | const rootEl = $shallowRef<HTMLElement>(); | ||||||
| let serverInfo: any = $ref(null); | let serverInfo: any = $ref(null); | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
| 	<MkSpacer :content-max="700" :margin-min="16" :margin-max="32"> | 	<MkSpacer :content-max="700" :margin-min="16" :margin-max="32"> | ||||||
| 		<FormSuspense :p="init"> | 		<FormSuspense :p="init"> | ||||||
| 			<div class="_gaps_m"> | 			<div class="_gaps_m"> | ||||||
| 				<FormFolder> | 				<MkFolder> | ||||||
| 					<template #icon><i class="ti ti-shield"></i></template> | 					<template #icon><i class="ti ti-shield"></i></template> | ||||||
| 					<template #label>{{ i18n.ts.botProtection }}</template> | 					<template #label>{{ i18n.ts.botProtection }}</template> | ||||||
| 					<template v-if="enableHcaptcha" #suffix>hCaptcha</template> | 					<template v-if="enableHcaptcha" #suffix>hCaptcha</template> | ||||||
|  | @ -13,9 +13,9 @@ | ||||||
| 					<template v-else #suffix>{{ i18n.ts.none }} ({{ i18n.ts.notRecommended }})</template> | 					<template v-else #suffix>{{ i18n.ts.none }} ({{ i18n.ts.notRecommended }})</template> | ||||||
| 
 | 
 | ||||||
| 					<XBotProtection/> | 					<XBotProtection/> | ||||||
| 				</FormFolder> | 				</MkFolder> | ||||||
| 
 | 
 | ||||||
| 				<FormFolder> | 				<MkFolder> | ||||||
| 					<template #icon><i class="ti ti-eye-off"></i></template> | 					<template #icon><i class="ti ti-eye-off"></i></template> | ||||||
| 					<template #label>{{ i18n.ts.sensitiveMediaDetection }}</template> | 					<template #label>{{ i18n.ts.sensitiveMediaDetection }}</template> | ||||||
| 					<template v-if="sensitiveMediaDetection === 'all'" #suffix>{{ i18n.ts.all }}</template> | 					<template v-if="sensitiveMediaDetection === 'all'" #suffix>{{ i18n.ts.all }}</template> | ||||||
|  | @ -56,9 +56,9 @@ | ||||||
| 
 | 
 | ||||||
| 						<MkButton primary @click="save"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton> | 						<MkButton primary @click="save"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton> | ||||||
| 					</div> | 					</div> | ||||||
| 				</FormFolder> | 				</MkFolder> | ||||||
| 
 | 
 | ||||||
| 				<FormFolder> | 				<MkFolder> | ||||||
| 					<template #label>Active Email Validation</template> | 					<template #label>Active Email Validation</template> | ||||||
| 					<template v-if="enableActiveEmailValidation" #suffix>Enabled</template> | 					<template v-if="enableActiveEmailValidation" #suffix>Enabled</template> | ||||||
| 					<template v-else #suffix>Disabled</template> | 					<template v-else #suffix>Disabled</template> | ||||||
|  | @ -69,9 +69,9 @@ | ||||||
| 							<template #label>Enable</template> | 							<template #label>Enable</template> | ||||||
| 						</MkSwitch> | 						</MkSwitch> | ||||||
| 					</div> | 					</div> | ||||||
| 				</FormFolder> | 				</MkFolder> | ||||||
| 
 | 
 | ||||||
| 				<FormFolder> | 				<MkFolder> | ||||||
| 					<template #label>Log IP address</template> | 					<template #label>Log IP address</template> | ||||||
| 					<template v-if="enableIpLogging" #suffix>Enabled</template> | 					<template v-if="enableIpLogging" #suffix>Enabled</template> | ||||||
| 					<template v-else #suffix>Disabled</template> | 					<template v-else #suffix>Disabled</template> | ||||||
|  | @ -81,9 +81,9 @@ | ||||||
| 							<template #label>Enable</template> | 							<template #label>Enable</template> | ||||||
| 						</MkSwitch> | 						</MkSwitch> | ||||||
| 					</div> | 					</div> | ||||||
| 				</FormFolder> | 				</MkFolder> | ||||||
| 
 | 
 | ||||||
| 				<FormFolder> | 				<MkFolder> | ||||||
| 					<template #label>Summaly Proxy</template> | 					<template #label>Summaly Proxy</template> | ||||||
| 
 | 
 | ||||||
| 					<div class="_gaps_m"> | 					<div class="_gaps_m"> | ||||||
|  | @ -94,7 +94,7 @@ | ||||||
| 
 | 
 | ||||||
| 						<MkButton primary @click="save"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton> | 						<MkButton primary @click="save"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton> | ||||||
| 					</div> | 					</div> | ||||||
| 				</FormFolder> | 				</MkFolder> | ||||||
| 			</div> | 			</div> | ||||||
| 		</FormSuspense> | 		</FormSuspense> | ||||||
| 	</MkSpacer> | 	</MkSpacer> | ||||||
|  | @ -105,7 +105,7 @@ | ||||||
| import { } from 'vue'; | import { } from 'vue'; | ||||||
| import XBotProtection from './bot-protection.vue'; | import XBotProtection from './bot-protection.vue'; | ||||||
| import XHeader from './_header_.vue'; | import XHeader from './_header_.vue'; | ||||||
| import FormFolder from '@/components/form/folder.vue'; | import MkFolder from '@/components/MkFolder.vue'; | ||||||
| import MkRadios from '@/components/MkRadios.vue'; | import MkRadios from '@/components/MkRadios.vue'; | ||||||
| import MkSwitch from '@/components/MkSwitch.vue'; | import MkSwitch from '@/components/MkSwitch.vue'; | ||||||
| import FormInfo from '@/components/MkInfo.vue'; | import FormInfo from '@/components/MkInfo.vue'; | ||||||
|  |  | ||||||
|  | @ -6,52 +6,52 @@ | ||||||
| 	</MkTab> | 	</MkTab> | ||||||
| 	<div v-if="origin === 'local'"> | 	<div v-if="origin === 'local'"> | ||||||
| 		<template v-if="tag == null"> | 		<template v-if="tag == null"> | ||||||
| 			<MkFolder class="_margin" persist-key="explore-pinned-users"> | 			<MkFoldableSection class="_margin" persist-key="explore-pinned-users"> | ||||||
| 				<template #header><i class="fas fa-bookmark ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.pinnedUsers }}</template> | 				<template #header><i class="fas fa-bookmark ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.pinnedUsers }}</template> | ||||||
| 				<XUserList :pagination="pinnedUsers"/> | 				<XUserList :pagination="pinnedUsers"/> | ||||||
| 			</MkFolder> | 			</MkFoldableSection> | ||||||
| 			<MkFolder class="_margin" persist-key="explore-popular-users"> | 			<MkFoldableSection class="_margin" persist-key="explore-popular-users"> | ||||||
| 				<template #header><i class="fas fa-chart-line ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.popularUsers }}</template> | 				<template #header><i class="fas fa-chart-line ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.popularUsers }}</template> | ||||||
| 				<XUserList :pagination="popularUsers"/> | 				<XUserList :pagination="popularUsers"/> | ||||||
| 			</MkFolder> | 			</MkFoldableSection> | ||||||
| 			<MkFolder class="_margin" persist-key="explore-recently-updated-users"> | 			<MkFoldableSection class="_margin" persist-key="explore-recently-updated-users"> | ||||||
| 				<template #header><i class="fas fa-comment-alt ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.recentlyUpdatedUsers }}</template> | 				<template #header><i class="fas fa-comment-alt ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.recentlyUpdatedUsers }}</template> | ||||||
| 				<XUserList :pagination="recentlyUpdatedUsers"/> | 				<XUserList :pagination="recentlyUpdatedUsers"/> | ||||||
| 			</MkFolder> | 			</MkFoldableSection> | ||||||
| 			<MkFolder class="_margin" persist-key="explore-recently-registered-users"> | 			<MkFoldableSection class="_margin" persist-key="explore-recently-registered-users"> | ||||||
| 				<template #header><i class="ti ti-plus ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.recentlyRegisteredUsers }}</template> | 				<template #header><i class="ti ti-plus ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.recentlyRegisteredUsers }}</template> | ||||||
| 				<XUserList :pagination="recentlyRegisteredUsers"/> | 				<XUserList :pagination="recentlyRegisteredUsers"/> | ||||||
| 			</MkFolder> | 			</MkFoldableSection> | ||||||
| 		</template> | 		</template> | ||||||
| 	</div> | 	</div> | ||||||
| 	<div v-else> | 	<div v-else> | ||||||
| 		<MkFolder ref="tagsEl" :foldable="true" :expanded="false" class="_margin"> | 		<MkFoldableSection ref="tagsEl" :foldable="true" :expanded="false" class="_margin"> | ||||||
| 			<template #header><i class="ti ti-hash ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.popularTags }}</template> | 			<template #header><i class="ti ti-hash ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.popularTags }}</template> | ||||||
| 
 | 
 | ||||||
| 			<div class="vxjfqztj"> | 			<div class="vxjfqztj"> | ||||||
| 				<MkA v-for="tag in tagsLocal" :key="'local:' + tag.tag" :to="`/explore/tags/${tag.tag}`" class="local">{{ tag.tag }}</MkA> | 				<MkA v-for="tag in tagsLocal" :key="'local:' + tag.tag" :to="`/explore/tags/${tag.tag}`" class="local">{{ tag.tag }}</MkA> | ||||||
| 				<MkA v-for="tag in tagsRemote" :key="'remote:' + tag.tag" :to="`/explore/tags/${tag.tag}`">{{ tag.tag }}</MkA> | 				<MkA v-for="tag in tagsRemote" :key="'remote:' + tag.tag" :to="`/explore/tags/${tag.tag}`">{{ tag.tag }}</MkA> | ||||||
| 			</div> | 			</div> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 		<MkFolder v-if="tag != null" :key="`${tag}`" class="_margin"> | 		<MkFoldableSection v-if="tag != null" :key="`${tag}`" class="_margin"> | ||||||
| 			<template #header><i class="ti ti-hash ti-fw" style="margin-right: 0.5em;"></i>{{ tag }}</template> | 			<template #header><i class="ti ti-hash ti-fw" style="margin-right: 0.5em;"></i>{{ tag }}</template> | ||||||
| 			<XUserList :pagination="tagUsers"/> | 			<XUserList :pagination="tagUsers"/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 
 | 
 | ||||||
| 		<template v-if="tag == null"> | 		<template v-if="tag == null"> | ||||||
| 			<MkFolder class="_margin"> | 			<MkFoldableSection class="_margin"> | ||||||
| 				<template #header><i class="fas fa-chart-line ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.popularUsers }}</template> | 				<template #header><i class="fas fa-chart-line ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.popularUsers }}</template> | ||||||
| 				<XUserList :pagination="popularUsersF"/> | 				<XUserList :pagination="popularUsersF"/> | ||||||
| 			</MkFolder> | 			</MkFoldableSection> | ||||||
| 			<MkFolder class="_margin"> | 			<MkFoldableSection class="_margin"> | ||||||
| 				<template #header><i class="fas fa-comment-alt ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.recentlyUpdatedUsers }}</template> | 				<template #header><i class="fas fa-comment-alt ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.recentlyUpdatedUsers }}</template> | ||||||
| 				<XUserList :pagination="recentlyUpdatedUsersF"/> | 				<XUserList :pagination="recentlyUpdatedUsersF"/> | ||||||
| 			</MkFolder> | 			</MkFoldableSection> | ||||||
| 			<MkFolder class="_margin"> | 			<MkFoldableSection class="_margin"> | ||||||
| 				<template #header><i class="fas fa-rocket ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.recentlyDiscoveredUsers }}</template> | 				<template #header><i class="fas fa-rocket ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.recentlyDiscoveredUsers }}</template> | ||||||
| 				<XUserList :pagination="recentlyRegisteredUsersF"/> | 				<XUserList :pagination="recentlyRegisteredUsersF"/> | ||||||
| 			</MkFolder> | 			</MkFoldableSection> | ||||||
| 		</template> | 		</template> | ||||||
| 	</div> | 	</div> | ||||||
| </MkSpacer> | </MkSpacer> | ||||||
|  | @ -60,7 +60,7 @@ | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import { computed, watch } from 'vue'; | import { computed, watch } from 'vue'; | ||||||
| import XUserList from '@/components/MkUserList.vue'; | import XUserList from '@/components/MkUserList.vue'; | ||||||
| import MkFolder from '@/components/MkFolder.vue'; | import MkFoldableSection from '@/components/MkFoldableSection.vue'; | ||||||
| import MkTab from '@/components/MkTab.vue'; | import MkTab from '@/components/MkTab.vue'; | ||||||
| import number from '@/filters/number'; | import number from '@/filters/number'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
|  | @ -72,7 +72,7 @@ const props = defineProps<{ | ||||||
| }>(); | }>(); | ||||||
| 
 | 
 | ||||||
| let origin = $ref('local'); | let origin = $ref('local'); | ||||||
| let tagsEl = $shallowRef<InstanceType<typeof MkFolder>>(); | let tagsEl = $shallowRef<InstanceType<typeof MkFoldableSection>>(); | ||||||
| let tagsLocal = $ref([]); | let tagsLocal = $ref([]); | ||||||
| let tagsRemote = $ref([]); | let tagsRemote = $ref([]); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ | ||||||
| import { computed, watch } from 'vue'; | import { computed, watch } from 'vue'; | ||||||
| import XFeatured from './explore.featured.vue'; | import XFeatured from './explore.featured.vue'; | ||||||
| import XUsers from './explore.users.vue'; | import XUsers from './explore.users.vue'; | ||||||
| import MkFolder from '@/components/MkFolder.vue'; | import MkFoldableSection from '@/components/MkFoldableSection.vue'; | ||||||
| import MkInput from '@/components/MkInput.vue'; | import MkInput from '@/components/MkInput.vue'; | ||||||
| import MkRadios from '@/components/MkRadios.vue'; | import MkRadios from '@/components/MkRadios.vue'; | ||||||
| import number from '@/filters/number'; | import number from '@/filters/number'; | ||||||
|  | @ -51,7 +51,7 @@ const props = withDefaults(defineProps<{ | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| let tab = $ref(props.initialTab); | let tab = $ref(props.initialTab); | ||||||
| let tagsEl = $shallowRef<InstanceType<typeof MkFolder>>(); | let tagsEl = $shallowRef<InstanceType<typeof MkFoldableSection>>(); | ||||||
| let searchQuery = $ref(null); | let searchQuery = $ref(null); | ||||||
| let searchOrigin = $ref('combined'); | let searchOrigin = $ref('combined'); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -27,12 +27,12 @@ | ||||||
| 						</div> | 						</div> | ||||||
| 					</div> | 					</div> | ||||||
| 				</Transition> | 				</Transition> | ||||||
| 				<FormFolder class="_margin"> | 				<MkFolder class="_margin"> | ||||||
| 					<template #icon><i class="ti ti-code"></i></template> | 					<template #icon><i class="ti ti-code"></i></template> | ||||||
| 					<template #label>{{ i18n.ts._play.viewSource }}</template> | 					<template #label>{{ i18n.ts._play.viewSource }}</template> | ||||||
| 
 | 
 | ||||||
| 					<MkTextarea :model-value="flash.script" readonly tall class="_monospace" spellcheck="false"></MkTextarea> | 					<MkTextarea :model-value="flash.script" readonly tall class="_monospace" spellcheck="false"></MkTextarea> | ||||||
| 				</FormFolder> | 				</MkFolder> | ||||||
| 				<div :class="$style.footer"> | 				<div :class="$style.footer"> | ||||||
| 					<Mfm :text="`By @${flash.user.username}`"/> | 					<Mfm :text="`By @${flash.user.username}`"/> | ||||||
| 					<div class="date"> | 					<div class="date"> | ||||||
|  | @ -65,7 +65,7 @@ import { definePageMetadata } from '@/scripts/page-metadata'; | ||||||
| import MkAsUi from '@/components/MkAsUi.vue'; | import MkAsUi from '@/components/MkAsUi.vue'; | ||||||
| import { AsUiComponent, AsUiRoot, patch, registerAsUiLib, render } from '@/scripts/aiscript/ui'; | import { AsUiComponent, AsUiRoot, patch, registerAsUiLib, render } from '@/scripts/aiscript/ui'; | ||||||
| import { createAiScriptEnv } from '@/scripts/aiscript/api'; | import { createAiScriptEnv } from '@/scripts/aiscript/api'; | ||||||
| import FormFolder from '@/components/form/folder.vue'; | import MkFolder from '@/components/MkFolder.vue'; | ||||||
| import MkTextarea from '@/components/MkTextarea.vue'; | import MkTextarea from '@/components/MkTextarea.vue'; | ||||||
| 
 | 
 | ||||||
| const props = defineProps<{ | const props = defineProps<{ | ||||||
|  |  | ||||||
|  | @ -4,22 +4,22 @@ | ||||||
| 	<MkSpacer :content-max="1400"> | 	<MkSpacer :content-max="1400"> | ||||||
| 		<div class="_root"> | 		<div class="_root"> | ||||||
| 			<div v-if="tab === 'explore'"> | 			<div v-if="tab === 'explore'"> | ||||||
| 				<MkFolder class="_margin"> | 				<MkFoldableSection class="_margin"> | ||||||
| 					<template #header><i class="ti ti-clock"></i>{{ i18n.ts.recentPosts }}</template> | 					<template #header><i class="ti ti-clock"></i>{{ i18n.ts.recentPosts }}</template> | ||||||
| 					<MkPagination v-slot="{items}" :pagination="recentPostsPagination" :disable-auto-load="true"> | 					<MkPagination v-slot="{items}" :pagination="recentPostsPagination" :disable-auto-load="true"> | ||||||
| 						<div class="vfpdbgtk"> | 						<div class="vfpdbgtk"> | ||||||
| 							<MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/> | 							<MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/> | ||||||
| 						</div> | 						</div> | ||||||
| 					</MkPagination> | 					</MkPagination> | ||||||
| 				</MkFolder> | 				</MkFoldableSection> | ||||||
| 				<MkFolder class="_margin"> | 				<MkFoldableSection class="_margin"> | ||||||
| 					<template #header><i class="ti ti-comet"></i>{{ i18n.ts.popularPosts }}</template> | 					<template #header><i class="ti ti-comet"></i>{{ i18n.ts.popularPosts }}</template> | ||||||
| 					<MkPagination v-slot="{items}" :pagination="popularPostsPagination" :disable-auto-load="true"> | 					<MkPagination v-slot="{items}" :pagination="popularPostsPagination" :disable-auto-load="true"> | ||||||
| 						<div class="vfpdbgtk"> | 						<div class="vfpdbgtk"> | ||||||
| 							<MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/> | 							<MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/> | ||||||
| 						</div> | 						</div> | ||||||
| 					</MkPagination> | 					</MkPagination> | ||||||
| 				</MkFolder> | 				</MkFoldableSection> | ||||||
| 			</div> | 			</div> | ||||||
| 			<div v-else-if="tab === 'liked'"> | 			<div v-else-if="tab === 'liked'"> | ||||||
| 				<MkPagination v-slot="{items}" :pagination="likedPostsPagination"> | 				<MkPagination v-slot="{items}" :pagination="likedPostsPagination"> | ||||||
|  | @ -44,7 +44,7 @@ | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import { computed, defineComponent, watch } from 'vue'; | import { computed, defineComponent, watch } from 'vue'; | ||||||
| import XUserList from '@/components/MkUserList.vue'; | import XUserList from '@/components/MkUserList.vue'; | ||||||
| import MkFolder from '@/components/MkFolder.vue'; | import MkFoldableSection from '@/components/MkFoldableSection.vue'; | ||||||
| import MkInput from '@/components/MkInput.vue'; | import MkInput from '@/components/MkInput.vue'; | ||||||
| import MkButton from '@/components/MkButton.vue'; | import MkButton from '@/components/MkButton.vue'; | ||||||
| import MkTab from '@/components/MkTab.vue'; | import MkTab from '@/components/MkTab.vue'; | ||||||
|  |  | ||||||
|  | @ -2,24 +2,24 @@ | ||||||
| <div class="_gaps_m"> | <div class="_gaps_m"> | ||||||
| 	<FormSection first> | 	<FormSection first> | ||||||
| 		<template #label><i class="ti ti-pencil"></i> {{ i18n.ts._exportOrImport.allNotes }}</template> | 		<template #label><i class="ti ti-pencil"></i> {{ i18n.ts._exportOrImport.allNotes }}</template> | ||||||
| 		<FormFolder> | 		<MkFolder> | ||||||
| 			<template #label>{{ i18n.ts.export }}</template> | 			<template #label>{{ i18n.ts.export }}</template> | ||||||
| 			<template #icon><i class="ti ti-download"></i></template> | 			<template #icon><i class="ti ti-download"></i></template> | ||||||
| 			<MkButton primary :class="$style.button" inline @click="exportNotes()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton> | 			<MkButton primary :class="$style.button" inline @click="exportNotes()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton> | ||||||
| 		</FormFolder> | 		</MkFolder> | ||||||
| 	</FormSection> | 	</FormSection> | ||||||
| 	<FormSection> | 	<FormSection> | ||||||
| 		<template #label><i class="ti ti-star"></i> {{ i18n.ts._exportOrImport.favoritedNotes }}</template> | 		<template #label><i class="ti ti-star"></i> {{ i18n.ts._exportOrImport.favoritedNotes }}</template> | ||||||
| 		<FormFolder> | 		<MkFolder> | ||||||
| 			<template #label>{{ i18n.ts.export }}</template> | 			<template #label>{{ i18n.ts.export }}</template> | ||||||
| 			<template #icon><i class="ti ti-download"></i></template> | 			<template #icon><i class="ti ti-download"></i></template> | ||||||
| 			<MkButton primary :class="$style.button" inline @click="exportFavorites()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton> | 			<MkButton primary :class="$style.button" inline @click="exportFavorites()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton> | ||||||
| 		</FormFolder> | 		</MkFolder> | ||||||
| 	</FormSection> | 	</FormSection> | ||||||
| 	<FormSection> | 	<FormSection> | ||||||
| 		<template #label><i class="ti ti-users"></i> {{ i18n.ts._exportOrImport.followingList }}</template> | 		<template #label><i class="ti ti-users"></i> {{ i18n.ts._exportOrImport.followingList }}</template> | ||||||
| 		<div class="_gaps_s"> | 		<div class="_gaps_s"> | ||||||
| 			<FormFolder> | 			<MkFolder> | ||||||
| 				<template #label>{{ i18n.ts.export }}</template> | 				<template #label>{{ i18n.ts.export }}</template> | ||||||
| 				<template #icon><i class="ti ti-download"></i></template> | 				<template #icon><i class="ti ti-download"></i></template> | ||||||
| 				<div class="_gaps_s"> | 				<div class="_gaps_s"> | ||||||
|  | @ -31,57 +31,57 @@ | ||||||
| 					</MkSwitch> | 					</MkSwitch> | ||||||
| 					<MkButton primary :class="$style.button" inline @click="exportFollowing()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton> | 					<MkButton primary :class="$style.button" inline @click="exportFollowing()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton> | ||||||
| 				</div> | 				</div> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 			<FormFolder> | 			<MkFolder> | ||||||
| 				<template #label>{{ i18n.ts.import }}</template> | 				<template #label>{{ i18n.ts.import }}</template> | ||||||
| 				<template #icon><i class="ti ti-upload"></i></template> | 				<template #icon><i class="ti ti-upload"></i></template> | ||||||
| 				<MkButton primary :class="$style.button" inline @click="importFollowing($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton> | 				<MkButton primary :class="$style.button" inline @click="importFollowing($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 		</div> | 		</div> | ||||||
| 	</FormSection> | 	</FormSection> | ||||||
| 	<FormSection> | 	<FormSection> | ||||||
| 		<template #label><i class="ti ti-users"></i> {{ i18n.ts._exportOrImport.userLists }}</template> | 		<template #label><i class="ti ti-users"></i> {{ i18n.ts._exportOrImport.userLists }}</template> | ||||||
| 		<div class="_gaps_s"> | 		<div class="_gaps_s"> | ||||||
| 			<FormFolder> | 			<MkFolder> | ||||||
| 				<template #label>{{ i18n.ts.export }}</template> | 				<template #label>{{ i18n.ts.export }}</template> | ||||||
| 				<template #icon><i class="ti ti-download"></i></template> | 				<template #icon><i class="ti ti-download"></i></template> | ||||||
| 				<MkButton primary :class="$style.button" inline @click="exportUserLists()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton> | 				<MkButton primary :class="$style.button" inline @click="exportUserLists()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 			<FormFolder> | 			<MkFolder> | ||||||
| 				<template #label>{{ i18n.ts.import }}</template> | 				<template #label>{{ i18n.ts.import }}</template> | ||||||
| 				<template #icon><i class="ti ti-upload"></i></template> | 				<template #icon><i class="ti ti-upload"></i></template> | ||||||
| 				<MkButton primary :class="$style.button" inline @click="importUserLists($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton> | 				<MkButton primary :class="$style.button" inline @click="importUserLists($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 		</div> | 		</div> | ||||||
| 	</FormSection> | 	</FormSection> | ||||||
| 	<FormSection> | 	<FormSection> | ||||||
| 		<template #label><i class="ti ti-user-off"></i> {{ i18n.ts._exportOrImport.muteList }}</template> | 		<template #label><i class="ti ti-user-off"></i> {{ i18n.ts._exportOrImport.muteList }}</template> | ||||||
| 		<div class="_gaps_s"> | 		<div class="_gaps_s"> | ||||||
| 			<FormFolder> | 			<MkFolder> | ||||||
| 				<template #label>{{ i18n.ts.export }}</template> | 				<template #label>{{ i18n.ts.export }}</template> | ||||||
| 				<template #icon><i class="ti ti-download"></i></template> | 				<template #icon><i class="ti ti-download"></i></template> | ||||||
| 				<MkButton primary :class="$style.button" inline @click="exportMuting()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton> | 				<MkButton primary :class="$style.button" inline @click="exportMuting()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 			<FormFolder> | 			<MkFolder> | ||||||
| 				<template #label>{{ i18n.ts.import }}</template> | 				<template #label>{{ i18n.ts.import }}</template> | ||||||
| 				<template #icon><i class="ti ti-upload"></i></template> | 				<template #icon><i class="ti ti-upload"></i></template> | ||||||
| 				<MkButton primary :class="$style.button" inline @click="importMuting($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton> | 				<MkButton primary :class="$style.button" inline @click="importMuting($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 		</div> | 		</div> | ||||||
| 	</FormSection> | 	</FormSection> | ||||||
| 	<FormSection> | 	<FormSection> | ||||||
| 		<template #label><i class="ti ti-user-off"></i> {{ i18n.ts._exportOrImport.blockingList }}</template> | 		<template #label><i class="ti ti-user-off"></i> {{ i18n.ts._exportOrImport.blockingList }}</template> | ||||||
| 		<div class="_gaps_s"> | 		<div class="_gaps_s"> | ||||||
| 			<FormFolder> | 			<MkFolder> | ||||||
| 				<template #label>{{ i18n.ts.export }}</template> | 				<template #label>{{ i18n.ts.export }}</template> | ||||||
| 				<template #icon><i class="ti ti-download"></i></template> | 				<template #icon><i class="ti ti-download"></i></template> | ||||||
| 				<MkButton primary :class="$style.button" inline @click="exportBlocking()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton> | 				<MkButton primary :class="$style.button" inline @click="exportBlocking()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 			<FormFolder> | 			<MkFolder> | ||||||
| 				<template #label>{{ i18n.ts.import }}</template> | 				<template #label>{{ i18n.ts.import }}</template> | ||||||
| 				<template #icon><i class="ti ti-upload"></i></template> | 				<template #icon><i class="ti ti-upload"></i></template> | ||||||
| 				<MkButton primary :class="$style.button" inline @click="importBlocking($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton> | 				<MkButton primary :class="$style.button" inline @click="importBlocking($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 		</div> | 		</div> | ||||||
| 	</FormSection> | 	</FormSection> | ||||||
| </div> | </div> | ||||||
|  | @ -91,7 +91,7 @@ | ||||||
| import { ref } from 'vue'; | import { ref } from 'vue'; | ||||||
| import MkButton from '@/components/MkButton.vue'; | import MkButton from '@/components/MkButton.vue'; | ||||||
| import FormSection from '@/components/form/section.vue'; | import FormSection from '@/components/form/section.vue'; | ||||||
| import FormFolder from '@/components/form/folder.vue'; | import MkFolder from '@/components/MkFolder.vue'; | ||||||
| import MkSwitch from '@/components/MkSwitch.vue'; | import MkSwitch from '@/components/MkSwitch.vue'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
| import { selectFile } from '@/scripts/select-file'; | import { selectFile } from '@/scripts/select-file'; | ||||||
|  |  | ||||||
|  | @ -32,7 +32,7 @@ | ||||||
| 	<FormSection> | 	<FormSection> | ||||||
| 		<div class="_gaps_m"> | 		<div class="_gaps_m"> | ||||||
| 			<MkSwitch v-model="rememberNoteVisibility" @update:model-value="save()">{{ i18n.ts.rememberNoteVisibility }}</MkSwitch> | 			<MkSwitch v-model="rememberNoteVisibility" @update:model-value="save()">{{ i18n.ts.rememberNoteVisibility }}</MkSwitch> | ||||||
| 			<FormFolder v-if="!rememberNoteVisibility"> | 			<MkFolder v-if="!rememberNoteVisibility"> | ||||||
| 				<template #label>{{ i18n.ts.defaultNoteVisibility }}</template> | 				<template #label>{{ i18n.ts.defaultNoteVisibility }}</template> | ||||||
| 				<template v-if="defaultNoteVisibility === 'public'" #suffix>{{ i18n.ts._visibility.public }}</template> | 				<template v-if="defaultNoteVisibility === 'public'" #suffix>{{ i18n.ts._visibility.public }}</template> | ||||||
| 				<template v-else-if="defaultNoteVisibility === 'home'" #suffix>{{ i18n.ts._visibility.home }}</template> | 				<template v-else-if="defaultNoteVisibility === 'home'" #suffix>{{ i18n.ts._visibility.home }}</template> | ||||||
|  | @ -48,7 +48,7 @@ | ||||||
| 					</MkSelect> | 					</MkSelect> | ||||||
| 					<MkSwitch v-model="defaultNoteLocalOnly">{{ i18n.ts._visibility.localOnly }}</MkSwitch> | 					<MkSwitch v-model="defaultNoteLocalOnly">{{ i18n.ts._visibility.localOnly }}</MkSwitch> | ||||||
| 				</div> | 				</div> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 		</div> | 		</div> | ||||||
| 	</FormSection> | 	</FormSection> | ||||||
| 
 | 
 | ||||||
|  | @ -61,7 +61,7 @@ import { } from 'vue'; | ||||||
| import MkSwitch from '@/components/MkSwitch.vue'; | import MkSwitch from '@/components/MkSwitch.vue'; | ||||||
| import MkSelect from '@/components/MkSelect.vue'; | import MkSelect from '@/components/MkSelect.vue'; | ||||||
| import FormSection from '@/components/form/section.vue'; | import FormSection from '@/components/form/section.vue'; | ||||||
| import FormFolder from '@/components/form/folder.vue'; | import MkFolder from '@/components/MkFolder.vue'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
| import { defaultStore } from '@/store'; | import { defaultStore } from '@/store'; | ||||||
| import { i18n } from '@/i18n'; | import { i18n } from '@/i18n'; | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ | ||||||
| 	</MkSelect> | 	</MkSelect> | ||||||
| 
 | 
 | ||||||
| 	<FormSlot> | 	<FormSlot> | ||||||
| 		<FormFolder> | 		<MkFolder> | ||||||
| 			<template #icon><i class="ti ti-list"></i></template> | 			<template #icon><i class="ti ti-list"></i></template> | ||||||
| 			<template #label>{{ i18n.ts._profile.metadataEdit }}</template> | 			<template #label>{{ i18n.ts._profile.metadataEdit }}</template> | ||||||
| 
 | 
 | ||||||
|  | @ -51,18 +51,18 @@ | ||||||
| 					<MkButton inline primary @click="saveFields"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton> | 					<MkButton inline primary @click="saveFields"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton> | ||||||
| 				</div> | 				</div> | ||||||
| 			</div> | 			</div> | ||||||
| 		</FormFolder> | 		</MkFolder> | ||||||
| 		<template #caption>{{ i18n.ts._profile.metadataDescription }}</template> | 		<template #caption>{{ i18n.ts._profile.metadataDescription }}</template> | ||||||
| 	</FormSlot> | 	</FormSlot> | ||||||
| 
 | 
 | ||||||
| 	<FormFolder> | 	<MkFolder> | ||||||
| 		<template #label>{{ i18n.ts.advancedSettings }}</template> | 		<template #label>{{ i18n.ts.advancedSettings }}</template> | ||||||
| 
 | 
 | ||||||
| 		<div class="_gaps_m"> | 		<div class="_gaps_m"> | ||||||
| 			<MkSwitch v-model="profile.isCat">{{ i18n.ts.flagAsCat }}<template #caption>{{ i18n.ts.flagAsCatDescription }}</template></MkSwitch> | 			<MkSwitch v-model="profile.isCat">{{ i18n.ts.flagAsCat }}<template #caption>{{ i18n.ts.flagAsCatDescription }}</template></MkSwitch> | ||||||
| 			<MkSwitch v-model="profile.isBot">{{ i18n.ts.flagAsBot }}<template #caption>{{ i18n.ts.flagAsBotDescription }}</template></MkSwitch> | 			<MkSwitch v-model="profile.isBot">{{ i18n.ts.flagAsBot }}<template #caption>{{ i18n.ts.flagAsBotDescription }}</template></MkSwitch> | ||||||
| 		</div> | 		</div> | ||||||
| 	</FormFolder> | 	</MkFolder> | ||||||
| 
 | 
 | ||||||
| 	<MkSwitch v-model="profile.showTimelineReplies">{{ i18n.ts.flagShowTimelineReplies }}<template #caption>{{ i18n.ts.flagShowTimelineRepliesDescription }} {{ i18n.ts.reflectMayTakeTime }}</template></MkSwitch> | 	<MkSwitch v-model="profile.showTimelineReplies">{{ i18n.ts.flagShowTimelineReplies }}<template #caption>{{ i18n.ts.flagShowTimelineRepliesDescription }} {{ i18n.ts.reflectMayTakeTime }}</template></MkSwitch> | ||||||
| </div> | </div> | ||||||
|  | @ -76,7 +76,7 @@ import MkTextarea from '@/components/MkTextarea.vue'; | ||||||
| import MkSwitch from '@/components/MkSwitch.vue'; | import MkSwitch from '@/components/MkSwitch.vue'; | ||||||
| import MkSelect from '@/components/MkSelect.vue'; | import MkSelect from '@/components/MkSelect.vue'; | ||||||
| import FormSplit from '@/components/form/split.vue'; | import FormSplit from '@/components/form/split.vue'; | ||||||
| import FormFolder from '@/components/form/folder.vue'; | import MkFolder from '@/components/MkFolder.vue'; | ||||||
| import FormSlot from '@/components/form/slot.vue'; | import FormSlot from '@/components/form/slot.vue'; | ||||||
| import { host } from '@/config'; | import { host } from '@/config'; | ||||||
| import { selectFile } from '@/scripts/select-file'; | import { selectFile } from '@/scripts/select-file'; | ||||||
|  |  | ||||||
|  | @ -7,12 +7,12 @@ | ||||||
| 	<FormSection> | 	<FormSection> | ||||||
| 		<template #label>{{ i18n.ts.sounds }}</template> | 		<template #label>{{ i18n.ts.sounds }}</template> | ||||||
| 		<div class="_gaps_s"> | 		<div class="_gaps_s"> | ||||||
| 			<FormFolder v-for="type in Object.keys(sounds)" :key="type"> | 			<MkFolder v-for="type in Object.keys(sounds)" :key="type"> | ||||||
| 				<template #label>{{ $t('_sfx.' + type) }}</template> | 				<template #label>{{ $t('_sfx.' + type) }}</template> | ||||||
| 				<template #suffix>{{ sounds[type].type ?? i18n.ts.none }}</template> | 				<template #suffix>{{ sounds[type].type ?? i18n.ts.none }}</template> | ||||||
| 
 | 
 | ||||||
| 				<XSound :type="sounds[type].type" :volume="sounds[type].volume" @update="(res) => updated(type, res)"/> | 				<XSound :type="sounds[type].type" :volume="sounds[type].volume" @update="(res) => updated(type, res)"/> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 		</div> | 		</div> | ||||||
| 	</FormSection> | 	</FormSection> | ||||||
| 
 | 
 | ||||||
|  | @ -27,7 +27,7 @@ import MkRange from '@/components/MkRange.vue'; | ||||||
| import MkButton from '@/components/MkButton.vue'; | import MkButton from '@/components/MkButton.vue'; | ||||||
| import FormLink from '@/components/form/link.vue'; | import FormLink from '@/components/form/link.vue'; | ||||||
| import FormSection from '@/components/form/section.vue'; | import FormSection from '@/components/form/section.vue'; | ||||||
| import FormFolder from '@/components/form/folder.vue'; | import MkFolder from '@/components/MkFolder.vue'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
| import { ColdDeviceStorage } from '@/store'; | import { ColdDeviceStorage } from '@/store'; | ||||||
| import { playFile } from '@/scripts/sound'; | import { playFile } from '@/scripts/sound'; | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| <template> | <template> | ||||||
| <div class="_gaps_m"> | <div class="_gaps_m"> | ||||||
| 	<FormFolder v-for="x in statusbars" :key="x.id"> | 	<MkFolder v-for="x in statusbars" :key="x.id"> | ||||||
| 		<template #label>{{ x.type ?? i18n.ts.notSet }}</template> | 		<template #label>{{ x.type ?? i18n.ts.notSet }}</template> | ||||||
| 		<template #suffix>{{ x.name }}</template> | 		<template #suffix>{{ x.name }}</template> | ||||||
| 		<XStatusbar :_id="x.id" :user-lists="userLists"/> | 		<XStatusbar :_id="x.id" :user-lists="userLists"/> | ||||||
| 	</FormFolder> | 	</MkFolder> | ||||||
| 	<MkButton primary @click="add">{{ i18n.ts.add }}</MkButton> | 	<MkButton primary @click="add">{{ i18n.ts.add }}</MkButton> | ||||||
| </div> | </div> | ||||||
| </template> | </template> | ||||||
|  | @ -14,7 +14,7 @@ import { computed, onMounted, ref, watch } from 'vue'; | ||||||
| import { v4 as uuid } from 'uuid'; | import { v4 as uuid } from 'uuid'; | ||||||
| import XStatusbar from './statusbar.statusbar.vue'; | import XStatusbar from './statusbar.statusbar.vue'; | ||||||
| import MkRadios from '@/components/MkRadios.vue'; | import MkRadios from '@/components/MkRadios.vue'; | ||||||
| import FormFolder from '@/components/form/folder.vue'; | import MkFolder from '@/components/MkFolder.vue'; | ||||||
| import MkButton from '@/components/MkButton.vue'; | import MkButton from '@/components/MkButton.vue'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
| import { defaultStore } from '@/store'; | import { defaultStore } from '@/store'; | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| 	<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template> | 	<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template> | ||||||
| 	<MkSpacer :content-max="800" :margin-min="16" :margin-max="32"> | 	<MkSpacer :content-max="800" :margin-min="16" :margin-max="32"> | ||||||
| 		<div class="cwepdizn _gaps_m"> | 		<div class="cwepdizn _gaps_m"> | ||||||
| 			<FormFolder :default-open="true"> | 			<MkFolder :default-open="true"> | ||||||
| 				<template #label>{{ i18n.ts.backgroundColor }}</template> | 				<template #label>{{ i18n.ts.backgroundColor }}</template> | ||||||
| 				<div class="cwepdizn-colors"> | 				<div class="cwepdizn-colors"> | ||||||
| 					<div class="row"> | 					<div class="row"> | ||||||
|  | @ -17,9 +17,9 @@ | ||||||
| 						</button> | 						</button> | ||||||
| 					</div> | 					</div> | ||||||
| 				</div> | 				</div> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 
 | 
 | ||||||
| 			<FormFolder :default-open="true"> | 			<MkFolder :default-open="true"> | ||||||
| 				<template #label>{{ i18n.ts.accentColor }}</template> | 				<template #label>{{ i18n.ts.accentColor }}</template> | ||||||
| 				<div class="cwepdizn-colors"> | 				<div class="cwepdizn-colors"> | ||||||
| 					<div class="row"> | 					<div class="row"> | ||||||
|  | @ -28,9 +28,9 @@ | ||||||
| 						</button> | 						</button> | ||||||
| 					</div> | 					</div> | ||||||
| 				</div> | 				</div> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 
 | 
 | ||||||
| 			<FormFolder :default-open="true"> | 			<MkFolder :default-open="true"> | ||||||
| 				<template #label>{{ i18n.ts.textColor }}</template> | 				<template #label>{{ i18n.ts.textColor }}</template> | ||||||
| 				<div class="cwepdizn-colors"> | 				<div class="cwepdizn-colors"> | ||||||
| 					<div class="row"> | 					<div class="row"> | ||||||
|  | @ -39,9 +39,9 @@ | ||||||
| 						</button> | 						</button> | ||||||
| 					</div> | 					</div> | ||||||
| 				</div> | 				</div> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 
 | 
 | ||||||
| 			<FormFolder :default-open="false"> | 			<MkFolder :default-open="false"> | ||||||
| 				<template #icon><i class="ti ti-code"></i></template> | 				<template #icon><i class="ti ti-code"></i></template> | ||||||
| 				<template #label>{{ i18n.ts.editCode }}</template> | 				<template #label>{{ i18n.ts.editCode }}</template> | ||||||
| 
 | 
 | ||||||
|  | @ -51,9 +51,9 @@ | ||||||
| 					</MkTextarea> | 					</MkTextarea> | ||||||
| 					<MkButton primary @click="applyThemeCode">{{ i18n.ts.apply }}</MkButton> | 					<MkButton primary @click="applyThemeCode">{{ i18n.ts.apply }}</MkButton> | ||||||
| 				</div> | 				</div> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 
 | 
 | ||||||
| 			<FormFolder :default-open="false"> | 			<MkFolder :default-open="false"> | ||||||
| 				<template #label>{{ i18n.ts.addDescription }}</template> | 				<template #label>{{ i18n.ts.addDescription }}</template> | ||||||
| 
 | 
 | ||||||
| 				<div class="_gaps_m"> | 				<div class="_gaps_m"> | ||||||
|  | @ -61,7 +61,7 @@ | ||||||
| 						<template #label>{{ i18n.ts._theme.description }}</template> | 						<template #label>{{ i18n.ts._theme.description }}</template> | ||||||
| 					</MkTextarea> | 					</MkTextarea> | ||||||
| 				</div> | 				</div> | ||||||
| 			</FormFolder> | 			</MkFolder> | ||||||
| 		</div> | 		</div> | ||||||
| 	</MkSpacer> | 	</MkSpacer> | ||||||
| </MkStickyContainer> | </MkStickyContainer> | ||||||
|  | @ -76,7 +76,7 @@ import JSON5 from 'json5'; | ||||||
| 
 | 
 | ||||||
| import MkButton from '@/components/MkButton.vue'; | import MkButton from '@/components/MkButton.vue'; | ||||||
| import MkTextarea from '@/components/MkTextarea.vue'; | import MkTextarea from '@/components/MkTextarea.vue'; | ||||||
| import FormFolder from '@/components/form/folder.vue'; | import MkFolder from '@/components/MkFolder.vue'; | ||||||
| 
 | 
 | ||||||
| import { $i } from '@/account'; | import { $i } from '@/account'; | ||||||
| import { Theme, applyTheme } from '@/scripts/theme'; | import { Theme, applyTheme } from '@/scripts/theme'; | ||||||
|  |  | ||||||
|  | @ -77,12 +77,12 @@ | ||||||
| 
 | 
 | ||||||
| 						<MkButton v-if="user.host != null" @click="updateRemoteUser"><i class="ti ti-refresh"></i> {{ i18n.ts.updateRemoteUser }}</MkButton> | 						<MkButton v-if="user.host != null" @click="updateRemoteUser"><i class="ti ti-refresh"></i> {{ i18n.ts.updateRemoteUser }}</MkButton> | ||||||
| 
 | 
 | ||||||
| 						<FormFolder> | 						<MkFolder> | ||||||
| 							<template #label>Raw</template> | 							<template #label>Raw</template> | ||||||
| 
 | 
 | ||||||
| 							<MkObjectView v-if="ap" tall :value="ap"> | 							<MkObjectView v-if="ap" tall :value="ap"> | ||||||
| 							</MkObjectView> | 							</MkObjectView> | ||||||
| 						</FormFolder> | 						</MkFolder> | ||||||
| 					</div> | 					</div> | ||||||
| 				</FormSection> | 				</FormSection> | ||||||
| 			</div> | 			</div> | ||||||
|  | @ -98,7 +98,7 @@ | ||||||
| 				<MkTextarea v-model="moderationNote" manual-save> | 				<MkTextarea v-model="moderationNote" manual-save> | ||||||
| 					<template #label>Moderation note</template> | 					<template #label>Moderation note</template> | ||||||
| 				</MkTextarea> | 				</MkTextarea> | ||||||
| 				<FormFolder> | 				<MkFolder> | ||||||
| 					<template #label>IP</template> | 					<template #label>IP</template> | ||||||
| 					<MkInfo v-if="!iAmAdmin" warn>{{ i18n.ts.requireAdminForView }}</MkInfo> | 					<MkInfo v-if="!iAmAdmin" warn>{{ i18n.ts.requireAdminForView }}</MkInfo> | ||||||
| 					<MkInfo v-else>The date is the IP address was first acknowledged.</MkInfo> | 					<MkInfo v-else>The date is the IP address was first acknowledged.</MkInfo> | ||||||
|  | @ -108,12 +108,12 @@ | ||||||
| 							<span class="ip">{{ record.ip }}</span> | 							<span class="ip">{{ record.ip }}</span> | ||||||
| 						</div> | 						</div> | ||||||
| 					</template> | 					</template> | ||||||
| 				</FormFolder> | 				</MkFolder> | ||||||
| 				<FormFolder> | 				<MkFolder> | ||||||
| 					<template #label>{{ i18n.ts.files }}</template> | 					<template #label>{{ i18n.ts.files }}</template> | ||||||
| 
 | 
 | ||||||
| 					<MkFileListForAdmin :pagination="filesPagination" view-mode="grid"/> | 					<MkFileListForAdmin :pagination="filesPagination" view-mode="grid"/> | ||||||
| 				</FormFolder> | 				</MkFolder> | ||||||
| 				<FormSection> | 				<FormSection> | ||||||
| 					<template #label>Drive Capacity Override</template> | 					<template #label>Drive Capacity Override</template> | ||||||
| 
 | 
 | ||||||
|  | @ -165,7 +165,7 @@ import FormSection from '@/components/form/section.vue'; | ||||||
| import MkButton from '@/components/MkButton.vue'; | import MkButton from '@/components/MkButton.vue'; | ||||||
| import MkInput from '@/components/MkInput.vue'; | import MkInput from '@/components/MkInput.vue'; | ||||||
| import FormSplit from '@/components/form/split.vue'; | import FormSplit from '@/components/form/split.vue'; | ||||||
| import FormFolder from '@/components/form/folder.vue'; | import MkFolder from '@/components/MkFolder.vue'; | ||||||
| import MkKeyValue from '@/components/MkKeyValue.vue'; | import MkKeyValue from '@/components/MkKeyValue.vue'; | ||||||
| import MkSelect from '@/components/MkSelect.vue'; | import MkSelect from '@/components/MkSelect.vue'; | ||||||
| import FormSuspense from '@/components/form/suspense.vue'; | import FormSuspense from '@/components/form/suspense.vue'; | ||||||
|  |  | ||||||
|  | @ -1,22 +1,22 @@ | ||||||
| <template> | <template> | ||||||
| <MkSpacer :content-max="700"> | <MkSpacer :content-max="700"> | ||||||
| 	<div class="_gaps"> | 	<div class="_gaps"> | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header><i class="ti ti-activity"></i> Heatmap</template> | 			<template #header><i class="ti ti-activity"></i> Heatmap</template> | ||||||
| 			<XHeatmap :user="user" :src="'notes'"/> | 			<XHeatmap :user="user" :src="'notes'"/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header><i class="ti ti-pencil"></i> Notes</template> | 			<template #header><i class="ti ti-pencil"></i> Notes</template> | ||||||
| 			<XNotes :user="user"/> | 			<XNotes :user="user"/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header><i class="ti ti-users"></i> Following</template> | 			<template #header><i class="ti ti-users"></i> Following</template> | ||||||
| 			<XFollowing :user="user"/> | 			<XFollowing :user="user"/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 		<MkFolder class="item"> | 		<MkFoldableSection class="item"> | ||||||
| 			<template #header><i class="ti ti-eye"></i> PV</template> | 			<template #header><i class="ti ti-eye"></i> PV</template> | ||||||
| 			<XPv :user="user"/> | 			<XPv :user="user"/> | ||||||
| 		</MkFolder> | 		</MkFoldableSection> | ||||||
| 	</div> | 	</div> | ||||||
| </MkSpacer> | </MkSpacer> | ||||||
| </template> | </template> | ||||||
|  | @ -28,7 +28,7 @@ import XHeatmap from './activity.heatmap.vue'; | ||||||
| import XPv from './activity.pv.vue'; | import XPv from './activity.pv.vue'; | ||||||
| import XNotes from './activity.notes.vue'; | import XNotes from './activity.notes.vue'; | ||||||
| import XFollowing from './activity.following.vue'; | import XFollowing from './activity.following.vue'; | ||||||
| import MkFolder from '@/components/MkFolder.vue'; | import MkFoldableSection from '@/components/MkFoldableSection.vue'; | ||||||
| 
 | 
 | ||||||
| const props = defineProps<{ | const props = defineProps<{ | ||||||
| 	user: misskey.entities.User; | 	user: misskey.entities.User; | ||||||
|  |  | ||||||
|  | @ -115,7 +115,7 @@ import XUserTimeline from './index.timeline.vue'; | ||||||
| import XNote from '@/components/MkNote.vue'; | import XNote from '@/components/MkNote.vue'; | ||||||
| import MkFollowButton from '@/components/MkFollowButton.vue'; | import MkFollowButton from '@/components/MkFollowButton.vue'; | ||||||
| import MkContainer from '@/components/MkContainer.vue'; | import MkContainer from '@/components/MkContainer.vue'; | ||||||
| import MkFolder from '@/components/MkFolder.vue'; | import MkFoldableSection from '@/components/MkFoldableSection.vue'; | ||||||
| import MkRemoteCaution from '@/components/MkRemoteCaution.vue'; | import MkRemoteCaution from '@/components/MkRemoteCaution.vue'; | ||||||
| import MkTab from '@/components/MkTab.vue'; | import MkTab from '@/components/MkTab.vue'; | ||||||
| import MkInfo from '@/components/MkInfo.vue'; | import MkInfo from '@/components/MkInfo.vue'; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue