Merge branch 'develop' into mkjs-n
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div
|
||||
class="ncvczrfv"
|
||||
:class="{ isSelected }"
|
||||
:class="[$style.root, { [$style.isSelected]: isSelected }]"
|
||||
draggable="true"
|
||||
:title="title"
|
||||
@click="onClick"
|
||||
@@ -9,25 +8,27 @@
|
||||
@dragstart="onDragstart"
|
||||
@dragend="onDragend"
|
||||
>
|
||||
<div v-if="$i?.avatarId == file.id" class="label">
|
||||
<img src="/client-assets/label.svg"/>
|
||||
<p>{{ i18n.ts.avatar }}</p>
|
||||
</div>
|
||||
<div v-if="$i?.bannerId == file.id" class="label">
|
||||
<img src="/client-assets/label.svg"/>
|
||||
<p>{{ i18n.ts.banner }}</p>
|
||||
</div>
|
||||
<div v-if="file.isSensitive" class="label red">
|
||||
<img src="/client-assets/label-red.svg"/>
|
||||
<p>{{ i18n.ts.nsfw }}</p>
|
||||
</div>
|
||||
<div style="pointer-events: none;">
|
||||
<div v-if="$i?.avatarId == file.id" :class="[$style.label]">
|
||||
<img :class="$style.labelImg" src="/client-assets/label.svg"/>
|
||||
<p :class="$style.labelText">{{ i18n.ts.avatar }}</p>
|
||||
</div>
|
||||
<div v-if="$i?.bannerId == file.id" :class="[$style.label]">
|
||||
<img :class="$style.labelImg" src="/client-assets/label.svg"/>
|
||||
<p :class="$style.labelText">{{ i18n.ts.banner }}</p>
|
||||
</div>
|
||||
<div v-if="file.isSensitive" :class="[$style.label, $style.red]">
|
||||
<img :class="$style.labelImg" src="/client-assets/label-red.svg"/>
|
||||
<p :class="$style.labelText">{{ i18n.ts.nsfw }}</p>
|
||||
</div>
|
||||
|
||||
<MkDriveFileThumbnail class="thumbnail" :file="file" fit="contain"/>
|
||||
<MkDriveFileThumbnail :class="$style.thumbnail" :file="file" fit="contain"/>
|
||||
|
||||
<p class="name">
|
||||
<span>{{ file.name.lastIndexOf('.') != -1 ? file.name.substr(0, file.name.lastIndexOf('.')) : file.name }}</span>
|
||||
<span v-if="file.name.lastIndexOf('.') != -1" class="ext">{{ file.name.substr(file.name.lastIndexOf('.')) }}</span>
|
||||
</p>
|
||||
<p :class="$style.name">
|
||||
<span>{{ file.name.lastIndexOf('.') != -1 ? file.name.substr(0, file.name.lastIndexOf('.')) : file.name }}</span>
|
||||
<span v-if="file.name.lastIndexOf('.') != -1" style="opacity: 0.5;">{{ file.name.substr(file.name.lastIndexOf('.')) }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -88,20 +89,13 @@ function onDragend() {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ncvczrfv {
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
position: relative;
|
||||
padding: 8px 0 0 0;
|
||||
min-height: 180px;
|
||||
border-radius: 8px;
|
||||
|
||||
&, * {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
> * {
|
||||
pointer-events: none;
|
||||
}
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: rgba(#000, 0.05);
|
||||
@@ -165,82 +159,78 @@ function onDragend() {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .label {
|
||||
.label {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
background: #0c7ac9;
|
||||
}
|
||||
|
||||
&:before {
|
||||
top: 0;
|
||||
left: 57px;
|
||||
width: 28px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
top: 57px;
|
||||
left: 0;
|
||||
width: 8px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
&.red {
|
||||
&:before,
|
||||
&:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
background: #0c7ac9;
|
||||
}
|
||||
|
||||
&:before {
|
||||
top: 0;
|
||||
left: 57px;
|
||||
width: 28px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
top: 57px;
|
||||
left: 0;
|
||||
width: 8px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
&.red {
|
||||
&:before,
|
||||
&:after {
|
||||
background: #c12113;
|
||||
}
|
||||
}
|
||||
|
||||
> img {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
> p {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
top: 19px;
|
||||
left: -28px;
|
||||
width: 120px;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
line-height: 28px;
|
||||
color: #fff;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
|
||||
> .thumbnail {
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
> .name {
|
||||
display: block;
|
||||
margin: 4px 0 0 0;
|
||||
font-size: 0.8em;
|
||||
text-align: center;
|
||||
word-break: break-all;
|
||||
color: var(--fg);
|
||||
overflow: hidden;
|
||||
|
||||
> .ext {
|
||||
opacity: 0.5;
|
||||
background: #c12113;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.labelImg {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.labelText {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
top: 19px;
|
||||
left: -28px;
|
||||
width: 120px;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
line-height: 28px;
|
||||
color: #fff;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.name {
|
||||
display: block;
|
||||
margin: 4px 0 0 0;
|
||||
font-size: 0.8em;
|
||||
text-align: center;
|
||||
word-break: break-all;
|
||||
color: var(--fg);
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div
|
||||
class="rghtznwe"
|
||||
:class="{ draghover }"
|
||||
:class="[$style.root, { [$style.draghover]: draghover }]"
|
||||
draggable="true"
|
||||
:title="title"
|
||||
@click="onClick"
|
||||
@@ -15,15 +14,15 @@
|
||||
@dragstart="onDragstart"
|
||||
@dragend="onDragend"
|
||||
>
|
||||
<p class="name">
|
||||
<template v-if="hover"><i class="ti ti-folder ti-fw"></i></template>
|
||||
<template v-if="!hover"><i class="ti ti-folder ti-fw"></i></template>
|
||||
<p :class="$style.name">
|
||||
<template v-if="hover"><i :class="$style.icon" class="ti ti-folder ti-fw"></i></template>
|
||||
<template v-if="!hover"><i :class="$style.icon" class="ti ti-folder ti-fw"></i></template>
|
||||
{{ folder.name }}
|
||||
</p>
|
||||
<p v-if="defaultStore.state.uploadFolder == folder.id" class="upload">
|
||||
<p v-if="defaultStore.state.uploadFolder == folder.id" :class="$style.upload">
|
||||
{{ i18n.ts.uploadFolder }}
|
||||
</p>
|
||||
<button v-if="selectMode" class="checkbox _button" :class="{ checked: isSelected }" @click.prevent.stop="checkboxClicked"></button>
|
||||
<button v-if="selectMode" class="_button" :class="[$style.checkbox, { [$style.checked]: isSelected }]" @click.prevent.stop="checkboxClicked"></button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -267,35 +266,14 @@ function onContextmenu(ev: MouseEvent) {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.rghtznwe {
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
position: relative;
|
||||
padding: 8px;
|
||||
height: 64px;
|
||||
background: var(--driveFolderBg);
|
||||
border-radius: 4px;
|
||||
|
||||
&, * {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
*:not(.checkbox) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
> .checkbox {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
right: 8px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: #fff;
|
||||
border: solid 1px #000;
|
||||
|
||||
&.checked {
|
||||
background: var(--accent);
|
||||
}
|
||||
}
|
||||
cursor: pointer;
|
||||
|
||||
&.draghover {
|
||||
&:after {
|
||||
@@ -310,24 +288,38 @@ function onContextmenu(ev: MouseEvent) {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .name {
|
||||
margin: 0;
|
||||
font-size: 0.9em;
|
||||
color: var(--desktopDriveFolderFg);
|
||||
.checkbox {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
right: 8px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: #fff;
|
||||
border: solid 1px #000;
|
||||
|
||||
> i {
|
||||
margin-right: 4px;
|
||||
margin-left: 2px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
> .upload {
|
||||
margin: 4px 4px;
|
||||
font-size: 0.8em;
|
||||
text-align: right;
|
||||
color: var(--desktopDriveFolderFg);
|
||||
&.checked {
|
||||
background: var(--accent);
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
margin: 0;
|
||||
font-size: 0.9em;
|
||||
color: var(--desktopDriveFolderFg);
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: 4px;
|
||||
margin-left: 2px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.upload {
|
||||
margin: 4px 4px;
|
||||
font-size: 0.8em;
|
||||
text-align: right;
|
||||
color: var(--desktopDriveFolderFg);
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="yfudmmck">
|
||||
<nav>
|
||||
<div class="path" @contextmenu.prevent.stop="() => {}">
|
||||
<div :class="$style.root">
|
||||
<nav :class="$style.nav">
|
||||
<div :class="$style.navPath" @contextmenu.prevent.stop="() => {}">
|
||||
<XNavFolder
|
||||
:class="{ current: folder == null }"
|
||||
:class="[$style.navPathItem, { [$style.navCurrent]: folder == null }]"
|
||||
:parentFolder="folder"
|
||||
@move="move"
|
||||
@upload="upload"
|
||||
@@ -11,37 +11,38 @@
|
||||
@removeFolder="removeFolder"
|
||||
/>
|
||||
<template v-for="f in hierarchyFolders">
|
||||
<span class="separator"><i class="ti ti-chevron-right"></i></span>
|
||||
<span :class="[$style.navPathItem, $style.navSeparator]"><i class="ti ti-chevron-right"></i></span>
|
||||
<XNavFolder
|
||||
:folder="f"
|
||||
:parentFolder="folder"
|
||||
:class="[$style.navPathItem]"
|
||||
@move="move"
|
||||
@upload="upload"
|
||||
@removeFile="removeFile"
|
||||
@removeFolder="removeFolder"
|
||||
/>
|
||||
</template>
|
||||
<span v-if="folder != null" class="separator"><i class="ti ti-chevron-right"></i></span>
|
||||
<span v-if="folder != null" class="folder current">{{ folder.name }}</span>
|
||||
<span v-if="folder != null" :class="[$style.navPathItem, $style.navSeparator]"><i class="ti ti-chevron-right"></i></span>
|
||||
<span v-if="folder != null" :class="[$style.navPathItem, $style.navCurrent]">{{ folder.name }}</span>
|
||||
</div>
|
||||
<button class="menu _button" @click="showMenu"><i class="ti ti-dots"></i></button>
|
||||
<button class="_button" :class="$style.navMenu" @click="showMenu"><i class="ti ti-dots"></i></button>
|
||||
</nav>
|
||||
<div
|
||||
ref="main" class="main"
|
||||
:class="{ uploading: uploadings.length > 0, fetching }"
|
||||
ref="main"
|
||||
:class="[$style.main, { [$style.uploading]: uploadings.length > 0, [$style.fetching]: fetching }]"
|
||||
@dragover.prevent.stop="onDragover"
|
||||
@dragenter="onDragenter"
|
||||
@dragleave="onDragleave"
|
||||
@drop.prevent.stop="onDrop"
|
||||
@contextmenu.stop="onContextmenu"
|
||||
>
|
||||
<div ref="contents" class="contents">
|
||||
<div v-show="folders.length > 0" ref="foldersContainer" class="folders">
|
||||
<div ref="contents">
|
||||
<div v-show="folders.length > 0" ref="foldersContainer" :class="$style.folders">
|
||||
<XFolder
|
||||
v-for="(f, i) in folders"
|
||||
:key="f.id"
|
||||
v-anim="i"
|
||||
class="folder"
|
||||
:class="$style.folder"
|
||||
:folder="f"
|
||||
:selectMode="select === 'folder'"
|
||||
:isSelected="selectedFolders.some(x => x.id === f.id)"
|
||||
@@ -54,15 +55,15 @@
|
||||
@dragend="isDragSource = false"
|
||||
/>
|
||||
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid -->
|
||||
<div v-for="(n, i) in 16" :key="i" class="padding"></div>
|
||||
<div v-for="(n, i) in 16" :key="i" :class="$style.padding"></div>
|
||||
<MkButton v-if="moreFolders" ref="moreFolders">{{ i18n.ts.loadMore }}</MkButton>
|
||||
</div>
|
||||
<div v-show="files.length > 0" ref="filesContainer" class="files">
|
||||
<div v-show="files.length > 0" ref="filesContainer" :class="$style.files">
|
||||
<XFile
|
||||
v-for="(file, i) in files"
|
||||
:key="file.id"
|
||||
v-anim="i"
|
||||
class="file"
|
||||
:class="$style.file"
|
||||
:file="file"
|
||||
:selectMode="select === 'file'"
|
||||
:isSelected="selectedFiles.some(x => x.id === file.id)"
|
||||
@@ -71,19 +72,19 @@
|
||||
@dragend="isDragSource = false"
|
||||
/>
|
||||
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid -->
|
||||
<div v-for="(n, i) in 16" :key="i" class="padding"></div>
|
||||
<div v-for="(n, i) in 16" :key="i" :class="$style.padding"></div>
|
||||
<MkButton v-show="moreFiles" ref="loadMoreFiles" @click="fetchMoreFiles">{{ i18n.ts.loadMore }}</MkButton>
|
||||
</div>
|
||||
<div v-if="files.length == 0 && folders.length == 0 && !fetching" class="empty">
|
||||
<p v-if="draghover">{{ i18n.t('empty-draghover') }}</p>
|
||||
<p v-if="!draghover && folder == null"><strong>{{ i18n.ts.emptyDrive }}</strong><br/>{{ i18n.t('empty-drive-description') }}</p>
|
||||
<p v-if="!draghover && folder != null">{{ i18n.ts.emptyFolder }}</p>
|
||||
<div v-if="files.length == 0 && folders.length == 0 && !fetching" :class="$style.empty">
|
||||
<div v-if="draghover">{{ i18n.t('empty-draghover') }}</div>
|
||||
<div v-if="!draghover && folder == null"><strong>{{ i18n.ts.emptyDrive }}</strong><br/>{{ i18n.t('empty-drive-description') }}</div>
|
||||
<div v-if="!draghover && folder != null">{{ i18n.ts.emptyFolder }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<MkLoading v-if="fetching"/>
|
||||
</div>
|
||||
<div v-if="draghover" class="dropzone"></div>
|
||||
<input ref="fileInput" type="file" accept="*/*" multiple tabindex="-1" @change="onChangeFileInput"/>
|
||||
<div v-if="draghover" :class="$style.dropzone"></div>
|
||||
<input ref="fileInput" style="display: none;" type="file" accept="*/*" multiple tabindex="-1" @change="onChangeFileInput"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -658,147 +659,116 @@ onBeforeUnmount(() => {
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.yfudmmck {
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
> nav {
|
||||
display: flex;
|
||||
z-index: 2;
|
||||
width: 100%;
|
||||
padding: 0 8px;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
font-size: 0.9em;
|
||||
box-shadow: 0 1px 0 var(--divider);
|
||||
.nav {
|
||||
display: flex;
|
||||
z-index: 2;
|
||||
width: 100%;
|
||||
padding: 0 8px;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
font-size: 0.9em;
|
||||
box-shadow: 0 1px 0 var(--divider);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
&, * {
|
||||
user-select: none;
|
||||
}
|
||||
.navPath {
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
line-height: 42px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
> .path {
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
line-height: 42px;
|
||||
white-space: nowrap;
|
||||
.navPathItem {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0 8px;
|
||||
line-height: 42px;
|
||||
cursor: pointer;
|
||||
|
||||
> * {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0 8px;
|
||||
line-height: 42px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
* {
|
||||
pointer-events: none;
|
||||
}
|
||||
&.navCurrent {
|
||||
font-weight: bold;
|
||||
cursor: default;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&.current {
|
||||
font-weight: bold;
|
||||
cursor: default;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.separator {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0.5;
|
||||
cursor: default;
|
||||
|
||||
> i {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .menu {
|
||||
margin-left: auto;
|
||||
padding: 0 12px;
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
> .main {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
padding: var(--margin);
|
||||
|
||||
&, * {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
&.fetching {
|
||||
cursor: wait !important;
|
||||
|
||||
* {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
> .contents {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
&.uploading {
|
||||
height: calc(100% - 38px - 100px);
|
||||
}
|
||||
|
||||
> .contents {
|
||||
|
||||
> .folders,
|
||||
> .files {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
> .folder,
|
||||
> .file {
|
||||
flex-grow: 1;
|
||||
width: 128px;
|
||||
margin: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
> .padding {
|
||||
flex-grow: 1;
|
||||
pointer-events: none;
|
||||
width: 128px + 8px;
|
||||
}
|
||||
}
|
||||
|
||||
> .empty {
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
|
||||
> p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.navSeparator {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0.5;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
> .dropzone {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 38px;
|
||||
width: 100%;
|
||||
height: calc(100% - 38px);
|
||||
border: dashed 2px var(--focus);
|
||||
.navMenu {
|
||||
margin-left: auto;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.main {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
padding: var(--margin);
|
||||
user-select: none;
|
||||
|
||||
&.fetching {
|
||||
cursor: wait !important;
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
> input {
|
||||
display: none;
|
||||
&.uploading {
|
||||
height: calc(100% - 38px - 100px);
|
||||
}
|
||||
}
|
||||
|
||||
.folders,
|
||||
.files {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.folder,
|
||||
.file {
|
||||
flex-grow: 1;
|
||||
width: 128px;
|
||||
margin: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.padding {
|
||||
flex-grow: 1;
|
||||
pointer-events: none;
|
||||
width: 128px + 8px;
|
||||
}
|
||||
|
||||
.empty {
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.dropzone {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 38px;
|
||||
width: 100%;
|
||||
height: calc(100% - 38px);
|
||||
border: dashed 2px var(--focus);
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<MkModal ref="modal" :prefer-type="'dialog'" @click="onBgClick" @closed="$emit('closed')">
|
||||
<MkModal ref="modal" :preferType="'dialog'" @click="onBgClick" @closed="$emit('closed')">
|
||||
<div ref="rootEl" :class="$style.root" :style="{ width: `${width}px`, height: `min(${height}px, 100%)` }" @keydown="onKeydown">
|
||||
<div ref="headerEl" :class="$style.header">
|
||||
<button v-if="withOkButton" :class="$style.headerButton" class="_button" @click="$emit('close')"><i class="ti ti-x"></i></button>
|
||||
|
@@ -4,25 +4,25 @@
|
||||
v-show="!isDeleted"
|
||||
ref="el"
|
||||
v-hotkey="keymap"
|
||||
class="lxwezrsl"
|
||||
:tabindex="!isDeleted ? '-1' : null"
|
||||
:class="{ renote: isRenote }"
|
||||
:class="[$style.root, { [$style.renote]: isRenote }]"
|
||||
>
|
||||
<MkNoteSub v-for="note in conversation" :key="note.id" class="reply-to-more" :note="note"/>
|
||||
<MkNoteSub v-if="appearNote.reply" :note="appearNote.reply" class="reply-to"/>
|
||||
<div v-if="isRenote" class="renote">
|
||||
<MkAvatar class="avatar" :user="note.user" link preview/>
|
||||
<i class="ti ti-repeat"></i>
|
||||
<I18n :src="i18n.ts.renotedBy" tag="span">
|
||||
<template #user>
|
||||
<MkA v-user-preview="note.userId" class="name" :to="userPage(note.user)">
|
||||
<MkUserName :user="note.user"/>
|
||||
</MkA>
|
||||
</template>
|
||||
</I18n>
|
||||
<div class="info">
|
||||
<button ref="renoteTime" class="_button time" @click="showRenoteMenu()">
|
||||
<i v-if="isMyRenote" class="ti ti-dots dropdownIcon"></i>
|
||||
<MkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note"/>
|
||||
<MkNoteSub v-if="appearNote.reply" :note="appearNote.reply" :class="$style.replyTo"/>
|
||||
<div v-if="isRenote" :class="$style.renote">
|
||||
<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
|
||||
<i class="ti ti-repeat" style="margin-right: 4px;"></i>
|
||||
<span :class="$style.renoteText">
|
||||
<I18n :src="i18n.ts.renotedBy" tag="span">
|
||||
<template #user>
|
||||
<MkA v-user-preview="note.userId" :class="$style.renoteName" :to="userPage(note.user)">
|
||||
<MkUserName :user="note.user"/>
|
||||
</MkA>
|
||||
</template>
|
||||
</I18n>
|
||||
</span>
|
||||
<div :class="$style.renoteInfo">
|
||||
<button ref="renoteTime" class="_button" :class="$style.renoteTime" @click="showRenoteMenu()">
|
||||
<i v-if="isMyRenote" class="ti ti-dots" style="margin-right: 4px;"></i>
|
||||
<MkTime :time="note.createdAt"/>
|
||||
</button>
|
||||
<span v-if="note.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[note.visibility]">
|
||||
@@ -33,16 +33,16 @@
|
||||
<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
<article class="article" @contextmenu.stop="onContextmenu">
|
||||
<header class="header">
|
||||
<MkAvatar class="avatar" :user="appearNote.user" indicator link preview/>
|
||||
<div class="body">
|
||||
<div class="top">
|
||||
<MkA v-user-preview="appearNote.user.id" class="name" :to="userPage(appearNote.user)">
|
||||
<article :class="$style.note" @contextmenu.stop="onContextmenu">
|
||||
<header :class="$style.noteHeader">
|
||||
<MkAvatar :class="$style.noteHeaderAvatar" :user="appearNote.user" indicator link preview/>
|
||||
<div :class="$style.noteHeaderBody">
|
||||
<div>
|
||||
<MkA v-user-preview="appearNote.user.id" :class="$style.noteHeaderName" :to="userPage(appearNote.user)">
|
||||
<MkUserName :nowrap="false" :user="appearNote.user"/>
|
||||
</MkA>
|
||||
<span v-if="appearNote.user.isBot" class="is-bot">bot</span>
|
||||
<div class="info">
|
||||
<span v-if="appearNote.user.isBot" :class="$style.isBot">bot</span>
|
||||
<div :class="$style.noteHeaderInfo">
|
||||
<span v-if="appearNote.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[appearNote.visibility]">
|
||||
<i v-if="appearNote.visibility === 'home'" class="ti ti-home"></i>
|
||||
<i v-else-if="appearNote.visibility === 'followers'" class="ti ti-lock"></i>
|
||||
@@ -51,84 +51,81 @@
|
||||
<span v-if="appearNote.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="username"><MkAcct :user="appearNote.user"/></div>
|
||||
<MkInstanceTicker v-if="showTicker" class="ticker" :instance="appearNote.user.instance"/>
|
||||
<div :class="$style.noteHeaderUsername"><MkAcct :user="appearNote.user"/></div>
|
||||
<MkInstanceTicker v-if="showTicker" :class="$style.ticker" :instance="appearNote.user.instance"/>
|
||||
</div>
|
||||
</header>
|
||||
<div class="main">
|
||||
<div class="body">
|
||||
<p v-if="appearNote.cw != null" class="cw">
|
||||
<Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$i"/>
|
||||
<MkCwButton v-model="showContent" :note="appearNote"/>
|
||||
</p>
|
||||
<div v-show="appearNote.cw == null || showContent" class="content">
|
||||
<div class="text">
|
||||
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
|
||||
<MkA v-if="appearNote.replyId" class="reply" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
|
||||
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :emojiUrls="appearNote.emojis"/>
|
||||
<a v-if="appearNote.renote != null" class="rp">RN:</a>
|
||||
<div v-if="translating || translation" class="translation">
|
||||
<MkLoading v-if="translating" mini/>
|
||||
<div v-else class="translated">
|
||||
<b>{{ i18n.t('translatedFrom', { x: translation.sourceLang }) }}: </b>
|
||||
<Mfm :text="translation.text" :author="appearNote.user" :i="$i" :emojiUrls="appearNote.emojis"/>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="$style.noteContent">
|
||||
<p v-if="appearNote.cw != null" :class="$style.cw">
|
||||
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :i="$i"/>
|
||||
<MkCwButton v-model="showContent" :note="appearNote"/>
|
||||
</p>
|
||||
<div v-show="appearNote.cw == null || showContent">
|
||||
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
|
||||
<MkA v-if="appearNote.replyId" :class="$style.noteReplyTarget" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
|
||||
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :emojiUrls="appearNote.emojis"/>
|
||||
<a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
|
||||
<div v-if="translating || translation" :class="$style.translation">
|
||||
<MkLoading v-if="translating" mini/>
|
||||
<div v-else>
|
||||
<b>{{ i18n.t('translatedFrom', { x: translation.sourceLang }) }}: </b>
|
||||
<Mfm :text="translation.text" :author="appearNote.user" :i="$i" :emojiUrls="appearNote.emojis"/>
|
||||
</div>
|
||||
<div v-if="appearNote.files.length > 0" class="files">
|
||||
<MkMediaList :mediaList="appearNote.files"/>
|
||||
</div>
|
||||
<MkPoll v-if="appearNote.poll" ref="pollViewer" :note="appearNote" class="poll"/>
|
||||
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="true" class="url-preview"/>
|
||||
<div v-if="appearNote.renote" class="renote"><MkNoteSimple :note="appearNote.renote" class="note"/></div>
|
||||
</div>
|
||||
<MkA v-if="appearNote.channel && !inChannel" class="channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA>
|
||||
<div v-if="appearNote.files.length > 0" :class="$style.files">
|
||||
<MkMediaList :mediaList="appearNote.files"/>
|
||||
</div>
|
||||
<MkPoll v-if="appearNote.poll" ref="pollViewer" :note="appearNote" :class="$style.poll"/>
|
||||
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="true" style="margin-top: 6px;"/>
|
||||
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/></div>
|
||||
</div>
|
||||
<footer class="footer">
|
||||
<div class="info">
|
||||
<MkA class="created-at" :to="notePage(appearNote)">
|
||||
<MkTime :time="appearNote.createdAt" mode="detail"/>
|
||||
</MkA>
|
||||
</div>
|
||||
<MkReactionsViewer ref="reactionsViewer" :note="appearNote"/>
|
||||
<button class="button _button" @click="reply()">
|
||||
<i class="ti ti-arrow-back-up"></i>
|
||||
<p v-if="appearNote.repliesCount > 0" class="count">{{ appearNote.repliesCount }}</p>
|
||||
</button>
|
||||
<button
|
||||
v-if="canRenote"
|
||||
ref="renoteButton"
|
||||
class="button _button"
|
||||
@mousedown="renote()"
|
||||
>
|
||||
<i class="ti ti-repeat"></i>
|
||||
<p v-if="appearNote.renoteCount > 0" class="count">{{ appearNote.renoteCount }}</p>
|
||||
</button>
|
||||
<button v-else class="button _button" disabled>
|
||||
<i class="ti ti-ban"></i>
|
||||
</button>
|
||||
<button v-if="appearNote.myReaction == null" ref="reactButton" class="button _button" @mousedown="react()">
|
||||
<i v-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
|
||||
<i v-else class="ti ti-plus"></i>
|
||||
</button>
|
||||
<button v-if="appearNote.myReaction != null" ref="reactButton" class="button _button reacted" @click="undoReact(appearNote)">
|
||||
<i class="ti ti-minus"></i>
|
||||
</button>
|
||||
<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" class="button _button" @mousedown="clip()">
|
||||
<i class="ti ti-paperclip"></i>
|
||||
</button>
|
||||
<button ref="menuButton" class="button _button" @mousedown="menu()">
|
||||
<i class="ti ti-dots"></i>
|
||||
</button>
|
||||
</footer>
|
||||
<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA>
|
||||
</div>
|
||||
<footer>
|
||||
<div :class="$style.noteFooterInfo">
|
||||
<MkA :to="notePage(appearNote)">
|
||||
<MkTime :time="appearNote.createdAt" mode="detail"/>
|
||||
</MkA>
|
||||
</div>
|
||||
<MkReactionsViewer ref="reactionsViewer" :note="appearNote"/>
|
||||
<button class="_button" :class="$style.noteFooterButton" @click="reply()">
|
||||
<i class="ti ti-arrow-back-up"></i>
|
||||
<p v-if="appearNote.repliesCount > 0" :class="$style.noteFooterButtonCount">{{ appearNote.repliesCount }}</p>
|
||||
</button>
|
||||
<button
|
||||
v-if="canRenote"
|
||||
ref="renoteButton"
|
||||
class="_button"
|
||||
:class="$style.noteFooterButton"
|
||||
@mousedown="renote()"
|
||||
>
|
||||
<i class="ti ti-repeat"></i>
|
||||
<p v-if="appearNote.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ appearNote.renoteCount }}</p>
|
||||
</button>
|
||||
<button v-else class="_button" :class="$style.noteFooterButton" disabled>
|
||||
<i class="ti ti-ban"></i>
|
||||
</button>
|
||||
<button v-if="appearNote.myReaction == null" ref="reactButton" :class="$style.noteFooterButton" class="_button" @mousedown="react()">
|
||||
<i v-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
|
||||
<i v-else class="ti ti-plus"></i>
|
||||
</button>
|
||||
<button v-if="appearNote.myReaction != null" ref="reactButton" class="_button" :class="[$style.noteFooterButton, $style.reacted]" @click="undoReact(appearNote)">
|
||||
<i class="ti ti-minus"></i>
|
||||
</button>
|
||||
<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" class="_button" :class="$style.noteFooterButton" @mousedown="clip()">
|
||||
<i class="ti ti-paperclip"></i>
|
||||
</button>
|
||||
<button ref="menuButton" class="_button" :class="$style.noteFooterButton" @mousedown="menu()">
|
||||
<i class="ti ti-dots"></i>
|
||||
</button>
|
||||
</footer>
|
||||
</article>
|
||||
<MkNoteSub v-for="note in replies" :key="note.id" :note="note" class="reply" :detail="true"/>
|
||||
<MkNoteSub v-for="note in replies" :key="note.id" :note="note" :class="$style.reply" :detail="true"/>
|
||||
</div>
|
||||
<div v-else class="_panel muted" @click="muted = false">
|
||||
<div v-else class="_panel" :class="$style.muted" @click="muted = false">
|
||||
<I18n :src="i18n.ts.userSaysSomething" tag="small">
|
||||
<template #name>
|
||||
<MkA v-user-preview="appearNote.userId" class="name" :to="userPage(appearNote.user)">
|
||||
<MkA v-user-preview="appearNote.userId" :to="userPage(appearNote.user)">
|
||||
<MkUserName :user="appearNote.user"/>
|
||||
</MkA>
|
||||
</template>
|
||||
@@ -438,318 +435,249 @@ if (appearNote.replyId) {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.lxwezrsl {
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
position: relative;
|
||||
transition: box-shadow 0.1s ease;
|
||||
overflow: clip;
|
||||
contain: content;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
.replyTo {
|
||||
opacity: 0.7;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
pointer-events: none;
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
width: calc(100% - 8px);
|
||||
height: calc(100% - 8px);
|
||||
border: dashed 1px var(--focus);
|
||||
border-radius: var(--radius);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
.replyToMore {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
&:hover > .article > .main > .footer > .button {
|
||||
.renote {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px 32px 8px 32px;
|
||||
line-height: 28px;
|
||||
white-space: pre;
|
||||
color: var(--renote);
|
||||
}
|
||||
|
||||
.renoteAvatar {
|
||||
flex-shrink: 0;
|
||||
display: inline-block;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
margin: 0 8px 0 0;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.renoteText {
|
||||
overflow: hidden;
|
||||
flex-shrink: 1;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.renoteName {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.renoteInfo {
|
||||
margin-left: auto;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.renoteTime {
|
||||
flex-shrink: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.renote + .note {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.note {
|
||||
padding: 32px;
|
||||
font-size: 1.2em;
|
||||
|
||||
&:hover > .main > .footer > .button {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
> .reply-to {
|
||||
opacity: 0.7;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
> .reply-to-more {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
> .renote {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px 32px 8px 32px;
|
||||
line-height: 28px;
|
||||
white-space: pre;
|
||||
color: var(--renote);
|
||||
|
||||
> .avatar {
|
||||
flex-shrink: 0;
|
||||
display: inline-block;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
margin: 0 8px 0 0;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
> i {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
> span {
|
||||
overflow: hidden;
|
||||
flex-shrink: 1;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
> .name {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
> .info {
|
||||
margin-left: auto;
|
||||
font-size: 0.9em;
|
||||
|
||||
> .time {
|
||||
flex-shrink: 0;
|
||||
color: inherit;
|
||||
|
||||
> .dropdownIcon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .renote + .article {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
> .article {
|
||||
padding: 32px;
|
||||
font-size: 1.2em;
|
||||
|
||||
> .header {
|
||||
display: flex;
|
||||
position: relative;
|
||||
margin-bottom: 16px;
|
||||
align-items: center;
|
||||
|
||||
> .avatar {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
}
|
||||
|
||||
> .body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding-left: 16px;
|
||||
font-size: 0.95em;
|
||||
|
||||
> .top {
|
||||
> .name {
|
||||
font-weight: bold;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
> .is-bot {
|
||||
display: inline-block;
|
||||
margin: 0 0.5em;
|
||||
padding: 4px 6px;
|
||||
font-size: 80%;
|
||||
line-height: 1;
|
||||
border: solid 0.5px var(--divider);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
> .info {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
> .username {
|
||||
margin-bottom: 2px;
|
||||
line-height: 1.3;
|
||||
word-wrap: anywhere;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .main {
|
||||
> .body {
|
||||
container-type: inline-size;
|
||||
|
||||
> .cw {
|
||||
cursor: default;
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow-wrap: break-word;
|
||||
|
||||
> .text {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
> .content {
|
||||
> .text {
|
||||
overflow-wrap: break-word;
|
||||
|
||||
> .reply {
|
||||
color: var(--accent);
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
> .rp {
|
||||
margin-left: 4px;
|
||||
font-style: oblique;
|
||||
color: var(--renote);
|
||||
}
|
||||
|
||||
> .translation {
|
||||
border: solid 0.5px var(--divider);
|
||||
border-radius: var(--radius);
|
||||
padding: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
> .url-preview {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
> .poll {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
> .renote {
|
||||
padding: 8px 0;
|
||||
|
||||
> .note {
|
||||
padding: 16px;
|
||||
border: dashed 1px var(--renote);
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .channel {
|
||||
opacity: 0.7;
|
||||
font-size: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
> .footer {
|
||||
> .info {
|
||||
margin: 16px 0;
|
||||
opacity: 0.7;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
> .button {
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
opacity: 0.7;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: 28px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--fgHighlighted);
|
||||
}
|
||||
|
||||
> .count {
|
||||
display: inline;
|
||||
margin: 0 0 0 8px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
&.reacted {
|
||||
color: var(--accent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .reply {
|
||||
border-top: solid 0.5px var(--divider);
|
||||
}
|
||||
}
|
||||
|
||||
.noteHeader {
|
||||
display: flex;
|
||||
position: relative;
|
||||
margin-bottom: 16px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.noteHeaderAvatar {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
}
|
||||
|
||||
.noteHeaderBody {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding-left: 16px;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
.noteHeaderName {
|
||||
font-weight: bold;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.isBot {
|
||||
display: inline-block;
|
||||
margin: 0 0.5em;
|
||||
padding: 4px 6px;
|
||||
font-size: 80%;
|
||||
line-height: 1;
|
||||
border: solid 0.5px var(--divider);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.noteHeaderInfo {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.noteHeaderUsername {
|
||||
margin-bottom: 2px;
|
||||
line-height: 1.3;
|
||||
word-wrap: anywhere;
|
||||
}
|
||||
|
||||
.noteContent {
|
||||
container-type: inline-size;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.cw {
|
||||
cursor: default;
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.noteReplyTarget {
|
||||
color: var(--accent);
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.rn {
|
||||
margin-left: 4px;
|
||||
font-style: oblique;
|
||||
color: var(--renote);
|
||||
}
|
||||
|
||||
.translation {
|
||||
border: solid 0.5px var(--divider);
|
||||
border-radius: var(--radius);
|
||||
padding: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.poll {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.quote {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.quoteNote {
|
||||
padding: 16px;
|
||||
border: dashed 1px var(--renote);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.channel {
|
||||
opacity: 0.7;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.noteFooterInfo {
|
||||
margin: 16px 0;
|
||||
opacity: 0.7;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.noteFooterButton {
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
opacity: 0.7;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: 28px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--fgHighlighted);
|
||||
}
|
||||
}
|
||||
|
||||
.noteFooterButtonCount {
|
||||
display: inline;
|
||||
margin: 0 0 0 8px;
|
||||
opacity: 0.7;
|
||||
|
||||
&.reacted {
|
||||
color: var(--accent);
|
||||
}
|
||||
}
|
||||
|
||||
.reply {
|
||||
border-top: solid 0.5px var(--divider);
|
||||
}
|
||||
|
||||
@container (max-width: 500px) {
|
||||
.lxwezrsl {
|
||||
.root {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
|
||||
@container (max-width: 450px) {
|
||||
.lxwezrsl {
|
||||
> .renote {
|
||||
padding: 8px 16px 0 16px;
|
||||
}
|
||||
.renote {
|
||||
padding: 8px 16px 0 16px;
|
||||
}
|
||||
|
||||
> .article {
|
||||
padding: 16px;
|
||||
.note {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
> .header {
|
||||
> .avatar {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.noteHeaderAvatar {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
@container (max-width: 350px) {
|
||||
.lxwezrsl {
|
||||
> .article {
|
||||
> .main {
|
||||
> .footer {
|
||||
> .button {
|
||||
&:not(:last-child) {
|
||||
margin-right: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.noteFooterButton {
|
||||
&:not(:last-child) {
|
||||
margin-right: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@container (max-width: 300px) {
|
||||
.lxwezrsl {
|
||||
.root {
|
||||
font-size: 0.825em;
|
||||
}
|
||||
|
||||
> .article {
|
||||
> .header {
|
||||
> .avatar {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
.noteHeaderAvatar {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
> .main {
|
||||
> .footer {
|
||||
> .button {
|
||||
&:not(:last-child) {
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.noteFooterButton {
|
||||
&:not(:last-child) {
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,11 +25,11 @@
|
||||
</div>
|
||||
|
||||
<div v-if="type === 'and' || type === 'or'" :class="$style.values" class="_gaps">
|
||||
<Sortable v-model="v.values" tag="div" class="_gaps" item-key="id" handle=".drag-handle" :group="{ name: 'roleFormula' }" :animation="150" :swap-threshold="0.5">
|
||||
<Sortable v-model="v.values" tag="div" class="_gaps" itemKey="id" handle=".drag-handle" :group="{ name: 'roleFormula' }" :animation="150" :swapThreshold="0.5">
|
||||
<template #item="{element}">
|
||||
<div :class="$style.item">
|
||||
<!-- divが無いとエラーになる https://github.com/SortableJS/vue.draggable.next/issues/189 -->
|
||||
<RolesEditorFormula :model-value="element" draggable @update:model-value="updated => valuesItemUpdated(updated)" @remove="removeItem(element)"/>
|
||||
<RolesEditorFormula :modelValue="element" draggable @update:modelValue="updated => valuesItemUpdated(updated)" @remove="removeItem(element)"/>
|
||||
</div>
|
||||
</template>
|
||||
</Sortable>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<MkStickyContainer>
|
||||
<template #header><XHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MkSpacer :content-max="700">
|
||||
<MkSpacer :contentMax="700">
|
||||
<div class="_gaps">
|
||||
<div class="_buttons">
|
||||
<MkButton primary rounded @click="edit"><i class="ti ti-pencil"></i> {{ i18n.ts.edit }}</MkButton>
|
||||
@@ -11,9 +11,9 @@
|
||||
<MkFolder>
|
||||
<template #icon><i class="ti ti-info-circle"></i></template>
|
||||
<template #label>{{ i18n.ts.info }}</template>
|
||||
<XEditor :model-value="role" readonly/>
|
||||
<XEditor :modelValue="role" readonly/>
|
||||
</MkFolder>
|
||||
<MkFolder v-if="role.target === 'manual'" default-open>
|
||||
<MkFolder v-if="role.target === 'manual'" defaultOpen>
|
||||
<template #icon><i class="ti ti-users"></i></template>
|
||||
<template #label>{{ i18n.ts.users }}</template>
|
||||
<template #suffix>{{ role.usersCount }}</template>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<MkStickyContainer>
|
||||
<template #header><XHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MkSpacer :content-max="700">
|
||||
<MkSpacer :contentMax="700">
|
||||
<div class="_gaps">
|
||||
<MkFolder>
|
||||
<template #label>{{ i18n.ts._role.baseRole }}</template>
|
||||
@@ -14,7 +14,7 @@
|
||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.rateLimitFactor, 'rateLimitFactor'])">
|
||||
<template #label>{{ i18n.ts._role._options.rateLimitFactor }}</template>
|
||||
<template #suffix>{{ Math.floor(policies.rateLimitFactor * 100) }}%</template>
|
||||
<MkRange :model-value="policies.rateLimitFactor * 100" :min="30" :max="300" :step="10" :text-converter="(v) => `${v}%`" @update:model-value="v => policies.rateLimitFactor = (v / 100)">
|
||||
<MkRange :modelValue="policies.rateLimitFactor * 100" :min="30" :max="300" :step="10" :textConverter="(v) => `${v}%`" @update:modelValue="v => policies.rateLimitFactor = (v / 100)">
|
||||
<template #caption>{{ i18n.ts._role._options.descriptionOfRateLimitFactor }}</template>
|
||||
</MkRange>
|
||||
</MkFolder>
|
||||
@@ -156,13 +156,13 @@
|
||||
<MkFoldableSection>
|
||||
<template #header>Manual roles</template>
|
||||
<div class="_gaps_s">
|
||||
<MkRolePreview v-for="role in roles.filter(x => x.target === 'manual')" :key="role.id" :role="role" :for-moderation="true"/>
|
||||
<MkRolePreview v-for="role in roles.filter(x => x.target === 'manual')" :key="role.id" :role="role" :forModeration="true"/>
|
||||
</div>
|
||||
</MkFoldableSection>
|
||||
<MkFoldableSection>
|
||||
<template #header>Conditional roles</template>
|
||||
<div class="_gaps_s">
|
||||
<MkRolePreview v-for="role in roles.filter(x => x.target === 'conditional')" :key="role.id" :role="role" :for-moderation="true"/>
|
||||
<MkRolePreview v-for="role in roles.filter(x => x.target === 'conditional')" :key="role.id" :role="role" :forModeration="true"/>
|
||||
</div>
|
||||
</MkFoldableSection>
|
||||
</div>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<MkStickyContainer>
|
||||
<template #header><XHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
|
||||
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
|
||||
<FormSuspense :p="init">
|
||||
<div class="_gaps_m">
|
||||
<MkFolder>
|
||||
@@ -33,7 +33,7 @@
|
||||
<option value="remote">{{ i18n.ts.remoteOnly }}</option>
|
||||
</MkRadios>
|
||||
|
||||
<MkRange v-model="sensitiveMediaDetectionSensitivity" :min="0" :max="4" :step="1" :text-converter="(v) => `${v + 1}`">
|
||||
<MkRange v-model="sensitiveMediaDetectionSensitivity" :min="0" :max="4" :step="1" :textConverter="(v) => `${v + 1}`">
|
||||
<template #label>{{ i18n.ts._sensitiveMediaDetection.sensitivity }}</template>
|
||||
<template #caption>{{ i18n.ts._sensitiveMediaDetection.sensitivityDescription }}</template>
|
||||
</MkRange>
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
<div class="_gaps_m">
|
||||
<span>{{ i18n.ts.activeEmailValidationDescription }}</span>
|
||||
<MkSwitch v-model="enableActiveEmailValidation" @update:model-value="save">
|
||||
<MkSwitch v-model="enableActiveEmailValidation" @update:modelValue="save">
|
||||
<template #label>Enable</template>
|
||||
</MkSwitch>
|
||||
</div>
|
||||
@@ -77,7 +77,7 @@
|
||||
<template v-else #suffix>Disabled</template>
|
||||
|
||||
<div class="_gaps_m">
|
||||
<MkSwitch v-model="enableIpLogging" @update:model-value="save">
|
||||
<MkSwitch v-model="enableIpLogging" @update:modelValue="save">
|
||||
<template #label>Enable</template>
|
||||
</MkSwitch>
|
||||
</div>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<MkStickyContainer>
|
||||
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MkSpacer :content-max="800" :margin-min="16" :margin-max="32">
|
||||
<MkSpacer :contentMax="800" :marginMin="16" :marginMax="32">
|
||||
<FormSuspense :p="init" class="_gaps">
|
||||
<MkInput v-model="title">
|
||||
<template #label>{{ i18n.ts.title }}</template>
|
||||
|
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<MkStickyContainer>
|
||||
<template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MkSpacer :content-max="1400">
|
||||
<MkSpacer :contentMax="1400">
|
||||
<div class="_root">
|
||||
<div v-if="tab === 'explore'">
|
||||
<MkFoldableSection class="_margin">
|
||||
<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" :disableAutoLoad="true">
|
||||
<div :class="$style.items">
|
||||
<MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/>
|
||||
</div>
|
||||
@@ -14,7 +14,7 @@
|
||||
</MkFoldableSection>
|
||||
<MkFoldableSection class="_margin">
|
||||
<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" :disableAutoLoad="true">
|
||||
<div :class="$style.items">
|
||||
<MkGalleryPostPreview v-for="post in items" :key="post.id" :post="post" class="post"/>
|
||||
</div>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<MkStickyContainer>
|
||||
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MkSpacer :content-max="1000" :margin-min="16" :margin-max="32">
|
||||
<MkSpacer :contentMax="1000" :marginMin="16" :marginMax="32">
|
||||
<div class="_root">
|
||||
<Transition :name="defaultStore.state.animation ? 'fade' : ''" mode="out-in">
|
||||
<div v-if="post" class="rkxwuolj">
|
||||
|
@@ -9,7 +9,7 @@
|
||||
</template>
|
||||
|
||||
<div style="padding: 8px;">
|
||||
<MkChart :src="chartSrc" :args="{ user, withoutAll: true }" span="day" :limit="limit" :bar="true" :stacked="true" :detailed="false" :aspect-ratio="5"/>
|
||||
<MkChart :src="chartSrc" :args="{ user, withoutAll: true }" span="day" :limit="limit" :bar="true" :stacked="true" :detailed="false" :aspectRatio="5"/>
|
||||
</div>
|
||||
</MkContainer>
|
||||
</template>
|
||||
|
@@ -5,15 +5,16 @@ const dateTimeIntervals = {
|
||||
};
|
||||
|
||||
export function dateUTC(time: number[]): Date {
|
||||
const d = time.length === 2 ? Date.UTC(time[0], time[1])
|
||||
: time.length === 3 ? Date.UTC(time[0], time[1], time[2])
|
||||
: time.length === 4 ? Date.UTC(time[0], time[1], time[2], time[3])
|
||||
: time.length === 5 ? Date.UTC(time[0], time[1], time[2], time[3], time[4])
|
||||
: time.length === 6 ? Date.UTC(time[0], time[1], time[2], time[3], time[4], time[5])
|
||||
: time.length === 7 ? Date.UTC(time[0], time[1], time[2], time[3], time[4], time[5], time[6])
|
||||
: null;
|
||||
const d =
|
||||
time.length === 2 ? Date.UTC(time[0], time[1])
|
||||
: time.length === 3 ? Date.UTC(time[0], time[1], time[2])
|
||||
: time.length === 4 ? Date.UTC(time[0], time[1], time[2], time[3])
|
||||
: time.length === 5 ? Date.UTC(time[0], time[1], time[2], time[3], time[4])
|
||||
: time.length === 6 ? Date.UTC(time[0], time[1], time[2], time[3], time[4], time[5])
|
||||
: time.length === 7 ? Date.UTC(time[0], time[1], time[2], time[3], time[4], time[5], time[6])
|
||||
: null;
|
||||
|
||||
if (!d) throw 'wrong number of arguments';
|
||||
if (!d) throw new Error('wrong number of arguments');
|
||||
|
||||
return new Date(d);
|
||||
}
|
||||
|
@@ -1,14 +1,20 @@
|
||||
<template>
|
||||
<span v-if="!fetching" class="nmidsaqw">
|
||||
<span v-if="!fetching" :class="$style.root">
|
||||
<template v-if="display === 'marquee'">
|
||||
<Transition name="change" mode="default">
|
||||
<Transition
|
||||
:enterActiveClass="$style.transition_change_enterActive"
|
||||
:leaveActiveClass="$style.transition_change_leaveActive"
|
||||
:enterFromClass="$style.transition_change_enterFrom"
|
||||
:leaveToClass="$style.transition_change_leaveTo"
|
||||
mode="default"
|
||||
>
|
||||
<MarqueeText :key="key" :duration="marqueeDuration" :reverse="marqueeReverse">
|
||||
<span v-for="instance in instances" :key="instance.id" class="item" :class="{ colored }" :style="{ background: colored ? instance.themeColor : null }">
|
||||
<img class="icon" :src="getInstanceIcon(instance)" alt=""/>
|
||||
<MkA :to="`/instance-info/${instance.host}`" class="host _monospace">
|
||||
<span v-for="instance in instances" :key="instance.id" :class="[$style.item, { [$style.colored]: colored }]" :style="{ background: colored ? instance.themeColor : null }">
|
||||
<img :class="$style.icon" :src="getInstanceIcon(instance)" alt=""/>
|
||||
<MkA :to="`/instance-info/${instance.host}`" :class="$style.host" class="_monospace">
|
||||
{{ instance.host }}
|
||||
</MkA>
|
||||
<span class="divider"></span>
|
||||
<span :class="$style.divider"></span>
|
||||
</span>
|
||||
</MarqueeText>
|
||||
</Transition>
|
||||
@@ -61,46 +67,47 @@ function getInstanceIcon(instance): string {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.change-enter-active, .change-leave-active {
|
||||
<style lang="scss" module>
|
||||
.transition_change_enterActive,
|
||||
.transition_change_leaveActive {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
transition: all 1s ease;
|
||||
}
|
||||
.change-enter-from {
|
||||
opacity: 0;
|
||||
.transition_change_enterFrom {
|
||||
opacity: 0;
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
.change-leave-to {
|
||||
opacity: 0;
|
||||
.transition_change_leaveTo {
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.nmidsaqw {
|
||||
.root {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
::v-deep(.item) {
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
margin-right: 5em;
|
||||
.item {
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
margin-right: 5em;
|
||||
|
||||
> .icon {
|
||||
display: inline-block;
|
||||
height: var(--height);
|
||||
aspect-ratio: 1;
|
||||
vertical-align: bottom;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
> .host {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
&.colored {
|
||||
padding-right: 1em;
|
||||
color: #fff;
|
||||
}
|
||||
&.colored {
|
||||
padding-right: 1em;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
display: inline-block;
|
||||
height: var(--height);
|
||||
aspect-ratio: 1;
|
||||
vertical-align: bottom;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.host {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,10 +1,16 @@
|
||||
<template>
|
||||
<span v-if="!fetching" class="xbhtxfms">
|
||||
<span v-if="!fetching" :class="$style.root">
|
||||
<template v-if="display === 'marquee'">
|
||||
<Transition name="change" mode="default">
|
||||
<Transition
|
||||
:enterActiveClass="$style.transition_change_enterActive"
|
||||
:leaveActiveClass="$style.transition_change_leaveActive"
|
||||
:enterFromClass="$style.transition_change_enterFrom"
|
||||
:leaveToClass="$style.transition_change_leaveTo"
|
||||
mode="default"
|
||||
>
|
||||
<MarqueeText :key="key" :duration="marqueeDuration" :reverse="marqueeReverse">
|
||||
<span v-for="item in items" class="item">
|
||||
<a class="link" :href="item.link" rel="nofollow noopener" target="_blank" :title="item.title">{{ item.title }}</a><span class="divider"></span>
|
||||
<span v-for="item in items" :class="$style.item">
|
||||
<a :href="item.link" rel="nofollow noopener" target="_blank" :title="item.title">{{ item.title }}</a><span :class="$style.divider"></span>
|
||||
</span>
|
||||
</MarqueeText>
|
||||
</Transition>
|
||||
@@ -54,39 +60,40 @@ useInterval(tick, Math.max(5000, props.refreshIntervalSec * 1000), {
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.change-enter-active, .change-leave-active {
|
||||
<style lang="scss" module>
|
||||
.transition_change_enterActive,
|
||||
.transition_change_leaveActive {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
transition: all 1s ease;
|
||||
}
|
||||
.change-enter-from {
|
||||
opacity: 0;
|
||||
.transition_change_enterFrom {
|
||||
opacity: 0;
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
.change-leave-to {
|
||||
opacity: 0;
|
||||
.transition_change_leaveTo {
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.xbhtxfms {
|
||||
.root {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
::v-deep(.item) {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
vertical-align: bottom;
|
||||
margin: 0;
|
||||
.item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
vertical-align: bottom;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
> .divider {
|
||||
display: inline-block;
|
||||
width: 0.5px;
|
||||
height: var(--height);
|
||||
margin: 0 3em;
|
||||
background: currentColor;
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
.divider {
|
||||
display: inline-block;
|
||||
width: 0.5px;
|
||||
height: var(--height);
|
||||
margin: 0 3em;
|
||||
background: currentColor;
|
||||
opacity: 0.3;
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,14 +1,20 @@
|
||||
<template>
|
||||
<span v-if="!fetching" class="osdsvwzy">
|
||||
<span v-if="!fetching" :class="$style.root">
|
||||
<template v-if="display === 'marquee'">
|
||||
<Transition name="change" mode="default">
|
||||
<Transition
|
||||
:enterActiveClass="$style.transition_change_enterActive"
|
||||
:leaveActiveClass="$style.transition_change_leaveActive"
|
||||
:enterFromClass="$style.transition_change_enterFrom"
|
||||
:leaveToClass="$style.transition_change_leaveTo"
|
||||
mode="default"
|
||||
>
|
||||
<MarqueeText :key="key" :duration="marqueeDuration" :reverse="marqueeReverse">
|
||||
<span v-for="note in notes" :key="note.id" class="item">
|
||||
<img class="avatar" :src="note.user.avatarUrl" decoding="async"/>
|
||||
<MkA class="text" :to="notePage(note)">
|
||||
<Mfm class="text" :text="getNoteSummary(note)" :plain="true" :nowrap="true"/>
|
||||
<span v-for="note in notes" :key="note.id" :class="$style.item">
|
||||
<img :class="$style.avatar" :src="note.user.avatarUrl" decoding="async"/>
|
||||
<MkA :class="$style.text" :to="notePage(note)">
|
||||
<Mfm :text="getNoteSummary(note)" :plain="true" :nowrap="true"/>
|
||||
</MkA>
|
||||
<span class="divider"></span>
|
||||
<span :class="$style.divider"></span>
|
||||
</span>
|
||||
</MarqueeText>
|
||||
</Transition>
|
||||
@@ -60,54 +66,53 @@ useInterval(tick, Math.max(5000, props.refreshIntervalSec * 1000), {
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.change-enter-active, .change-leave-active {
|
||||
<style lang="scss" module>
|
||||
.transition_change_enterActive,
|
||||
.transition_change_leaveActive {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
transition: all 1s ease;
|
||||
}
|
||||
.change-enter-from {
|
||||
opacity: 0;
|
||||
.transition_change_enterFrom {
|
||||
opacity: 0;
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
.change-leave-to {
|
||||
opacity: 0;
|
||||
.transition_change_leaveTo {
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.osdsvwzy {
|
||||
.root {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
::v-deep(.item) {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
vertical-align: bottom;
|
||||
margin: 0;
|
||||
.item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
vertical-align: bottom;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
> .avatar {
|
||||
display: inline-block;
|
||||
height: var(--height);
|
||||
aspect-ratio: 1;
|
||||
vertical-align: bottom;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.avatar {
|
||||
display: inline-block;
|
||||
height: var(--height);
|
||||
aspect-ratio: 1;
|
||||
vertical-align: bottom;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
> .text {
|
||||
> .text {
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
.text {
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
> .divider {
|
||||
display: inline-block;
|
||||
width: 0.5px;
|
||||
height: 16px;
|
||||
margin: 0 3em;
|
||||
background: currentColor;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.divider {
|
||||
display: inline-block;
|
||||
width: 0.5px;
|
||||
height: 16px;
|
||||
margin: 0 3em;
|
||||
background: currentColor;
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
@@ -330,11 +330,7 @@ async function deleteProfile() {
|
||||
flex-shrink: 0;
|
||||
padding-top: var(--columnGap);
|
||||
padding-bottom: var(--columnGap);
|
||||
padding-right: var(--columnGap);
|
||||
|
||||
&:first-of-type {
|
||||
padding-left: var(--columnGap);
|
||||
}
|
||||
padding-left: var(--columnGap);
|
||||
|
||||
> .column:not(:last-of-type) {
|
||||
margin-bottom: var(--columnGap);
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<i class="ti ti-antenna"></i><span style="margin-left: 8px;">{{ column.name }}</span>
|
||||
</template>
|
||||
|
||||
<MkTimeline v-if="column.antennaId" ref="timeline" src="antenna" :antenna="column.antennaId" @after="() => emit('loaded')"/>
|
||||
<MkTimeline v-if="column.antennaId" ref="timeline" src="antenna" :antenna="column.antennaId"/>
|
||||
</XColumn>
|
||||
</template>
|
||||
|
||||
@@ -21,10 +21,6 @@ const props = defineProps<{
|
||||
isStacked: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'loaded'): void;
|
||||
}>();
|
||||
|
||||
let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();
|
||||
|
||||
onMounted(() => {
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<div style="padding: 8px; text-align: center;">
|
||||
<MkButton primary gradate rounded inline @click="post"><i class="ti ti-pencil"></i></MkButton>
|
||||
</div>
|
||||
<MkTimeline ref="timeline" src="channel" :channel="column.channelId" @after="() => emit('loaded')"/>
|
||||
<MkTimeline ref="timeline" src="channel" :channel="column.channelId"/>
|
||||
</template>
|
||||
</XColumn>
|
||||
</template>
|
||||
@@ -27,10 +27,6 @@ const props = defineProps<{
|
||||
isStacked: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'loaded'): void;
|
||||
}>();
|
||||
|
||||
let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();
|
||||
let channel = $shallowRef<misskey.entities.Channel>();
|
||||
|
||||
|
@@ -296,8 +296,10 @@ function onDrop(ev) {
|
||||
}
|
||||
|
||||
> .body {
|
||||
background: transparent !important;
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: inherit;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -306,6 +308,8 @@ function onDrop(ev) {
|
||||
background: var(--bg) !important;
|
||||
|
||||
> .body {
|
||||
background: var(--bg) !important;
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: inherit;
|
||||
}
|
||||
|
@@ -17,9 +17,6 @@ defineProps<{
|
||||
isStacked: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
}>();
|
||||
|
||||
const pagination = {
|
||||
endpoint: 'notes/mentions' as const,
|
||||
limit: 10,
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<i class="ti ti-list"></i><span style="margin-left: 8px;">{{ column.name }}</span>
|
||||
</template>
|
||||
|
||||
<MkTimeline v-if="column.listId" ref="timeline" src="list" :list="column.listId" @after="() => emit('loaded')"/>
|
||||
<MkTimeline v-if="column.listId" ref="timeline" src="list" :list="column.listId"/>
|
||||
</XColumn>
|
||||
</template>
|
||||
|
||||
@@ -21,10 +21,6 @@ const props = defineProps<{
|
||||
isStacked: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'loaded'): void;
|
||||
}>();
|
||||
|
||||
let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();
|
||||
|
||||
if (props.column.listId == null) {
|
||||
|
@@ -25,9 +25,6 @@ defineProps<{
|
||||
isStacked: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
}>();
|
||||
|
||||
let pageMetadata = $ref<null | ComputedRef<PageMetadata>>();
|
||||
|
||||
provide('router', mainRouter);
|
||||
|
@@ -17,9 +17,6 @@ defineProps<{
|
||||
isStacked: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
}>();
|
||||
|
||||
const pagination = {
|
||||
endpoint: 'notes/mentions' as const,
|
||||
limit: 10,
|
||||
|
@@ -19,9 +19,6 @@ const props = defineProps<{
|
||||
isStacked: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
}>();
|
||||
|
||||
function func() {
|
||||
os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSettingWindow.vue')), {
|
||||
includingTypes: props.column.includingTypes,
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<i class="ti ti-badge"></i><span style="margin-left: 8px;">{{ column.name }}</span>
|
||||
</template>
|
||||
|
||||
<MkTimeline v-if="column.roleId" ref="timeline" src="role" :role="column.roleId" @after="() => emit('loaded')"/>
|
||||
<MkTimeline v-if="column.roleId" ref="timeline" src="role" :role="column.roleId"/>
|
||||
</XColumn>
|
||||
</template>
|
||||
|
||||
@@ -21,10 +21,6 @@ const props = defineProps<{
|
||||
isStacked: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'loaded'): void;
|
||||
}>();
|
||||
|
||||
let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();
|
||||
|
||||
onMounted(() => {
|
||||
|
@@ -15,7 +15,7 @@
|
||||
</p>
|
||||
<p :class="$style.disabledDescription">{{ i18n.ts._disabledTimeline.description }}</p>
|
||||
</div>
|
||||
<MkTimeline v-else-if="column.tl" ref="timeline" :key="column.tl" :src="column.tl" @after="() => emit('loaded')"/>
|
||||
<MkTimeline v-else-if="column.tl" ref="timeline" :key="column.tl" :src="column.tl"/>
|
||||
</XColumn>
|
||||
</template>
|
||||
|
||||
@@ -34,10 +34,6 @@ const props = defineProps<{
|
||||
isStacked: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'loaded'): void;
|
||||
}>();
|
||||
|
||||
let disabled = $ref(false);
|
||||
|
||||
const isLocalTimelineAvailable = (($i == null && instance.policies.ltlAvailable) || ($i != null && $i.policies.ltlAvailable));
|
||||
|
@@ -21,9 +21,6 @@ const props = defineProps<{
|
||||
isStacked: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
}>();
|
||||
|
||||
let edit = $ref(false);
|
||||
|
||||
function addWidget(widget) {
|
||||
|
@@ -1,9 +1,17 @@
|
||||
<template>
|
||||
<div :class="$style.root" style="container-type: inline-size;">
|
||||
<div :class="showBottom ? $style.rootWithBottom : $style.root" style="container-type: inline-size;">
|
||||
<RouterView/>
|
||||
|
||||
<XCommon/>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
デッキUIが設定されている場合はデッキUIに戻れるようにする (ただし?zenが明示された場合は表示しない)
|
||||
See https://github.com/misskey-dev/misskey/issues/10905
|
||||
-->
|
||||
<div v-if="showBottom" :class="$style.bottom">
|
||||
<button v-tooltip="i18n.ts.goToMisskey" :class="['_button', '_shadow', $style.button]" @click="goToMisskey"><i class="ti ti-home"></i></button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@@ -11,10 +19,13 @@ import { provide, ComputedRef } from 'vue';
|
||||
import XCommon from './_common_/common.vue';
|
||||
import { mainRouter } from '@/router';
|
||||
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata';
|
||||
import { instanceName } from '@/config';
|
||||
import { instanceName, ui } from '@/config';
|
||||
import { i18n } from '@/i18n';
|
||||
|
||||
let pageMetadata = $ref<null | ComputedRef<PageMetadata>>();
|
||||
|
||||
const showBottom = !(new URLSearchParams(location.search)).has('zen') && ui === 'deck';
|
||||
|
||||
provide('router', mainRouter);
|
||||
provideMetadataReceiver((info) => {
|
||||
pageMetadata = info;
|
||||
@@ -23,6 +34,10 @@ provideMetadataReceiver((info) => {
|
||||
}
|
||||
});
|
||||
|
||||
function goToMisskey() {
|
||||
window.location.href = '/';
|
||||
}
|
||||
|
||||
document.documentElement.style.overflowY = 'scroll';
|
||||
</script>
|
||||
|
||||
@@ -31,4 +46,29 @@ document.documentElement.style.overflowY = 'scroll';
|
||||
min-height: 100dvh;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.rootWithBottom {
|
||||
min-height: calc(100dvh - (60px + (var(--margin) * 2) + env(safe-area-inset-bottom, 0px)));
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
height: calc(60px + (var(--margin) * 2) + env(safe-area-inset-bottom, 0px));
|
||||
width: 100%;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.button {
|
||||
position: fixed !important;
|
||||
padding: 0;
|
||||
aspect-ratio: 1;
|
||||
width: 100%;
|
||||
max-width: 60px;
|
||||
margin: auto;
|
||||
border-radius: 100%;
|
||||
background: var(--panel);
|
||||
color: var(--fg);
|
||||
right: var(--margin);
|
||||
bottom: calc(var(--margin) + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<MkContainer :show-header="widgetProps.showHeader" :naked="widgetProps.transparent">
|
||||
<MkContainer :showHeader="widgetProps.showHeader" :naked="widgetProps.transparent">
|
||||
<template #icon><i class="ti ti-server"></i></template>
|
||||
<template #header>{{ i18n.ts._widgets.serverMetric }}</template>
|
||||
<template #func="{ buttonStyleClass }"><button class="_button" :class="buttonStyleClass" @click="toggleView()"><i class="ti ti-selector"></i></button></template>
|
||||
|
Reference in New Issue
Block a user