to keep things manageable i merged a lot of one off values into just a handful of common sizes, so some parts of the ui will look different than upstream even with the "Misskey" rounding mode
248 lines
6.1 KiB
Vue
248 lines
6.1 KiB
Vue
<!--
|
|
SPDX-FileCopyrightText: syuilo and other misskey contributors
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
-->
|
|
|
|
<template>
|
|
<div v-if="meta" :class="$style.root">
|
|
<div :class="[$style.main, $style.panel]">
|
|
<img :src="instance.iconUrl || instance.faviconUrl || '/apple-touch-icon.png'" alt="" :class="$style.mainIcon"/>
|
|
<button class="_button _acrylic" :class="$style.mainMenu" @click="showMenu"><i class="ph-dots-three ph-bold ph-lg"></i></button>
|
|
<div :class="$style.mainFg">
|
|
<h1 :class="$style.mainTitle">
|
|
<!-- 背景色によってはロゴが見えなくなるのでとりあえず無効に -->
|
|
<!-- <img class="logo" v-if="meta.logoImageUrl" :src="meta.logoImageUrl"><span v-else class="text">{{ instanceName }}</span> -->
|
|
<span>{{ instanceName }}</span>
|
|
</h1>
|
|
<div :class="$style.mainAbout">
|
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
<div v-html="meta.description || i18n.ts.headlineMisskey"></div>
|
|
</div>
|
|
<div v-if="instance.disableRegistration" :class="$style.mainWarn">
|
|
<MkInfo warn>{{ i18n.ts.invitationRequiredToRegister }}</MkInfo>
|
|
</div>
|
|
<div v-if="instance.approvalRequiredForSignup" :class="$style.mainWarn">
|
|
<MkInfo warn>{{ i18n.ts.approvalRequiredToRegister }}</MkInfo>
|
|
</div>
|
|
<div class="_gaps_s" :class="$style.mainActions">
|
|
<MkButton :class="$style.mainAction" full rounded gradate data-cy-signup style="margin-right: 12px;" @click="signup()">{{ i18n.ts.joinThisServer }}</MkButton>
|
|
<MkButton :class="$style.mainAction" full rounded @click="exploreOtherServers()">{{ i18n.ts.exploreOtherServers }}</MkButton>
|
|
<MkButton :class="$style.mainAction" full rounded data-cy-signin @click="signin()">{{ i18n.ts.login }}</MkButton>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-if="stats" :class="$style.stats">
|
|
<div :class="[$style.statsItem, $style.panel]">
|
|
<div :class="$style.statsItemLabel">{{ i18n.ts.users }}</div>
|
|
<div :class="$style.statsItemCount"><MkNumber :value="stats.originalUsersCount"/></div>
|
|
</div>
|
|
<div :class="[$style.statsItem, $style.panel]">
|
|
<div :class="$style.statsItemLabel">{{ i18n.ts.notes }}</div>
|
|
<div :class="$style.statsItemCount"><MkNumber :value="stats.originalNotesCount"/></div>
|
|
</div>
|
|
</div>
|
|
<div v-if="instance.policies.ltlAvailable" :class="[$style.tl, $style.panel]">
|
|
<div :class="$style.tlHeader">{{ i18n.ts.letsLookAtTimeline }}</div>
|
|
<div :class="$style.tlBody">
|
|
<MkTimeline src="local"/>
|
|
</div>
|
|
</div>
|
|
<div :class="$style.panel">
|
|
<XActiveUsersChart/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { } from 'vue';
|
|
import * as Misskey from 'misskey-js';
|
|
import XTimeline from './welcome.timeline.vue';
|
|
import XSigninDialog from '@/components/MkSigninDialog.vue';
|
|
import XSignupDialog from '@/components/MkSignupDialog.vue';
|
|
import MkButton from '@/components/MkButton.vue';
|
|
import MkTimeline from '@/components/MkTimeline.vue';
|
|
import MkInfo from '@/components/MkInfo.vue';
|
|
import { instanceName } from '@/config.js';
|
|
import * as os from '@/os.js';
|
|
import { i18n } from '@/i18n.js';
|
|
import { instance } from '@/instance.js';
|
|
import number from '@/filters/number.js';
|
|
import MkNumber from '@/components/MkNumber.vue';
|
|
import XActiveUsersChart from '@/components/MkVisitorDashboard.ActiveUsersChart.vue';
|
|
|
|
let meta = $ref<Misskey.entities.Instance>();
|
|
let stats = $ref(null);
|
|
|
|
os.api('meta', { detail: true }).then(_meta => {
|
|
meta = _meta;
|
|
});
|
|
|
|
os.api('stats', {
|
|
}).then((res) => {
|
|
stats = res;
|
|
});
|
|
|
|
function signin() {
|
|
os.popup(XSigninDialog, {
|
|
autoSet: true,
|
|
}, {}, 'closed');
|
|
}
|
|
|
|
function signup() {
|
|
os.popup(XSignupDialog, {
|
|
autoSet: true,
|
|
}, {}, 'closed');
|
|
}
|
|
|
|
function showMenu(ev) {
|
|
os.popupMenu([{
|
|
text: i18n.ts.instanceInfo,
|
|
icon: 'ph-info ph-bold ph-lg',
|
|
action: () => {
|
|
os.pageWindow('/about');
|
|
},
|
|
}, {
|
|
text: i18n.ts.aboutMisskey,
|
|
icon: 'ph-info ph-bold ph-lg',
|
|
action: () => {
|
|
os.pageWindow('/about-sharkey');
|
|
},
|
|
}, null, (instance.impressumUrl) ? {
|
|
text: i18n.ts.impressum,
|
|
icon: 'ph-newspaper-clipping ph-bold pg-lg',
|
|
action: () => {
|
|
window.open(instance.impressumUrl, '_blank');
|
|
},
|
|
} : undefined, (instance.tosUrl) ? {
|
|
text: i18n.ts.termsOfService,
|
|
icon: 'ph-notebook ph-bold pg-lg',
|
|
action: () => {
|
|
window.open(instance.tosUrl, '_blank');
|
|
},
|
|
} : undefined, (instance.privacyPolicyUrl) ? {
|
|
text: i18n.ts.privacyPolicy,
|
|
icon: 'ph-shield ph-bold pg-lg',
|
|
action: () => {
|
|
window.open(instance.privacyPolicyUrl, '_blank');
|
|
},
|
|
} : undefined, (!instance.impressumUrl && !instance.tosUrl && !instance.privacyPolicyUrl) ? undefined : null, {
|
|
text: i18n.ts.help,
|
|
icon: 'ph-question ph-bold ph-lg',
|
|
action: () => {
|
|
window.open('https://misskey-hub.net/help.md', '_blank');
|
|
},
|
|
}], ev.currentTarget ?? ev.target);
|
|
}
|
|
|
|
function exploreOtherServers() {
|
|
window.open('https://joinsharkey.org/#findaninstance', '_blank');
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" module>
|
|
.root {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16px;
|
|
padding: 32px 0 0 0;
|
|
}
|
|
|
|
.panel {
|
|
position: relative;
|
|
background: var(--panel);
|
|
border-radius: var(--radius);
|
|
box-shadow: 0 12px 32px rgb(0 0 0 / 25%);
|
|
}
|
|
|
|
.main {
|
|
text-align: center;
|
|
}
|
|
|
|
.mainIcon {
|
|
width: 85px;
|
|
margin-top: -47px;
|
|
vertical-align: bottom;
|
|
filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.5));
|
|
}
|
|
|
|
.mainMenu {
|
|
position: absolute;
|
|
top: 16px;
|
|
right: 16px;
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: var(--radius-sm);
|
|
font-size: 18px;
|
|
}
|
|
|
|
.mainFg {
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
.mainTitle {
|
|
display: block;
|
|
margin: 0;
|
|
padding: 16px 32px 24px 32px;
|
|
font-size: 1.4em;
|
|
}
|
|
|
|
.mainLogo {
|
|
vertical-align: bottom;
|
|
max-height: 120px;
|
|
max-width: min(100%, 300px);
|
|
}
|
|
|
|
.mainAbout {
|
|
padding: 0 32px;
|
|
}
|
|
|
|
.mainWarn {
|
|
padding: 32px 32px 0 32px;
|
|
}
|
|
|
|
.mainActions {
|
|
padding: 32px;
|
|
}
|
|
|
|
.mainAction {
|
|
line-height: 28px;
|
|
}
|
|
|
|
.stats {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
grid-gap: 16px;
|
|
}
|
|
|
|
.statsItem {
|
|
overflow: clip;
|
|
padding: 16px 20px;
|
|
}
|
|
|
|
.statsItemLabel {
|
|
color: var(--fgTransparentWeak);
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
.statsItemCount {
|
|
font-weight: bold;
|
|
font-size: 1.2em;
|
|
color: var(--accent);
|
|
}
|
|
|
|
.tl {
|
|
overflow: clip;
|
|
}
|
|
|
|
.tlHeader {
|
|
padding: 12px 16px;
|
|
border-bottom: solid 1px var(--divider);
|
|
}
|
|
|
|
.tlBody {
|
|
height: 350px;
|
|
overflow: auto;
|
|
}
|
|
</style>
|