Merge pull request 'Replace classic view sidebars w/ default UI sidebars + fix wallpapers' (#10097) from Freeplay/calckey:classic into develop

Reviewed-on: https://codeberg.org/calckey/calckey/pulls/10097
This commit is contained in:
Kainoa Kanter 2023-05-12 01:44:02 +00:00
commit 60ab37f034
14 changed files with 83 additions and 588 deletions

View file

@ -1,4 +1,4 @@
html, body { html {
background-color: var(--bg); background-color: var(--bg);
color: var(--fg); color: var(--fg);
} }

View file

@ -144,6 +144,10 @@ export default defineComponent({
padding: var(--x-padding); padding: var(--x-padding);
-webkit-backdrop-filter: var(--blur, blur(8px)); -webkit-backdrop-filter: var(--blur, blur(8px));
backdrop-filter: var(--blur, blur(20px)); backdrop-filter: var(--blur, blur(20px));
margin-inline: -12px;
padding-inline: 12px;
mask: linear-gradient(to right, transparent, black 12px calc(100% - 12px), transparent);
-webkit-mask: linear-gradient(to right, transparent, black 12px calc(100% - 12px), transparent);
> .title { > .title {
margin: 0; margin: 0;

View file

@ -58,13 +58,12 @@ defineExpose({
.giivymft { .giivymft {
&.noGap { &.noGap {
> .notes { > .notes {
background: var(--panel); background: var(--panel) !important;
border-radius: var(--radius); border-radius: var(--radius);
} }
} }
&:not(.noGap) { &:not(.noGap) {
> .notes { > .notes {
background: var(--bg);
.qtqtichx { .qtqtichx {
background: var(--panel); background: var(--panel);
border-radius: var(--radius); border-radius: var(--radius);

View file

@ -158,7 +158,7 @@ definePageMetadata(
} }
> .tl { > .tl {
background: var(--bg); background: none;
border-radius: var(--radius); border-radius: var(--radius);
overflow: clip; overflow: clip;
} }

View file

@ -218,7 +218,9 @@ definePageMetadata(
} }
.fcuexfpr { .fcuexfpr {
background: var(--bg); #calckey_app > :not(.wallpaper) & {
background: var(--bg);
}
> .note { > .note {
> .main { > .main {

View file

@ -391,7 +391,7 @@ onMounted(() => {
} }
> .tl { > .tl {
background: var(--bg); background: none;
border-radius: var(--radius); border-radius: var(--radius);
overflow: clip; overflow: clip;
} }

View file

@ -125,7 +125,7 @@ definePageMetadata(
} }
> .tl { > .tl {
background: var(--bg); background: none;
border-radius: var(--radius); border-radius: var(--radius);
overflow: clip; overflow: clip;
} }

View file

@ -40,7 +40,6 @@
html { html {
touch-action: manipulation; touch-action: manipulation;
background-color: var(--bg);
background-attachment: fixed; background-attachment: fixed;
background-size: cover; background-size: cover;
background-position: center; background-position: center;

View file

@ -1,5 +1,5 @@
<template> <template>
<header class="mvcprjjd" :class="{ iconOnly }"> <header class="mvcprjjd sidebar" :class="{ iconOnly }">
<div class="body"> <div class="body">
<div class="top"> <div class="top">
<div <div
@ -236,23 +236,22 @@ function more(ev: MouseEvent) {
.mvcprjjd { .mvcprjjd {
$nav-width: 250px; $nav-width: 250px;
$nav-icon-only-width: 80px; $nav-icon-only-width: 80px;
flex: 0 0 $nav-width; flex: 0 0 $nav-width;
width: $nav-width; width: $nav-width;
box-sizing: border-box; box-sizing: border-box;
> .body { > .body {
position: fixed; position: sticky;
top: 0; top: 0;
left: 0;
z-index: 1001;
width: $nav-icon-only-width; width: $nav-icon-only-width;
// 100vh ... https://css-tricks.com/the-trick-to-viewport-units-on-mobile/ // 100vh ... https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
height: calc(var(--vh, 1vh) * 100); height: calc(var(--vh, 1vh) * 100);
box-sizing: border-box; box-sizing: border-box;
overflow: auto; overflow: auto;
overflow-x: clip; overflow-x: clip;
background: var(--navBg); #calckey_app > :not(.wallpaper) & {
background: var(--navBg);
}
contain: strict; contain: strict;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -260,17 +259,15 @@ function more(ev: MouseEvent) {
&:not(.iconOnly) { &:not(.iconOnly) {
> .body { > .body {
margin-left: -200px;
padding-left: 200px;
box-sizing: content-box;
width: $nav-width; width: $nav-width;
> .top { > .top {
position: sticky; position: relative;
top: 0;
z-index: 1; z-index: 1;
padding: 2rem 0; padding: 2rem 0;
background: var(--X14);
-webkit-backdrop-filter: var(--blur, blur(8px));
backdrop-filter: var(--blur, blur(8px));
> .banner { > .banner {
position: absolute; position: absolute;
top: 0; top: 0;
@ -298,12 +295,7 @@ function more(ev: MouseEvent) {
} }
> .bottom { > .bottom {
position: sticky;
bottom: 0;
padding: 20px 0; padding: 20px 0;
background: var(--X14);
-webkit-backdrop-filter: var(--blur, blur(8px));
backdrop-filter: var(--blur, blur(8px));
> .post { > .post {
position: relative; position: relative;
@ -474,13 +466,7 @@ function more(ev: MouseEvent) {
width: $nav-icon-only-width; width: $nav-icon-only-width;
> .top { > .top {
position: sticky;
top: 0;
z-index: 1;
padding: 2rem 0; padding: 2rem 0;
background: var(--X14);
-webkit-backdrop-filter: var(--blur, blur(8px));
backdrop-filter: var(--blur, blur(8px));
> .account { > .account {
display: block; display: block;
@ -497,12 +483,7 @@ function more(ev: MouseEvent) {
} }
> .bottom { > .bottom {
position: sticky;
bottom: 0;
padding: 20px 0; padding: 20px 0;
background: var(--X14);
-webkit-backdrop-filter: var(--blur, blur(8px));
backdrop-filter: var(--blur, blur(8px));
> .post { > .post {
display: block; display: block;

View file

@ -1,409 +0,0 @@
<template>
<div class="npcljfve" :class="{ iconOnly }">
<button
v-click-anime
class="item _button account"
@click="openAccountMenu"
>
<MkAvatar :user="$i" class="avatar" disableLink /><MkAcct
class="text"
:user="$i"
/>
</button>
<div class="post" data-cy-open-post-form @click="post">
<MkButton class="button" gradate full rounded>
<i class="ph-pencil ph-bold ph-lg ph-fw ph-lg"></i
><span v-if="!iconOnly" class="text">{{ i18n.ts.note }}</span>
</MkButton>
</div>
<div class="divider"></div>
<MkA
v-click-anime
class="item index"
active-class="active"
to="/"
exact
>
<i class="ph-house ph-bold ph-lg ph-fw ph-lg"></i
><span class="text">{{ i18n.ts.timeline }}</span>
</MkA>
<template v-for="item in menu">
<div v-if="item === '-'" class="divider"></div>
<component
:is="navbarItemDef[item].to ? 'MkA' : 'button'"
v-else-if="
navbarItemDef[item] && navbarItemDef[item].show !== false
"
v-click-anime
class="item _button"
:class="item"
active-class="active"
:to="navbarItemDef[item].to"
v-on="
navbarItemDef[item].action
? { click: navbarItemDef[item].action }
: {}
"
>
<i class="ph-fw ph-lg" :class="navbarItemDef[item].icon"></i
><span class="text">{{ $ts[navbarItemDef[item].title] }}</span>
<span v-if="navbarItemDef[item].indicated" class="indicator"
><i class="ph-circle ph-fill"></i
></span>
</component>
</template>
<div class="divider"></div>
<MkA
v-if="$i.isAdmin || $i.isModerator"
v-click-anime
class="item"
active-class="active"
to="/admin"
:behavior="settingsWindowed ? 'modalWindow' : null"
>
<i class="ph-door ph-bold ph-lg ph-fw ph-lg"></i
><span class="text">{{ i18n.ts.controlPanel }}</span>
</MkA>
<button v-click-anime class="item _button" @click="more">
<i class="ph-dots-three-outline ph-bold ph-lg ph-fw ph-lg"></i
><span class="text">{{ i18n.ts.more }}</span>
<span v-if="otherNavItemIndicated" class="indicator"
><i class="ph-circle ph-fill"></i
></span>
</button>
<MkA
v-click-anime
class="item"
active-class="active"
to="/settings"
:behavior="settingsWindowed ? 'modalWindow' : null"
>
<i class="ph-gear-six ph-bold ph-lg ph-fw ph-lg"></i
><span class="text">{{ i18n.ts.settings }}</span>
</MkA>
<div class="divider"></div>
<div class="about">
<MkA v-click-anime class="link" @click="openInstanceMenu">
<img
:src="
$instance.iconUrl ||
$instance.faviconUrl ||
'/favicon.ico'
"
class="_ghost"
/>
</MkA>
</div>
<!--<MisskeyLogo class="misskey"/>-->
</div>
</template>
<script lang="ts">
import { defineAsyncComponent, defineComponent } from "vue";
import { host } from "@/config";
import { search } from "@/scripts/search";
import * as os from "@/os";
import { navbarItemDef } from "@/navbar";
import { openAccountMenu } from "@/account";
import MkButton from "@/components/MkButton.vue";
import { StickySidebar } from "@/scripts/sticky-sidebar";
//import MisskeyLogo from '@assets/client/misskey.svg';
import { i18n } from "@/i18n";
export default defineComponent({
components: {
MkButton,
//MisskeyLogo,
},
data() {
return {
host: host,
accounts: [],
connection: null,
navbarItemDef: navbarItemDef,
iconOnly: false,
settingsWindowed: false,
i18n,
};
},
computed: {
menu(): string[] {
return this.$store.state.menu;
},
otherNavItemIndicated(): boolean {
for (const def in this.navbarItemDef) {
if (this.menu.includes(def)) continue;
if (this.navbarItemDef[def].indicated) return true;
}
return false;
},
},
watch: {
"$store.reactiveState.menuDisplay.value"() {
this.calcViewState();
},
iconOnly() {
this.$nextTick(() => {
this.$emit("change-view-mode");
});
},
},
created() {
window.addEventListener("resize", this.calcViewState);
this.calcViewState();
},
mounted() {
const sticky = new StickySidebar(this.$el.parentElement, 16);
window.addEventListener(
"scroll",
() => {
sticky.calc(window.scrollY);
},
{ passive: true }
);
},
methods: {
calcViewState() {
this.iconOnly =
window.innerWidth <= 1400 ||
this.$store.state.menuDisplay === "sideIcon";
this.settingsWindowed = window.innerWidth > 1400;
},
post() {
os.post();
},
search() {
search();
},
more(ev) {
os.popup(
defineAsyncComponent(
() => import("@/components/MkLaunchPad.vue")
),
{
src: ev.currentTarget ?? ev.target,
},
{},
"closed"
);
},
openAccountMenu: (ev) => {
openAccountMenu(
{
withExtraOperation: true,
},
ev
);
},
},
});
function openInstanceMenu(ev: MouseEvent) {
os.popupMenu(
[
{
text: instance.name ?? host,
type: "label",
},
{
type: "link",
text: i18n.ts.instanceInfo,
icon: "ph-info ph-bold ph-lg",
to: "/about",
},
null,
{
type: "parent",
text: i18n.ts.help,
icon: "ph-question ph-bold ph-lg",
children: [
{
type: "link",
to: "/mfm-cheat-sheet",
text: i18n.ts._mfm.cheatSheet,
icon: "ph-code ph-bold ph-lg",
},
{
type: "link",
to: "/scratchpad",
text: i18n.ts.scratchpad,
icon: "ph-terminal-window ph-bold ph-lg",
},
{
type: "link",
to: "/api-console",
text: "API Console",
icon: "ph-terminal-window ph-bold ph-lg",
},
null,
{
text: i18n.ts.document,
icon: "ph-question ph-bold ph-lg",
action: () => {
window.open(
"https://misskey-hub.net/help.html",
"_blank"
);
},
},
],
},
{
type: "link",
text: i18n.ts.aboutMisskey,
to: "/about-calckey",
},
],
ev.currentTarget ?? ev.target,
{
align: "left",
}
);
}
</script>
<style lang="scss" scoped>
.npcljfve {
$ui-font-size: 1em; // TODO:
$nav-icon-only-width: 78px; // TODO:
$avatar-size: 32px;
$avatar-margin: 8px;
padding: 0 16px;
box-sizing: border-box;
width: 260px;
&.iconOnly {
flex: 0 0 $nav-icon-only-width;
width: $nav-icon-only-width !important;
> .divider {
margin: 8px auto;
width: calc(100% - 32px);
}
> .post {
> .button {
width: 46px;
height: 46px;
padding: 0;
margin-inline: 0 !important;
}
}
> .item {
padding-left: 0;
width: 100%;
text-align: center;
font-size: $ui-font-size * 1.1;
line-height: 3.7rem;
> i,
> .avatar {
margin-right: 0;
}
> i {
left: 10px;
}
> .text {
display: none;
}
}
}
> .divider {
margin: 10px 0;
border-top: solid 0.5px var(--divider);
}
> .post {
position: sticky;
top: 0;
z-index: 1;
padding: 16px 0;
background: var(--bg);
> .button {
min-width: 0;
}
}
> .about {
fill: currentColor;
padding: 8px 0 16px 0;
text-align: center;
> .link {
display: block;
width: 32px;
margin: 0 auto;
img {
display: block;
width: 100%;
}
}
}
> .item {
position: relative;
display: block;
font-size: $ui-font-size;
line-height: 2.6rem;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
text-align: left;
box-sizing: border-box;
> i {
width: 32px;
justify-content: center;
}
> i,
> .avatar {
margin-right: $avatar-margin;
}
> .avatar {
width: $avatar-size;
height: $avatar-size;
vertical-align: middle;
}
> .indicator {
position: absolute;
top: 0;
left: 0;
color: var(--navIndicator);
font-size: 8px;
animation: blink 1s infinite;
}
&:hover {
text-decoration: none;
color: var(--navHoverFg);
}
&.active {
color: var(--navActive);
}
}
}
</style>

View file

@ -13,9 +13,7 @@
class="columns" class="columns"
:class="{ fullView, withGlobalHeader: showMenuOnTop }" :class="{ fullView, withGlobalHeader: showMenuOnTop }"
> >
<div v-if="!showMenuOnTop" class="sidebar"> <XSidebar v-if="!showMenuOnTop"/>
<XSidebar />
</div>
<div v-else ref="widgetsLeft" class="widgets left"> <div v-else ref="widgetsLeft" class="widgets left">
<XWidgets <XWidgets
:place="'left'" :place="'left'"
@ -57,7 +55,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { defineAsyncComponent, markRaw, ref, onMounted, provide } from "vue"; import { defineAsyncComponent, markRaw, ref, onMounted, provide } from "vue";
import XSidebar from "./classic.sidebar.vue"; import XSidebar from "./_common_/navbar.vue";
import XCommon from "./_common_/common.vue"; import XCommon from "./_common_/common.vue";
import type { ComputedRef } from "vue"; import type { ComputedRef } from "vue";
import type { PageMetadata } from "@/scripts/page-metadata"; import type { PageMetadata } from "@/scripts/page-metadata";
@ -72,7 +70,7 @@ import {
import { defaultStore } from "@/store"; import { defaultStore } from "@/store";
import { i18n } from "@/i18n"; import { i18n } from "@/i18n";
const XHeaderMenu = defineAsyncComponent(() => import("./classic.header.vue")); const XHeaderMenu = defineAsyncComponent(() => import("./classic.header.vue"));
const XWidgets = defineAsyncComponent(() => import("./classic.widgets.vue")); const XWidgets = defineAsyncComponent(() => import("./universal.widgets.vue"));
const DESKTOP_THRESHOLD = 1100; const DESKTOP_THRESHOLD = 1100;
@ -101,7 +99,7 @@ provide("shouldSpacerMin", true);
function attachSticky(el) { function attachSticky(el) {
const sticky = new StickySidebar( const sticky = new StickySidebar(
el, el,
defaultStore.state.menuDisplay === "top" ? 0 : 16, defaultStore.state.menuDisplay === 0,
defaultStore.state.menuDisplay === "top" ? 60 : 0 defaultStore.state.menuDisplay === "top" ? 60 : 0
); // TODO: 60px ); // TODO: 60px
window.addEventListener( window.addEventListener(
@ -236,9 +234,18 @@ onMounted(() => {
min-height: calc(var(--vh, 1vh) * 100); min-height: calc(var(--vh, 1vh) * 100);
box-sizing: border-box; box-sizing: border-box;
--navBg: transparent;
--X14: var(--acrylicBg);
&.wallpaper { &.wallpaper {
background: var(--wallpaperOverlay); background: var(--wallpaperOverlay);
//backdrop-filter: var(--blur, blur(4px)); :deep(main) {
background: var(--acrylicBg) !important;
backdrop-filter: blur(12px);
}
:deep(.tl), :deep(.notes) {
background: none !important;
}
} }
> .columns { > .columns {
@ -250,7 +257,7 @@ onMounted(() => {
&.fullView { &.fullView {
margin: 0; margin: 0;
> .sidebar { > :deep(.sidebar) {
display: none; display: none;
} }
@ -266,6 +273,50 @@ onMounted(() => {
} }
} }
> :deep(.sidebar) {
margin-left: -200px;
padding-left: 200px;
box-sizing: content-box;
.banner {
pointer-events: none;
mask: radial-gradient(farthest-side at top, hsl(0, 0%, 0%) 0%,
hsla(0, 0%, 0%, 0.987) 0.3%,
hsla(0, 0%, 0%, 0.951) 1.4%,
hsla(0, 0%, 0%, 0.896) 3.2%,
hsla(0, 0%, 0%, 0.825) 5.8%,
hsla(0, 0%, 0%, 0.741) 9.3%,
hsla(0, 0%, 0%, 0.648) 13.6%,
hsla(0, 0%, 0%, 0.55) 18.9%,
hsla(0, 0%, 0%, 0.45) 25.1%,
hsla(0, 0%, 0%, 0.352) 32.4%,
hsla(0, 0%, 0%, 0.259) 40.7%,
hsla(0, 0%, 0%, 0.175) 50.2%,
hsla(0, 0%, 0%, 0.104) 60.8%,
hsla(0, 0%, 0%, 0.049) 72.6%,
hsla(0, 0%, 0%, 0.013) 85.7%,
hsla(0, 0%, 0%, 0) 100%) !important;
-webkit-mask: radial-gradient(farthest-side at top, hsl(0, 0%, 0%) 0%,
hsla(0, 0%, 0%, 0.987) 0.3%,
hsla(0, 0%, 0%, 0.951) 1.4%,
hsla(0, 0%, 0%, 0.896) 3.2%,
hsla(0, 0%, 0%, 0.825) 5.8%,
hsla(0, 0%, 0%, 0.741) 9.3%,
hsla(0, 0%, 0%, 0.648) 13.6%,
hsla(0, 0%, 0%, 0.55) 18.9%,
hsla(0, 0%, 0%, 0.45) 25.1%,
hsla(0, 0%, 0%, 0.352) 32.4%,
hsla(0, 0%, 0%, 0.259) 40.7%,
hsla(0, 0%, 0%, 0.175) 50.2%,
hsla(0, 0%, 0%, 0.104) 60.8%,
hsla(0, 0%, 0%, 0.049) 72.6%,
hsla(0, 0%, 0%, 0.013) 85.7%,
hsla(0, 0%, 0%, 0) 100%) !important;
width: 125% !important;
left: -12.5% !important;
height: 125% !important;
}
}
> .main { > .main {
min-width: 0; min-width: 0;
width: 750px; width: 750px;
@ -282,7 +333,6 @@ onMounted(() => {
> .widgets { > .widgets {
//--panelBorder: none; //--panelBorder: none;
width: 300px; width: 300px;
margin-top: 16px;
@media (max-width: $widgets-hide-threshold) { @media (max-width: $widgets-hide-threshold) {
display: none; display: none;
@ -293,10 +343,6 @@ onMounted(() => {
} }
} }
> .sidebar {
margin-top: 16px;
}
&.withGlobalHeader { &.withGlobalHeader {
> .main { > .main {
margin-top: 0; margin-top: 0;
@ -314,7 +360,7 @@ onMounted(() => {
@media (max-width: 850px) { @media (max-width: 850px) {
margin: 0; margin: 0;
> .sidebar { > :deep(.sidebar) {
border-right: solid 0.5px var(--divider); border-right: solid 0.5px var(--divider);
} }

View file

@ -1,127 +0,0 @@
<template>
<div class="ddiqwdnk">
<MkAd class="a" :prefer="['widget']" />
<XWidgets
class="widgets"
:edit="editMode"
:widgets="
$store.reactiveState.widgets.value.filter(
(w) => w.place === place
)
"
@add-widget="addWidget"
@remove-widget="removeWidget"
@update-widget="updateWidget"
@update-widgets="updateWidgets"
@exit="editMode = false"
/>
<button
v-if="editMode"
class="_textButton edit"
style="font-size: 0.9em"
@click="editMode = false"
>
<i class="ph-check ph-bold ph-lg"></i> {{ i18n.ts.editWidgetsExit }}
</button>
<button
v-else
class="_textButton edit"
style="font-size: 0.9em"
@click="editMode = true"
>
<i class="ph-pencil ph-bold ph-lg"></i> {{ i18n.ts.editWidgets }}
</button>
</div>
</template>
<script lang="ts">
import { defineComponent, defineAsyncComponent } from "vue";
import XWidgets from "@/components/MkWidgets.vue";
import { i18n } from "@/i18n";
export default defineComponent({
components: {
XWidgets,
},
props: {
place: {
type: String,
},
},
emits: ["mounted"],
data() {
return {
editMode: false,
i18n,
};
},
mounted() {
this.$emit("mounted", this.$el);
},
methods: {
addWidget(widget) {
this.$store.set("widgets", [
{
...widget,
place: this.place,
},
...this.$store.state.widgets,
]);
},
removeWidget(widget) {
this.$store.set(
"widgets",
this.$store.state.widgets.filter((w) => w.id !== widget.id)
);
},
updateWidget({ id, data }) {
this.$store.set(
"widgets",
this.$store.state.widgets.map((w) =>
w.id === id
? {
...w,
data,
}
: w
)
);
},
updateWidgets(widgets) {
this.$store.set("widgets", [
...this.$store.state.widgets.filter(
(w) => w.place !== this.place
),
...widgets,
]);
},
},
});
</script>
<style lang="scss" scoped>
.ddiqwdnk {
position: sticky;
height: min-content;
box-sizing: border-box;
padding-bottom: 8px;
> .widgets,
> .a {
width: 300px;
}
> .edit {
display: block;
margin: 16px auto;
}
}
</style>

View file

@ -323,6 +323,8 @@ function onDrop(ev) {
overflow: hidden; overflow: hidden;
contain: strict; contain: strict;
background: var(--bg);
&.draghover { &.draghover {
&:after { &:after {
content: ""; content: "";

View file

@ -464,13 +464,11 @@ console.log(mainRouter.currentRoute.value.name);
> .contents { > .contents {
width: 100%; width: 100%;
min-width: 0; min-width: 0;
background: var(--bg);
} }
> .widgets { > .widgets {
padding: 0 var(--margin); padding: 0 var(--margin);
border-left: solid 0.5px var(--divider); border-left: solid 0.5px var(--divider);
background: var(--bg);
@media (max-width: $widgets-hide-threshold) { @media (max-width: $widgets-hide-threshold) {
display: none; display: none;