Merge branch 'misskey-dev:develop' into error-style
This commit is contained in:
commit
32d50fc8ed
54 changed files with 1585 additions and 239 deletions
|
@ -9,6 +9,9 @@ export const meta = {
|
|||
|
||||
requireCredential: false,
|
||||
|
||||
allowGet: true,
|
||||
cacheSec: 60,
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
optional: false, nullable: false,
|
||||
|
|
|
@ -5,7 +5,7 @@ html
|
|||
head
|
||||
meta(charset='utf-8')
|
||||
meta(name='application-name' content='Misskey')
|
||||
title Misskey BIOS
|
||||
title Misskey Repair Tool
|
||||
style
|
||||
include ../bios.css
|
||||
script
|
||||
|
@ -13,7 +13,7 @@ html
|
|||
|
||||
body
|
||||
header
|
||||
h1 Misskey BIOS #{version}
|
||||
h1 Misskey Repair Tool #{version}
|
||||
main
|
||||
div.tabs
|
||||
button#ls edit local storage
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
<template>
|
||||
<!-- このコンポーネントの要素のclassは親から利用されるのでむやみに弄らないこと -->
|
||||
<section>
|
||||
<header class="_acrylic" @click="shown = !shown">
|
||||
<i class="toggle fa-fw" :class="shown ? 'fas fa-chevron-down' : 'fas fa-chevron-up'"></i> <slot></slot> ({{ emojis.length }})
|
||||
</header>
|
||||
<div v-if="shown">
|
||||
<button v-for="emoji in emojis"
|
||||
<div v-if="shown" class="body">
|
||||
<button
|
||||
v-for="emoji in emojis"
|
||||
:key="emoji"
|
||||
class="_button"
|
||||
class="_button item"
|
||||
@click="emit('chosen', emoji, $event)"
|
||||
>
|
||||
<MkEmoji :emoji="emoji" :normal="true"/>
|
||||
<MkEmoji class="emoji" :emoji="emoji" :normal="true"/>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
@ -3,63 +3,67 @@
|
|||
<input ref="search" v-model.trim="q" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" :placeholder="i18n.ts.search" type="search" @paste.stop="paste" @keyup.enter="done()">
|
||||
<div ref="emojis" class="emojis">
|
||||
<section class="result">
|
||||
<div v-if="searchResultCustom.length > 0">
|
||||
<button v-for="emoji in searchResultCustom"
|
||||
<div v-if="searchResultCustom.length > 0" class="body">
|
||||
<button
|
||||
v-for="emoji in searchResultCustom"
|
||||
:key="emoji.id"
|
||||
class="_button"
|
||||
class="_button item"
|
||||
:title="emoji.name"
|
||||
tabindex="0"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<!--<MkEmoji v-if="emoji.char != null" :emoji="emoji.char"/>-->
|
||||
<img :src="disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/>
|
||||
<img class="emoji" :src="disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="searchResultUnicode.length > 0">
|
||||
<button v-for="emoji in searchResultUnicode"
|
||||
<div v-if="searchResultUnicode.length > 0" class="body">
|
||||
<button
|
||||
v-for="emoji in searchResultUnicode"
|
||||
:key="emoji.name"
|
||||
class="_button"
|
||||
class="_button item"
|
||||
:title="emoji.name"
|
||||
tabindex="0"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<MkEmoji :emoji="emoji.char"/>
|
||||
<MkEmoji class="emoji" :emoji="emoji.char"/>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div v-if="tab === 'index'" class="index">
|
||||
<div v-if="tab === 'index'" class="group index">
|
||||
<section v-if="showPinned">
|
||||
<div>
|
||||
<button v-for="emoji in pinned"
|
||||
<div class="body">
|
||||
<button
|
||||
v-for="emoji in pinned"
|
||||
:key="emoji"
|
||||
class="_button"
|
||||
class="_button item"
|
||||
tabindex="0"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<MkEmoji :emoji="emoji" :normal="true"/>
|
||||
<MkEmoji class="emoji" :emoji="emoji" :normal="true"/>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<header class="_acrylic"><i class="far fa-clock fa-fw"></i> {{ i18n.ts.recentUsed }}</header>
|
||||
<div>
|
||||
<button v-for="emoji in recentlyUsedEmojis"
|
||||
<div class="body">
|
||||
<button
|
||||
v-for="emoji in recentlyUsedEmojis"
|
||||
:key="emoji"
|
||||
class="_button"
|
||||
class="_button item"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<MkEmoji :emoji="emoji" :normal="true"/>
|
||||
<MkEmoji class="emoji" :emoji="emoji" :normal="true"/>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div>
|
||||
<div class="group">
|
||||
<header class="_acrylic">{{ i18n.ts.customEmojis }}</header>
|
||||
<XSection v-for="category in customEmojiCategories" :key="'custom:' + category" :initial-shown="false" :emojis="customEmojis.filter(e => e.category === category).map(e => ':' + e.name + ':')" @chosen="chosen">{{ category || i18n.ts.other }}</XSection>
|
||||
</div>
|
||||
<div>
|
||||
<div class="group">
|
||||
<header class="_acrylic">{{ i18n.ts.emoji }}</header>
|
||||
<XSection v-for="category in categories" :key="category" :emojis="emojilist.filter(e => e.category === category).map(e => e.char)" @chosen="chosen">{{ category }}</XSection>
|
||||
</div>
|
||||
|
@ -76,6 +80,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { ref, computed, watch, onMounted } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import XSection from './emoji-picker.section.vue';
|
||||
import { emojilist, UnicodeEmojiDef, unicodeEmojiCategories as categories } from '@/scripts/emojilist';
|
||||
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
|
||||
import Ripple from '@/components/ripple.vue';
|
||||
|
@ -83,7 +88,6 @@ import * as os from '@/os';
|
|||
import { isTouchUsing } from '@/scripts/touch';
|
||||
import { deviceKind } from '@/scripts/device-kind';
|
||||
import { emojiCategories, instance } from '@/instance';
|
||||
import XSection from './emoji-picker.section.vue';
|
||||
import { i18n } from '@/i18n';
|
||||
import { defaultStore } from '@/store';
|
||||
|
||||
|
@ -266,7 +270,7 @@ watch(q, () => {
|
|||
function focus() {
|
||||
if (!['smartphone', 'tablet'].includes(deviceKind) && !isTouchUsing) {
|
||||
search.value?.focus({
|
||||
preventScroll: true
|
||||
preventScroll: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -415,19 +419,16 @@ defineExpose({
|
|||
font-size: 15px;
|
||||
}
|
||||
|
||||
> div {
|
||||
> .body {
|
||||
display: grid;
|
||||
grid-template-columns: var(--columns);
|
||||
font-size: 30px;
|
||||
|
||||
> button {
|
||||
> .item {
|
||||
aspect-ratio: 1 / 1;
|
||||
width: auto;
|
||||
height: auto;
|
||||
min-width: 0;
|
||||
|
||||
> * {
|
||||
font-size: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -478,7 +479,7 @@ defineExpose({
|
|||
display: none;
|
||||
}
|
||||
|
||||
> div {
|
||||
> .group {
|
||||
&:not(.index) {
|
||||
padding: 4px 0 8px 0;
|
||||
border-top: solid 0.5px var(--divider);
|
||||
|
@ -513,16 +514,18 @@ defineExpose({
|
|||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
> .body {
|
||||
position: relative;
|
||||
padding: $pad;
|
||||
|
||||
> button {
|
||||
> .item {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
width: var(--eachSize);
|
||||
height: var(--eachSize);
|
||||
contain: strict;
|
||||
border-radius: 4px;
|
||||
font-size: 24px;
|
||||
|
||||
&:focus-visible {
|
||||
outline: solid 2px var(--focus);
|
||||
|
@ -538,8 +541,7 @@ defineExpose({
|
|||
box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
|
||||
}
|
||||
|
||||
> * {
|
||||
font-size: 24px;
|
||||
> .emoji {
|
||||
height: 1.25em;
|
||||
vertical-align: -.25em;
|
||||
pointer-events: none;
|
||||
|
|
|
@ -178,6 +178,8 @@ onUnmounted(() => {
|
|||
-webkit-backdrop-filter: var(--blur, blur(15px));
|
||||
backdrop-filter: var(--blur, blur(15px));
|
||||
border-bottom: solid 0.5px var(--divider);
|
||||
contain: strict;
|
||||
height: var(--height);
|
||||
|
||||
&.thin {
|
||||
--height: 45px;
|
||||
|
|
|
@ -11,7 +11,7 @@ import { decode } from 'blurhash';
|
|||
|
||||
const props = withDefaults(defineProps<{
|
||||
src?: string | null;
|
||||
hash: string;
|
||||
hash?: string;
|
||||
alt?: string;
|
||||
title?: string | null;
|
||||
size?: number;
|
||||
|
|
|
@ -154,7 +154,7 @@ function createDoughnut(chartEl, tooltip, data) {
|
|||
}
|
||||
|
||||
onMounted(() => {
|
||||
os.apiGet('federation/stats', { limit: 15 }).then(fedStats => {
|
||||
os.apiGet('federation/stats', { limit: 20 }).then(fedStats => {
|
||||
createDoughnut(subDoughnutEl, externalTooltipHandler1, fedStats.topSubInstances.map(x => ({
|
||||
name: x.host,
|
||||
color: x.themeColor,
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
<div v-if="hide" class="qjewsnkg" @click="hide = false">
|
||||
<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.comment" :alt="image.comment"/>
|
||||
<div class="text">
|
||||
<div>
|
||||
<b><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b>
|
||||
<span>{{ $ts.clickToShow }}</span>
|
||||
<div class="wrapper">
|
||||
<b style="display: block;"><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b>
|
||||
<span style="display: block;">{{ $ts.clickToShow }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -37,8 +37,8 @@ let hide = $ref(true);
|
|||
const url = (props.raw || defaultStore.state.loadRawImages)
|
||||
? props.image.url
|
||||
: defaultStore.state.disableShowingAnimatedImages
|
||||
? getStaticImageUrl(props.image.thumbnailUrl)
|
||||
: props.image.thumbnailUrl;
|
||||
? getStaticImageUrl(props.image.thumbnailUrl)
|
||||
: props.image.thumbnailUrl;
|
||||
|
||||
// Plugin:register_note_view_interruptor を使って書き換えられる可能性があるためwatchする
|
||||
watch(() => props.image, () => {
|
||||
|
@ -68,15 +68,11 @@ watch(() => props.image, () => {
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
> div {
|
||||
> .wrapper {
|
||||
display: table-cell;
|
||||
text-align: center;
|
||||
font-size: 0.8em;
|
||||
color: #fff;
|
||||
|
||||
> * {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<MkA :to="`/@${page.user.username}/pages/${page.name}`" class="vhpxefrj _block _isolated" tabindex="-1">
|
||||
<MkA :to="`/@${page.user.username}/pages/${page.name}`" class="vhpxefrj _block" tabindex="-1">
|
||||
<div v-if="page.eyeCatchingImage" class="thumbnail" :style="`background-image: url('${page.eyeCatchingImage.thumbnailUrl}')`"></div>
|
||||
<article>
|
||||
<header>
|
||||
|
@ -23,12 +23,12 @@ export default defineComponent({
|
|||
props: {
|
||||
page: {
|
||||
type: Object,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
userName
|
||||
}
|
||||
userName,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div v-show="files.length != 0" class="skeikyzd">
|
||||
<XDraggable v-model="_files" class="files" item-key="id" animation="150" delay="100" delay-on-touch-only="true">
|
||||
<template #item="{element}">
|
||||
<div @click="showFileMenu(element, $event)" @contextmenu.prevent="showFileMenu(element, $event)">
|
||||
<div class="file" @click="showFileMenu(element, $event)" @contextmenu.prevent="showFileMenu(element, $event)">
|
||||
<MkDriveFileThumbnail :data-id="element.id" class="thumbnail" :file="element" fit="cover"/>
|
||||
<div v-if="element.isSensitive" class="sensitive">
|
||||
<i class="fas fa-exclamation-triangle icon"></i>
|
||||
|
@ -22,18 +22,18 @@ import * as os from '@/os';
|
|||
export default defineComponent({
|
||||
components: {
|
||||
XDraggable: defineAsyncComponent(() => import('vuedraggable').then(x => x.default)),
|
||||
MkDriveFileThumbnail
|
||||
MkDriveFileThumbnail,
|
||||
},
|
||||
|
||||
props: {
|
||||
files: {
|
||||
type: Array,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
detachMediaFn: {
|
||||
type: Function,
|
||||
required: false
|
||||
}
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
|
||||
emits: ['updated', 'detach', 'changeSensitive', 'changeName'],
|
||||
|
@ -51,8 +51,8 @@ export default defineComponent({
|
|||
},
|
||||
set(value) {
|
||||
this.$emit('updated', value);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
@ -66,7 +66,7 @@ export default defineComponent({
|
|||
toggleSensitive(file) {
|
||||
os.api('drive/files/update', {
|
||||
fileId: file.id,
|
||||
isSensitive: !file.isSensitive
|
||||
isSensitive: !file.isSensitive,
|
||||
}).then(() => {
|
||||
this.$emit('changeSensitive', file, !file.isSensitive);
|
||||
});
|
||||
|
@ -75,12 +75,12 @@ export default defineComponent({
|
|||
const { canceled, result } = await os.inputText({
|
||||
title: this.$ts.enterFileName,
|
||||
default: file.name,
|
||||
allowEmpty: false
|
||||
allowEmpty: false,
|
||||
});
|
||||
if (canceled) return;
|
||||
os.api('drive/files/update', {
|
||||
fileId: file.id,
|
||||
name: result
|
||||
name: result,
|
||||
}).then(() => {
|
||||
this.$emit('changeName', file, result);
|
||||
file.name = result;
|
||||
|
@ -88,13 +88,13 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
async describe(file) {
|
||||
os.popup(defineAsyncComponent(() => import("@/components/media-caption.vue")), {
|
||||
os.popup(defineAsyncComponent(() => import('@/components/media-caption.vue')), {
|
||||
title: this.$ts.describeFile,
|
||||
input: {
|
||||
placeholder: this.$ts.inputNewDescription,
|
||||
default: file.comment !== null ? file.comment : "",
|
||||
default: file.comment !== null ? file.comment : '',
|
||||
},
|
||||
image: file
|
||||
image: file,
|
||||
}, {
|
||||
done: result => {
|
||||
if (!result || result.canceled) return;
|
||||
|
@ -105,7 +105,7 @@ export default defineComponent({
|
|||
}).then(() => {
|
||||
file.comment = comment;
|
||||
});
|
||||
}
|
||||
},
|
||||
}, 'closed');
|
||||
},
|
||||
|
||||
|
@ -114,22 +114,22 @@ export default defineComponent({
|
|||
this.menu = os.popupMenu([{
|
||||
text: this.$ts.renameFile,
|
||||
icon: 'fas fa-i-cursor',
|
||||
action: () => { this.rename(file); }
|
||||
action: () => { this.rename(file); },
|
||||
}, {
|
||||
text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
|
||||
icon: file.isSensitive ? 'fas fa-eye-slash' : 'fas fa-eye',
|
||||
action: () => { this.toggleSensitive(file); }
|
||||
action: () => { this.toggleSensitive(file); },
|
||||
}, {
|
||||
text: this.$ts.describeFile,
|
||||
icon: 'fas fa-i-cursor',
|
||||
action: () => { this.describe(file); }
|
||||
action: () => { this.describe(file); },
|
||||
}, {
|
||||
text: this.$ts.attachCancel,
|
||||
icon: 'fas fa-times-circle',
|
||||
action: () => { this.detachMedia(file.id); }
|
||||
action: () => { this.detachMedia(file.id); },
|
||||
}], ev.currentTarget ?? ev.target).then(() => this.menu = null);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -142,7 +142,7 @@ export default defineComponent({
|
|||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
> div {
|
||||
> .file {
|
||||
position: relative;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<div v-size="{ max: [310, 500] }" class="gafaadew"
|
||||
<div
|
||||
v-size="{ max: [310, 500] }" class="gafaadew"
|
||||
:class="{ modal, _popup: modal }"
|
||||
@dragover.stop="onDragover"
|
||||
@dragenter="onDragenter"
|
||||
|
@ -11,7 +12,7 @@
|
|||
<button v-click-anime v-tooltip="i18n.ts.switchAccount" class="account _button" @click="openAccountMenu">
|
||||
<MkAvatar :user="postAccount ?? $i" class="avatar"/>
|
||||
</button>
|
||||
<div>
|
||||
<div class="right">
|
||||
<span class="text-count" :class="{ over: textLength > maxTextLength }">{{ maxTextLength - textLength }}</span>
|
||||
<span v-if="localOnly" class="local-only"><i class="fas fa-biohazard"></i></span>
|
||||
<button ref="visibilityButton" v-tooltip="i18n.ts.visibility" class="_button visibility" :disabled="channel != null" @click="setVisibility">
|
||||
|
@ -68,6 +69,8 @@ import * as misskey from 'misskey-js';
|
|||
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||
import { length } from 'stringz';
|
||||
import { toASCII } from 'punycode/';
|
||||
import * as Acct from 'misskey-js/built/acct';
|
||||
import { throttle } from 'throttle-debounce';
|
||||
import XNoteSimple from './note-simple.vue';
|
||||
import XNotePreview from './note-preview.vue';
|
||||
import XPostFormAttaches from './post-form-attaches.vue';
|
||||
|
@ -75,14 +78,12 @@ import XPollEditor from './poll-editor.vue';
|
|||
import { host, url } from '@/config';
|
||||
import { erase, unique } from '@/scripts/array';
|
||||
import { extractMentions } from '@/scripts/extract-mentions';
|
||||
import * as Acct from 'misskey-js/built/acct';
|
||||
import { formatTimeString } from '@/scripts/format-time-string';
|
||||
import { Autocomplete } from '@/scripts/autocomplete';
|
||||
import * as os from '@/os';
|
||||
import { stream } from '@/stream';
|
||||
import { selectFiles } from '@/scripts/select-file';
|
||||
import { defaultStore, notePostInterruptors, postFormActions } from '@/store';
|
||||
import { throttle } from 'throttle-debounce';
|
||||
import MkInfo from '@/components/ui/info.vue';
|
||||
import { i18n } from '@/i18n';
|
||||
import { instance } from '@/instance';
|
||||
|
@ -181,7 +182,7 @@ const placeholder = $computed((): string => {
|
|||
i18n.ts._postForm._placeholders.c,
|
||||
i18n.ts._postForm._placeholders.d,
|
||||
i18n.ts._postForm._placeholders.e,
|
||||
i18n.ts._postForm._placeholders.f
|
||||
i18n.ts._postForm._placeholders.f,
|
||||
];
|
||||
return xs[Math.floor(Math.random() * xs.length)];
|
||||
}
|
||||
|
@ -238,10 +239,10 @@ if (props.reply && props.reply.text != null) {
|
|||
|
||||
for (const x of extractMentions(ast)) {
|
||||
const mention = x.host ?
|
||||
`@${x.username}@${toASCII(x.host)}` :
|
||||
(otherHost == null || otherHost === host) ?
|
||||
`@${x.username}` :
|
||||
`@${x.username}@${toASCII(otherHost)}`;
|
||||
`@${x.username}@${toASCII(x.host)}` :
|
||||
(otherHost == null || otherHost === host) ?
|
||||
`@${x.username}` :
|
||||
`@${x.username}@${toASCII(otherHost)}`;
|
||||
|
||||
// 自分は除外
|
||||
if ($i.username === x.username && (x.host == null || x.host === host)) continue;
|
||||
|
@ -263,7 +264,7 @@ if (props.reply && ['home', 'followers', 'specified'].includes(props.reply.visib
|
|||
visibility = props.reply.visibility;
|
||||
if (props.reply.visibility === 'specified') {
|
||||
os.api('users/show', {
|
||||
userIds: props.reply.visibleUserIds.filter(uid => uid !== $i.id && uid !== props.reply.userId)
|
||||
userIds: props.reply.visibleUserIds.filter(uid => uid !== $i.id && uid !== props.reply.userId),
|
||||
}).then(users => {
|
||||
users.forEach(pushVisibleUser);
|
||||
});
|
||||
|
@ -399,7 +400,7 @@ function setVisibility() {
|
|||
if (defaultStore.state.rememberNoteVisibility) {
|
||||
defaultStore.set('localOnly', localOnly);
|
||||
}
|
||||
}
|
||||
},
|
||||
}, 'closed');
|
||||
}
|
||||
|
||||
|
@ -522,8 +523,8 @@ function saveDraft() {
|
|||
visibility: visibility,
|
||||
localOnly: localOnly,
|
||||
files: files,
|
||||
poll: poll
|
||||
}
|
||||
poll: poll,
|
||||
},
|
||||
};
|
||||
|
||||
localStorage.setItem('drafts', JSON.stringify(draftData));
|
||||
|
@ -612,11 +613,11 @@ function showActions(ev) {
|
|||
text: action.title,
|
||||
action: () => {
|
||||
action.handler({
|
||||
text: text
|
||||
text: text,
|
||||
}, (key, value) => {
|
||||
if (key === 'text') { text = value; }
|
||||
});
|
||||
}
|
||||
},
|
||||
})), ev.currentTarget ?? ev.target);
|
||||
}
|
||||
|
||||
|
@ -726,7 +727,7 @@ onMounted(() => {
|
|||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
> .right {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
@ -924,7 +925,7 @@ onMounted(() => {
|
|||
line-height: 50px;
|
||||
}
|
||||
|
||||
> div {
|
||||
> .right {
|
||||
> .text-count {
|
||||
line-height: 50px;
|
||||
}
|
||||
|
|
|
@ -70,10 +70,11 @@ onMounted(() => {
|
|||
});
|
||||
|
||||
useTooltip(buttonRef, async (showing) => {
|
||||
const reactions = await os.api('notes/reactions', {
|
||||
const reactions = await os.apiGet('notes/reactions', {
|
||||
noteId: props.note.id,
|
||||
type: props.reaction,
|
||||
limit: 11,
|
||||
_cacheKey_: props.count,
|
||||
});
|
||||
|
||||
const users = reactions.map(x => x.user);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="jmgmzlwq _block"><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i>{{ $ts.remoteUserCaution }}<a :href="href" rel="nofollow noopener" target="_blank">{{ $ts.showOnRemote }}</a></div>
|
||||
<div class="jmgmzlwq _block"><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i>{{ $ts.remoteUserCaution }}<a class="link" :href="href" rel="nofollow noopener" target="_blank">{{ $ts.showOnRemote }}</a></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -15,7 +15,7 @@ defineProps<{
|
|||
background: var(--infoWarnBg);
|
||||
color: var(--infoWarnFg);
|
||||
|
||||
> a {
|
||||
> .link {
|
||||
margin-left: 4px;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
|
|
@ -144,6 +144,7 @@ export default defineComponent({
|
|||
.ukygtjoj {
|
||||
position: relative;
|
||||
overflow: hidden; overflow: clip;
|
||||
contain: content;
|
||||
|
||||
&.naked {
|
||||
background: transparent !important;
|
||||
|
|
|
@ -133,8 +133,10 @@ const fetchMore = async (): Promise<void> => {
|
|||
limit: SECOND_FETCH_LIMIT + 1,
|
||||
...(props.pagination.offsetMode ? {
|
||||
offset: offset.value,
|
||||
} : props.pagination.reversed ? {
|
||||
sinceId: items.value[0].id,
|
||||
} : {
|
||||
untilId: props.pagination.reversed ? items.value[0].id : items.value[items.value.length - 1].id,
|
||||
untilId: items.value[items.value.length - 1].id,
|
||||
}),
|
||||
}).then(res => {
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
|
@ -169,8 +171,10 @@ const fetchMoreAhead = async (): Promise<void> => {
|
|||
limit: SECOND_FETCH_LIMIT + 1,
|
||||
...(props.pagination.offsetMode ? {
|
||||
offset: offset.value,
|
||||
} : props.pagination.reversed ? {
|
||||
untilId: items.value[0].id,
|
||||
} : {
|
||||
sinceId: props.pagination.reversed ? items.value[0].id : items.value[items.value.length - 1].id,
|
||||
sinceId: items.value[items.value.length - 1].id,
|
||||
}),
|
||||
}).then(res => {
|
||||
if (res.length > SECOND_FETCH_LIMIT) {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<div v-if="playerEnabled" class="player" :style="`padding: ${(player.height || 0) / (player.width || 1) * 100}% 0 0`">
|
||||
<button class="disablePlayer" :title="$ts.disablePlayer" @click="playerEnabled = false"><i class="fas fa-times"></i></button>
|
||||
<iframe :src="player.url + (player.url.match(/\?/) ? '&autoplay=1&auto_play=1' : '?autoplay=1&auto_play=1')" :width="player.width || '100%'" :heigth="player.height || 250" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen />
|
||||
<iframe :src="player.url + (player.url.match(/\?/) ? '&autoplay=1&auto_play=1' : '?autoplay=1&auto_play=1')" :width="player.width || '100%'" :heigth="player.height || 250" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen/>
|
||||
</div>
|
||||
<div v-else-if="tweetId && tweetExpanded" ref="twitter" class="twitter">
|
||||
<iframe ref="tweet" scrolling="no" frameborder="no" :style="{ position: 'relative', width: '100%', height: `${tweetHeight}px` }" :src="`https://platform.twitter.com/embed/index.html?embedId=${embedId}&hideCard=false&hideThread=false&lang=en&theme=${$store.state.darkMode ? 'dark' : 'light'}&id=${tweetId}`"></iframe>
|
||||
</div>
|
||||
<div v-else v-size="{ max: [400, 350] }" class="mk-url-preview">
|
||||
<transition :name="$store.state.animation ? 'zoom' : ''" mode="out-in">
|
||||
<component :is="self ? 'MkA' : 'a'" v-if="!fetching" :class="{ compact }" :[attr]="self ? url.substr(local.length) : url" rel="nofollow noopener" :target="target" :title="url">
|
||||
<component :is="self ? 'MkA' : 'a'" v-if="!fetching" class="link" :class="{ compact }" :[attr]="self ? url.substr(local.length) : url" rel="nofollow noopener" :target="target" :title="url">
|
||||
<div v-if="thumbnail" class="thumbnail" :style="`background-image: url('${thumbnail}')`">
|
||||
<button v-if="!playerEnabled && player.url" class="_button" :title="$ts.enablePlayer" @click.prevent="playerEnabled = true"><i class="fas fa-play-circle"></i></button>
|
||||
</div>
|
||||
|
@ -57,7 +57,7 @@ let sitename = $ref<string | null>(null);
|
|||
let player = $ref({
|
||||
url: null,
|
||||
width: null,
|
||||
height: null
|
||||
height: null,
|
||||
});
|
||||
let playerEnabled = $ref(false);
|
||||
let tweetId = $ref<string | null>(null);
|
||||
|
@ -143,7 +143,7 @@ onUnmounted(() => {
|
|||
|
||||
.mk-url-preview {
|
||||
&.max-width_400px {
|
||||
> a {
|
||||
> .link {
|
||||
font-size: 12px;
|
||||
|
||||
> .thumbnail {
|
||||
|
@ -157,7 +157,7 @@ onUnmounted(() => {
|
|||
}
|
||||
|
||||
&.max-width_350px {
|
||||
> a {
|
||||
> .link {
|
||||
font-size: 10px;
|
||||
|
||||
> .thumbnail {
|
||||
|
@ -205,7 +205,7 @@ onUnmounted(() => {
|
|||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
> .link {
|
||||
position: relative;
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
|
|
|
@ -113,6 +113,7 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
> .widget, .customize-container {
|
||||
contain: content;
|
||||
margin: var(--margin) 0;
|
||||
|
||||
&:first-of-type {
|
||||
|
|
|
@ -164,4 +164,11 @@ export const menuDef = reactive({
|
|||
}], ev.currentTarget ?? ev.target);
|
||||
},
|
||||
},
|
||||
reload: {
|
||||
title: 'reload',
|
||||
icon: 'fas fa-refresh',
|
||||
action: (ev) => {
|
||||
location.reload();
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -61,6 +61,7 @@ export class Router extends EventEmitter<{
|
|||
props: Map<string, string> | null;
|
||||
key: string;
|
||||
}) => void;
|
||||
same: () => void;
|
||||
}> {
|
||||
private routes: RouteDef[];
|
||||
private currentPath: string;
|
||||
|
@ -210,11 +211,15 @@ export class Router extends EventEmitter<{
|
|||
}
|
||||
|
||||
public push(path: string) {
|
||||
const beforePath = this.currentPath;
|
||||
if (path === beforePath) {
|
||||
this.emit('same');
|
||||
return;
|
||||
}
|
||||
if (this.navHook) {
|
||||
const cancel = this.navHook(path);
|
||||
if (cancel) return;
|
||||
}
|
||||
const beforePath = this.currentPath;
|
||||
this.navigate(path, null);
|
||||
this.emit('push', {
|
||||
beforePath,
|
||||
|
|
|
@ -12,19 +12,21 @@
|
|||
<XUsers origin="remote"/>
|
||||
</div>
|
||||
<div v-else-if="tab === 'search'">
|
||||
<div class="_isolated">
|
||||
<MkInput v-model="searchQuery" :debounce="true" type="search">
|
||||
<template #prefix><i class="fas fa-search"></i></template>
|
||||
<template #label>{{ $ts.searchUser }}</template>
|
||||
</MkInput>
|
||||
<MkRadios v-model="searchOrigin">
|
||||
<option value="combined">{{ $ts.all }}</option>
|
||||
<option value="local">{{ $ts.local }}</option>
|
||||
<option value="remote">{{ $ts.remote }}</option>
|
||||
</MkRadios>
|
||||
</div>
|
||||
<MkSpacer :content-max="1200">
|
||||
<div>
|
||||
<MkInput v-model="searchQuery" :debounce="true" type="search" class="_formBlock">
|
||||
<template #prefix><i class="fas fa-search"></i></template>
|
||||
<template #label>{{ $ts.searchUser }}</template>
|
||||
</MkInput>
|
||||
<MkRadios v-model="searchOrigin" class="_formBlock">
|
||||
<option value="combined">{{ $ts.all }}</option>
|
||||
<option value="local">{{ $ts.local }}</option>
|
||||
<option value="remote">{{ $ts.remote }}</option>
|
||||
</MkRadios>
|
||||
</div>
|
||||
|
||||
<XUserList v-if="searchQuery" ref="searchEl" class="_gap" :pagination="searchPagination"/>
|
||||
<XUserList v-if="searchQuery" ref="searchEl" class="_gap" :pagination="searchPagination"/>
|
||||
</MkSpacer>
|
||||
</div>
|
||||
</div>
|
||||
</MkStickyContainer>
|
||||
|
@ -42,6 +44,7 @@ import * as os from '@/os';
|
|||
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||
import { i18n } from '@/i18n';
|
||||
import { instance } from '@/instance';
|
||||
import XUserList from '@/components/user-list.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
tag?: string;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<MkStickyContainer>
|
||||
<template #header><MkPageHeader/></template>
|
||||
<div class="mwysmxbg">
|
||||
<div class="_isolated">{{ $ts._mfm.intro }}</div>
|
||||
<div>{{ $ts._mfm.intro }}</div>
|
||||
<div class="section _block">
|
||||
<div class="title">{{ $ts._mfm.mention }}</div>
|
||||
<div class="content">
|
||||
|
|
|
@ -1,41 +1,43 @@
|
|||
<template><MkStickyContainer>
|
||||
<template>
|
||||
<MkStickyContainer>
|
||||
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MkSpacer :content-max="800">
|
||||
<div class="fcuexfpr">
|
||||
<transition :name="$store.state.animation ? 'fade' : ''" mode="out-in">
|
||||
<div v-if="note" class="note">
|
||||
<div v-if="showNext" class="_gap">
|
||||
<XNotes class="_content" :pagination="nextPagination" :no-gap="true"/>
|
||||
</div>
|
||||
|
||||
<div class="main _gap">
|
||||
<MkButton v-if="!showNext && hasNext" class="load next" @click="showNext = true"><i class="fas fa-chevron-up"></i></MkButton>
|
||||
<div class="note _gap">
|
||||
<MkRemoteCaution v-if="note.user.host != null" :href="note.url ?? note.uri" class="_isolated"/>
|
||||
<XNoteDetailed :key="note.id" v-model:note="note" class="_isolated note"/>
|
||||
<MkSpacer :content-max="800">
|
||||
<div class="fcuexfpr">
|
||||
<transition :name="$store.state.animation ? 'fade' : ''" mode="out-in">
|
||||
<div v-if="note" class="note">
|
||||
<div v-if="showNext" class="_gap">
|
||||
<XNotes class="_content" :pagination="nextPagination" :no-gap="true"/>
|
||||
</div>
|
||||
<div v-if="clips && clips.length > 0" class="_content clips _gap">
|
||||
<div class="title">{{ $ts.clip }}</div>
|
||||
<MkA v-for="item in clips" :key="item.id" :to="`/clips/${item.id}`" class="item _panel _gap">
|
||||
<b>{{ item.name }}</b>
|
||||
<div v-if="item.description" class="description">{{ item.description }}</div>
|
||||
<div class="user">
|
||||
<MkAvatar :user="item.user" class="avatar" :show-indicator="true"/> <MkUserName :user="item.user" :nowrap="false"/>
|
||||
</div>
|
||||
</MkA>
|
||||
</div>
|
||||
<MkButton v-if="!showPrev && hasPrev" class="load prev" @click="showPrev = true"><i class="fas fa-chevron-down"></i></MkButton>
|
||||
</div>
|
||||
|
||||
<div v-if="showPrev" class="_gap">
|
||||
<XNotes class="_content" :pagination="prevPagination" :no-gap="true"/>
|
||||
<div class="main _gap">
|
||||
<MkButton v-if="!showNext && hasNext" class="load next" @click="showNext = true"><i class="fas fa-chevron-up"></i></MkButton>
|
||||
<div class="note _gap">
|
||||
<MkRemoteCaution v-if="note.user.host != null" :href="note.url ?? note.uri"/>
|
||||
<XNoteDetailed :key="note.id" v-model:note="note" class="note"/>
|
||||
</div>
|
||||
<div v-if="clips && clips.length > 0" class="_content clips _gap">
|
||||
<div class="title">{{ $ts.clip }}</div>
|
||||
<MkA v-for="item in clips" :key="item.id" :to="`/clips/${item.id}`" class="item _panel _gap">
|
||||
<b>{{ item.name }}</b>
|
||||
<div v-if="item.description" class="description">{{ item.description }}</div>
|
||||
<div class="user">
|
||||
<MkAvatar :user="item.user" class="avatar" :show-indicator="true"/> <MkUserName :user="item.user" :nowrap="false"/>
|
||||
</div>
|
||||
</MkA>
|
||||
</div>
|
||||
<MkButton v-if="!showPrev && hasPrev" class="load prev" @click="showPrev = true"><i class="fas fa-chevron-down"></i></MkButton>
|
||||
</div>
|
||||
|
||||
<div v-if="showPrev" class="_gap">
|
||||
<XNotes class="_content" :pagination="prevPagination" :no-gap="true"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<MkError v-else-if="error" @retry="fetch()"/>
|
||||
<MkLoading v-else/>
|
||||
</transition>
|
||||
</div>
|
||||
</MkSpacer></MkStickyContainer>
|
||||
<MkError v-else-if="error" @retry="fetch()"/>
|
||||
<MkLoading v-else/>
|
||||
</transition>
|
||||
</div>
|
||||
</MkSpacer>
|
||||
</MkStickyContainer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<MkPagination v-slot="{items}" ref="list" :pagination="type === 'following' ? followingPagination : followersPagination" class="mk-following-or-followers">
|
||||
<div class="users _isolated">
|
||||
<div class="users">
|
||||
<MkUserInfo v-for="user in items.map(x => type === 'following' ? x.followee : x.follower)" :key="user.id" class="user" :user="user"/>
|
||||
</div>
|
||||
</MkPagination>
|
||||
|
|
|
@ -258,6 +258,10 @@ mainRouter.addListener('push', ctx => {
|
|||
}
|
||||
});
|
||||
|
||||
mainRouter.addListener('same', () => {
|
||||
window.scroll({ top: 0, behavior: 'smooth' });
|
||||
});
|
||||
|
||||
window.addEventListener('popstate', (event) => {
|
||||
mainRouter.change(location.pathname + location.search + location.hash, event.state?.key);
|
||||
const scrollPos = scrollPosStore.get(event.state?.key) ?? 0;
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
<template>
|
||||
<div class="kmwsukvl">
|
||||
<div>
|
||||
<div class="body">
|
||||
<button v-click-anime class="item _button account" @click="openAccountMenu">
|
||||
<MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/>
|
||||
</button>
|
||||
<MkA v-click-anime class="item index" active-class="active" to="/" exact>
|
||||
<i class="fas fa-home fa-fw"></i><span class="text">{{ $ts.timeline }}</span>
|
||||
<i class="icon fas fa-home fa-fw"></i><span class="text">{{ $ts.timeline }}</span>
|
||||
</MkA>
|
||||
<template v-for="item in menu">
|
||||
<div v-if="item === '-'" class="divider"></div>
|
||||
<component :is="menuDef[item].to ? 'MkA' : 'button'" v-else-if="menuDef[item] && (menuDef[item].show !== false)" v-click-anime class="item _button" :class="[item, { active: menuDef[item].active }]" active-class="active" :to="menuDef[item].to" v-on="menuDef[item].action ? { click: menuDef[item].action } : {}">
|
||||
<i class="fa-fw" :class="menuDef[item].icon"></i><span class="text">{{ $ts[menuDef[item].title] }}</span>
|
||||
<span v-if="menuDef[item].indicated" class="indicator"><i class="fas fa-circle"></i></span>
|
||||
<i class="icon fa-fw" :class="menuDef[item].icon"></i><span class="text">{{ $ts[menuDef[item].title] }}</span>
|
||||
<span v-if="menuDef[item].indicated" class="indicator"><i class="icon fas fa-circle"></i></span>
|
||||
</component>
|
||||
</template>
|
||||
<div class="divider"></div>
|
||||
<MkA v-if="$i.isAdmin || $i.isModerator" v-click-anime class="item" active-class="active" to="/admin">
|
||||
<i class="fas fa-door-open fa-fw"></i><span class="text">{{ $ts.controlPanel }}</span>
|
||||
<i class="icon fas fa-door-open fa-fw"></i><span class="text">{{ $ts.controlPanel }}</span>
|
||||
</MkA>
|
||||
<button v-click-anime class="item _button" @click="more">
|
||||
<i class="fa fa-ellipsis-h fa-fw"></i><span class="text">{{ $ts.more }}</span>
|
||||
<span v-if="otherMenuItemIndicated" class="indicator"><i class="fas fa-circle"></i></span>
|
||||
<i class="icon fa fa-ellipsis-h fa-fw"></i><span class="text">{{ $ts.more }}</span>
|
||||
<span v-if="otherMenuItemIndicated" class="indicator"><i class="icon fas fa-circle"></i></span>
|
||||
</button>
|
||||
<MkA v-click-anime class="item" active-class="active" to="/settings">
|
||||
<i class="fas fa-cog fa-fw"></i><span class="text">{{ $ts.settings }}</span>
|
||||
<i class="icon fas fa-cog fa-fw"></i><span class="text">{{ $ts.settings }}</span>
|
||||
</MkA>
|
||||
<button class="item _button post" data-cy-open-post-form @click="post">
|
||||
<i class="fas fa-pencil-alt fa-fw"></i><span class="text">{{ $ts.note }}</span>
|
||||
<i class="icon fas fa-pencil-alt fa-fw"></i><span class="text">{{ $ts.note }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -81,7 +81,7 @@ export default defineComponent({
|
|||
$avatar-size: 32px;
|
||||
$avatar-margin: 8px;
|
||||
|
||||
> div {
|
||||
> .body {
|
||||
|
||||
> .divider {
|
||||
margin: 16px 16px;
|
||||
|
@ -102,12 +102,12 @@ export default defineComponent({
|
|||
box-sizing: border-box;
|
||||
color: var(--navFg);
|
||||
|
||||
> i {
|
||||
> .icon {
|
||||
position: relative;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
> i,
|
||||
> .icon,
|
||||
> .avatar {
|
||||
margin-right: $avatar-margin;
|
||||
}
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
<template>
|
||||
<div class="mvcprjjd" :class="{ iconOnly }">
|
||||
<div>
|
||||
<div class="body">
|
||||
<button v-click-anime class="item _button account" @click="openAccountMenu">
|
||||
<MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/>
|
||||
</button>
|
||||
<MkA v-click-anime class="item index" active-class="active" to="/" exact>
|
||||
<i class="fas fa-home fa-fw"></i><span class="text">{{ $ts.timeline }}</span>
|
||||
<i class="icon fas fa-home fa-fw"></i><span class="text">{{ $ts.timeline }}</span>
|
||||
</MkA>
|
||||
<template v-for="item in menu">
|
||||
<div v-if="item === '-'" class="divider"></div>
|
||||
<component :is="menuDef[item].to ? 'MkA' : 'button'" v-else-if="menuDef[item] && (menuDef[item].show !== false)" v-click-anime class="item _button" :class="[item, { active: menuDef[item].active }]" active-class="active" :to="menuDef[item].to" v-on="menuDef[item].action ? { click: menuDef[item].action } : {}">
|
||||
<i class="fa-fw" :class="menuDef[item].icon"></i><span class="text">{{ $ts[menuDef[item].title] }}</span>
|
||||
<span v-if="menuDef[item].indicated" class="indicator"><i class="fas fa-circle"></i></span>
|
||||
<i class="icon fa-fw" :class="menuDef[item].icon"></i><span class="text">{{ $ts[menuDef[item].title] }}</span>
|
||||
<span v-if="menuDef[item].indicated" class="indicator"><i class="icon fas fa-circle"></i></span>
|
||||
</component>
|
||||
</template>
|
||||
<div class="divider"></div>
|
||||
<MkA v-if="$i.isAdmin || $i.isModerator" v-click-anime class="item" active-class="active" to="/admin">
|
||||
<i class="fas fa-door-open fa-fw"></i><span class="text">{{ $ts.controlPanel }}</span>
|
||||
<i class="icon fas fa-door-open fa-fw"></i><span class="text">{{ $ts.controlPanel }}</span>
|
||||
</MkA>
|
||||
<button v-click-anime class="item _button" @click="more">
|
||||
<i class="fa fa-ellipsis-h fa-fw"></i><span class="text">{{ $ts.more }}</span>
|
||||
<span v-if="otherMenuItemIndicated" class="indicator"><i class="fas fa-circle"></i></span>
|
||||
<i class="icon fa fa-ellipsis-h fa-fw"></i><span class="text">{{ $ts.more }}</span>
|
||||
<span v-if="otherMenuItemIndicated" class="indicator"><i class="icon fas fa-circle"></i></span>
|
||||
</button>
|
||||
<MkA v-click-anime class="item" active-class="active" to="/settings">
|
||||
<i class="fas fa-cog fa-fw"></i><span class="text">{{ $ts.settings }}</span>
|
||||
<i class="icon fas fa-cog fa-fw"></i><span class="text">{{ $ts.settings }}</span>
|
||||
</MkA>
|
||||
<button class="item _button post" data-cy-open-post-form @click="os.post">
|
||||
<i class="fas fa-pencil-alt fa-fw"></i><span class="text">{{ $ts.note }}</span>
|
||||
<i class="icon fas fa-pencil-alt fa-fw"></i><span class="text">{{ $ts.note }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -88,7 +88,7 @@ function more(ev: MouseEvent) {
|
|||
width: $nav-width;
|
||||
box-sizing: border-box;
|
||||
|
||||
> div {
|
||||
> .body {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
@ -100,6 +100,7 @@ function more(ev: MouseEvent) {
|
|||
overflow: auto;
|
||||
overflow-x: clip;
|
||||
background: var(--navBg);
|
||||
contain: strict;
|
||||
|
||||
> .divider {
|
||||
margin: 16px 16px;
|
||||
|
@ -120,12 +121,12 @@ function more(ev: MouseEvent) {
|
|||
box-sizing: border-box;
|
||||
color: var(--navFg);
|
||||
|
||||
> i {
|
||||
> .icon {
|
||||
position: relative;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
> i,
|
||||
> .icon,
|
||||
> .avatar {
|
||||
margin-right: $avatar-margin;
|
||||
}
|
||||
|
@ -230,7 +231,7 @@ function more(ev: MouseEvent) {
|
|||
flex: 0 0 $nav-icon-only-width;
|
||||
width: $nav-icon-only-width;
|
||||
|
||||
> div {
|
||||
> .body {
|
||||
width: $nav-icon-only-width;
|
||||
|
||||
> .divider {
|
||||
|
@ -246,13 +247,13 @@ function more(ev: MouseEvent) {
|
|||
font-size: $ui-font-size * 1.1;
|
||||
line-height: initial;
|
||||
|
||||
> i,
|
||||
> .icon,
|
||||
> .avatar {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
> i {
|
||||
> .icon {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
|
@ -261,7 +262,7 @@ function more(ev: MouseEvent) {
|
|||
}
|
||||
|
||||
&:hover, &.active {
|
||||
> i, > .text {
|
||||
> .icon, > .text {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
@ -284,7 +285,7 @@ function more(ev: MouseEvent) {
|
|||
&.post {
|
||||
height: $nav-icon-only-width;
|
||||
|
||||
> i {
|
||||
> .icon {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue