Compare commits

..

10 Commits

Author SHA1 Message Date
syuilo
af6a578fa6 13.0.0-rc.2 2023-01-14 13:49:13 +09:00
tamaina
73d735a1f7 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-01-14 04:48:17 +00:00
tamaina
b8b1899a9f chore: fix ref name (pages/timeline.vue) 2023-01-14 04:47:59 +00:00
syuilo
d52f0617a1 fix(server): ドライブ容量超過時のエラーが適切にレスポンスされない問題を修正
Fix #9550
2023-01-14 13:41:53 +09:00
syuilo
c730973294 多分 fix #9551 2023-01-14 13:36:18 +09:00
syuilo
2c2e064871 refactor(client): use css modules 2023-01-14 13:29:41 +09:00
syuilo
e3c39d4b52 refactor(client): use css modules 2023-01-14 12:45:20 +09:00
syuilo
5da74897ae refactor(client): use css modules 2023-01-14 12:43:54 +09:00
syuilo
4b1009b34e refactor(client): use css modules 2023-01-14 12:30:32 +09:00
syuilo
203a7ad073 refactor(client): use css modules 2023-01-14 12:15:02 +09:00
11 changed files with 321 additions and 311 deletions

View File

@@ -133,6 +133,7 @@ You should also include the user name that made the change.
- Server: 非公開のクリップのURLでOGPレンダリングされる問題を修正 @syuilo - Server: 非公開のクリップのURLでOGPレンダリングされる問題を修正 @syuilo
- Server: アンテナタイムライン(ストリーミング)が、フォローしていないユーザーの鍵投稿も拾ってしまう @syuilo - Server: アンテナタイムライン(ストリーミング)が、フォローしていないユーザーの鍵投稿も拾ってしまう @syuilo
- Server: follow request list api pagination @sim1222 - Server: follow request list api pagination @sim1222
- Server: ドライブ容量超過時のエラーが適切にレスポンスされない問題を修正 @syuilo
- Client: パスワードマネージャーなどでユーザー名がオートコンプリートされない問題を修正 @massongit - Client: パスワードマネージャーなどでユーザー名がオートコンプリートされない問題を修正 @massongit
- Client: 日付形式の文字列などがカスタム絵文字として表示されるのを修正 @syuilo - Client: 日付形式の文字列などがカスタム絵文字として表示されるのを修正 @syuilo
- Client: case insensitive emoji search @saschanaz - Client: case insensitive emoji search @saschanaz

View File

@@ -1,6 +1,6 @@
{ {
"name": "misskey", "name": "misskey",
"version": "13.0.0-rc.1", "version": "13.0.0-rc.2",
"codename": "indigo", "codename": "indigo",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@@ -90,7 +90,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
} }
} }
const meta = await this.metaService.fetch(); const instance = await this.metaService.fetch();
try { try {
// Create file // Create file
@@ -102,8 +102,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
folderId: ps.folderId, folderId: ps.folderId,
force: ps.force, force: ps.force,
sensitive: ps.isSensitive, sensitive: ps.isSensitive,
requestIp: meta.enableIpLogging ? ip : null, requestIp: instance.enableIpLogging ? ip : null,
requestHeaders: meta.enableIpLogging ? headers : null, requestHeaders: instance.enableIpLogging ? headers : null,
}); });
return await this.driveFileEntityService.pack(driveFile, { self: true }); return await this.driveFileEntityService.pack(driveFile, { self: true });
} catch (err) { } catch (err) {
@@ -116,7 +116,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
} }
throw new ApiError(); throw new ApiError();
} finally { } finally {
cleanup!(); cleanup!();
} }
}); });
} }

View File

@@ -60,7 +60,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private queryService: QueryService, private queryService: QueryService,
) { ) {
super(meta, paramDef, async (ps, me) => { super(meta, paramDef, async (ps, me) => {
const query = this.queryService.makePaginationQuery(this.followRequestsRepository.createQueryBuilder('request'), ps.sinceId, ps.untilId); const query = this.queryService.makePaginationQuery(this.followRequestsRepository.createQueryBuilder('request'), ps.sinceId, ps.untilId)
.andWhere('request.followeeId = :meId', { meId: me.id });
const requests = await query const requests = await query
.take(ps.limit) .take(ps.limit)

View File

@@ -1,11 +1,11 @@
<template> <template>
<span class="zjobosdg"> <span>
<span v-text="hh"></span> <span v-text="hh"></span>
<span class="colon" :class="{ showColon }">:</span> <span :class="[$style.colon, { [$style.showColon]: showColon }]">:</span>
<span v-text="mm"></span> <span v-text="mm"></span>
<span v-if="showS" class="colon" :class="{ showColon }">:</span> <span v-if="showS" :class="[$style.colon, { [$style.showColon]: showColon }]">:</span>
<span v-if="showS" v-text="ss"></span> <span v-if="showS" v-text="ss"></span>
<span v-if="showMs" class="colon" :class="{ showColon }">:</span> <span v-if="showMs" :class="[$style.colon, { [$style.showColon]: showColon }]">:</span>
<span v-if="showMs" v-text="ms"></span> <span v-if="showMs" v-text="ms"></span>
</span> </span>
</template> </template>
@@ -62,16 +62,14 @@ onUnmounted(() => {
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" module>
.zjobosdg { .colon {
> .colon { opacity: 0;
opacity: 0; transition: opacity 1s ease;
transition: opacity 1s ease;
&.showColon { &.showColon {
opacity: 1; opacity: 1;
transition: opacity 0s; transition: opacity 0s;
}
} }
} }
</style> </style>

View File

@@ -1,8 +1,15 @@
<template> <template>
<Transition :name="transitionName" :duration="transitionDuration" appear @after-leave="emit('closed')" @enter="emit('opening')" @after-enter="onOpened"> <Transition
<div v-show="manualShowing != null ? manualShowing : showing" v-hotkey.global="keymap" class="qzhlnise" :class="{ drawer: type === 'drawer', dialog: type === 'dialog' || type === 'dialog:top', popup: type === 'popup' }" :style="{ zIndex, pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }"> :name="transitionName"
<div class="bg _modalBg" :class="{ transparent: transparentBg && (type === 'popup') }" :style="{ zIndex }" @click="onBgClick" @mousedown="onBgClick" @contextmenu.prevent.stop="() => {}"></div> :enter-active-class="$style['transition_' + transitionName + '_enterActive']"
<div ref="content" class="content" :class="{ fixed, top: type === 'dialog:top' }" :style="{ zIndex }" @click.self="onBgClick"> :leave-active-class="$style['transition_' + transitionName + '_leaveActive']"
:enter-from-class="$style['transition_' + transitionName + '_enterFrom']"
:leave-to-class="$style['transition_' + transitionName + '_leaveTo']"
:duration="transitionDuration" appear @after-leave="emit('closed')" @enter="emit('opening')" @after-enter="onOpened"
>
<div v-show="manualShowing != null ? manualShowing : showing" v-hotkey.global="keymap" :class="[$style.root, { [$style.drawer]: type === 'drawer', [$style.dialog]: type === 'dialog' || type === 'dialog:top', [$style.popup]: type === 'popup' }]" :style="{ zIndex, pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
<div class="_modalBg" :class="[$style.bg, { [$style.bgTransparent]: transparentBg && (type === 'popup') }]" :style="{ zIndex }" @click="onBgClick" @mousedown="onBgClick" @contextmenu.prevent.stop="() => {}"></div>
<div ref="content" :class="[$style.content, { [$style.fixed]: fixed, [$style.top]: type === 'dialog:top' }]" :style="{ zIndex }" @click.self="onBgClick">
<slot :max-height="maxHeight" :type="type"></slot> <slot :max-height="maxHeight" :type="type"></slot>
</div> </div>
</div> </div>
@@ -280,8 +287,9 @@ defineExpose({
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" module>
.send-enter-active, .send-leave-active { .transition_send_enterActive,
.transition_send_leaveActive {
> .bg { > .bg {
transition: opacity 0.3s !important; transition: opacity 0.3s !important;
} }
@@ -291,7 +299,8 @@ defineExpose({
transition: opacity 0.3s ease-in, transform 0.3s cubic-bezier(.5,-0.5,1,.5) !important; transition: opacity 0.3s ease-in, transform 0.3s cubic-bezier(.5,-0.5,1,.5) !important;
} }
} }
.send-enter-from, .send-leave-to { .transition_send_enterFrom,
.transition_send_leaveTo {
> .bg { > .bg {
opacity: 0; opacity: 0;
} }
@@ -303,7 +312,8 @@ defineExpose({
} }
} }
.modal-enter-active, .modal-leave-active { .transition_modal_enterActive,
.transition_modal_leaveActive {
> .bg { > .bg {
transition: opacity 0.2s !important; transition: opacity 0.2s !important;
} }
@@ -313,7 +323,8 @@ defineExpose({
transition: opacity 0.2s, transform 0.2s !important; transition: opacity 0.2s, transform 0.2s !important;
} }
} }
.modal-enter-from, .modal-leave-to { .transition_modal_enterFrom,
.transition_modal_leaveTo {
> .bg { > .bg {
opacity: 0; opacity: 0;
} }
@@ -326,7 +337,8 @@ defineExpose({
} }
} }
.modal-popup-enter-active, .modal-popup-leave-active { .transition_modal-popup_enterActive,
.transition_modal-popup_leaveActive {
> .bg { > .bg {
transition: opacity 0.1s !important; transition: opacity 0.1s !important;
} }
@@ -336,7 +348,8 @@ defineExpose({
transition: opacity 0.1s cubic-bezier(0, 0, 0.2, 1), transform 0.1s cubic-bezier(0, 0, 0.2, 1) !important; transition: opacity 0.1s cubic-bezier(0, 0, 0.2, 1), transform 0.1s cubic-bezier(0, 0, 0.2, 1) !important;
} }
} }
.modal-popup-enter-from, .modal-popup-leave-to { .transition_modal-popup_enterFrom,
.transition_modal-popup_leaveTo {
> .bg { > .bg {
opacity: 0; opacity: 0;
} }
@@ -349,7 +362,7 @@ defineExpose({
} }
} }
.modal-drawer-enter-active { .transition_modal-drawer_enterActive {
> .bg { > .bg {
transition: opacity 0.2s !important; transition: opacity 0.2s !important;
} }
@@ -358,7 +371,7 @@ defineExpose({
transition: transform 0.2s cubic-bezier(0,.5,0,1) !important; transition: transform 0.2s cubic-bezier(0,.5,0,1) !important;
} }
} }
.modal-drawer-leave-active { .transition_modal-drawer_leaveActive {
> .bg { > .bg {
transition: opacity 0.2s !important; transition: opacity 0.2s !important;
} }
@@ -367,7 +380,8 @@ defineExpose({
transition: transform 0.2s cubic-bezier(0,.5,0,1) !important; transition: transform 0.2s cubic-bezier(0,.5,0,1) !important;
} }
} }
.modal-drawer-enter-from, .modal-drawer-leave-to { .transition_modal-drawer_enterFrom,
.transition_modal-drawer_leaveTo {
> .bg { > .bg {
opacity: 0; opacity: 0;
} }
@@ -378,15 +392,7 @@ defineExpose({
} }
} }
.qzhlnise { .root {
> .bg {
&.transparent {
background: transparent;
-webkit-backdrop-filter: none;
backdrop-filter: none;
}
}
&.dialog { &.dialog {
> .content { > .content {
position: fixed; position: fixed;
@@ -408,12 +414,12 @@ defineExpose({
mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 16px, rgba(0,0,0,1) calc(100% - 16px), rgba(0,0,0,0) 100%); mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 16px, rgba(0,0,0,1) calc(100% - 16px), rgba(0,0,0,0) 100%);
} }
> ::v-deep(*) { &:global > * {
margin: auto; margin: auto;
} }
&.top { &.top {
> ::v-deep(*) { &:global > * {
margin-top: 0; margin-top: 0;
} }
} }
@@ -445,11 +451,18 @@ defineExpose({
right: 0; right: 0;
margin: auto; margin: auto;
> ::v-deep(*) { &:global > * {
margin: auto; margin: auto;
} }
} }
} }
}
.bg {
&.bgTransparent {
background: transparent;
-webkit-backdrop-filter: none;
backdrop-filter: none;
}
} }
</style> </style>

View File

@@ -1,16 +1,16 @@
<template> <template>
<div v-if="chosen" class="qiivuoyo"> <div v-if="chosen" :class="$style.root">
<div v-if="!showMenu" class="main" :class="chosen.place"> <div v-if="!showMenu" :class="[$style.main, $style['form_' + chosen.place]]">
<a :href="chosen.url" target="_blank"> <a :href="chosen.url" target="_blank" :class="$style.link">
<img :src="chosen.imageUrl"> <img :src="chosen.imageUrl" :class="$style.img">
<button class="_button menu" @click.prevent.stop="toggleMenu"><span class="ti ti-info-circle info-circle"></span></button> <button class="_button" :class="$style.i" @click.prevent.stop="toggleMenu"><i :class="$style.iIcon" class="ti ti-info-circle"></i></button>
</a> </a>
</div> </div>
<div v-else class="menu"> <div v-else :class="$style.menu">
<div class="body"> <div :class="$style.menuContainer">
<div>Ads by {{ host }}</div> <div>Ads by {{ host }}</div>
<!--<MkButton class="button" primary>{{ $ts._ad.like }}</MkButton>--> <!--<MkButton class="button" primary>{{ $ts._ad.like }}</MkButton>-->
<MkButton v-if="chosen.ratio !== 0" class="button" @click="reduceFrequency">{{ $ts._ad.reduceFrequencyOfThisAd }}</MkButton> <MkButton v-if="chosen.ratio !== 0" :class="$style.menuButton" @click="reduceFrequency">{{ $ts._ad.reduceFrequencyOfThisAd }}</MkButton>
<button class="_textButton" @click="toggleMenu">{{ $ts._ad.back }}</button> <button class="_textButton" @click="toggleMenu">{{ $ts._ad.back }}</button>
</div> </div>
</div> </div>
@@ -92,95 +92,99 @@ function reduceFrequency(): void {
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" module>
.qiivuoyo { .root {
background-size: auto auto; background-size: auto auto;
background-image: repeating-linear-gradient(45deg, transparent, transparent 8px, var(--ad) 8px, var(--ad) 14px ); background-image: repeating-linear-gradient(45deg, transparent, transparent 8px, var(--ad) 8px, var(--ad) 14px );
}
> .main { .main {
text-align: center; text-align: center;
> a { &.form_square {
display: inline-block; > .link,
position: relative; > .link > .img {
vertical-align: bottom; max-width: min(300px, 100%);
max-height: 300px;
&:hover {
> img {
filter: contrast(120%);
}
}
> img {
display: block;
object-fit: contain;
margin: auto;
border-radius: 5px;
}
> .menu {
position: absolute;
top: 1px;
right: 1px;
> .info-circle {
border: 3px solid var(--panel);
border-radius: 50%;
background: var(--panel);
}
}
}
&.square {
> a ,
> a > img {
max-width: min(300px, 100%);
max-height: 300px;
}
}
&.horizontal {
padding: 8px;
> a ,
> a > img {
max-width: min(600px, 100%);
max-height: 80px;
}
}
&.horizontal-big {
padding: 8px;
> a ,
> a > img {
max-width: min(600px, 100%);
max-height: 250px;
}
}
&.vertical {
> a ,
> a > img {
max-width: min(100px, 100%);
}
} }
} }
> .menu { &.form_horizontal {
padding: 8px; padding: 8px;
text-align: center;
> .body { > .link,
padding: 8px; > .link > .img {
margin: 0 auto; max-width: min(600px, 100%);
max-width: 400px; max-height: 80px;
border: solid 1px var(--divider); }
}
> .button { &.form_horizontal-big {
margin: 8px auto; padding: 8px;
}
> .link,
> .link > .img {
max-width: min(600px, 100%);
max-height: 250px;
}
}
&.form_vertical {
> .link,
> .link > .img {
max-width: min(100px, 100%);
} }
} }
} }
.link {
display: inline-block;
position: relative;
vertical-align: bottom;
&:hover {
> .img {
filter: contrast(120%);
}
}
}
.img {
display: block;
object-fit: contain;
margin: auto;
border-radius: 5px;
}
.i {
position: absolute;
top: 1px;
right: 1px;
display: grid;
place-content: center;
background: var(--panel);
border-radius: 100%;
padding: 2px;
}
.iIcon {
font-size: 14px;
line-height: 17px;
}
.menu {
padding: 8px;
text-align: center;
}
.menuContainer {
padding: 8px;
margin: 0 auto;
max-width: 400px;
border: solid 1px var(--divider);
}
.menuButton {
margin: 8px auto;
}
</style> </style>

View File

@@ -1,5 +1,5 @@
<template> <template>
<MfmCore :text="text" :plain="plain" :nowrap="nowrap" :author="author" :is-note="isNote" class="havbbuyv" :class="{ nowrap }"/> <MfmCore :text="text" :plain="plain" :nowrap="nowrap" :author="author" :is-note="isNote" :class="[$style.root, { [$style.nowrap]: nowrap }]"/>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@@ -157,8 +157,8 @@ const props = withDefaults(defineProps<{
} }
</style> </style>
<style lang="scss" scoped> <style lang="scss" module>
.havbbuyv { .root {
white-space: pre-wrap; white-space: pre-wrap;
&.nowrap { &.nowrap {
@@ -167,24 +167,5 @@ const props = withDefaults(defineProps<{
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
::v-deep(.quote) {
display: block;
margin: 8px;
padding: 6px 0 6px 12px;
color: var(--fg);
border-left: solid 3px var(--fg);
opacity: 0.7;
}
::v-deep(pre) {
font-size: 0.8em;
}
> ::v-deep(code) {
font-size: 0.8em;
word-break: break-all;
padding: 4px 6px;
}
} }
</style> </style>

View File

@@ -1,36 +1,36 @@
<template> <template>
<div v-if="show" ref="el" class="fdidabkb" :class="{ slim: narrow, thin: thin_ }" :style="{ background: bg }" @click="onClick"> <div v-if="show" ref="el" :class="[$style.root, { [$style.slim]: narrow, [$style.thin]: thin_ }]" :style="{ background: bg }" @click="onClick">
<div v-if="narrow" class="buttons left"> <div v-if="narrow" :class="$style.buttonsLeft">
<MkAvatar v-if="props.displayMyAvatar && $i" class="avatar" :user="$i" :disable-preview="true"/> <MkAvatar v-if="props.displayMyAvatar && $i" :class="$style.avatar" :user="$i" :disable-preview="true"/>
</div> </div>
<template v-if="metadata"> <template v-if="metadata">
<div v-if="!hideTitle" class="titleContainer" @click="showTabsPopup"> <div v-if="!hideTitle" :class="$style.titleContainer" @click="showTabsPopup">
<MkAvatar v-if="metadata.avatar" class="avatar" :user="metadata.avatar" :disable-preview="true" :show-indicator="true"/> <MkAvatar v-if="metadata.avatar" :class="$style.titleAvatar" :user="metadata.avatar" :disable-preview="true" :show-indicator="true"/>
<i v-else-if="metadata.icon" class="icon" :class="metadata.icon"></i> <i v-else-if="metadata.icon" :class="[$style.titleIcon, metadata.icon]"></i>
<div class="title"> <div :class="$style.title">
<MkUserName v-if="metadata.userName" :user="metadata.userName" :nowrap="true" class="title"/> <MkUserName v-if="metadata.userName" :user="metadata.userName" :nowrap="true"/>
<div v-else-if="metadata.title" class="title">{{ metadata.title }}</div> <div v-else-if="metadata.title">{{ metadata.title }}</div>
<div v-if="!narrow && metadata.subtitle" class="subtitle"> <div v-if="!narrow && metadata.subtitle" :class="$style.subtitle">
{{ metadata.subtitle }} {{ metadata.subtitle }}
</div> </div>
<div v-if="narrow && hasTabs" class="subtitle activeTab"> <div v-if="narrow && hasTabs" :class="[$style.subtitle, $style.activeTab]">
{{ tabs.find(tab => tab.key === props.tab)?.title }} {{ tabs.find(tab => tab.key === props.tab)?.title }}
<i class="chevron ti ti-chevron-down"></i> <i class="ti ti-chevron-down" :class="$style.chevron"></i>
</div> </div>
</div> </div>
</div> </div>
<div v-if="!narrow || hideTitle" class="tabs"> <div v-if="!narrow || hideTitle" :class="$style.tabs">
<button v-for="tab in tabs" :ref="(el) => tabRefs[tab.key] = (el as HTMLElement)" v-tooltip.noDelay="tab.title" class="tab _button" :class="{ active: tab.key != null && tab.key === props.tab }" @mousedown="(ev) => onTabMousedown(tab, ev)" @click="(ev) => onTabClick(tab, ev)"> <button v-for="tab in tabs" :ref="(el) => tabRefs[tab.key] = (el as HTMLElement)" v-tooltip.noDelay="tab.title" class="_button" :class="[$style.tab, { [$style.active]: tab.key != null && tab.key === props.tab }]" @mousedown="(ev) => onTabMousedown(tab, ev)" @click="(ev) => onTabClick(tab, ev)">
<i v-if="tab.icon" class="icon" :class="tab.icon"></i> <i v-if="tab.icon" :class="[$style.tabIcon, tab.icon]"></i>
<span v-if="!tab.iconOnly" class="title">{{ tab.title }}</span> <span v-if="!tab.iconOnly" :class="$style.tabTitle">{{ tab.title }}</span>
</button> </button>
<div ref="tabHighlightEl" class="highlight"></div> <div ref="tabHighlightEl" :class="$style.tabHighlight"></div>
</div> </div>
</template> </template>
<div class="buttons right"> <div :class="$style.buttonsRight">
<template v-for="action in actions"> <template v-for="action in actions">
<button v-tooltip.noDelay="action.text" class="_button button" :class="{ highlighted: action.highlighted }" @click.stop="action.handler" @touchstart="preventDrag"><i :class="action.icon"></i></button> <button v-tooltip.noDelay="action.text" class="_button" :class="[$style.button, { [$style.highlighted]: action.highlighted }]" @click.stop="action.handler" @touchstart="preventDrag"><i :class="action.icon"></i></button>
</template> </template>
</div> </div>
</div> </div>
@@ -178,8 +178,8 @@ onUnmounted(() => {
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" module>
.fdidabkb { .root {
--height: 50px; --height: 50px;
display: flex; display: flex;
width: 100%; width: 100%;
@@ -215,154 +215,156 @@ onUnmounted(() => {
} }
} }
} }
}
> .buttons { .buttons {
--margin: 8px; --margin: 8px;
display: flex; display: flex;
align-items: center; align-items: center;
min-width: var(--height); min-width: var(--height);
height: var(--height); height: var(--height);
margin: 0 var(--margin); margin: 0 var(--margin);
&.left { &:empty {
margin-right: auto; width: var(--height);
}
}
> .avatar { .buttonsLeft {
$size: 32px; composes: buttons;
display: inline-block; margin-right: auto;
width: $size; }
height: $size;
vertical-align: bottom;
margin: 0 8px;
pointer-events: none;
}
}
&.right { .buttonsRight {
margin-left: auto; composes: buttons;
} margin-left: auto;
}
&:empty { .avatar {
width: var(--height); $size: 32px;
} display: inline-block;
width: $size;
height: $size;
vertical-align: bottom;
margin: 0 8px;
pointer-events: none;
}
> .button { .button {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: calc(var(--height) - (var(--margin) * 2)); height: calc(var(--height) - (var(--margin) * 2));
width: calc(var(--height) - (var(--margin) * 2)); width: calc(var(--height) - (var(--margin) * 2));
box-sizing: border-box; box-sizing: border-box;
position: relative; position: relative;
border-radius: 5px; border-radius: 5px;
&:hover { &:hover {
background: rgba(0, 0, 0, 0.05); background: rgba(0, 0, 0, 0.05);
}
&.highlighted {
color: var(--accent);
}
}
> .fullButton {
& + .fullButton {
margin-left: 12px;
}
}
} }
> .titleContainer { &.highlighted {
display: flex; color: var(--accent);
align-items: center;
max-width: 400px;
overflow: auto;
white-space: nowrap;
text-align: left;
font-weight: bold;
flex-shrink: 0;
margin-left: 24px;
> .avatar {
$size: 32px;
display: inline-block;
width: $size;
height: $size;
vertical-align: bottom;
margin: 0 8px;
pointer-events: none;
}
> .icon {
margin-right: 8px;
width: 16px;
text-align: center;
}
> .title {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
line-height: 1.1;
> .subtitle {
opacity: 0.6;
font-size: 0.8em;
font-weight: normal;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&.activeTab {
text-align: center;
> .chevron {
display: inline-block;
margin-left: 6px;
}
}
}
}
} }
}
> .tabs { .fullButton {
position: relative; & + .fullButton {
margin-left: 16px; margin-left: 12px;
font-size: 0.8em; }
overflow: auto; }
white-space: nowrap;
> .tab { .titleContainer {
display: flex;
align-items: center;
max-width: 400px;
overflow: auto;
white-space: nowrap;
text-align: left;
font-weight: bold;
flex-shrink: 0;
margin-left: 24px;
}
.titleAvatar {
$size: 32px;
display: inline-block;
width: $size;
height: $size;
vertical-align: bottom;
margin: 0 8px;
pointer-events: none;
}
.titleIcon {
margin-right: 8px;
width: 16px;
text-align: center;
}
.title {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
line-height: 1.1;
}
.subtitle {
opacity: 0.6;
font-size: 0.8em;
font-weight: normal;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&.activeTab {
text-align: center;
> .chevron {
display: inline-block; display: inline-block;
position: relative; margin-left: 6px;
padding: 0 10px;
height: 100%;
font-weight: normal;
opacity: 0.7;
&:hover {
opacity: 1;
}
&.active {
opacity: 1;
}
> .icon + .title {
margin-left: 8px;
}
}
> .highlight {
position: absolute;
bottom: 0;
height: 3px;
background: var(--accent);
border-radius: 999px;
transition: all 0.2s ease;
pointer-events: none;
} }
} }
} }
.tabs {
position: relative;
margin-left: 16px;
font-size: 0.8em;
overflow: auto;
white-space: nowrap;
}
.tab {
display: inline-block;
position: relative;
padding: 0 10px;
height: 100%;
font-weight: normal;
opacity: 0.7;
&:hover {
opacity: 1;
}
&.active {
opacity: 1;
}
}
.tabIcon + .tabTitle {
margin-left: 8px;
}
.tabHighlight {
position: absolute;
bottom: 0;
height: 3px;
background: var(--accent);
border-radius: 999px;
transition: all 0.2s ease;
pointer-events: none;
}
</style> </style>

View File

@@ -12,6 +12,15 @@ import MkA from '@/components/global/MkA.vue';
import { host } from '@/config'; import { host } from '@/config';
import { MFM_TAGS } from '@/scripts/mfm-tags'; import { MFM_TAGS } from '@/scripts/mfm-tags';
const QUOTE_STYLE = `
display: block;
margin: 8px;
padding: 6px 0 6px 12px;
color: var(--fg);
border-left: solid 3px var(--fg);
opacity: 0.7;
`.split('\n').join(' ');
export default defineComponent({ export default defineComponent({
props: { props: {
text: { text: {
@@ -276,11 +285,11 @@ export default defineComponent({
case 'quote': { case 'quote': {
if (!this.nowrap) { if (!this.nowrap) {
return [h('div', { return [h('div', {
class: 'quote', style: QUOTE_STYLE,
}, genEl(token.children))]; }, genEl(token.children))];
} else { } else {
return [h('span', { return [h('span', {
class: 'quote', style: QUOTE_STYLE,
}, genEl(token.children))]; }, genEl(token.children))];
} }
} }

View File

@@ -9,7 +9,8 @@
<div v-if="queue > 0" :class="$style.new"><button class="_buttonPrimary" @click="top()">{{ i18n.ts.newNoteRecived }}</button></div> <div v-if="queue > 0" :class="$style.new"><button class="_buttonPrimary" @click="top()">{{ i18n.ts.newNoteRecived }}</button></div>
<div :class="$style.tl"> <div :class="$style.tl">
<XTimeline <XTimeline
ref="tl" :key="src" ref="tlComponent"
:key="src"
:src="src" :src="src"
:sound="true" :sound="true"
@queue="queueUpdated" @queue="queueUpdated"