mirror of
https://github.com/hotomoe/hotomoe
synced 2024-12-11 21:28:14 +09:00
spec(frontend): kawaii モード (MisskeyIO#632)
This commit is contained in:
parent
23a12b9579
commit
f4fbc220d5
@ -0,0 +1,18 @@
|
|||||||
|
LICENSE
|
||||||
|
-------
|
||||||
|
|
||||||
|
Copyright (c) by [さわらつき](https://github.com/SAWARATSUKI)
|
||||||
|
|
||||||
|
The following files:
|
||||||
|
|
||||||
|
- misskey-io.png
|
||||||
|
- about-icon.png
|
||||||
|
|
||||||
|
are licensed under proprietary license. To view a copy of this license, visit https://github.com/SAWARATSUKI/KawaiiLogos/blob/main/README_EN.md#license
|
||||||
|
AND SHOULD NOT be considered as part of this project, which is licensed under AGPL-3.0-only.
|
||||||
|
|
||||||
|
The following files:
|
||||||
|
|
||||||
|
- about-icon.png (uwl.png)
|
||||||
|
|
||||||
|
were copied from [misskey-dev/misskey-hub-next](https://github.com/misskey-dev/misskey-hub-next/tree/221a89760e80d75a00600c4e37e22c0f226a6017/public/img/uwu)
|
BIN
packages/frontend/assets/kawaii/about-icon.png
Normal file
BIN
packages/frontend/assets/kawaii/about-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 152 KiB |
BIN
packages/frontend/assets/kawaii/misskey-io.png
Normal file
BIN
packages/frontend/assets/kawaii/misskey-io.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 157 KiB |
@ -124,8 +124,8 @@ export async function common(createVue: () => App<Element>) {
|
|||||||
miLocalStorage.setItem('v', instance.version);
|
miLocalStorage.setItem('v', instance.version);
|
||||||
});
|
});
|
||||||
|
|
||||||
//#region loginId
|
|
||||||
const params = new URLSearchParams(location.search);
|
const params = new URLSearchParams(location.search);
|
||||||
|
//#region loginId
|
||||||
const loginId = params.get('loginId');
|
const loginId = params.get('loginId');
|
||||||
|
|
||||||
if (loginId) {
|
if (loginId) {
|
||||||
@ -142,6 +142,17 @@ export async function common(createVue: () => App<Element>) {
|
|||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
//#region kawaii
|
||||||
|
if (params.has('kawaii') || params.has('uwu')) {
|
||||||
|
const v = params.get('kawaii') ?? params.get('uwu');
|
||||||
|
if (v === 'false' || v === '0' || v === 'no' || v === 'off') {
|
||||||
|
miLocalStorage.removeItem('kawaii');
|
||||||
|
} else {
|
||||||
|
miLocalStorage.setItem('kawaii', 'true');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
// NOTE: この処理は必ずクライアント更新チェック処理より後に来ること(テーマ再構築のため)
|
// NOTE: この処理は必ずクライアント更新チェック処理より後に来ること(テーマ再構築のため)
|
||||||
watch(defaultStore.reactiveState.darkMode, (darkMode) => {
|
watch(defaultStore.reactiveState.darkMode, (darkMode) => {
|
||||||
applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme'));
|
applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme'));
|
||||||
|
@ -6,7 +6,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="instance" :class="$style.root">
|
<div v-if="instance" :class="$style.root">
|
||||||
<div :class="[$style.main, $style.panel]">
|
<div :class="[$style.main, $style.panel]">
|
||||||
<img :src="instance.iconUrl || '/favicon.ico'" alt="" :class="$style.mainIcon"/>
|
<img v-if="miLocalStorage.getItem('kawaii')" src="/client-assets/kawaii/misskey-io.png" alt="Logo by @sawaratsuki@misskey.io" :class="$style.mainIconAlt"/>
|
||||||
|
<img v-else :src="instance.iconUrl || '/favicon.ico'" alt="" :class="$style.mainIcon"/>
|
||||||
<button class="_button _acrylic" :class="$style.mainMenu" @click="showMenu"><i class="ti ti-dots"></i></button>
|
<button class="_button _acrylic" :class="$style.mainMenu" @click="showMenu"><i class="ti ti-dots"></i></button>
|
||||||
<div :class="$style.mainFg">
|
<div :class="$style.mainFg">
|
||||||
<h1 :class="$style.mainTitle">
|
<h1 :class="$style.mainTitle">
|
||||||
@ -81,6 +82,7 @@ import * as os from '@/os.js';
|
|||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { instance } from '@/instance.js';
|
import { instance } from '@/instance.js';
|
||||||
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
import MkNumber from '@/components/MkNumber.vue';
|
import MkNumber from '@/components/MkNumber.vue';
|
||||||
import XActiveUsersChart from '@/components/MkVisitorDashboard.ActiveUsersChart.vue';
|
import XActiveUsersChart from '@/components/MkVisitorDashboard.ActiveUsersChart.vue';
|
||||||
import { openInstanceMenu } from '@/ui/_common_/common';
|
import { openInstanceMenu } from '@/ui/_common_/common';
|
||||||
@ -139,6 +141,13 @@ function exploreOtherServers() {
|
|||||||
filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.5));
|
filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mainIconAlt {
|
||||||
|
width: 85%;
|
||||||
|
margin-top: -47px;
|
||||||
|
vertical-align: bottom;
|
||||||
|
filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
.mainMenu {
|
.mainMenu {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 16px;
|
top: 16px;
|
||||||
|
@ -38,7 +38,8 @@ type Keys =
|
|||||||
`aiscript:${string}` |
|
`aiscript:${string}` |
|
||||||
'lastEmojisFetchedAt' | // DEPRECATED, stored in indexeddb (13.9.0~)
|
'lastEmojisFetchedAt' | // DEPRECATED, stored in indexeddb (13.9.0~)
|
||||||
'emojis' | // DEPRECATED, stored in indexeddb (13.9.0~);
|
'emojis' | // DEPRECATED, stored in indexeddb (13.9.0~);
|
||||||
`channelLastReadedAt:${string}`
|
`channelLastReadedAt:${string}` |
|
||||||
|
'kawaii'
|
||||||
|
|
||||||
export const miLocalStorage = {
|
export const miLocalStorage = {
|
||||||
getItem: (key: Keys): string | null => window.localStorage.getItem(key),
|
getItem: (key: Keys): string | null => window.localStorage.getItem(key),
|
||||||
|
@ -11,7 +11,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<div class="_gaps_m znqjceqz">
|
<div class="_gaps_m znqjceqz">
|
||||||
<div v-panel class="about">
|
<div v-panel class="about">
|
||||||
<div ref="containerEl" class="container" :class="{ playing: easterEggEngine != null }">
|
<div ref="containerEl" class="container" :class="{ playing: easterEggEngine != null }">
|
||||||
<img src="/client-assets/about-icon.png" alt="" class="icon" draggable="false" @load="iconLoaded" @click="gravity"/>
|
<img v-if="miLocalStorage.getItem('kawaii')" src="/client-assets/kawaii/about-icon.png" alt="" class="iconAlt" draggable="false" @load="iconLoaded" @click="gravity"/>
|
||||||
|
<img v-else src="/client-assets/about-icon.png" alt="" class="icon" draggable="false" @load="iconLoaded" @click="gravity"/>
|
||||||
|
<Mfm v-if="miLocalStorage.getItem('kawaii')" text="Logo by @sawaratsuki@misskey.io" class="iconCredit"/>
|
||||||
<div class="misskey">Misskey</div>
|
<div class="misskey">Misskey</div>
|
||||||
<div class="version">v{{ version }}</div>
|
<div class="version">v{{ version }}</div>
|
||||||
<span v-for="emoji in easterEggEmojis" :key="emoji.id" class="emoji" :data-physics-x="emoji.left" :data-physics-y="emoji.top" :class="{ _physics_circle_: !emoji.emoji.startsWith(':') }">
|
<span v-for="emoji in easterEggEmojis" :key="emoji.id" class="emoji" :data-physics-x="emoji.left" :data-physics-y="emoji.top" :class="{ _physics_circle_: !emoji.emoji.startsWith(':') }">
|
||||||
@ -137,6 +139,7 @@ import { physics } from '@/scripts/physics.js';
|
|||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { instance } from '@/instance.js';
|
import { instance } from '@/instance.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { claimAchievement, claimedAchievements } from '@/scripts/achievements.js';
|
import { claimAchievement, claimedAchievements } from '@/scripts/achievements.js';
|
||||||
@ -443,6 +446,21 @@ definePageMetadata(() => ({
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .iconAlt {
|
||||||
|
display: block;
|
||||||
|
width: 85%;
|
||||||
|
margin: 0 auto;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .iconCredit {
|
||||||
|
margin: 0 auto;
|
||||||
|
width: max-content;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
> .misskey {
|
> .misskey {
|
||||||
margin: 0.75em auto 0 auto;
|
margin: 0.75em auto 0 auto;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
|
@ -11,7 +11,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<div class="_gaps_m">
|
<div class="_gaps_m">
|
||||||
<div :class="$style.banner" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }">
|
<div :class="$style.banner" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }">
|
||||||
<div style="overflow: clip;">
|
<div style="overflow: clip;">
|
||||||
<img :src="instance.iconUrl ?? instance.faviconUrl ?? '/favicon.ico'" alt="" :class="$style.bannerIcon"/>
|
<img v-if="miLocalStorage.getItem('kawaii')" src="/client-assets/kawaii/misskey-io.png" alt="" :class="$style.bannerIconAlt"/>
|
||||||
|
<img v-else :src="instance.iconUrl ?? instance.faviconUrl ?? '/favicon.ico'" alt="" :class="$style.bannerIcon"/>
|
||||||
|
<Mfm v-if="miLocalStorage.getItem('kawaii')" text="Logo by @sawaratsuki@misskey.io" :class="$style.iconCredit"/>
|
||||||
<div :class="$style.bannerName">
|
<div :class="$style.bannerName">
|
||||||
<b>{{ instance.name ?? host }}</b>
|
<b>{{ instance.name ?? host }}</b>
|
||||||
</div>
|
</div>
|
||||||
@ -168,6 +170,7 @@ import { i18n } from '@/i18n.js';
|
|||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { claimAchievement } from '@/scripts/achievements.js';
|
import { claimAchievement } from '@/scripts/achievements.js';
|
||||||
import { instance } from '@/instance.js';
|
import { instance } from '@/instance.js';
|
||||||
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
initialTab?: string;
|
initialTab?: string;
|
||||||
@ -230,6 +233,12 @@ definePageMetadata(() => ({
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bannerIconAlt {
|
||||||
|
display: block;
|
||||||
|
margin: 16px auto 0 auto;
|
||||||
|
width: 85%;
|
||||||
|
}
|
||||||
|
|
||||||
.bannerName {
|
.bannerName {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
@ -238,6 +247,13 @@ definePageMetadata(() => ({
|
|||||||
background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
|
background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .iconCredit {
|
||||||
|
margin: 0 auto;
|
||||||
|
width: max-content;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.rules {
|
.rules {
|
||||||
counter-reset: item;
|
counter-reset: item;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
@ -110,7 +110,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<!--
|
<!--
|
||||||
*** LICENSE NOTICE ***
|
*** LICENSE NOTICE ***
|
||||||
* This SVG is derived from the https://skeb.jp/ website, All rights reserved to *Skeb Inc.* https://skeb.co.jp/
|
* This SVG is derived from the https://skeb.jp/ website, All rights reserved to *Skeb Inc.* https://skeb.co.jp/
|
||||||
* This resource SHOULD NOT be considered as a part of the this project that has licensed under AGPL-3.0-only
|
* This resource SHOULD NOT be considered as a part of this project that has licensed under AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
<svg class="ti ti-fw" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
|
<svg class="ti ti-fw" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
|
||||||
<linearGradient id="a" x1="14.645309%" x2="85.354691%" y1="14.645309%" y2="85.363492%">
|
<linearGradient id="a" x1="14.645309%" x2="85.354691%" y1="14.645309%" y2="85.363492%">
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* SPDX-License-Identifier: ISC
|
* SPDX-License-Identifier: ISC
|
||||||
*
|
*
|
||||||
* This file is derived from the project that has licensed under the ISC license.
|
* This file is derived from the project that has licensed under the ISC license.
|
||||||
* This file SHOULD NOT be considered as a part of the this project that has licensed under AGPL-3.0-only
|
* This file SHOULD NOT be considered as a part of this project that has licensed under AGPL-3.0-only
|
||||||
* Adapted from https://github.com/isaacs/ttlcache/blob/b6002f971e122e3b35e23d00ac6a8365d505c14d/examples/rate-limiter-window.ts
|
* Adapted from https://github.com/isaacs/ttlcache/blob/b6002f971e122e3b35e23d00ac6a8365d505c14d/examples/rate-limiter-window.ts
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<div :class="$style.top">
|
<div :class="$style.top">
|
||||||
<div :class="$style.banner" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div>
|
<div :class="$style.banner" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div>
|
||||||
<button v-tooltip.noDelay.right="instance.name ?? i18n.ts.instance" class="_button" :class="$style.instance" @click="openInstanceMenu">
|
<button v-tooltip.noDelay.right="instance.name ?? i18n.ts.instance" class="_button" :class="$style.instance" @click="openInstanceMenu">
|
||||||
<img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon"/>
|
<img v-if="miLocalStorage.getItem('kawaii')" src="/client-assets/kawaii/misskey-io.png" alt="" :class="$style.instanceIconAlt"/>
|
||||||
|
<img v-else :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.middle">
|
<div :class="$style.middle">
|
||||||
@ -68,6 +69,7 @@ import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js';
|
|||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { instance } from '@/instance.js';
|
import { instance } from '@/instance.js';
|
||||||
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
|
|
||||||
const iconOnly = ref(false);
|
const iconOnly = ref(false);
|
||||||
|
|
||||||
@ -173,6 +175,11 @@ function more(ev: MouseEvent) {
|
|||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.instanceIconAlt {
|
||||||
|
display: inline-block;
|
||||||
|
width: 85%;
|
||||||
|
}
|
||||||
|
|
||||||
.bottom {
|
.bottom {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user