summaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/app/auth/script.ts1
-rw-r--r--src/client/app/auth/views/index.vue9
-rw-r--r--src/client/app/base.pug2
-rw-r--r--src/client/app/boot.js6
-rw-r--r--src/client/app/common/scripts/streaming/home.ts28
-rw-r--r--src/client/app/common/views/components/analog-clock.vue127
-rw-r--r--src/client/app/common/views/components/avatar.vue2
-rw-r--r--src/client/app/common/views/components/forkit.vue2
-rw-r--r--src/client/app/common/views/components/index.ts2
-rw-r--r--src/client/app/common/views/components/media-list.vue87
-rw-r--r--src/client/app/common/views/components/messaging-room.message.vue4
-rw-r--r--src/client/app/common/views/components/messaging-room.vue8
-rw-r--r--src/client/app/common/views/components/messaging.vue2
-rw-r--r--src/client/app/common/views/components/note-menu.vue12
-rw-r--r--src/client/app/common/views/components/othello.game.vue10
-rw-r--r--src/client/app/common/views/components/othello.gameroom.vue2
-rw-r--r--src/client/app/common/views/components/othello.room.vue16
-rw-r--r--src/client/app/common/views/components/twitter-setting.vue14
-rw-r--r--src/client/app/common/views/components/uploader.vue2
-rw-r--r--src/client/app/common/views/components/url-preview.vue23
-rw-r--r--src/client/app/common/views/components/welcome-timeline.vue2
-rw-r--r--src/client/app/common/views/widgets/analog-clock.vue41
-rw-r--r--src/client/app/common/views/widgets/index.ts4
-rw-r--r--src/client/app/common/views/widgets/memo.vue111
-rw-r--r--src/client/app/common/views/widgets/rss.vue13
-rw-r--r--src/client/app/desktop/api/choose-drive-file.ts17
-rw-r--r--src/client/app/desktop/api/choose-drive-folder.ts15
-rw-r--r--src/client/app/desktop/api/contextmenu.ts17
-rw-r--r--src/client/app/desktop/api/dialog.ts19
-rw-r--r--src/client/app/desktop/api/input.ts21
-rw-r--r--src/client/app/desktop/api/notify.ts13
-rw-r--r--src/client/app/desktop/api/post.ts21
-rw-r--r--src/client/app/desktop/api/update-avatar.ts32
-rw-r--r--src/client/app/desktop/api/update-banner.ts32
-rw-r--r--src/client/app/desktop/assets/header-icon.dark.svg150
-rw-r--r--src/client/app/desktop/assets/header-icon.light.svg150
-rw-r--r--src/client/app/desktop/assets/header-logo-white.svg25
-rw-r--r--src/client/app/desktop/assets/header-logo.svg25
-rw-r--r--src/client/app/desktop/script.ts13
-rw-r--r--src/client/app/desktop/style.styl51
-rw-r--r--src/client/app/desktop/views/components/analog-clock.vue108
-rw-r--r--src/client/app/desktop/views/components/calendar.vue36
-rw-r--r--src/client/app/desktop/views/components/drive.file.vue6
-rw-r--r--src/client/app/desktop/views/components/drive.folder.vue2
-rw-r--r--src/client/app/desktop/views/components/drive.vue2
-rw-r--r--src/client/app/desktop/views/components/home.vue44
-rw-r--r--src/client/app/desktop/views/components/index.ts2
-rw-r--r--src/client/app/desktop/views/components/note-detail.sub.vue123
-rw-r--r--src/client/app/desktop/views/components/note-detail.vue9
-rw-r--r--src/client/app/desktop/views/components/note-preview.vue47
-rw-r--r--src/client/app/desktop/views/components/notes.note.sub.vue22
-rw-r--r--src/client/app/desktop/views/components/notes.note.vue36
-rw-r--r--src/client/app/desktop/views/components/notes.vue12
-rw-r--r--src/client/app/desktop/views/components/post-form-window.vue2
-rw-r--r--src/client/app/desktop/views/components/post-form.vue31
-rw-r--r--src/client/app/desktop/views/components/settings.2fa.vue8
-rw-r--r--src/client/app/desktop/views/components/settings.api.vue2
-rw-r--r--src/client/app/desktop/views/components/settings.profile.vue18
-rw-r--r--src/client/app/desktop/views/components/settings.vue20
-rw-r--r--src/client/app/desktop/views/components/sub-note-content.vue9
-rw-r--r--src/client/app/desktop/views/components/timeline.core.vue36
-rw-r--r--src/client/app/desktop/views/components/timeline.vue24
-rw-r--r--src/client/app/desktop/views/components/ui-notification.vue14
-rw-r--r--src/client/app/desktop/views/components/ui.header.account.vue6
-rw-r--r--src/client/app/desktop/views/components/ui.header.clock.vue2
-rw-r--r--src/client/app/desktop/views/components/ui.header.nav.vue33
-rw-r--r--src/client/app/desktop/views/components/ui.header.notifications.vue39
-rw-r--r--src/client/app/desktop/views/components/ui.header.vue20
-rw-r--r--src/client/app/desktop/views/components/ui.vue2
-rw-r--r--src/client/app/desktop/views/components/user-list-timeline.vue18
-rw-r--r--src/client/app/desktop/views/components/user-preview.vue2
-rw-r--r--src/client/app/desktop/views/components/users-list.vue2
-rw-r--r--src/client/app/desktop/views/components/widget-container.vue6
-rw-r--r--src/client/app/desktop/views/components/window.vue15
-rw-r--r--src/client/app/desktop/views/pages/favorites.vue5
-rw-r--r--src/client/app/desktop/views/pages/home.vue33
-rw-r--r--src/client/app/desktop/views/pages/index.vue2
-rw-r--r--src/client/app/desktop/views/pages/user/user.header.vue2
-rw-r--r--src/client/app/desktop/views/pages/user/user.home.vue2
-rw-r--r--src/client/app/desktop/views/pages/user/user.profile.vue2
-rw-r--r--src/client/app/desktop/views/pages/user/user.timeline.vue17
-rw-r--r--src/client/app/desktop/views/pages/welcome.vue185
-rw-r--r--src/client/app/desktop/views/widgets/activity.vue2
-rw-r--r--src/client/app/desktop/views/widgets/post-form.vue15
-rw-r--r--src/client/app/desktop/views/widgets/profile.vue8
-rw-r--r--src/client/app/init.ts11
-rw-r--r--src/client/app/mios.ts79
-rw-r--r--src/client/app/mobile/script.ts6
-rw-r--r--src/client/app/mobile/views/components/drive.file-detail.vue2
-rw-r--r--src/client/app/mobile/views/components/drive.vue16
-rw-r--r--src/client/app/mobile/views/components/friends-maker.vue10
-rw-r--r--src/client/app/mobile/views/components/note-detail.sub.vue101
-rw-r--r--src/client/app/mobile/views/components/note-detail.vue23
-rw-r--r--src/client/app/mobile/views/components/note-preview.vue74
-rw-r--r--src/client/app/mobile/views/components/note.sub.vue65
-rw-r--r--src/client/app/mobile/views/components/note.vue56
-rw-r--r--src/client/app/mobile/views/components/notes.vue16
-rw-r--r--src/client/app/mobile/views/components/post-form.vue77
-rw-r--r--src/client/app/mobile/views/components/sub-note-content.vue7
-rw-r--r--src/client/app/mobile/views/components/ui.header.vue64
-rw-r--r--src/client/app/mobile/views/components/ui.nav.vue85
-rw-r--r--src/client/app/mobile/views/components/ui.vue6
-rw-r--r--src/client/app/mobile/views/components/user-list-timeline.vue36
-rw-r--r--src/client/app/mobile/views/components/user-timeline.vue9
-rw-r--r--src/client/app/mobile/views/components/users-list.vue2
-rw-r--r--src/client/app/mobile/views/pages/favorites.vue94
-rw-r--r--src/client/app/mobile/views/pages/home.timeline.vue18
-rw-r--r--src/client/app/mobile/views/pages/home.vue32
-rw-r--r--src/client/app/mobile/views/pages/index.vue2
-rw-r--r--src/client/app/mobile/views/pages/notifications.vue2
-rw-r--r--src/client/app/mobile/views/pages/settings.vue24
-rw-r--r--src/client/app/mobile/views/pages/settings/settings.profile.vue30
-rw-r--r--src/client/app/mobile/views/pages/user-list.vue70
-rw-r--r--src/client/app/mobile/views/pages/user-lists.vue68
-rw-r--r--src/client/app/mobile/views/pages/user.vue2
-rw-r--r--src/client/app/mobile/views/pages/user/home.vue2
-rw-r--r--src/client/app/mobile/views/pages/widgets.vue24
-rw-r--r--src/client/app/mobile/views/widgets/activity.vue2
-rw-r--r--src/client/app/mobile/views/widgets/profile.vue8
-rw-r--r--src/client/app/store.ts59
-rw-r--r--src/client/assets/title.dark.svg140
-rw-r--r--src/client/assets/title.light.svg140
-rw-r--r--src/client/assets/welcome-bg.dark.svg1
-rw-r--r--src/client/assets/welcome-bg.light.svg1
-rw-r--r--src/client/assets/welcome-bg.svg579
-rw-r--r--src/client/assets/welcome-fg.svg380
126 files changed, 2273 insertions, 2312 deletions
diff --git a/src/client/app/auth/script.ts b/src/client/app/auth/script.ts
index 20f59bf033..fd985c46ad 100644
--- a/src/client/app/auth/script.ts
+++ b/src/client/app/auth/script.ts
@@ -20,6 +20,7 @@ init(launch => {
// Init router
const router = new VueRouter({
mode: 'history',
+ base: '/auth/',
routes: [
{ path: '/:token', component: Index },
]
diff --git a/src/client/app/auth/views/index.vue b/src/client/app/auth/views/index.vue
index 0fcd9bfe53..826bcd125d 100644
--- a/src/client/app/auth/views/index.vue
+++ b/src/client/app/auth/views/index.vue
@@ -1,6 +1,6 @@
<template>
<div class="index">
- <main v-if="os.isSignedIn">
+ <main v-if="$store.getters.isSignedIn">
<p class="fetching" v-if="fetching">読み込み中<mk-ellipsis/></p>
<x-form
ref="form"
@@ -22,7 +22,7 @@
<p>セッションが存在しません。</p>
</div>
</main>
- <main class="signin" v-if="!os.isSignedIn">
+ <main class="signin" v-if="!$store.getters.isSignedIn">
<h1>サインインしてください</h1>
<mk-signin/>
</main>
@@ -51,7 +51,7 @@ export default Vue.extend({
}
},
mounted() {
- if (!this.$root.$data.os.isSignedIn) return;
+ if (!this.$store.getters.isSignedIn) return;
// Fetch session
(this as any).api('auth/session/show', {
@@ -62,7 +62,7 @@ export default Vue.extend({
// 既に連携していた場合
if (this.session.app.isAuthorized) {
- this.$root.$data.os.api('auth/accept', {
+ (this as any).api('auth/accept', {
token: this.session.token
}).then(() => {
this.accepted();
@@ -72,6 +72,7 @@ export default Vue.extend({
}
}).catch(error => {
this.state = 'fetch-session-error';
+ this.fetching = false;
});
},
methods: {
diff --git a/src/client/app/base.pug b/src/client/app/base.pug
index c182fd6f64..a77a8a9595 100644
--- a/src/client/app/base.pug
+++ b/src/client/app/base.pug
@@ -19,7 +19,7 @@ html
| Misskey
block desc
- meta(name='description' content='A SNS')
+ meta(name='description' content='A planet of fediverse')
block meta
diff --git a/src/client/app/boot.js b/src/client/app/boot.js
index 7b884c8a54..08c3fdeaee 100644
--- a/src/client/app/boot.js
+++ b/src/client/app/boot.js
@@ -32,9 +32,9 @@
//#region Detect app name
let app = null;
- if (url.pathname == '/docs') app = 'docs';
- if (url.pathname == '/dev') app = 'dev';
- if (url.pathname == '/auth') app = 'auth';
+ if (url.pathname == '/docs' || url.pathname.startsWith('/docs/')) app = 'docs';
+ if (url.pathname == '/dev' || url.pathname.startsWith('/dev/')) app = 'dev';
+ if (url.pathname == '/auth' || url.pathname.startsWith('/auth/')) app = 'auth';
//#endregion
//#region Detect the user language
diff --git a/src/client/app/common/scripts/streaming/home.ts b/src/client/app/common/scripts/streaming/home.ts
index 44d07e331a..50bbb56896 100644
--- a/src/client/app/common/scripts/streaming/home.ts
+++ b/src/client/app/common/scripts/streaming/home.ts
@@ -24,10 +24,32 @@ export class HomeStream extends Stream {
if (os.debug) {
console.log('I updated:', i);
}
- merge(me, i);
- // キャッシュ更新
- os.bakeMe();
+ os.store.dispatch('mergeMe', i);
+ });
+
+ this.on('read_all_notifications', () => {
+ os.store.dispatch('mergeMe', {
+ hasUnreadNotification: false
+ });
+ });
+
+ this.on('unread_notification', () => {
+ os.store.dispatch('mergeMe', {
+ hasUnreadNotification: true
+ });
+ });
+
+ this.on('read_all_messaging_messages', () => {
+ os.store.dispatch('mergeMe', {
+ hasUnreadMessagingMessage: false
+ });
+ });
+
+ this.on('unread_messaging_message', () => {
+ os.store.dispatch('mergeMe', {
+ hasUnreadMessagingMessage: true
+ });
});
this.on('clientSettingUpdated', x => {
diff --git a/src/client/app/common/views/components/analog-clock.vue b/src/client/app/common/views/components/analog-clock.vue
new file mode 100644
index 0000000000..53fb2a8dad
--- /dev/null
+++ b/src/client/app/common/views/components/analog-clock.vue
@@ -0,0 +1,127 @@
+<template>
+<svg class="mk-analog-clock" viewBox="0 0 10 10" preserveAspectRatio="none">
+ <circle v-for="angle, i in graduations"
+ :cx="5 + (Math.sin(angle) * (5 - graduationsPadding))"
+ :cy="5 - (Math.cos(angle) * (5 - graduationsPadding))"
+ :r="i % 5 == 0 ? 0.125 : 0.05"
+ :fill="i % 5 == 0 ? majorGraduationColor : minorGraduationColor"/>
+
+ <line
+ :x1="5 - (Math.sin(sAngle) * (sHandLengthRatio * handsTailLength))"
+ :y1="5 + (Math.cos(sAngle) * (sHandLengthRatio * handsTailLength))"
+ :x2="5 + (Math.sin(sAngle) * ((sHandLengthRatio * 5) - handsPadding))"
+ :y2="5 - (Math.cos(sAngle) * ((sHandLengthRatio * 5) - handsPadding))"
+ :stroke="sHandColor"
+ stroke-width="0.05"/>
+ <line
+ :x1="5 - (Math.sin(mAngle) * (mHandLengthRatio * handsTailLength))"
+ :y1="5 + (Math.cos(mAngle) * (mHandLengthRatio * handsTailLength))"
+ :x2="5 + (Math.sin(mAngle) * ((mHandLengthRatio * 5) - handsPadding))"
+ :y2="5 - (Math.cos(mAngle) * ((mHandLengthRatio * 5) - handsPadding))"
+ :stroke="mHandColor"
+ stroke-width="0.1"/>
+ <line
+ :x1="5 - (Math.sin(hAngle) * (hHandLengthRatio * handsTailLength))"
+ :y1="5 + (Math.cos(hAngle) * (hHandLengthRatio * handsTailLength))"
+ :x2="5 + (Math.sin(hAngle) * ((hHandLengthRatio * 5) - handsPadding))"
+ :y2="5 - (Math.cos(hAngle) * ((hHandLengthRatio * 5) - handsPadding))"
+ :stroke="hHandColor"
+ stroke-width="0.1"/>
+</svg>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import { themeColor } from '../../../config';
+
+export default Vue.extend({
+ props: {
+ dark: {
+ type: Boolean,
+ default: false
+ }
+ },
+
+ data() {
+ return {
+ now: new Date(),
+ clock: null,
+
+ graduationsPadding: 0.5,
+ handsPadding: 1,
+ handsTailLength: 0.7,
+ hHandLengthRatio: 0.75,
+ mHandLengthRatio: 1,
+ sHandLengthRatio: 1
+ };
+ },
+
+ computed: {
+ majorGraduationColor(): string {
+ return this.dark ? 'rgba(255, 255, 255, 0.3)' : 'rgba(0, 0, 0, 0.3)';
+ },
+ minorGraduationColor(): string {
+ return this.dark ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)';
+ },
+
+ sHandColor(): string {
+ return this.dark ? 'rgba(255, 255, 255, 0.5)' : 'rgba(0, 0, 0, 0.3)';
+ },
+ mHandColor(): string {
+ return this.dark ? '#fff' : '#777';
+ },
+ hHandColor(): string {
+ return themeColor;
+ },
+
+ s(): number {
+ return this.now.getSeconds();
+ },
+ m(): number {
+ return this.now.getMinutes();
+ },
+ h(): number {
+ return this.now.getHours();
+ },
+
+ hAngle(): number {
+ return Math.PI * (this.h % 12 + this.m / 60) / 6;
+ },
+ mAngle(): number {
+ return Math.PI * (this.m + this.s / 60) / 30;
+ },
+ sAngle(): number {
+ return Math.PI * this.s / 30;
+ },
+
+ graduations(): any {
+ const angles = [];
+ for (let i = 0; i < 60; i++) {
+ const angle = Math.PI * i / 30;
+ angles.push(angle);
+ }
+
+ return angles;
+ }
+ },
+
+ mounted() {
+ this.clock = setInterval(this.tick, 1000);
+ },
+
+ beforeDestroy() {
+ clearInterval(this.clock);
+ },
+
+ methods: {
+ tick() {
+ this.now = new Date();
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+.mk-analog-clock
+ display block
+</style>
diff --git a/src/client/app/common/views/components/avatar.vue b/src/client/app/common/views/components/avatar.vue
index 3e1b17635f..a65b62882f 100644
--- a/src/client/app/common/views/components/avatar.vue
+++ b/src/client/app/common/views/components/avatar.vue
@@ -32,7 +32,7 @@ export default Vue.extend({
? `rgb(${ this.user.avatarColor.join(',') })`
: null,
backgroundImage: this.lightmode ? null : `url(${ this.user.avatarUrl }?thumbnail)`,
- borderRadius: (this as any).clientSettings.circleIcons ? '100%' : null
+ borderRadius: this.$store.state.settings.circleIcons ? '100%' : null
};
}
}
diff --git a/src/client/app/common/views/components/forkit.vue b/src/client/app/common/views/components/forkit.vue
index 2a463ebfd7..bb71db19db 100644
--- a/src/client/app/common/views/components/forkit.vue
+++ b/src/client/app/common/views/components/forkit.vue
@@ -13,7 +13,7 @@
.a
display block
- position absolute
+ position fixed
top 0
right 0
diff --git a/src/client/app/common/views/components/index.ts b/src/client/app/common/views/components/index.ts
index c1a7bc61d7..df74f5ddfb 100644
--- a/src/client/app/common/views/components/index.ts
+++ b/src/client/app/common/views/components/index.ts
@@ -1,5 +1,6 @@
import Vue from 'vue';
+import analogClock from './analog-clock.vue';
import signin from './signin.vue';
import signup from './signup.vue';
import forkit from './forkit.vue';
@@ -27,6 +28,7 @@ import Switch from './switch.vue';
import Othello from './othello.vue';
import welcomeTimeline from './welcome-timeline.vue';
+Vue.component('mk-analog-clock', analogClock);
Vue.component('mk-signin', signin);
Vue.component('mk-signup', signup);
Vue.component('mk-forkit', forkit);
diff --git a/src/client/app/common/views/components/media-list.vue b/src/client/app/common/views/components/media-list.vue
index ff9d5e1022..2f8a1943ad 100644
--- a/src/client/app/common/views/components/media-list.vue
+++ b/src/client/app/common/views/components/media-list.vue
@@ -1,9 +1,11 @@
<template>
-<div class="mk-media-list" :data-count="mediaList.length">
- <template v-for="media in mediaList">
- <mk-media-video :video="media" :key="media.id" v-if="media.type.startsWith('video')" :inline-playable="mediaList.length === 1"/>
- <mk-media-image :image="media" :key="media.id" v-else :raw="raw"/>
- </template>
+<div class="mk-media-list">
+ <div :data-count="mediaList.length" ref="grid">
+ <template v-for="media in mediaList">
+ <mk-media-video :video="media" :key="media.id" v-if="media.type.startsWith('video')" :inline-playable="mediaList.length === 1"/>
+ <mk-media-image :image="media" :key="media.id" v-else :raw="raw"/>
+ </template>
+ </div>
</div>
</template>
@@ -18,47 +20,60 @@ export default Vue.extend({
raw: {
default: false
}
+ },
+ mounted() {
+ // for Safari bug
+ this.$refs.grid.style.height = this.$refs.grid.clientHeight ? `${this.$refs.grid.clientHeight}px` : '128px';
}
});
</script>
<style lang="stylus" scoped>
.mk-media-list
- display grid
- grid-gap 4px
- height 256px
+ width 100%
- @media (max-width 500px)
- height 192px
+ &:before
+ content ''
+ display block
+ padding-top 56.25% // 16:9
+
+ > div
+ position absolute
+ top 0
+ right 0
+ bottom 0
+ left 0
+ display grid
+ grid-gap 4px
+
+ &[data-count="1"]
+ grid-template-rows 1fr
+ &[data-count="2"]
+ grid-template-columns 1fr 1fr
+ grid-template-rows 1fr
+ &[data-count="3"]
+ grid-template-columns 1fr 0.5fr
+ grid-template-rows 1fr 1fr
+ :nth-child(1)
+ grid-row 1 / 3
+ :nth-child(3)
+ grid-column 2 / 3
+ grid-row 2 / 3
+ &[data-count="4"]
+ grid-template-columns 1fr 1fr
+ grid-template-rows 1fr 1fr
- &[data-count="1"]
- grid-template-rows 1fr
- &[data-count="2"]
- grid-template-columns 1fr 1fr
- grid-template-rows 1fr
- &[data-count="3"]
- grid-template-columns 1fr 0.5fr
- grid-template-rows 1fr 1fr
:nth-child(1)
- grid-row 1 / 3
+ grid-column 1 / 2
+ grid-row 1 / 2
+ :nth-child(2)
+ grid-column 2 / 3
+ grid-row 1 / 2
:nth-child(3)
+ grid-column 1 / 2
+ grid-row 2 / 3
+ :nth-child(4)
grid-column 2 / 3
- grid-row 2/3
- &[data-count="4"]
- grid-template-columns 1fr 1fr
- grid-template-rows 1fr 1fr
-
- :nth-child(1)
- grid-column 1 / 2
- grid-row 1 / 2
- :nth-child(2)
- grid-column 2 / 3
- grid-row 1 / 2
- :nth-child(3)
- grid-column 1 / 2
- grid-row 2 / 3
- :nth-child(4)
- grid-column 2 / 3
- grid-row 2 / 3
+ grid-row 2 / 3
</style>
diff --git a/src/client/app/common/views/components/messaging-room.message.vue b/src/client/app/common/views/components/messaging-room.message.vue
index ef39199dc4..a77b5f3658 100644
--- a/src/client/app/common/views/components/messaging-room.message.vue
+++ b/src/client/app/common/views/components/messaging-room.message.vue
@@ -8,7 +8,7 @@
<img src="/assets/desktop/messaging/delete.png" alt="Delete"/>
</button>
<div class="content" v-if="!message.isDeleted">
- <mk-note-html class="text" v-if="message.text" ref="text" :text="message.text" :i="os.i"/>
+ <mk-note-html class="text" v-if="message.text" ref="text" :text="message.text" :i="$store.state.i"/>
<div class="file" v-if="message.file">
<a :href="message.file.url" target="_blank" :title="message.file.name">
<img v-if="message.file.type.split('/')[0] == 'image'" :src="message.file.url" :alt="message.file.name"/>
@@ -42,7 +42,7 @@ export default Vue.extend({
},
computed: {
isMe(): boolean {
- return this.message.userId == (this as any).os.i.id;
+ return this.message.userId == this.$store.state.i.id;
},
urls(): string[] {
if (this.message.text) {
diff --git a/src/client/app/common/views/components/messaging-room.vue b/src/client/app/common/views/components/messaging-room.vue
index 79756b22eb..b2831d6928 100644
--- a/src/client/app/common/views/components/messaging-room.vue
+++ b/src/client/app/common/views/components/messaging-room.vue
@@ -72,7 +72,7 @@ export default Vue.extend({
},
mounted() {
- this.connection = new MessagingStream((this as any).os, (this as any).os.i, this.user.id);
+ this.connection = new MessagingStream((this as any).os, this.$store.state.i, this.user.id);
this.connection.on('message', this.onMessage);
this.connection.on('read', this.onRead);
@@ -164,7 +164,7 @@ export default Vue.extend({
const isBottom = this.isBottom();
this.messages.push(message);
- if (message.userId != (this as any).os.i.id && !document.hidden) {
+ if (message.userId != this.$store.state.i.id && !document.hidden) {
this.connection.send({
type: 'read',
id: message.id
@@ -176,7 +176,7 @@ export default Vue.extend({
this.$nextTick(() => {
this.scrollToBottom();
});
- } else if (message.userId != (this as any).os.i.id) {
+ } else if (message.userId != this.$store.state.i.id) {
// Notify
this.notifyNewMessage();
}
@@ -229,7 +229,7 @@ export default Vue.extend({
onVisibilitychange() {
if (document.hidden) return;
this.messages.forEach(message => {
- if (message.userId !== (this as any).os.i.id && !message.isRead) {
+ if (message.userId !== this.$store.state.i.id && !message.isRead) {
this.connection.send({
type: 'read',
id: message.id
diff --git a/src/client/app/common/views/components/messaging.vue b/src/client/app/common/views/components/messaging.vue
index 11f9c366d4..2ddec29984 100644
--- a/src/client/app/common/views/components/messaging.vue
+++ b/src/client/app/common/views/components/messaging.vue
@@ -95,7 +95,7 @@ export default Vue.extend({
methods: {
getAcct,
isMe(message) {
- return message.userId == (this as any).os.i.id;
+ return message.userId == this.$store.state.i.id;
},
onMessage(message) {
this.messages = this.messages.filter(m => !(
diff --git a/src/client/app/common/views/components/note-menu.vue b/src/client/app/common/views/components/note-menu.vue
index 88dc22aaf4..a400610a2b 100644
--- a/src/client/app/common/views/components/note-menu.vue
+++ b/src/client/app/common/views/components/note-menu.vue
@@ -3,7 +3,8 @@
<div class="backdrop" ref="backdrop" @click="close"></div>
<div class="popover" :class="{ compact }" ref="popover">
<button @click="favorite">%i18n:@favorite%</button>
- <button v-if="note.userId == os.i.id" @click="pin">%i18n:@pin%</button>
+ <button v-if="note.userId == $store.state.i.id" @click="pin">%i18n:@pin%</button>
+ <button v-if="note.userId == $store.state.i.id" @click="del">%i18n:@delete%</button>
<a v-if="note.uri" :href="note.uri" target="_blank">%i18n:@remote%</a>
</div>
</div>
@@ -59,6 +60,15 @@ export default Vue.extend({
});
},
+ del() {
+ if (!window.confirm('%i18n:@delete-confirm%')) return;
+ (this as any).api('notes/delete', {
+ noteId: this.note.id
+ }).then(() => {
+ this.$destroy();
+ });
+ },
+
favorite() {
(this as any).api('notes/favorites/create', {
noteId: this.note.id
diff --git a/src/client/app/common/views/components/othello.game.vue b/src/client/app/common/views/components/othello.game.vue
index ea75558d10..4c63bd18b8 100644
--- a/src/client/app/common/views/components/othello.game.vue
+++ b/src/client/app/common/views/components/othello.game.vue
@@ -61,13 +61,13 @@ export default Vue.extend({
computed: {
iAmPlayer(): boolean {
- if (!(this as any).os.isSignedIn) return false;
- return this.game.user1Id == (this as any).os.i.id || this.game.user2Id == (this as any).os.i.id;
+ if (!this.$store.getters.isSignedIn) return false;
+ return this.game.user1Id == this.$store.state.i.id || this.game.user2Id == this.$store.state.i.id;
},
myColor(): Color {
if (!this.iAmPlayer) return null;
- if (this.game.user1Id == (this as any).os.i.id && this.game.black == 1) return true;
- if (this.game.user2Id == (this as any).os.i.id && this.game.black == 2) return true;
+ if (this.game.user1Id == this.$store.state.i.id && this.game.black == 1) return true;
+ if (this.game.user2Id == this.$store.state.i.id && this.game.black == 2) return true;
return false;
},
opColor(): Color {
@@ -91,7 +91,7 @@ export default Vue.extend({
},
isMyTurn(): boolean {
if (this.turnUser == null) return null;
- return this.turnUser.id == (this as any).os.i.id;
+ return this.turnUser.id == this.$store.state.i.id;
}
},
diff --git a/src/client/app/common/views/components/othello.gameroom.vue b/src/client/app/common/views/components/othello.gameroom.vue
index dba9ccd16d..2dbd04ce49 100644
--- a/src/client/app/common/views/components/othello.gameroom.vue
+++ b/src/client/app/common/views/components/othello.gameroom.vue
@@ -25,7 +25,7 @@ export default Vue.extend({
},
created() {
this.g = this.game;
- this.connection = new OthelloGameStream((this as any).os, (this as any).os.i, this.game);
+ this.connection = new OthelloGameStream((this as any).os, this.$store.state.i, this.game);
this.connection.on('started', this.onStarted);
},
beforeDestroy() {
diff --git a/src/client/app/common/views/components/othello.room.vue b/src/client/app/common/views/components/othello.room.vue
index 86368b3cc3..dcf41f2e04 100644
--- a/src/client/app/common/views/components/othello.room.vue
+++ b/src/client/app/common/views/components/othello.room.vue
@@ -116,13 +116,13 @@ export default Vue.extend({
return categories.filter((item, pos) => categories.indexOf(item) == pos);
},
isAccepted(): boolean {
- if (this.game.user1Id == (this as any).os.i.id && this.game.user1Accepted) return true;
- if (this.game.user2Id == (this as any).os.i.id && this.game.user2Accepted) return true;
+ if (this.game.user1Id == this.$store.state.i.id && this.game.user1Accepted) return true;
+ if (this.game.user2Id == this.$store.state.i.id && this.game.user2Accepted) return true;
return false;
},
isOpAccepted(): boolean {
- if (this.game.user1Id != (this as any).os.i.id && this.game.user1Accepted) return true;
- if (this.game.user2Id != (this as any).os.i.id && this.game.user2Accepted) return true;
+ if (this.game.user1Id != this.$store.state.i.id && this.game.user1Accepted) return true;
+ if (this.game.user2Id != this.$store.state.i.id && this.game.user2Accepted) return true;
return false;
}
},
@@ -133,8 +133,8 @@ export default Vue.extend({
this.connection.on('init-form', this.onInitForm);
this.connection.on('message', this.onMessage);
- if (this.game.user1Id != (this as any).os.i.id && this.game.settings.form1) this.form = this.game.settings.form1;
- if (this.game.user2Id != (this as any).os.i.id && this.game.settings.form2) this.form = this.game.settings.form2;
+ if (this.game.user1Id != this.$store.state.i.id && this.game.settings.form1) this.form = this.game.settings.form1;
+ if (this.game.user2Id != this.$store.state.i.id && this.game.settings.form2) this.form = this.game.settings.form2;
},
beforeDestroy() {
@@ -185,12 +185,12 @@ export default Vue.extend({
},
onInitForm(x) {
- if (x.userId == (this as any).os.i.id) return;
+ if (x.userId == this.$store.state.i.id) return;
this.form = x.form;
},
onMessage(x) {
- if (x.userId == (this as any).os.i.id) return;
+ if (x.userId == this.$store.state.i.id) return;
this.messages.unshift(x.message);
},
diff --git a/src/client/app/common/views/components/twitter-setting.vue b/src/client/app/common/views/components/twitter-setting.vue
index 9a2a1c3d40..d1cb78c544 100644
--- a/src/client/app/common/views/components/twitter-setting.vue
+++ b/src/client/app/common/views/components/twitter-setting.vue
@@ -1,13 +1,13 @@
<template>
<div class="mk-twitter-setting">
<p>%i18n:@description%<a :href="`${docsUrl}/link-to-twitter`" target="_blank">%i18n:@detail%</a></p>
- <p class="account" v-if="os.i.twitter" :title="`Twitter ID: ${os.i.twitter.userId}`">%i18n:@connected-to%: <a :href="`https://twitter.com/${os.i.twitter.screenName}`" target="_blank">@{{ os.i.twitter.screenName }}</a></p>
+ <p class="account" v-if="$store.state.i.twitter" :title="`Twitter ID: ${$store.state.i.twitter.userId}`">%i18n:@connected-to%: <a :href="`https://twitter.com/${$store.state.i.twitter.screenName}`" target="_blank">@{{ $store.state.i.twitter.screenName }}</a></p>
<p>
- <a :href="`${apiUrl}/connect/twitter`" target="_blank" @click.prevent="connect">{{ os.i.twitter ? '%i18n:@reconnect%' : '%i18n:@connect%' }}</a>
- <span v-if="os.i.twitter"> or </span>
- <a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="os.i.twitter" @click.prevent="disconnect">%i18n:@disconnect%</a>
+ <a :href="`${apiUrl}/connect/twitter`" target="_blank" @click.prevent="connect">{{ $store.state.i.twitter ? '%i18n:@reconnect%' : '%i18n:@connect%' }}</a>
+ <span v-if="$store.state.i.twitter"> or </span>
+ <a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="$store.state.i.twitter" @click.prevent="disconnect">%i18n:@disconnect%</a>
</p>
- <p class="id" v-if="os.i.twitter">Twitter ID: {{ os.i.twitter.userId }}</p>
+ <p class="id" v-if="$store.state.i.twitter">Twitter ID: {{ $store.state.i.twitter.userId }}</p>
</div>
</template>
@@ -24,8 +24,8 @@ export default Vue.extend({
};
},
mounted() {
- this.$watch('os.i', () => {
- if ((this as any).os.i.twitter) {
+ this.$watch('$store.state.i', () => {
+ if (this.$store.state.i.twitter) {
if (this.form) this.form.close();
}
}, {
diff --git a/src/client/app/common/views/components/uploader.vue b/src/client/app/common/views/components/uploader.vue
index a6caa80f3c..f4797d89f7 100644
--- a/src/client/app/common/views/components/uploader.vue
+++ b/src/client/app/common/views/components/uploader.vue
@@ -50,7 +50,7 @@ export default Vue.extend({
reader.readAsDataURL(file);
const data = new FormData();
- data.append('i', (this as any).os.i.token);
+ data.append('i', this.$store.state.i.token);
data.append('file', file);
if (folder) data.append('folderId', folder);
diff --git a/src/client/app/common/views/components/url-preview.vue b/src/client/app/common/views/components/url-preview.vue
index 028b911e24..38979871c1 100644
--- a/src/client/app/common/views/components/url-preview.vue
+++ b/src/client/app/common/views/components/url-preview.vue
@@ -68,7 +68,7 @@ iframe
root(isDark)
> a
display block
- font-size 16px
+ font-size 14px
border solid 1px isDark ? #191b1f : #eee
border-radius 4px
overflow hidden
@@ -136,8 +136,17 @@ root(isDark)
left 0
width 100%
+ @media (max-width 550px)
+ font-size 12px
+
+ > .thumbnail
+ height 80px
+
+ > article
+ padding 12px
+
@media (max-width 500px)
- font-size 8px
+ font-size 10px
> .thumbnail
height 70px
@@ -145,6 +154,16 @@ root(isDark)
> article
padding 8px
+ > header
+ margin-bottom 4px
+
+ > footer
+ margin-top 4px
+
+ > img
+ width 12px
+ height 12px
+
.mk-url-preview[data-darkmode]
root(true)
diff --git a/src/client/app/common/views/components/welcome-timeline.vue b/src/client/app/common/views/components/welcome-timeline.vue
index cad59d24f0..a9d558df66 100644
--- a/src/client/app/common/views/components/welcome-timeline.vue
+++ b/src/client/app/common/views/components/welcome-timeline.vue
@@ -13,7 +13,7 @@
</div>
</header>
<div class="text">
- <mk-note-html :text="note.text"/>
+ <mk-note-html v-if="note.text" :text="note.text"/>
</div>
</div>
</div>
diff --git a/src/client/app/common/views/widgets/analog-clock.vue b/src/client/app/common/views/widgets/analog-clock.vue
new file mode 100644
index 0000000000..b1177d4ddf
--- /dev/null
+++ b/src/client/app/common/views/widgets/analog-clock.vue
@@ -0,0 +1,41 @@
+<template>
+<div class="mkw-analog-clock">
+ <mk-widget-container :naked="props.naked" :show-header="false">
+ <div class="mkw-analog-clock--body">
+ <mk-analog-clock :dark="$store.state.device.darkmode"/>
+ </div>
+ </mk-widget-container>
+</div>
+</template>
+
+<script lang="ts">
+import define from '../../../common/define-widget';
+export default define({
+ name: 'analog-clock',
+ props: () => ({
+ naked: false
+ })
+}).extend({
+ methods: {
+ func() {
+ this.props.naked = !this.props.naked;
+ this.save();
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+@import '~const.styl'
+
+root(isDark)
+ .mkw-analog-clock--body
+ padding 8px
+
+.mkw-analog-clock[data-darkmode]
+ root(true)
+
+.mkw-analog-clock:not([data-darkmode])
+ root(false)
+
+</style>
diff --git a/src/client/app/common/views/widgets/index.ts b/src/client/app/common/views/widgets/index.ts
index 9107d90ce7..a4cabc43ba 100644
--- a/src/client/app/common/views/widgets/index.ts
+++ b/src/client/app/common/views/widgets/index.ts
@@ -1,8 +1,10 @@
import Vue from 'vue';
+import wAnalogClock from './analog-clock.vue';
import wVersion from './version.vue';
import wRss from './rss.vue';
import wServer from './server.vue';
+import wMemo from './memo.vue';
import wBroadcast from './broadcast.vue';
import wCalendar from './calendar.vue';
import wPhotoStream from './photo-stream.vue';
@@ -11,6 +13,7 @@ import wTips from './tips.vue';
import wDonation from './donation.vue';
import wNav from './nav.vue';
+Vue.component('mkw-analog-clock', wAnalogClock);
Vue.component('mkw-nav', wNav);
Vue.component('mkw-calendar', wCalendar);
Vue.component('mkw-photo-stream', wPhotoStream);
@@ -19,5 +22,6 @@ Vue.component('mkw-tips', wTips);
Vue.component('mkw-donation', wDonation);
Vue.component('mkw-broadcast', wBroadcast);
Vue.component('mkw-server', wServer);
+Vue.component('mkw-memo', wMemo);
Vue.component('mkw-rss', wRss);
Vue.component('mkw-version', wVersion);
diff --git a/src/client/app/common/views/widgets/memo.vue b/src/client/app/common/views/widgets/memo.vue
new file mode 100644
index 0000000000..30f0d3b009
--- /dev/null
+++ b/src/client/app/common/views/widgets/memo.vue
@@ -0,0 +1,111 @@
+<template>
+<div class="mkw-memo">
+ <mk-widget-container :show-header="!props.compact">
+ <template slot="header">%fa:R sticky-note%%i18n:@title%</template>
+
+ <div class="mkw-memo--body">
+ <textarea v-model="text" placeholder="%i18n:@memo%" @input="onChange"></textarea>
+ <button @click="saveMemo" :disabled="!changed">%i18n:@save%</button>
+ </div>
+ </mk-widget-container>
+</div>
+</template>
+
+<script lang="ts">
+import define from '../../define-widget';
+
+export default define({
+ name: 'memo',
+ props: () => ({
+ compact: false
+ })
+}).extend({
+ data() {
+ return {
+ text: null,
+ changed: false
+ };
+ },
+
+ created() {
+ this.text = this.$store.state.settings.memo;
+
+ this.$watch('$store.state.settings.memo', text => {
+ this.text = text;
+ });
+ },
+
+ methods: {
+ func() {
+ this.props.compact = !this.props.compact;
+ this.save();
+ },
+
+ onChange() {
+ this.changed = true;
+ },
+
+ saveMemo() {
+ this.$store.dispatch('settings/set', {
+ key: 'memo',
+ value: this.text
+ });
+ this.changed = false;
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+@import '~const.styl'
+
+root(isDark)
+ .mkw-memo--body
+ padding-bottom 28px + 16px
+
+ > textarea
+ display block
+ width 100%
+ max-width 100%
+ min-width 100%
+ padding 16px
+ color isDark ? #fff : #222
+ background isDark ? #282c37 : #fff
+ border none
+ border-bottom solid 1px isDark ? #1c2023 : #eee
+ border-radius 0
+
+ > button
+ display block
+ position absolute
+ bottom 8px
+ right 8px
+ margin 0
+ padding 0 10px
+ height 28px
+ color $theme-color-foreground
+ background $theme-color !important
+ outline none
+ border none
+ border-radius 4px
+ transition background 0.1s ease
+ cursor pointer
+
+ &:hover
+ background lighten($theme-color, 10%) !important
+
+ &:active
+ background darken($theme-color, 10%) !important
+ transition background 0s ease
+
+ &:disabled
+ opacity 0.7
+ cursor default
+
+.mkw-memo[data-darkmode]
+ root(true)
+
+.mkw-memo:not([data-darkmode])
+ root(false)
+
+</style>
diff --git a/src/client/app/common/views/widgets/rss.vue b/src/client/app/common/views/widgets/rss.vue
index 9e2c6b6490..7ac453e450 100644
--- a/src/client/app/common/views/widgets/rss.vue
+++ b/src/client/app/common/views/widgets/rss.vue
@@ -19,12 +19,12 @@ import define from '../../../common/define-widget';
export default define({
name: 'rss',
props: () => ({
- compact: false
+ compact: false,
+ url: 'http://news.yahoo.co.jp/pickup/rss.xml'
})
}).extend({
data() {
return {
- url: 'http://news.yahoo.co.jp/pickup/rss.xml',
items: [],
fetching: true,
clock: null
@@ -43,7 +43,7 @@ export default define({
this.save();
},
fetch() {
- fetch(`https://api.rss2json.com/v1/api.json?rss_url=${this.url}`, {
+ fetch(`https://api.rss2json.com/v1/api.json?rss_url=${this.props.url}`, {
cache: 'no-cache'
}).then(res => {
res.json().then(feed => {
@@ -53,7 +53,12 @@ export default define({
});
},
setting() {
- alert('not implemented yet');
+ const url = window.prompt('URL', this.props.url);
+ if (url && url != '') {
+ this.props.url = url;
+ this.save();
+ this.fetch();
+ }
}
}
});
diff --git a/src/client/app/desktop/api/choose-drive-file.ts b/src/client/app/desktop/api/choose-drive-file.ts
index fbda600e6e..3d0004b741 100644
--- a/src/client/app/desktop/api/choose-drive-file.ts
+++ b/src/client/app/desktop/api/choose-drive-file.ts
@@ -1,18 +1,17 @@
+import OS from '../../mios';
import { url } from '../../config';
import MkChooseFileFromDriveWindow from '../views/components/choose-file-from-drive-window.vue';
-export default function(opts) {
+export default (os: OS) => opts => {
return new Promise((res, rej) => {
const o = opts || {};
if (document.body.clientWidth > 800) {
- const w = new MkChooseFileFromDriveWindow({
- propsData: {
- title: o.title,
- multiple: o.multiple,
- initFolder: o.currentFolder
- }
- }).$mount();
+ const w = os.new(MkChooseFileFromDriveWindow, {
+ title: o.title,
+ multiple: o.multiple,
+ initFolder: o.currentFolder
+ });
w.$once('selected', file => {
res(file);
});
@@ -27,4 +26,4 @@ export default function(opts) {
'height=500, width=800');
}
});
-}
+};
diff --git a/src/client/app/desktop/api/choose-drive-folder.ts b/src/client/app/desktop/api/choose-drive-folder.ts
index 9b33a20d9a..68dc7988b5 100644
--- a/src/client/app/desktop/api/choose-drive-folder.ts
+++ b/src/client/app/desktop/api/choose-drive-folder.ts
@@ -1,17 +1,16 @@
+import OS from '../../mios';
import MkChooseFolderFromDriveWindow from '../views/components/choose-folder-from-drive-window.vue';
-export default function(opts) {
+export default (os: OS) => opts => {
return new Promise((res, rej) => {
const o = opts || {};
- const w = new MkChooseFolderFromDriveWindow({
- propsData: {
- title: o.title,
- initFolder: o.currentFolder
- }
- }).$mount();
+ const w = os.new(MkChooseFolderFromDriveWindow, {
+ title: o.title,
+ initFolder: o.currentFolder
+ });
w.$once('selected', folder => {
res(folder);
});
document.body.appendChild(w.$el);
});
-}
+};
diff --git a/src/client/app/desktop/api/contextmenu.ts b/src/client/app/desktop/api/contextmenu.ts
index b70d7122d3..c92f087551 100644
--- a/src/client/app/desktop/api/contextmenu.ts
+++ b/src/client/app/desktop/api/contextmenu.ts
@@ -1,16 +1,15 @@
+import OS from '../../mios';
import Ctx from '../views/components/context-menu.vue';
-export default function(e, menu, opts?) {
+export default (os: OS) => (e, menu, opts?) => {
const o = opts || {};
- const vm = new Ctx({
- propsData: {
- menu,
- x: e.pageX - window.pageXOffset,
- y: e.pageY - window.pageYOffset,
- }
- }).$mount();
+ const vm = os.new(Ctx, {
+ menu,
+ x: e.pageX - window.pageXOffset,
+ y: e.pageY - window.pageYOffset,
+ });
vm.$once('closed', () => {
if (o.closed) o.closed();
});
document.body.appendChild(vm.$el);
-}
+};
diff --git a/src/client/app/desktop/api/dialog.ts b/src/client/app/desktop/api/dialog.ts
index 07935485b0..23f35b7aa9 100644
--- a/src/client/app/desktop/api/dialog.ts
+++ b/src/client/app/desktop/api/dialog.ts
@@ -1,19 +1,18 @@
+import OS from '../../mios';
import Dialog from '../views/components/dialog.vue';
-export default function(opts) {
+export default (os: OS) => opts => {
return new Promise<string>((res, rej) => {
const o = opts || {};
- const d = new Dialog({
- propsData: {
- title: o.title,
- text: o.text,
- modal: o.modal,
- buttons: o.actions
- }
- }).$mount();
+ const d = os.new(Dialog, {
+ title: o.title,
+ text: o.text,
+ modal: o.modal,
+ buttons: o.actions
+ });
d.$once('clicked', id => {
res(id);
});
document.body.appendChild(d.$el);
});
-}
+};
diff --git a/src/client/app/desktop/api/input.ts b/src/client/app/desktop/api/input.ts
index ce26a8112f..bd7bfa0129 100644
--- a/src/client/app/desktop/api/input.ts
+++ b/src/client/app/desktop/api/input.ts
@@ -1,20 +1,19 @@
+import OS from '../../mios';
import InputDialog from '../views/components/input-dialog.vue';
-export default function(opts) {
+export default (os: OS) => opts => {
return new Promise<string>((res, rej) => {
const o = opts || {};
- const d = new InputDialog({
- propsData: {
- title: o.title,
- placeholder: o.placeholder,
- default: o.default,
- type: o.type || 'text',
- allowEmpty: o.allowEmpty
- }
- }).$mount();
+ const d = os.new(InputDialog, {
+ title: o.title,
+ placeholder: o.placeholder,
+ default: o.default,
+ type: o.type || 'text',
+ allowEmpty: o.allowEmpty
+ });
d.$once('done', text => {
res(text);
});
document.body.appendChild(d.$el);
});
-}
+};
diff --git a/src/client/app/desktop/api/notify.ts b/src/client/app/desktop/api/notify.ts
index 1f89f40ce6..72e5827607 100644
--- a/src/client/app/desktop/api/notify.ts
+++ b/src/client/app/desktop/api/notify.ts
@@ -1,10 +1,9 @@
+import OS from '../../mios';
import Notification from '../views/components/ui-notification.vue';
-export default function(message) {
- const vm = new Notification({
- propsData: {
- message
- }
- }).$mount();
+export default (os: OS) => message => {
+ const vm = os.new(Notification, {
+ message
+ });
document.body.appendChild(vm.$el);
-}
+};
diff --git a/src/client/app/desktop/api/post.ts b/src/client/app/desktop/api/post.ts
index b569610e1d..af71829c7b 100644
--- a/src/client/app/desktop/api/post.ts
+++ b/src/client/app/desktop/api/post.ts
@@ -1,21 +1,18 @@
+import OS from '../../mios';
import PostFormWindow from '../views/components/post-form-window.vue';
import RenoteFormWindow from '../views/components/renote-form-window.vue';
-export default function(opts) {
+export default (os: OS) => opts => {
const o = opts || {};
if (o.renote) {
- const vm = new RenoteFormWindow({
- propsData: {
- renote: o.renote
- }
- }).$mount();
+ const vm = os.new(RenoteFormWindow, {
+ renote: o.renote
+ });
document.body.appendChild(vm.$el);
} else {
- const vm = new PostFormWindow({
- propsData: {
- reply: o.reply
- }
- }).$mount();
+ const vm = os.new(PostFormWindow, {
+ reply: o.reply
+ });
document.body.appendChild(vm.$el);
}
-}
+};
diff --git a/src/client/app/desktop/api/update-avatar.ts b/src/client/app/desktop/api/update-avatar.ts
index 8ddaebc072..887367a24e 100644
--- a/src/client/app/desktop/api/update-avatar.ts
+++ b/src/client/app/desktop/api/update-avatar.ts
@@ -6,17 +6,15 @@ import ProgressDialog from '../views/components/progress-dialog.vue';
export default (os: OS) => (cb, file = null) => {
const fileSelected = file => {
- const w = new CropWindow({
- propsData: {
- image: file,
- title: 'アバターとして表示する部分を選択',
- aspectRatio: 1 / 1
- }
- }).$mount();
+ const w = os.new(CropWindow, {
+ image: file,
+ title: 'アバターとして表示する部分を選択',
+ aspectRatio: 1 / 1
+ });
w.$once('cropped', blob => {
const data = new FormData();
- data.append('i', os.i.token);
+ data.append('i', os.store.state.i.token);
data.append('file', blob, file.name + '.cropped.png');
os.api('drive/folders/find', {
@@ -42,11 +40,9 @@ export default (os: OS) => (cb, file = null) => {
};
const upload = (data, folder) => {
- const dialog = new ProgressDialog({
- propsData: {
- title: '新しいアバターをアップロードしています'
- }
- }).$mount();
+ const dialog = os.new(ProgressDialog, {
+ title: '新しいアバターをアップロードしています'
+ });
document.body.appendChild(dialog.$el);
if (folder) data.append('folderId', folder.id);
@@ -70,8 +66,14 @@ export default (os: OS) => (cb, file = null) => {
os.api('i/update', {
avatarId: file.id
}).then(i => {
- os.i.avatarId = i.avatarId;
- os.i.avatarUrl = i.avatarUrl;
+ os.store.commit('updateIKeyValue', {
+ key: 'avatarId',
+ value: i.avatarId
+ });
+ os.store.commit('updateIKeyValue', {
+ key: 'avatarUrl',
+ value: i.avatarUrl
+ });
os.apis.dialog({
title: '%fa:info-circle%アバターを更新しました',
diff --git a/src/client/app/desktop/api/update-banner.ts b/src/client/app/desktop/api/update-banner.ts
index 1a5da272bd..4e6dd4e2c7 100644
--- a/src/client/app/desktop/api/update-banner.ts
+++ b/src/client/app/desktop/api/update-banner.ts
@@ -6,17 +6,15 @@ import ProgressDialog from '../views/components/progress-dialog.vue';
export default (os: OS) => {
const cropImage = file => new Promise((resolve, reject) => {
- const w = new CropWindow({
- propsData: {
- image: file,
- title: 'バナーとして表示する部分を選択',
- aspectRatio: 16 / 9
- }
- }).$mount();
+ const w = os.new(CropWindow, {
+ image: file,
+ title: 'バナーとして表示する部分を選択',
+ aspectRatio: 16 / 9
+ });
w.$once('cropped', blob => {
const data = new FormData();
- data.append('i', os.i.token);
+ data.append('i', os.store.state.i.token);
data.append('file', blob, file.name + '.cropped.png');
os.api('drive/folders/find', {
@@ -44,11 +42,9 @@ export default (os: OS) => {
});
const upload = (data, folder) => new Promise((resolve, reject) => {
- const dialog = new ProgressDialog({
- propsData: {
- title: '新しいバナーをアップロードしています'
- }
- }).$mount();
+ const dialog = os.new(ProgressDialog, {
+ title: '新しいバナーをアップロードしています'
+ });
document.body.appendChild(dialog.$el);
if (folder) data.append('folderId', folder.id);
@@ -73,8 +69,14 @@ export default (os: OS) => {
return os.api('i/update', {
bannerId: file.id
}).then(i => {
- os.i.bannerId = i.bannerId;
- os.i.bannerUrl = i.bannerUrl;
+ os.store.commit('updateIKeyValue', {
+ key: 'bannerId',
+ value: i.bannerId
+ });
+ os.store.commit('updateIKeyValue', {
+ key: 'bannerUrl',
+ value: i.bannerUrl
+ });
os.apis.dialog({
title: '%fa:info-circle%バナーを更新しました',
diff --git a/src/client/app/desktop/assets/header-icon.dark.svg b/src/client/app/desktop/assets/header-icon.dark.svg
new file mode 100644
index 0000000000..fa42856fa5
--- /dev/null
+++ b/src/client/app/desktop/assets/header-icon.dark.svg
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="512"
+ height="512"
+ viewBox="0 0 135.46667 135.46667"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.1 r15371"
+ sodipodi:docname="header-icon.dark.svg"
+ inkscape:export-filename="C:\Users\syuilo\projects\misskey\assets\favicon\32.png"
+ inkscape:export-xdpi="6"
+ inkscape:export-ydpi="6">
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="simplify"
+ id="path-effect5115"
+ is_visible="true"
+ steps="1"
+ threshold="0.000408163"
+ smooth_angles="360"
+ helper_size="0"
+ simplify_individual_paths="false"
+ simplify_just_coalesce="false"
+ simplifyindividualpaths="false"
+ simplifyJustCoalesce="false" />
+ <inkscape:path-effect
+ effect="simplify"
+ id="path-effect5111"
+ is_visible="true"
+ steps="1"
+ threshold="0.000408163"
+ smooth_angles="360"
+ helper_size="0"
+ simplify_individual_paths="false"
+ simplify_just_coalesce="false"
+ simplifyindividualpaths="false"
+ simplifyJustCoalesce="false" />
+ <inkscape:path-effect
+ effect="simplify"
+ id="path-effect5104"
+ is_visible="true"
+ steps="1"
+ threshold="0.000408163"
+ smooth_angles="360"
+ helper_size="0"
+ simplify_individual_paths="false"
+ simplify_just_coalesce="false"
+ simplifyindividualpaths="false"
+ simplifyJustCoalesce="false" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4142136"
+ inkscape:cx="114.309"
+ inkscape:cy="251.50613"
+ inkscape:document-units="px"
+ inkscape:current-layer="g4502"
+ showgrid="true"
+ units="px"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="false"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:snap-center="true"
+ inkscape:snap-page="true"
+ inkscape:window-width="1920"
+ inkscape:window-height="1027"
+ inkscape:window-x="-8"
+ inkscape:window-y="1072"
+ inkscape:window-maximized="1"
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-midpoints="true"
+ inkscape:object-paths="true"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ objecttolerance="1"
+ guidetolerance="1"
+ inkscape:snap-nodes="false"
+ inkscape:snap-others="false">
+ <inkscape:grid
+ type="xygrid"
+ id="grid4504"
+ spacingx="4.2333334"
+ spacingy="4.2333334"
+ empcolor="#ff3fff"
+ empopacity="0.25098039"
+ empspacing="4" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="レイヤー 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-30.809093,-111.78601)">
+ <g
+ id="g4502"
+ transform="matrix(1.096096,0,0,1.096096,-2.960633,-44.023579)">
+ <g
+ style="fill:#ffffff;fill-opacity:1"
+ transform="translate(-1.3333333e-6,-1.3439941e-6)"
+ id="g5125">
+ <g
+ transform="matrix(0.91391326,0,0,0.91391326,7.9719907,17.595761)"
+ id="text4489"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:141.03404236px;line-height:476.69509888px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.28950602px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ aria-label="Mi">
+ <path
+ sodipodi:nodetypes="zccssscssccscczzzccsccsscscsccz"
+ inkscape:connector-curvature="0"
+ id="path5210"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';fill:#ffffff;fill-opacity:1;stroke-width:0.28950602px"
+ d="m 75.196381,231.17126 c -5.855419,0.0202 -10.885068,-3.50766 -13.2572,-7.61584 -1.266603,-1.79454 -3.772419,-2.43291 -3.807919,0 v 11.2332 c 0,4.51309 -1.645397,8.41504 -4.936191,11.70583 -3.196772,3.19677 -7.098714,4.79516 -11.705826,4.79516 -4.513089,0 -8.415031,-1.59839 -11.705825,-4.79516 -3.196772,-3.29079 -4.795158,-7.19274 -4.795158,-11.70583 v -61.7729 c 0,-3.47884 0.987238,-6.6286 2.961715,-9.44928 2.068499,-2.91471 4.701135,-4.9362 7.897906,-6.06447 1.786431,-0.65816 3.666885,-0.98724 5.641362,-0.98724 5.077225,0 9.308247,1.97448 12.693064,5.92343 1.786431,1.97448 2.820681,3.00873 3.102749,3.10275 0,0 13.408119,16.21319 13.78421,16.49526 0.376091,0.28206 1.480789,2.43848 4.127113,2.43848 2.646324,0 3.89218,-2.15642 4.26827,-2.43848 0.376091,-0.28207 13.784088,-16.49526 13.784088,-16.49526 0.09402,0.094 1.081261,-0.94022 2.961715,-3.10275 3.478837,-3.94895 7.756866,-5.92343 12.834096,-5.92343 1.88045,0 3.76091,0.32908 5.64136,0.98724 3.19677,1.12827 5.7824,3.14976 7.75688,6.06447 2.06849,2.82068 3.10274,5.97044 3.10274,9.44928 v 61.7729 c 0,4.51309 -1.6454,8.41504 -4.93619,11.70583 -3.19677,3.19677 -7.09871,4.79516 -11.70582,4.79516 -4.51309,0 -8.41504,-1.59839 -11.705828,-4.79516 -3.196772,-3.29079 -4.795158,-7.19274 -4.795158,-11.70583 v -11.2332 c -0.277898,-3.06563 -2.987588,-1.13379 -3.948953,0 -2.538613,4.70114 -7.401781,7.59567 -13.2572,7.61584 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path5212"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';fill:#ffffff;fill-opacity:1;stroke-width:0.28950602px"
+ d="m 145.83461,185.00361 q -5.92343,0 -10.15445,-4.08999 -4.08999,-4.23102 -4.08999,-10.15445 0,-5.92343 4.08999,-10.01342 4.23102,-4.23102 10.15445,-4.23102 5.92343,0 10.15445,4.23102 4.23102,4.08999 4.23102,10.01342 0,5.92343 -4.23102,10.15445 -4.23102,4.08999 -10.15445,4.08999 z m 0.14103,2.82068 q 5.92343,0 10.01342,4.23102 4.23102,4.23102 4.23102,10.15445 v 34.83541 q 0,5.92343 -4.23102,10.15445 -4.08999,4.08999 -10.01342,4.08999 -5.92343,0 -10.15445,-4.08999 -4.23102,-4.23102 -4.23102,-10.15445 v -34.83541 q 0,-5.92343 4.23102,-10.15445 4.23102,-4.23102 10.15445,-4.23102 z" />
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/src/client/app/desktop/assets/header-icon.light.svg b/src/client/app/desktop/assets/header-icon.light.svg
new file mode 100644
index 0000000000..61e2026243
--- /dev/null
+++ b/src/client/app/desktop/assets/header-icon.light.svg
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="512"
+ height="512"
+ viewBox="0 0 135.46667 135.46667"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.1 r15371"
+ sodipodi:docname="header-icon.light.svg"
+ inkscape:export-filename="C:\Users\syuilo\projects\misskey\assets\favicon\32.png"
+ inkscape:export-xdpi="6"
+ inkscape:export-ydpi="6">
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="simplify"
+ id="path-effect5115"
+ is_visible="true"
+ steps="1"
+ threshold="0.000408163"
+ smooth_angles="360"
+ helper_size="0"
+ simplify_individual_paths="false"
+ simplify_just_coalesce="false"
+ simplifyindividualpaths="false"
+ simplifyJustCoalesce="false" />
+ <inkscape:path-effect
+ effect="simplify"
+ id="path-effect5111"
+ is_visible="true"
+ steps="1"
+ threshold="0.000408163"
+ smooth_angles="360"
+ helper_size="0"
+ simplify_individual_paths="false"
+ simplify_just_coalesce="false"
+ simplifyindividualpaths="false"
+ simplifyJustCoalesce="false" />
+ <inkscape:path-effect
+ effect="simplify"
+ id="path-effect5104"
+ is_visible="true"
+ steps="1"
+ threshold="0.000408163"
+ smooth_angles="360"
+ helper_size="0"
+ simplify_individual_paths="false"
+ simplify_just_coalesce="false"
+ simplifyindividualpaths="false"
+ simplifyJustCoalesce="false" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4142136"
+ inkscape:cx="114.309"
+ inkscape:cy="251.50613"
+ inkscape:document-units="px"
+ inkscape:current-layer="g4502"
+ showgrid="true"
+ units="px"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="false"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:snap-center="true"
+ inkscape:snap-page="true"
+ inkscape:window-width="1920"
+ inkscape:window-height="1027"
+ inkscape:window-x="-8"
+ inkscape:window-y="1072"
+ inkscape:window-maximized="1"
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-midpoints="true"
+ inkscape:object-paths="true"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ objecttolerance="1"
+ guidetolerance="1"
+ inkscape:snap-nodes="false"
+ inkscape:snap-others="false">
+ <inkscape:grid
+ type="xygrid"
+ id="grid4504"
+ spacingx="4.2333334"
+ spacingy="4.2333334"
+ empcolor="#ff3fff"
+ empopacity="0.25098039"
+ empspacing="4" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="レイヤー 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-30.809093,-111.78601)">
+ <g
+ id="g4502"
+ transform="matrix(1.096096,0,0,1.096096,-2.960633,-44.023579)">
+ <g
+ style="fill:#000000;fill-opacity:1"
+ transform="translate(-1.3333333e-6,-1.3439941e-6)"
+ id="g5125">
+ <g
+ transform="matrix(0.91391326,0,0,0.91391326,7.9719907,17.595761)"
+ id="text4489"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:141.03404236px;line-height:476.69509888px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.28950602px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ aria-label="Mi">
+ <path
+ sodipodi:nodetypes="zccssscssccscczzzccsccsscscsccz"
+ inkscape:connector-curvature="0"
+ id="path5210"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';fill:#000000;fill-opacity:1;stroke-width:0.28950602px"
+ d="m 75.196381,231.17126 c -5.855419,0.0202 -10.885068,-3.50766 -13.2572,-7.61584 -1.266603,-1.79454 -3.772419,-2.43291 -3.807919,0 v 11.2332 c 0,4.51309 -1.645397,8.41504 -4.936191,11.70583 -3.196772,3.19677 -7.098714,4.79516 -11.705826,4.79516 -4.513089,0 -8.415031,-1.59839 -11.705825,-4.79516 -3.196772,-3.29079 -4.795158,-7.19274 -4.795158,-11.70583 v -61.7729 c 0,-3.47884 0.987238,-6.6286 2.961715,-9.44928 2.068499,-2.91471 4.701135,-4.9362 7.897906,-6.06447 1.786431,-0.65816 3.666885,-0.98724 5.641362,-0.98724 5.077225,0 9.308247,1.97448 12.693064,5.92343 1.786431,1.97448 2.820681,3.00873 3.102749,3.10275 0,0 13.408119,16.21319 13.78421,16.49526 0.376091,0.28206 1.480789,2.43848 4.127113,2.43848 2.646324,0 3.89218,-2.15642 4.26827,-2.43848 0.376091,-0.28207 13.784088,-16.49526 13.784088,-16.49526 0.09402,0.094 1.081261,-0.94022 2.961715,-3.10275 3.478837,-3.94895 7.756866,-5.92343 12.834096,-5.92343 1.88045,0 3.76091,0.32908 5.64136,0.98724 3.19677,1.12827 5.7824,3.14976 7.75688,6.06447 2.06849,2.82068 3.10274,5.97044 3.10274,9.44928 v 61.7729 c 0,4.51309 -1.6454,8.41504 -4.93619,11.70583 -3.19677,3.19677 -7.09871,4.79516 -11.70582,4.79516 -4.51309,0 -8.41504,-1.59839 -11.705828,-4.79516 -3.196772,-3.29079 -4.795158,-7.19274 -4.795158,-11.70583 v -11.2332 c -0.277898,-3.06563 -2.987588,-1.13379 -3.948953,0 -2.538613,4.70114 -7.401781,7.59567 -13.2572,7.61584 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path5212"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';fill:#000000;fill-opacity:1;stroke-width:0.28950602px"
+ d="m 145.83461,185.00361 q -5.92343,0 -10.15445,-4.08999 -4.08999,-4.23102 -4.08999,-10.15445 0,-5.92343 4.08999,-10.01342 4.23102,-4.23102 10.15445,-4.23102 5.92343,0 10.15445,4.23102 4.23102,4.08999 4.23102,10.01342 0,5.92343 -4.23102,10.15445 -4.23102,4.08999 -10.15445,4.08999 z m 0.14103,2.82068 q 5.92343,0 10.01342,4.23102 4.23102,4.23102 4.23102,10.15445 v 34.83541 q 0,5.92343 -4.23102,10.15445 -4.08999,4.08999 -10.01342,4.08999 -5.92343,0 -10.15445,-4.08999 -4.23102,-4.23102 -4.23102,-10.15445 v -34.83541 q 0,-5.92343 4.23102,-10.15445 4.23102,-4.23102 10.15445,-4.23102 z" />
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/src/client/app/desktop/assets/header-logo-white.svg b/src/client/app/desktop/assets/header-logo-white.svg
deleted file mode 100644
index 8082edb30d..0000000000
--- a/src/client/app/desktop/assets/header-logo-white.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
- y="0px" width="256px" height="256px" viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve">
-<circle fill="#FFFFFF" cx="128" cy="153.6" r="19.201"/>
-<circle fill="#FFFFFF" cx="51.2" cy="153.6" r="19.2"/>
-<circle fill="#FFFFFF" cx="204.8" cy="153.6" r="19.2"/>
-<polyline fill="none" stroke="#FFFFFF" stroke-width="16" stroke-linejoin="round" stroke-miterlimit="10" points="51.2,153.6
- 89.601,102.4 128,153.6 166.4,102.4 204.799,153.6 "/>
-<circle fill="#FFFFFF" cx="89.6" cy="102.4" r="19.2"/>
-<circle fill="#FFFFFF" cx="166.4" cy="102.4" r="19.199"/>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-</svg>
diff --git a/src/client/app/desktop/assets/header-logo.svg b/src/client/app/desktop/assets/header-logo.svg
deleted file mode 100644
index 3a2207954a..0000000000
--- a/src/client/app/desktop/assets/header-logo.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
- y="0px" width="256px" height="256px" viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve">
-<circle cx="128" cy="153.6" r="19.201"/>
-<circle cx="51.2" cy="153.6" r="19.2"/>
-<circle cx="204.8" cy="153.6" r="19.2"/>
-<polyline fill="none" stroke="#000000" stroke-width="16" stroke-linejoin="round" stroke-miterlimit="10" points="51.2,153.6
- 89.601,102.4 128,153.6 166.4,102.4 204.799,153.6 "/>
-<circle cx="89.6" cy="102.4" r="19.2"/>
-<circle cx="166.4" cy="102.4" r="19.199"/>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-</svg>
diff --git a/src/client/app/desktop/script.ts b/src/client/app/desktop/script.ts
index 2658a86b95..8fb6096afa 100644
--- a/src/client/app/desktop/script.ts
+++ b/src/client/app/desktop/script.ts
@@ -2,7 +2,6 @@
* Desktop Client
*/
-import Vue from 'vue';
import VueRouter from 'vue-router';
// Style
@@ -68,12 +67,12 @@ init(async (launch) => {
// Launch the app
const [, os] = launch(router, os => ({
- chooseDriveFolder,
- chooseDriveFile,
- dialog,
- input,
- post,
- notify,
+ chooseDriveFolder: chooseDriveFolder(os),
+ chooseDriveFile: chooseDriveFile(os),
+ dialog: dialog(os),
+ input: input(os),
+ post: post(os),
+ notify: notify(os),
updateAvatar: updateAvatar(os),
updateBanner: updateBanner(os)
}));
diff --git a/src/client/app/desktop/style.styl b/src/client/app/desktop/style.styl
index ea48fbee3d..f2a60955fd 100644
--- a/src/client/app/desktop/style.styl
+++ b/src/client/app/desktop/style.styl
@@ -6,43 +6,26 @@
*::input-placeholder
color #D8CBC5
-*
- &:focus
- outline none
+*:focus
+ outline none
- &::scrollbar
- width 5px
- background transparent
-
- &:horizontal
- height 5px
-
- &::scrollbar-button
- width 0
- height 0
- background rgba(0, 0, 0, 0.2)
-
- &::scrollbar-piece
- background transparent
-
- &:start
- background transparent
-
- &::scrollbar-thumb
- background rgba(0, 0, 0, 0.2)
+html
+ height 100%
+ background #f7f7f7
- &:hover
- background rgba(0, 0, 0, 0.4)
+ &, *
+ &::-webkit-scrollbar
+ width 6px
+ height 6px
- &:active
- background $theme-color
+ &::-webkit-scrollbar-thumb
+ background rgba(0, 0, 0, 0.2)
- &::scrollbar-corner
- background rgba(0, 0, 0, 0.2)
+ &:hover
+ background rgba(0, 0, 0, 0.4)
-html
- height 100%
- background #f7f7f7
+ &:active
+ background $theme-color
&[data-darkmode]
background #191B22
@@ -51,10 +34,6 @@ html
&::-webkit-scrollbar-track
background-color #282C37
- &::-webkit-scrollbar
- width 6px
- height 6px
-
&::-webkit-scrollbar-thumb
background-color #454954
diff --git a/src/client/app/desktop/views/components/analog-clock.vue b/src/client/app/desktop/views/components/analog-clock.vue
deleted file mode 100644
index 81eec81598..0000000000
--- a/src/client/app/desktop/views/components/analog-clock.vue
+++ /dev/null
@@ -1,108 +0,0 @@
-<template>
-<canvas class="mk-analog-clock" ref="canvas" width="256" height="256"></canvas>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-import { themeColor } from '../../../config';
-
-const Vec2 = function(this: any, x, y) {
- this.x = x;
- this.y = y;
-};
-
-export default Vue.extend({
- data() {
- return {
- clock: null
- };
- },
- mounted() {
- this.tick();
- this.clock = setInterval(this.tick, 1000);
- },
- beforeDestroy() {
- clearInterval(this.clock);
- },
- methods: {
- tick() {
- const canv = this.$refs.canvas as any;
-
- const now = new Date();
- const s = now.getSeconds();
- const m = now.getMinutes();
- const h = now.getHours();
-
- const ctx = canv.getContext('2d');
- const canvW = canv.width;
- const canvH = canv.height;
- ctx.clearRect(0, 0, canvW, canvH);
-
- { // 背景
- const center = Math.min((canvW / 2), (canvH / 2));
- const lineStart = center * 0.90;
- const shortLineEnd = center * 0.87;
- const longLineEnd = center * 0.84;
- for (let i = 0; i < 60; i++) {
- const angle = Math.PI * i / 30;
- const uv = new Vec2(Math.sin(angle), -Math.cos(angle));
- ctx.beginPath();
- ctx.lineWidth = 1;
- ctx.moveTo((canvW / 2) + uv.x * lineStart, (canvH / 2) + uv.y * lineStart);
- if (i % 5 == 0) {
- ctx.strokeStyle = 'rgba(255, 255, 255, 0.2)';
- ctx.lineTo((canvW / 2) + uv.x * longLineEnd, (canvH / 2) + uv.y * longLineEnd);
- } else {
- ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
- ctx.lineTo((canvW / 2) + uv.x * shortLineEnd, (canvH / 2) + uv.y * shortLineEnd);
- }
- ctx.stroke();
- }
- }
-
- { // 分
- const angle = Math.PI * (m + s / 60) / 30;
- const length = Math.min(canvW, canvH) / 2.6;
- const uv = new Vec2(Math.sin(angle), -Math.cos(angle));
- ctx.beginPath();
- ctx.strokeStyle = '#ffffff';
- ctx.lineWidth = 2;
- ctx.moveTo(canvW / 2 - uv.x * length / 5, canvH / 2 - uv.y * length / 5);
- ctx.lineTo(canvW / 2 + uv.x * length, canvH / 2 + uv.y * length);
- ctx.stroke();
- }
-
- { // 時
- const angle = Math.PI * (h % 12 + m / 60) / 6;
- const length = Math.min(canvW, canvH) / 4;
- const uv = new Vec2(Math.sin(angle), -Math.cos(angle));
- ctx.beginPath();
- ctx.strokeStyle = themeColor;
- ctx.lineWidth = 2;
- ctx.moveTo(canvW / 2 - uv.x * length / 5, canvH / 2 - uv.y * length / 5);
- ctx.lineTo(canvW / 2 + uv.x * length, canvH / 2 + uv.y * length);
- ctx.stroke();
- }
-
- { // 秒
- const angle = Math.PI * s / 30;
- const length = Math.min(canvW, canvH) / 2.6;
- const uv = new Vec2(Math.sin(angle), -Math.cos(angle));
- ctx.beginPath();
- ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
- ctx.lineWidth = 1;
- ctx.moveTo(canvW / 2 - uv.x * length / 5, canvH / 2 - uv.y * length / 5);
- ctx.lineTo(canvW / 2 + uv.x * length, canvH / 2 + uv.y * length);
- ctx.stroke();
- }
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-.mk-analog-clock
- display block
- width 256px
- height 256px
-</style>
diff --git a/src/client/app/desktop/views/components/calendar.vue b/src/client/app/desktop/views/components/calendar.vue
index 9a93841e52..3b0330cf61 100644
--- a/src/client/app/desktop/views/components/calendar.vue
+++ b/src/client/app/desktop/views/components/calendar.vue
@@ -138,6 +138,7 @@ root(isDark)
background isDark ? #282C37 : #fff
border solid 1px rgba(#000, 0.075)
border-radius 6px
+ overflow hidden
&[data-melt]
background transparent !important
@@ -151,9 +152,12 @@ root(isDark)
line-height 42px
font-size 0.9em
font-weight bold
- color #888
+ color isDark ? #c5ced6 : #888
box-shadow 0 1px rgba(#000, 0.07)
+ if isDark
+ background #313543
+
> [data-fa]
margin-right 4px
@@ -165,13 +169,13 @@ root(isDark)
width 42px
font-size 0.9em
line-height 42px
- color #ccc
+ color isDark ? #9baec8 : #ccc
&:hover
- color #aaa
+ color isDark ? #b2c1d5 : #aaa
&:active
- color #999
+ color isDark ? #b2c1d5 : #999
&:first-of-type
left 0
@@ -194,49 +198,49 @@ root(isDark)
font-size 14px
&.weekday
- color #19a2a9
+ color isDark ? #43d5dc : #19a2a9
&[data-is-donichi]
- color #ef95a0
+ color isDark ? #ff6679 : #ef95a0
&[data-today]
- box-shadow 0 0 0 1px #19a2a9 inset
+ box-shadow 0 0 0 1px isDark ? #43d5dc : #19a2a9 inset
border-radius 6px
&[data-is-donichi]
- box-shadow 0 0 0 1px #ef95a0 inset
+ box-shadow 0 0 0 1px isDark ? #ff6679 : #ef95a0 inset
&.day
cursor pointer
- color #777
+ color isDark ? #c5ced6 : #777
> div
border-radius 6px
&:hover > div
- background rgba(#000, 0.025)
+ background rgba(#000, isDark ? 0.1 : 0.025)
&:active > div
- background rgba(#000, 0.05)
+ background rgba(#000, isDark ? 0.2 : 0.05)
&[data-is-donichi]
- color #ef95a0
+ color isDark ? #ff6679 : #ef95a0
&[data-is-out-of-range]
cursor default
- color rgba(#777, 0.5)
+ color rgba(isDark ? #c5ced6 : #777, 0.5)
&[data-is-donichi]
- color rgba(#ef95a0, 0.5)
+ color rgba(isDark ? #ff6679 : #ef95a0, 0.5)
&[data-selected]
font-weight bold
> div
- background rgba(#000, 0.025)
+ background rgba(#000, isDark ? 0.1 : 0.025)
&:active > div
- background rgba(#000, 0.05)
+ background rgba(#000, isDark ? 0.2 : 0.05)
&[data-today]
> div
diff --git a/src/client/app/desktop/views/components/drive.file.vue b/src/client/app/desktop/views/components/drive.file.vue
index fb553e1ae7..62a189d849 100644
--- a/src/client/app/desktop/views/components/drive.file.vue
+++ b/src/client/app/desktop/views/components/drive.file.vue
@@ -9,10 +9,10 @@
@contextmenu.prevent.stop="onContextmenu"
:title="title"
>
- <div class="label" v-if="os.i.avatarId == file.id"><img src="/assets/label.svg"/>
+ <div class="label" v-if="$store.state.i.avatarId == file.id"><img src="/assets/label.svg"/>
<p>%i18n:@avatar%</p>
</div>
- <div class="label" v-if="os.i.bannerId == file.id"><img src="/assets/label.svg"/>
+ <div class="label" v-if="$store.state.i.bannerId == file.id"><img src="/assets/label.svg"/>
<p>%i18n:@banner%</p>
</div>
<div class="thumbnail" ref="thumbnail" :style="`background-color: ${ background }`">
@@ -62,7 +62,7 @@ export default Vue.extend({
onContextmenu(e) {
this.isContextmenuShowing = true;
- contextmenu(e, [{
+ contextmenu((this as any).os)(e, [{
type: 'item',
text: '%i18n:@contextmenu.rename%',
icon: '%fa:i-cursor%',
diff --git a/src/client/app/desktop/views/components/drive.folder.vue b/src/client/app/desktop/views/components/drive.folder.vue
index 16f474f4e0..06f2b3f80c 100644
--- a/src/client/app/desktop/views/components/drive.folder.vue
+++ b/src/client/app/desktop/views/components/drive.folder.vue
@@ -52,7 +52,7 @@ export default Vue.extend({
onContextmenu(e) {
this.isContextmenuShowing = true;
- contextmenu(e, [{
+ contextmenu((this as any).os)(e, [{
type: 'item',
text: '%i18n:@contextmenu.move-to-this-folder%',
icon: '%fa:arrow-right%',
diff --git a/src/client/app/desktop/views/components/drive.vue b/src/client/app/desktop/views/components/drive.vue
index cae40f306c..9a738070f1 100644
--- a/src/client/app/desktop/views/components/drive.vue
+++ b/src/client/app/desktop/views/components/drive.vue
@@ -136,7 +136,7 @@ export default Vue.extend({
},
methods: {
onContextmenu(e) {
- contextmenu(e, [{
+ contextmenu((this as any).os)(e, [{
type: 'item',
text: '%i18n:@contextmenu.create-folder%',
icon: '%fa:R folder%',
diff --git a/src/client/app/desktop/views/components/home.vue b/src/client/app/desktop/views/components/home.vue
index d84c1e404f..9f6cf9614a 100644
--- a/src/client/app/desktop/views/components/home.vue
+++ b/src/client/app/desktop/views/components/home.vue
@@ -6,25 +6,27 @@
<div class="adder">
<p>%i18n:@add-widget%</p>
<select v-model="widgetAdderSelected">
- <option value="profile">%i18n:@profile%</option>
- <option value="calendar">%i18n:@calendar%</option>
- <option value="timemachine">%i18n:@timemachine%</option>
- <option value="activity">%i18n:@activity%</option>
- <option value="rss">%i18n:@rss%</option>
- <option value="trends">%i18n:@trends%</option>
- <option value="photo-stream">%i18n:@photo-stream%</option>
- <option value="slideshow">%i18n:@slideshow%</option>
- <option value="version">%i18n:@version%</option>
- <option value="broadcast">%i18n:@broadcast%</option>
- <option value="notifications">%i18n:@notifications%</option>
- <option value="users">%i18n:@users%</option>
- <option value="polls">%i18n:@polls%</option>
- <option value="post-form">%i18n:@post-form%</option>
- <option value="messaging">%i18n:@messaging%</option>
- <option value="server">%i18n:@server%</option>
- <option value="donation">%i18n:@donation%</option>
- <option value="nav">%i18n:@nav%</option>
- <option value="tips">%i18n:@tips%</option>
+ <option value="profile">%i18n:common.widgets.profile%</option>
+ <option value="analog-clock">%i18n:common.widgets.analog-clock%</option>
+ <option value="calendar">%i18n:common.widgets.calendar%</option>
+ <option value="timemachine">%i18n:common.widgets.timemachine%</option>
+ <option value="activity">%i18n:common.widgets.activity%</option>
+ <option value="rss">%i18n:common.widgets.rss%</option>
+ <option value="trends">%i18n:common.widgets.trends%</option>
+ <option value="photo-stream">%i18n:common.widgets.photo-stream%</option>
+ <option value="slideshow">%i18n:common.widgets.slideshow%</option>
+ <option value="version">%i18n:common.widgets.version%</option>
+ <option value="broadcast">%i18n:common.widgets.broadcast%</option>
+ <option value="notifications">%i18n:common.widgets.notifications%</option>
+ <option value="users">%i18n:common.widgets.users%</option>
+ <option value="polls">%i18n:common.widgets.polls%</option>
+ <option value="post-form">%i18n:common.widgets.post-form%</option>
+ <option value="messaging">%i18n:common.widgets.messaging%</option>
+ <option value="memo">%i18n:common.widgets.memo%</option>
+ <option value="server">%i18n:common.widgets.server%</option>
+ <option value="donation">%i18n:common.widgets.donation%</option>
+ <option value="nav">%i18n:common.widgets.nav%</option>
+ <option value="tips">%i18n:common.widgets.tips%</option>
</select>
<button @click="addWidget">%i18n:@add%</button>
</div>
@@ -51,7 +53,7 @@
<div class="main">
<a @click="hint">カスタマイズのヒント</a>
<div>
- <mk-post-form v-if="clientSettings.showPostFormOnTopOfTl"/>
+ <mk-post-form v-if="$store.state.settings.showPostFormOnTopOfTl"/>
<mk-timeline ref="tl" @loaded="onTlLoaded"/>
</div>
</div>
@@ -61,7 +63,7 @@
<component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" @chosen="warp"/>
</div>
<div class="main">
- <mk-post-form v-if="clientSettings.showPostFormOnTopOfTl"/>
+ <mk-post-form v-if="$store.state.settings.showPostFormOnTopOfTl"/>
<mk-timeline ref="tl" @loaded="onTlLoaded" v-if="mode == 'timeline'"/>
<mk-mentions @loaded="onTlLoaded" v-if="mode == 'mentions'"/>
</div>
diff --git a/src/client/app/desktop/views/components/index.ts b/src/client/app/desktop/views/components/index.ts
index f58d0706df..7b7a38afa2 100644
--- a/src/client/app/desktop/views/components/index.ts
+++ b/src/client/app/desktop/views/components/index.ts
@@ -9,7 +9,6 @@ import subNoteContent from './sub-note-content.vue';
import window from './window.vue';
import noteFormWindow from './post-form-window.vue';
import renoteFormWindow from './renote-form-window.vue';
-import analogClock from './analog-clock.vue';
import ellipsisIcon from './ellipsis-icon.vue';
import mediaImage from './media-image.vue';
import mediaImageDialog from './media-image-dialog.vue';
@@ -40,7 +39,6 @@ Vue.component('mk-sub-note-content', subNoteContent);
Vue.component('mk-window', window);
Vue.component('mk-post-form-window', noteFormWindow);
Vue.component('mk-renote-form-window', renoteFormWindow);
-Vue.component('mk-analog-clock', analogClock);
Vue.component('mk-ellipsis-icon', ellipsisIcon);
Vue.component('mk-media-image', mediaImage);
Vue.component('mk-media-image-dialog', mediaImageDialog);
diff --git a/src/client/app/desktop/views/components/note-detail.sub.vue b/src/client/app/desktop/views/components/note-detail.sub.vue
deleted file mode 100644
index c798b41b25..0000000000
--- a/src/client/app/desktop/views/components/note-detail.sub.vue
+++ /dev/null
@@ -1,123 +0,0 @@
-<template>
-<div class="sub" :title="title">
- <mk-avatar class="avatar" :user="note.user"/>
- <div class="main">
- <header>
- <div class="left">
- <router-link class="name" :to="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</router-link>
- <span class="username"><mk-acct :user="note.user"/></span>
- </div>
- <div class="right">
- <router-link class="time" :to="note | notePage">
- <mk-time :time="note.createdAt"/>
- </router-link>
- </div>
- </header>
- <div class="body">
- <div class="text">
- <span v-if="note.isHidden" style="opacity: 0.5">%i18n:@private%</span>
- <mk-note-html v-if="note.text" :text="note.text" :i="os.i"/>
- </div>
- <div class="media" v-if="note.mediaIds.length > 0">
- <mk-media-list :media-list="note.media"/>
- </div>
- </div>
- </div>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-import dateStringify from '../../../common/scripts/date-stringify';
-
-export default Vue.extend({
- props: ['note'],
- computed: {
- title(): string {
- return dateStringify(this.note.createdAt);
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-root(isDark)
- margin 0
- padding 20px 32px
- background isDark ? #21242d : #fdfdfd
-
- &:after
- content ""
- display block
- clear both
-
- &:hover
- > .main > footer > button
- color #888
-
- > .avatar
- display block
- float left
- margin 0 16px 0 0
- width 44px
- height 44px
- border-radius 4px
-
- > .main
- float left
- width calc(100% - 60px)
-
- > header
- margin-bottom 4px
- white-space nowrap
-
- &:after
- content ""
- display block
- clear both
-
- > .left
- float left
-
- > .name
- display inline
- margin 0
- padding 0
- color isDark ? #fff : #777
- font-size 1em
- font-weight 700
- text-align left
- text-decoration none
-
- &:hover
- text-decoration underline
-
- > .username
- text-align left
- margin 0 0 0 8px
- color isDark ? #606984 : #ccc
-
- > .right
- float right
-
- > .time
- font-size 0.9em
- color isDark ? #606984 : #c0c0c0
-
- > .body
- > .text
- cursor default
- display block
- margin 0
- padding 0
- overflow-wrap break-word
- font-size 1em
- color isDark ? #959ba7 : #717171
-
-.sub[data-darkmode]
- root(true)
-
-.sub:not([data-darkmode])
- root(false)
-
-</style>
diff --git a/src/client/app/desktop/views/components/note-detail.vue b/src/client/app/desktop/views/components/note-detail.vue
index 5b48b7a1ba..2f28d223dd 100644
--- a/src/client/app/desktop/views/components/note-detail.vue
+++ b/src/client/app/desktop/views/components/note-detail.vue
@@ -39,7 +39,8 @@
<div class="body">
<div class="text">
<span v-if="p.isHidden" style="opacity: 0.5">%i18n:@private%</span>
- <mk-note-html v-if="p.text" :text="p.text" :i="os.i"/>
+ <span v-if="p.deletedAt" style="opacity: 0.5">%i18n:@deleted%</span>
+ <mk-note-html v-if="p.text" :text="p.text" :i="$store.state.i"/>
</div>
<div class="media" v-if="p.media.length > 0">
<mk-media-list :media-list="p.media" :raw="true"/>
@@ -88,7 +89,7 @@ import MkPostFormWindow from './post-form-window.vue';
import MkRenoteFormWindow from './renote-form-window.vue';
import MkNoteMenu from '../../../common/views/components/note-menu.vue';
import MkReactionPicker from '../../../common/views/components/reaction-picker.vue';
-import XSub from './note-detail.sub.vue';
+import XSub from './notes.note.sub.vue';
export default Vue.extend({
components: {
@@ -158,7 +159,7 @@ export default Vue.extend({
// Draw map
if (this.p.geo) {
- const shouldShowMap = (this as any).os.isSignedIn ? (this as any).clientSettings.showMaps : true;
+ const shouldShowMap = this.$store.getters.isSignedIn ? this.$store.state.settings.showMaps : true;
if (shouldShowMap) {
(this as any).os.getGoogleMaps().then(maps => {
const uluru = new maps.LatLng(this.p.geo.coordinates[1], this.p.geo.coordinates[0]);
@@ -217,8 +218,6 @@ export default Vue.extend({
@import '~const.styl'
root(isDark)
- margin 0 auto
- padding 0
overflow hidden
text-align left
background isDark ? #282C37 : #fff
diff --git a/src/client/app/desktop/views/components/note-preview.vue b/src/client/app/desktop/views/components/note-preview.vue
index 302c5e803f..1d9ee2cd0a 100644
--- a/src/client/app/desktop/views/components/note-preview.vue
+++ b/src/client/app/desktop/views/components/note-preview.vue
@@ -5,9 +5,18 @@
<header>
<router-link class="name" :to="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</router-link>
<span class="username"><mk-acct :user="note.user"/></span>
- <router-link class="time" :to="note | notePage">
- <mk-time :time="note.createdAt"/>
- </router-link>
+ <div class="info">
+ <span class="mobile" v-if="note.viaMobile">%fa:mobile-alt%</span>
+ <router-link class="created-at" :to="note | notePage">
+ <mk-time :time="note.createdAt"/>
+ </router-link>
+ <span class="visibility" v-if="note.visibility != 'public'">
+ <template v-if="note.visibility == 'home'">%fa:home%</template>
+ <template v-if="note.visibility == 'followers'">%fa:unlock%</template>
+ <template v-if="note.visibility == 'specified'">%fa:envelope%</template>
+ <template v-if="note.visibility == 'private'">%fa:lock%</template>
+ </span>
+ </div>
</header>
<div class="body">
<mk-sub-note-content class="text" :note="note"/>
@@ -32,24 +41,20 @@ export default Vue.extend({
<style lang="stylus" scoped>
root(isDark)
+ display flex
font-size 0.9em
- &:after
- content ""
- display block
- clear both
-
> .avatar
+ flex-shrink 0
display block
- float left
- margin 0 16px 0 0
- width 52px
- height 52px
+ margin 0 12px 0 0
+ width 48px
+ height 48px
border-radius 8px
> .main
- float left
- width calc(100% - 68px)
+ flex 1
+ min-width 0
> header
display flex
@@ -75,9 +80,18 @@ root(isDark)
text-overflow ellipsis
color isDark ? #606984 : #d1d8da
- > .time
+ > .info
margin-left auto
- color isDark ? #606984 : #b2b8bb
+ font-size 0.9em
+
+ > *
+ color isDark ? #606984 : #b2b8bb
+
+ > .mobile
+ margin-right 6px
+
+ > .visibility
+ margin-left 6px
> .body
@@ -85,7 +99,6 @@ root(isDark)
cursor default
margin 0
padding 0
- font-size 1.1em
color isDark ? #959ba7 : #717171
.mk-note-preview[data-darkmode]
diff --git a/src/client/app/desktop/views/components/notes.note.sub.vue b/src/client/app/desktop/views/components/notes.note.sub.vue
index 5f0c46b4c6..827112ecd8 100644
--- a/src/client/app/desktop/views/components/notes.note.sub.vue
+++ b/src/client/app/desktop/views/components/notes.note.sub.vue
@@ -44,27 +44,23 @@ export default Vue.extend({
<style lang="stylus" scoped>
root(isDark)
+ display flex
margin 0
padding 16px 32px
font-size 0.9em
background isDark ? #21242d : #fcfcfc
- &:after
- content ""
- display block
- clear both
-
> .avatar
+ flex-shrink 0
display block
- float left
- margin 0 14px 0 0
- width 52px
- height 52px
+ margin 0 12px 0 0
+ width 48px
+ height 48px
border-radius 8px
> .main
- float left
- width calc(100% - 66px)
+ flex 1
+ min-width 0
> header
display flex
@@ -89,6 +85,7 @@ root(isDark)
> .is-admin
> .is-bot
> .is-cat
+ align-self center
margin 0 0.5em 0 0
padding 1px 5px
font-size 10px
@@ -118,14 +115,11 @@ root(isDark)
margin-left 6px
> .body
- max-height 128px
- overflow hidden
> .text
cursor default
margin 0
padding 0
- font-size 1.1em
color isDark ? #959ba7 : #717171
pre
diff --git a/src/client/app/desktop/views/components/notes.note.vue b/src/client/app/desktop/views/components/notes.note.vue
index 4448820eb9..5f4b0532a8 100644
--- a/src/client/app/desktop/views/components/notes.note.vue
+++ b/src/client/app/desktop/views/components/notes.note.vue
@@ -1,6 +1,6 @@
<template>
<div class="note" tabindex="-1" :title="title" @keydown="onKeydown">
- <div class="reply-to" v-if="p.reply && (!os.isSignedIn || clientSettings.showReplyTarget)">
+ <div class="reply-to" v-if="p.reply && (!$store.getters.isSignedIn || $store.state.settings.showReplyTarget)">
<x-sub :note="p.reply"/>
</div>
<div class="renote" v-if="isRenote">
@@ -41,9 +41,10 @@
</p>
<div class="content" v-show="p.cw == null || showContent">
<div class="text">
- <span v-if="p.isHidden" style="opacity: 0.5">(この投稿は非公開です)</span>
+ <span v-if="p.isHidden" style="opacity: 0.5">%i18n:@private%</span>
+ <span v-if="p.deletedAt" style="opacity: 0.5">%i18n:@deleted%</span>
<a class="reply" v-if="p.reply">%fa:reply%</a>
- <mk-note-html v-if="p.text && !canHideText(p)" :text="p.text" :i="os.i" :class="$style.text"/>
+ <mk-note-html v-if="p.text && !canHideText(p)" :text="p.text" :i="$store.state.i" :class="$style.text"/>
<a class="rp" v-if="p.renote">RP:</a>
</div>
<div class="media" v-if="p.media.length > 0">
@@ -166,7 +167,7 @@ export default Vue.extend({
},
created() {
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection = (this as any).os.stream.getConnection();
this.connectionId = (this as any).os.stream.use();
}
@@ -175,13 +176,13 @@ export default Vue.extend({
mounted() {
this.capture(true);
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection.on('_connected_', this.onStreamConnected);
}
// Draw map
if (this.p.geo) {
- const shouldShowMap = (this as any).os.isSignedIn ? (this as any).clientSettings.showMaps : true;
+ const shouldShowMap = this.$store.getters.isSignedIn ? this.$store.state.settings.showMaps : true;
if (shouldShowMap) {
(this as any).os.getGoogleMaps().then(maps => {
const uluru = new maps.LatLng(this.p.geo.coordinates[1], this.p.geo.coordinates[0]);
@@ -201,7 +202,7 @@ export default Vue.extend({
beforeDestroy() {
this.decapture(true);
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection.off('_connected_', this.onStreamConnected);
(this as any).os.stream.dispose(this.connectionId);
}
@@ -211,7 +212,7 @@ export default Vue.extend({
canHideText,
capture(withHandler = false) {
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection.send({
type: 'capture',
id: this.p.id
@@ -221,7 +222,7 @@ export default Vue.extend({
},
decapture(withHandler = false) {
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection.send({
type: 'decapture',
id: this.p.id
@@ -347,7 +348,7 @@ root(isDark)
> .renote
display flex
align-items center
- padding 16px 32px
+ padding 16px 32px 8px 32px
line-height 28px
white-space pre
color #9dbb00
@@ -386,20 +387,16 @@ root(isDark)
padding-top 8px
> article
+ display flex
padding 28px 32px 18px 32px
- &:after
- content ""
- display block
- clear both
-
&:hover
> .main > footer > button
color isDark ? #707b97 : #888
> .avatar
+ flex-shrink 0
display block
- float left
margin 0 16px 10px 0
width 58px
height 58px
@@ -409,8 +406,8 @@ root(isDark)
//top 74px
> .main
- float left
- width calc(100% - 74px)
+ flex 1
+ min-width 0
> header
display flex
@@ -435,6 +432,7 @@ root(isDark)
> .is-admin
> .is-bot
> .is-cat
+ align-self center
margin 0 .5em 0 0
padding 1px 6px
font-size 12px
@@ -478,7 +476,6 @@ root(isDark)
margin 0
padding 0
overflow-wrap break-word
- font-size 1.1em
color isDark ? #fff : #717171
> .text
@@ -505,7 +502,6 @@ root(isDark)
margin 0
padding 0
overflow-wrap break-word
- font-size 1.1em
color isDark ? #fff : #717171
>>> .title
diff --git a/src/client/app/desktop/views/components/notes.vue b/src/client/app/desktop/views/components/notes.vue
index 55b0de3fbd..5a147f31e2 100644
--- a/src/client/app/desktop/views/components/notes.vue
+++ b/src/client/app/desktop/views/components/notes.vue
@@ -118,24 +118,24 @@ export default Vue.extend({
prepend(note, silent = false) {
//#region 弾く
- const isMyNote = note.userId == (this as any).os.i.id;
+ const isMyNote = note.userId == this.$store.state.i.id;
const isPureRenote = note.renoteId != null && note.text == null && note.mediaIds.length == 0 && note.poll == null;
- if ((this as any).clientSettings.showMyRenotes === false) {
+ if (this.$store.state.settings.showMyRenotes === false) {
if (isMyNote && isPureRenote) {
return;
}
}
- if ((this as any).clientSettings.showRenotedMyNotes === false) {
- if (isPureRenote && (note.renote.userId == (this as any).os.i.id)) {
+ if (this.$store.state.settings.showRenotedMyNotes === false) {
+ if (isPureRenote && (note.renote.userId == this.$store.state.i.id)) {
return;
}
}
//#endregion
// 投稿が自分のものではないかつ、タブが非表示またはスクロール位置が最上部ではないならタイトルで通知
- if ((document.hidden || !this.isScrollTop()) && note.userId !== (this as any).os.i.id) {
+ if ((document.hidden || !this.isScrollTop()) && note.userId !== this.$store.state.i.id) {
this.unreadCount++;
document.title = `(${this.unreadCount}) ${getNoteSummary(note)}`;
}
@@ -199,7 +199,7 @@ export default Vue.extend({
this.clearNotification();
}
- if ((this as any).clientSettings.fetchOnScroll !== false) {
+ if (this.$store.state.settings.fetchOnScroll !== false) {
const current = window.scrollY + window.innerHeight;
if (current > document.body.offsetHeight - 8) this.loadMore();
}
diff --git a/src/client/app/desktop/views/components/post-form-window.vue b/src/client/app/desktop/views/components/post-form-window.vue
index 18bb39f9bc..c55d6f1a1e 100644
--- a/src/client/app/desktop/views/components/post-form-window.vue
+++ b/src/client/app/desktop/views/components/post-form-window.vue
@@ -71,6 +71,6 @@ export default Vue.extend({
content ')'
.notePreview
- margin 16px 22px
+ margin 16px 22px 0 22px
</style>
diff --git a/src/client/app/desktop/views/components/post-form.vue b/src/client/app/desktop/views/components/post-form.vue
index 0696d4e82b..7b2adfe707 100644
--- a/src/client/app/desktop/views/components/post-form.vue
+++ b/src/client/app/desktop/views/components/post-form.vue
@@ -49,6 +49,7 @@ import Vue from 'vue';
import * as XDraggable from 'vuedraggable';
import getKao from '../../../common/scripts/get-kao';
import MkVisibilityChooser from '../../../common/views/components/visibility-chooser.vue';
+import parse from '../../../../../text/parse';
export default Vue.extend({
components: {
@@ -85,11 +86,21 @@ export default Vue.extend({
},
placeholder(): string {
+ const xs = [
+ '%i18n:common.note-placeholders.a%',
+ '%i18n:common.note-placeholders.b%',
+ '%i18n:common.note-placeholders.c%',
+ '%i18n:common.note-placeholders.d%',
+ '%i18n:common.note-placeholders.e%',
+ '%i18n:common.note-placeholders.f%'
+ ];
+ const x = xs[Math.floor(Math.random() * xs.length)];
+
return this.renote
? '%i18n:@quote-placeholder%'
: this.reply
? '%i18n:@reply-placeholder%'
- : '%i18n:@note-placeholder%';
+ : x;
},
submitText(): string {
@@ -97,7 +108,7 @@ export default Vue.extend({
? '%i18n:@renote%'
: this.reply
? '%i18n:@reply%'
- : '%i18n:@note%';
+ : '%i18n:@submit%';
},
canPost(): boolean {
@@ -110,6 +121,22 @@ export default Vue.extend({
this.text = `@${this.reply.user.username}@${this.reply.user.host} `;
}
+ if (this.reply && this.reply.text != null) {
+ const ast = parse(this.reply.text);
+
+ ast.filter(t => t.type == 'mention').forEach(x => {
+ const mention = x.host ? `@${x.username}@${x.host}` : `@${x.username}`;
+
+ // 自分は除外
+ if (this.$store.state.i.username == x.username && x.host == null) return;
+
+ // 重複は除外
+ if (this.text.indexOf(`${mention} `) != -1) return;
+
+ this.text += `${mention} `;
+ });
+ }
+
this.$nextTick(() => {
// 書きかけの投稿を復元
const draft = JSON.parse(localStorage.getItem('drafts') || '{}')[this.draftId];
diff --git a/src/client/app/desktop/views/components/settings.2fa.vue b/src/client/app/desktop/views/components/settings.2fa.vue
index 0809dd798c..3e8c860eba 100644
--- a/src/client/app/desktop/views/components/settings.2fa.vue
+++ b/src/client/app/desktop/views/components/settings.2fa.vue
@@ -2,8 +2,8 @@
<div class="2fa">
<p>%i18n:@intro%<a href="%i18n:@url%" target="_blank">%i18n:@detail%</a></p>
<div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:@caution%</p></div>
- <p v-if="!data && !os.i.twoFactorEnabled"><button @click="register" class="ui primary">%i18n:@register%</button></p>
- <template v-if="os.i.twoFactorEnabled">
+ <p v-if="!data && !$store.state.i.twoFactorEnabled"><button @click="register" class="ui primary">%i18n:@register%</button></p>
+ <template v-if="$store.state.i.twoFactorEnabled">
<p>%i18n:@already-registered%</p>
<button @click="unregister" class="ui">%i18n:@unregister%</button>
</template>
@@ -54,7 +54,7 @@ export default Vue.extend({
password: password
}).then(() => {
(this as any).apis.notify('%i18n:@unregistered%');
- (this as any).os.i.twoFactorEnabled = false;
+ this.$store.state.i.twoFactorEnabled = false;
});
});
},
@@ -64,7 +64,7 @@ export default Vue.extend({
token: this.token
}).then(() => {
(this as any).apis.notify('%i18n:@success%');
- (this as any).os.i.twoFactorEnabled = true;
+ this.$store.state.i.twoFactorEnabled = true;
}).catch(() => {
(this as any).apis.notify('%i18n:@failed%');
});
diff --git a/src/client/app/desktop/views/components/settings.api.vue b/src/client/app/desktop/views/components/settings.api.vue
index b8eef3de63..113764c3e1 100644
--- a/src/client/app/desktop/views/components/settings.api.vue
+++ b/src/client/app/desktop/views/components/settings.api.vue
@@ -1,6 +1,6 @@
<template>
<div class="root api">
- <p>%i18n:@token% <code>{{ os.i.token }}</code></p>
+ <p>%i18n:@token% <code>{{ $store.state.i.token }}</code></p>
<p>%i18n:@intro%</p>
<div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:@caution%</p></div>
<p>%i18n:@regeneration-of-token%</p>
diff --git a/src/client/app/desktop/views/components/settings.profile.vue b/src/client/app/desktop/views/components/settings.profile.vue
index 132ab12f1c..9932cbf7db 100644
--- a/src/client/app/desktop/views/components/settings.profile.vue
+++ b/src/client/app/desktop/views/components/settings.profile.vue
@@ -2,7 +2,7 @@
<div class="profile">
<label class="avatar ui from group">
<p>%i18n:@avatar%</p>
- <img class="avatar" :src="`${os.i.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
+ <img class="avatar" :src="`${$store.state.i.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
<button class="ui" @click="updateAvatar">%i18n:@choice-avatar%</button>
</label>
<label class="ui from group">
@@ -24,8 +24,8 @@
<button class="ui primary" @click="save">%i18n:@save%</button>
<section>
<h2>その他</h2>
- <mk-switch v-model="os.i.isBot" @change="onChangeIsBot" text="%i18n:@is-bot%"/>
- <mk-switch v-model="os.i.isCat" @change="onChangeIsCat" text="%i18n:@is-cat%"/>
+ <mk-switch v-model="$store.state.i.isBot" @change="onChangeIsBot" text="%i18n:@is-bot%"/>
+ <mk-switch v-model="$store.state.i.isCat" @change="onChangeIsCat" text="%i18n:@is-cat%"/>
</section>
</div>
</template>
@@ -43,10 +43,10 @@ export default Vue.extend({
};
},
created() {
- this.name = (this as any).os.i.name || '';
- this.location = (this as any).os.i.profile.location;
- this.description = (this as any).os.i.description;
- this.birthday = (this as any).os.i.profile.birthday;
+ this.name = this.$store.state.i.name || '';
+ this.location = this.$store.state.i.profile.location;
+ this.description = this.$store.state.i.description;
+ this.birthday = this.$store.state.i.profile.birthday;
},
methods: {
updateAvatar() {
@@ -64,12 +64,12 @@ export default Vue.extend({
},
onChangeIsBot() {
(this as any).api('i/update', {
- isBot: (this as any).os.i.isBot
+ isBot: this.$store.state.i.isBot
});
},
onChangeIsCat() {
(this as any).api('i/update', {
- isCat: (this as any).os.i.isCat
+ isCat: this.$store.state.i.isCat
});
}
}
diff --git a/src/client/app/desktop/views/components/settings.vue b/src/client/app/desktop/views/components/settings.vue
index dac5fe67cb..1bfff8cc83 100644
--- a/src/client/app/desktop/views/components/settings.vue
+++ b/src/client/app/desktop/views/components/settings.vue
@@ -20,7 +20,7 @@
<section class="web" v-show="page == 'web'">
<h1>%i18n:@behaviour%</h1>
- <mk-switch v-model="clientSettings.fetchOnScroll" @change="onChangeFetchOnScroll" text="%i18n:@fetch-on-scroll%">
+ <mk-switch v-model="$store.state.settings.fetchOnScroll" @change="onChangeFetchOnScroll" text="%i18n:@fetch-on-scroll%">
<span>%i18n:@fetch-on-scroll-desc%</span>
</mk-switch>
<mk-switch v-model="autoPopout" text="%i18n:@auto-popout%">
@@ -41,14 +41,14 @@
</div>
<div class="div">
<mk-switch v-model="darkmode" text="%i18n:@dark-mode%"/>
- <mk-switch v-model="clientSettings.circleIcons" @change="onChangeCircleIcons" text="%i18n:@circle-icons%"/>
- <mk-switch v-model="clientSettings.gradientWindowHeader" @change="onChangeGradientWindowHeader" text="%i18n:@gradient-window-header%"/>
+ <mk-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons" text="%i18n:@circle-icons%"/>
+ <mk-switch v-model="$store.state.settings.gradientWindowHeader" @change="onChangeGradientWindowHeader" text="%i18n:@gradient-window-header%"/>
</div>
- <mk-switch v-model="clientSettings.showPostFormOnTopOfTl" @change="onChangeShowPostFormOnTopOfTl" text="%i18n:@post-form-on-timeline%"/>
- <mk-switch v-model="clientSettings.showReplyTarget" @change="onChangeShowReplyTarget" text="%i18n:@show-reply-target%"/>
- <mk-switch v-model="clientSettings.showMyRenotes" @change="onChangeShowMyRenotes" text="%i18n:@show-my-renotes%"/>
- <mk-switch v-model="clientSettings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes" text="%i18n:@show-renoted-my-notes%"/>
- <mk-switch v-model="clientSettings.showMaps" @change="onChangeShowMaps" text="%i18n:@show-maps%">
+ <mk-switch v-model="$store.state.settings.showPostFormOnTopOfTl" @change="onChangeShowPostFormOnTopOfTl" text="%i18n:@post-form-on-timeline%"/>
+ <mk-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget" text="%i18n:@show-reply-target%"/>
+ <mk-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes" text="%i18n:@show-my-renotes%"/>
+ <mk-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes" text="%i18n:@show-renoted-my-notes%"/>
+ <mk-switch v-model="$store.state.settings.showMaps" @change="onChangeShowMaps" text="%i18n:@show-maps%">
<span>%i18n:@show-maps-desc%</span>
</mk-switch>
</section>
@@ -72,7 +72,7 @@
<section class="web" v-show="page == 'web'">
<h1>%i18n:@mobile%</h1>
- <mk-switch v-model="clientSettings.disableViaMobile" @change="onChangeDisableViaMobile" text="%i18n:@disable-via-mobile%"/>
+ <mk-switch v-model="$store.state.settings.disableViaMobile" @change="onChangeDisableViaMobile" text="%i18n:@disable-via-mobile%"/>
</section>
<section class="web" v-show="page == 'web'">
@@ -100,7 +100,7 @@
<section class="notification" v-show="page == 'notification'">
<h1>%i18n:@notification%</h1>
- <mk-switch v-model="os.i.settings.autoWatch" @change="onChangeAutoWatch" text="%i18n:@auto-watch%">
+ <mk-switch v-model="$store.state.i.settings.autoWatch" @change="onChangeAutoWatch" text="%i18n:@auto-watch%">
<span>%i18n:@auto-watch-desc%</span>
</mk-switch>
</section>
diff --git a/src/client/app/desktop/views/components/sub-note-content.vue b/src/client/app/desktop/views/components/sub-note-content.vue
index 03b634b0ff..45ce6a6f8f 100644
--- a/src/client/app/desktop/views/components/sub-note-content.vue
+++ b/src/client/app/desktop/views/components/sub-note-content.vue
@@ -1,13 +1,14 @@
<template>
<div class="mk-sub-note-content">
<div class="body">
- <span v-if="note.isHidden" style="opacity: 0.5">%i18n:@hidden%</span>
+ <span v-if="note.isHidden" style="opacity: 0.5">%i18n:@private%</span>
+ <span v-if="note.deletedAt" style="opacity: 0.5">%i18n:@deleted%</span>
<a class="reply" v-if="note.replyId">%fa:reply%</a>
- <mk-note-html :text="note.text" :i="os.i"/>
- <a class="rp" v-if="note.renoteId" :href="`/note:${note.renoteId}`">RP: ...</a>
+ <mk-note-html v-if="note.text" :text="note.text" :i="$store.state.i"/>
+ <a class="rp" v-if="note.renoteId" :href="`/notes/${note.renoteId}`">RP: ...</a>
</div>
<details v-if="note.media.length > 0">
- <summary>({{ note.media.length }}%i18n:@media%)</summary>
+ <summary>({{ '%i18n:@media-count%'.replace('{}', note.media.length) }})</summary>
<mk-media-list :media-list="note.media"/>
</details>
<details v-if="note.poll">
diff --git a/src/client/app/desktop/views/components/timeline.core.vue b/src/client/app/desktop/views/components/timeline.core.vue
index 254a5b9d63..1728dad286 100644
--- a/src/client/app/desktop/views/components/timeline.core.vue
+++ b/src/client/app/desktop/views/components/timeline.core.vue
@@ -5,7 +5,7 @@
<mk-ellipsis-icon/>
</div>
- <mk-notes ref="timeline" :more="canFetchMore ? more : null">
+ <mk-notes ref="timeline" :more="existMore ? more : null">
<p :class="$style.empty" slot="empty">
%fa:R comments%%i18n:@empty%
</p>
@@ -15,7 +15,6 @@
<script lang="ts">
import Vue from 'vue';
-import getNoteSummary from '../../../../../renderers/get-note-summary';
const fetchLimit = 10;
@@ -34,14 +33,13 @@ export default Vue.extend({
existMore: false,
connection: null,
connectionId: null,
- unreadCount: 0,
date: null
};
},
computed: {
alone(): boolean {
- return (this as any).os.i.followingCount == 0;
+ return this.$store.state.i.followingCount == 0;
},
stream(): any {
@@ -76,7 +74,6 @@ export default Vue.extend({
}
document.addEventListener('keydown', this.onKeydown);
- document.addEventListener('visibilitychange', this.onVisibilitychange, false);
this.fetch();
},
@@ -90,7 +87,6 @@ export default Vue.extend({
this.stream.dispose(this.connectionId);
document.removeEventListener('keydown', this.onKeydown);
- document.removeEventListener('visibilitychange', this.onVisibilitychange);
},
methods: {
@@ -101,8 +97,8 @@ export default Vue.extend({
(this as any).api(this.endpoint, {
limit: fetchLimit + 1,
untilDate: this.date ? this.date.getTime() : undefined,
- includeMyRenotes: (this as any).clientSettings.showMyRenotes,
- includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
+ includeMyRenotes: this.$store.state.settings.showMyRenotes,
+ includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
}).then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
@@ -120,12 +116,14 @@ export default Vue.extend({
this.moreFetching = true;
- (this as any).api(this.endpoint, {
+ const promise = (this as any).api(this.endpoint, {
limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id,
- includeMyRenotes: (this as any).clientSettings.showMyRenotes,
- includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
- }).then(notes => {
+ includeMyRenotes: this.$store.state.settings.showMyRenotes,
+ includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
+ });
+
+ promise.then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
} else {
@@ -134,14 +132,11 @@ export default Vue.extend({
notes.forEach(n => (this.$refs.timeline as any).append(n));
this.moreFetching = false;
});
+
+ return promise;
},
onNote(note) {
- if (document.hidden && note.userId !== (this as any).os.i.id) {
- this.unreadCount++;
- document.title = `(${this.unreadCount}) ${getNoteSummary(note)}`;
- }
-
// Prepend a note
(this.$refs.timeline as any).prepend(note);
},
@@ -159,13 +154,6 @@ export default Vue.extend({
this.fetch();
},
- onVisibilitychange() {
- if (!document.hidden) {
- this.unreadCount = 0;
- document.title = 'Misskey';
- }
- },
-
onKeydown(e) {
if (e.target.tagName != 'INPUT' && e.target.tagName != 'TEXTAREA') {
if (e.which == 84) { // t
diff --git a/src/client/app/desktop/views/components/timeline.vue b/src/client/app/desktop/views/components/timeline.vue
index a776e40a24..0728b78aa9 100644
--- a/src/client/app/desktop/views/components/timeline.vue
+++ b/src/client/app/desktop/views/components/timeline.vue
@@ -31,8 +31,23 @@ export default Vue.extend({
};
},
+ watch: {
+ src() {
+ this.saveSrc();
+ },
+
+ list() {
+ this.saveSrc();
+ }
+ },
+
created() {
- if ((this as any).os.i.followingCount == 0) {
+ if (this.$store.state.device.tl) {
+ this.src = this.$store.state.device.tl.src;
+ if (this.src == 'list') {
+ this.list = this.$store.state.device.tl.arg;
+ }
+ } else if (this.$store.state.i.followingCount == 0) {
this.src = 'local';
}
},
@@ -44,6 +59,13 @@ export default Vue.extend({
},
methods: {
+ saveSrc() {
+ this.$store.commit('device/setTl', {
+ src: this.src,
+ arg: this.list
+ });
+ },
+
warp(date) {
(this.$refs.tl as any).warp(date);
},
diff --git a/src/client/app/desktop/views/components/ui-notification.vue b/src/client/app/desktop/views/components/ui-notification.vue
index 9983f02c5e..68413914c0 100644
--- a/src/client/app/desktop/views/components/ui-notification.vue
+++ b/src/client/app/desktop/views/components/ui-notification.vue
@@ -36,7 +36,7 @@ export default Vue.extend({
</script>
<style lang="stylus" scoped>
-.mk-ui-notification
+root(isDark)
display block
position fixed
z-index 10000
@@ -46,10 +46,10 @@ export default Vue.extend({
margin 0 auto
padding 128px 0 0 0
width 500px
- color rgba(#000, 0.6)
- background rgba(#fff, 0.9)
+ color rgba(isDark ? #fff : #000, 0.6)
+ background rgba(isDark ? #282C37 : #fff, 0.9)
border-radius 0 0 8px 8px
- box-shadow 0 2px 4px rgba(#000, 0.2)
+ box-shadow 0 2px 4px rgba(#000, isDark ? 0.4 : 0.2)
transform translateY(-64px)
opacity 0
@@ -58,4 +58,10 @@ export default Vue.extend({
line-height 64px
text-align center
+.mk-ui-notification[data-darkmode]
+ root(true)
+
+.mk-ui-notification:not([data-darkmode])
+ root(false)
+
</style>
diff --git a/src/client/app/desktop/views/components/ui.header.account.vue b/src/client/app/desktop/views/components/ui.header.account.vue
index f3f6539496..8d26691f84 100644
--- a/src/client/app/desktop/views/components/ui.header.account.vue
+++ b/src/client/app/desktop/views/components/ui.header.account.vue
@@ -1,14 +1,14 @@
<template>
<div class="account">
<button class="header" :data-active="isOpen" @click="toggle">
- <span class="username">{{ os.i.username }}<template v-if="!isOpen">%fa:angle-down%</template><template v-if="isOpen">%fa:angle-up%</template></span>
- <mk-avatar class="avatar" :user="os.i"/>
+ <span class="username">{{ $store.state.i.username }}<template v-if="!isOpen">%fa:angle-down%</template><template v-if="isOpen">%fa:angle-up%</template></span>
+ <mk-avatar class="avatar" :user="$store.state.i"/>
</button>
<transition name="zoom-in-top">
<div class="menu" v-if="isOpen">
<ul>
<li>
- <router-link :to="`/@${ os.i.username }`">%fa:user%<span>%i18n:@profile%</span>%fa:angle-right%</router-link>
+ <router-link :to="`/@${ $store.state.i.username }`">%fa:user%<span>%i18n:@profile%</span>%fa:angle-right%</router-link>
</li>
<li @click="drive">
<p>%fa:cloud%<span>%i18n:@drive%</span>%fa:angle-right%</p>
diff --git a/src/client/app/desktop/views/components/ui.header.clock.vue b/src/client/app/desktop/views/components/ui.header.clock.vue
index cd23a67506..1c3f12f2f2 100644
--- a/src/client/app/desktop/views/components/ui.header.clock.vue
+++ b/src/client/app/desktop/views/components/ui.header.clock.vue
@@ -8,7 +8,7 @@
</time>
</div>
<div class="content">
- <mk-analog-clock/>
+ <mk-analog-clock :dark="true"/>
</div>
</div>
</template>
diff --git a/src/client/app/desktop/views/components/ui.header.nav.vue b/src/client/app/desktop/views/components/ui.header.nav.vue
index 0800d96eb6..4780c57cb4 100644
--- a/src/client/app/desktop/views/components/ui.header.nav.vue
+++ b/src/client/app/desktop/views/components/ui.header.nav.vue
@@ -1,7 +1,7 @@
<template>
<div class="nav">
<ul>
- <template v-if="os.isSignedIn">
+ <template v-if="$store.getters.isSignedIn">
<li class="home" :class="{ active: $route.name == 'index' }">
<router-link to="/">
%fa:home%
@@ -12,7 +12,7 @@
<a @click="messaging">
%fa:comments%
<p>%i18n:@messaging%</p>
- <template v-if="hasUnreadMessagingMessages">%fa:circle%</template>
+ <template v-if="hasUnreadMessagingMessage">%fa:circle%</template>
</a>
</li>
<li class="game">
@@ -35,48 +35,33 @@ import MkGameWindow from './game-window.vue';
export default Vue.extend({
data() {
return {
- hasUnreadMessagingMessages: false,
hasGameInvitations: false,
connection: null,
connectionId: null
};
},
+ computed: {
+ hasUnreadMessagingMessage(): boolean {
+ return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadMessagingMessage;
+ }
+ },
mounted() {
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection = (this as any).os.stream.getConnection();
this.connectionId = (this as any).os.stream.use();
- this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages);
- this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage);
this.connection.on('othello_invited', this.onOthelloInvited);
this.connection.on('othello_no_invites', this.onOthelloNoInvites);
-
- // Fetch count of unread messaging messages
- (this as any).api('messaging/unread').then(res => {
- if (res.count > 0) {
- this.hasUnreadMessagingMessages = true;
- }
- });
}
},
beforeDestroy() {
- if ((this as any).os.isSignedIn) {
- this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages);
- this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage);
+ if (this.$store.getters.isSignedIn) {
this.connection.off('othello_invited', this.onOthelloInvited);
this.connection.off('othello_no_invites', this.onOthelloNoInvites);
(this as any).os.stream.dispose(this.connectionId);
}
},
methods: {
- onUnreadMessagingMessage() {
- this.hasUnreadMessagingMessages = true;
- },
-
- onReadAllMessagingMessages() {
- this.hasUnreadMessagingMessages = false;
- },
-
onOthelloInvited() {
this.hasGameInvitations = true;
},
diff --git a/src/client/app/desktop/views/components/ui.header.notifications.vue b/src/client/app/desktop/views/components/ui.header.notifications.vue
index ea814dd7a3..59a16df9ec 100644
--- a/src/client/app/desktop/views/components/ui.header.notifications.vue
+++ b/src/client/app/desktop/views/components/ui.header.notifications.vue
@@ -1,7 +1,7 @@
<template>
<div class="notifications">
<button :data-active="isOpen" @click="toggle" title="%i18n:@title%">
- %fa:R bell%<template v-if="hasUnreadNotifications">%fa:circle%</template>
+ %fa:R bell%<template v-if="hasUnreadNotification">%fa:circle%</template>
</button>
<div class="pop" v-if="isOpen">
<mk-notifications/>
@@ -16,44 +16,15 @@ import contains from '../../../common/scripts/contains';
export default Vue.extend({
data() {
return {
- isOpen: false,
- hasUnreadNotifications: false,
- connection: null,
- connectionId: null
+ isOpen: false
};
},
- mounted() {
- if ((this as any).os.isSignedIn) {
- this.connection = (this as any).os.stream.getConnection();
- this.connectionId = (this as any).os.stream.use();
-
- this.connection.on('read_all_notifications', this.onReadAllNotifications);
- this.connection.on('unread_notification', this.onUnreadNotification);
-
- // Fetch count of unread notifications
- (this as any).api('notifications/get_unread_count').then(res => {
- if (res.count > 0) {
- this.hasUnreadNotifications = true;
- }
- });
- }
- },
- beforeDestroy() {
- if ((this as any).os.isSignedIn) {
- this.connection.off('read_all_notifications', this.onReadAllNotifications);
- this.connection.off('unread_notification', this.onUnreadNotification);
- (this as any).os.stream.dispose(this.connectionId);
+ computed: {
+ hasUnreadNotification(): boolean {
+ return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadNotification;
}
},
methods: {
- onReadAllNotifications() {
- this.hasUnreadNotifications = false;
- },
-
- onUnreadNotification() {
- this.hasUnreadNotifications = true;
- },
-
toggle() {
this.isOpen ? this.close() : this.open();
},
diff --git a/src/client/app/desktop/views/components/ui.header.vue b/src/client/app/desktop/views/components/ui.header.vue
index 7729575b56..7045790054 100644
--- a/src/client/app/desktop/views/components/ui.header.vue
+++ b/src/client/app/desktop/views/components/ui.header.vue
@@ -4,16 +4,16 @@
<div class="main" ref="main">
<div class="backdrop"></div>
<div class="main">
- <p ref="welcomeback" v-if="os.isSignedIn">おかえりなさい、<b>{{ os.i | userName }}</b>さん</p>
+ <p ref="welcomeback" v-if="$store.getters.isSignedIn">おかえりなさい、<b>{{ $store.state.i | userName }}</b>さん</p>
<div class="container" ref="mainContainer">
<div class="left">
<x-nav/>
</div>
<div class="right">
<x-search/>
- <x-account v-if="os.isSignedIn"/>
- <x-notifications v-if="os.isSignedIn"/>
- <x-post v-if="os.isSignedIn"/>
+ <x-account v-if="$store.getters.isSignedIn"/>
+ <x-notifications v-if="$store.getters.isSignedIn"/>
+ <x-post v-if="$store.getters.isSignedIn"/>
<x-clock/>
</div>
</div>
@@ -45,11 +45,11 @@ export default Vue.extend({
mounted() {
this.$store.commit('setUiHeaderHeight', 48);
- if ((this as any).os.isSignedIn) {
- const ago = (new Date().getTime() - new Date((this as any).os.i.lastUsedAt).getTime()) / 1000;
+ if (this.$store.getters.isSignedIn) {
+ const ago = (new Date().getTime() - new Date(this.$store.state.i.lastUsedAt).getTime()) / 1000;
const isHisasiburi = ago >= 3600;
- (this as any).os.i.lastUsedAt = new Date();
- (this as any).os.bakeMe();
+ this.$store.state.i.lastUsedAt = new Date();
+
if (isHisasiburi) {
(this.$refs.welcomeback as any).style.display = 'block';
(this.$refs.main as any).style.overflow = 'hidden';
@@ -150,8 +150,8 @@ root(isDark)
display block
width 100%
height 48px
- background-image url(/assets/desktop/header-logo.svg)
- background-size 46px
+ background-image isDark ? url('/assets/desktop/header-icon.dark.svg') : url('/assets/desktop/header-icon.light.svg')
+ background-size 24px
background-position center
background-repeat no-repeat
opacity 0.3
diff --git a/src/client/app/desktop/views/components/ui.vue b/src/client/app/desktop/views/components/ui.vue
index 87f932ff14..b6dd22c1f8 100644
--- a/src/client/app/desktop/views/components/ui.vue
+++ b/src/client/app/desktop/views/components/ui.vue
@@ -4,7 +4,7 @@
<div class="content">
<slot></slot>
</div>
- <mk-stream-indicator v-if="os.isSignedIn"/>
+ <mk-stream-indicator v-if="$store.getters.isSignedIn"/>
</div>
</template>
diff --git a/src/client/app/desktop/views/components/user-list-timeline.vue b/src/client/app/desktop/views/components/user-list-timeline.vue
index 59d6abbbc1..03ac81a4a1 100644
--- a/src/client/app/desktop/views/components/user-list-timeline.vue
+++ b/src/client/app/desktop/views/components/user-list-timeline.vue
@@ -32,7 +32,7 @@ export default Vue.extend({
methods: {
init() {
if (this.connection) this.connection.close();
- this.connection = new UserListStream((this as any).os, (this as any).os.i, this.list.id);
+ this.connection = new UserListStream((this as any).os, this.$store.state.i, this.list.id);
this.connection.on('note', this.onNote);
this.connection.on('userAdded', this.onUserAdded);
this.connection.on('userRemoved', this.onUserRemoved);
@@ -46,8 +46,8 @@ export default Vue.extend({
(this as any).api('notes/user-list-timeline', {
listId: this.list.id,
limit: fetchLimit + 1,
- includeMyRenotes: (this as any).clientSettings.showMyRenotes,
- includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
+ includeMyRenotes: this.$store.state.settings.showMyRenotes,
+ includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
}).then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
@@ -62,13 +62,15 @@ export default Vue.extend({
more() {
this.moreFetching = true;
- (this as any).api('notes/user-list-timeline', {
+ const promise = (this as any).api('notes/user-list-timeline', {
listId: this.list.id,
limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id,
- includeMyRenotes: (this as any).clientSettings.showMyRenotes,
- includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
- }).then(notes => {
+ includeMyRenotes: this.$store.state.settings.showMyRenotes,
+ includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
+ });
+
+ promise.then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
} else {
@@ -77,6 +79,8 @@ export default Vue.extend({
notes.forEach(n => (this.$refs.timeline as any).append(n));
this.moreFetching = false;
});
+
+ return promise;
},
onNote(note) {
// Prepend a note
diff --git a/src/client/app/desktop/views/components/user-preview.vue b/src/client/app/desktop/views/components/user-preview.vue
index b8854a8032..788881ead5 100644
--- a/src/client/app/desktop/views/components/user-preview.vue
+++ b/src/client/app/desktop/views/components/user-preview.vue
@@ -19,7 +19,7 @@
<p>%i18n:@followers%</p><a>{{ u.followersCount }}</a>
</div>
</div>
- <mk-follow-button v-if="os.isSignedIn && user.id != os.i.id" :user="u"/>
+ <mk-follow-button v-if="$store.getters.isSignedIn && user.id != $store.state.i.id" :user="u"/>
</template>
</div>
</template>
diff --git a/src/client/app/desktop/views/components/users-list.vue b/src/client/app/desktop/views/components/users-list.vue
index 1ed5c33b13..0423db8ed7 100644
--- a/src/client/app/desktop/views/components/users-list.vue
+++ b/src/client/app/desktop/views/components/users-list.vue
@@ -3,7 +3,7 @@
<nav>
<div>
<span :data-active="mode == 'all'" @click="mode = 'all'">%i18n:@all%<span>{{ count }}</span></span>
- <span v-if="os.isSignedIn && youKnowCount" :data-active="mode == 'iknow'" @click="mode = 'iknow'">%i18n:@iknow%<span>{{ youKnowCount }}</span></span>
+ <span v-if="$store.getters.isSignedIn && youKnowCount" :data-active="mode == 'iknow'" @click="mode = 'iknow'">%i18n:@iknow%<span>{{ youKnowCount }}</span></span>
</div>
</nav>
<div class="users" v-if="!fetching && users.length != 0">
diff --git a/src/client/app/desktop/views/components/widget-container.vue b/src/client/app/desktop/views/components/widget-container.vue
index ab8327d39e..488e9cb249 100644
--- a/src/client/app/desktop/views/components/widget-container.vue
+++ b/src/client/app/desktop/views/components/widget-container.vue
@@ -23,9 +23,9 @@ export default Vue.extend({
},
computed: {
withGradient(): boolean {
- return (this as any).os.isSignedIn
- ? (this as any).clientSettings.gradientWindowHeader != null
- ? (this as any).clientSettings.gradientWindowHeader
+ return this.$store.getters.isSignedIn
+ ? this.$store.state.settings.gradientWindowHeader != null
+ ? this.$store.state.settings.gradientWindowHeader
: false
: false;
}
diff --git a/src/client/app/desktop/views/components/window.vue b/src/client/app/desktop/views/components/window.vue
index ac06ac8e57..ec044ad27e 100644
--- a/src/client/app/desktop/views/components/window.vue
+++ b/src/client/app/desktop/views/components/window.vue
@@ -4,7 +4,7 @@
<div class="main" ref="main" tabindex="-1" :data-is-modal="isModal" @mousedown="onBodyMousedown" @keydown="onKeydown" :style="{ width, height }">
<div class="body">
<header ref="header"
- :class="{ withGradient: clientSettings.gradientWindowHeader }"
+ :class="{ withGradient: $store.state.settings.gradientWindowHeader }"
@contextmenu.prevent="() => {}" @mousedown.prevent="onHeaderMousedown"
>
<h1><slot name="header"></slot></h1>
@@ -95,7 +95,7 @@ export default Vue.extend({
},
created() {
- if ((this as any).os.store.state.device.autoPopout && this.popoutUrl) {
+ if (this.$store.state.device.autoPopout && this.popoutUrl) {
this.popout();
this.preventMount = true;
} else {
@@ -488,7 +488,10 @@ root(isDark)
&:focus
&:not([data-is-modal])
> .body
- box-shadow 0 0 0px 1px rgba($theme-color, 0.5), 0 2px 6px 0 rgba(#000, 0.2)
+ if isDark
+ box-shadow 0 0 0px 1px rgba($theme-color, 0.5), 0 2px 12px 0 rgba(#000, 0.5)
+ else
+ box-shadow 0 0 0px 1px rgba($theme-color, 0.5), 0 2px 6px 0 rgba(#000, 0.2)
> .handle
$size = 8px
@@ -556,7 +559,11 @@ root(isDark)
overflow hidden
background isDark ? #282C37 : #fff
border-radius 6px
- box-shadow 0 2px 6px 0 rgba(#000, 0.2)
+
+ if isDark
+ box-shadow 0 2px 12px 0 rgba(#000, 0.5)
+ else
+ box-shadow 0 2px 6px 0 rgba(#000, 0.2)
> header
$header-height = 40px
diff --git a/src/client/app/desktop/views/pages/favorites.vue b/src/client/app/desktop/views/pages/favorites.vue
index 71d36cdf2b..8adb9412f2 100644
--- a/src/client/app/desktop/views/pages/favorites.vue
+++ b/src/client/app/desktop/views/pages/favorites.vue
@@ -2,7 +2,7 @@
<mk-ui>
<main v-if="!fetching">
<template v-for="favorite in favorites">
- <mk-note-detail :note="favorite.note" :key="favorite.note.id"/>
+ <mk-note-detail class="post" :note="favorite.note" :key="favorite.note.id"/>
</template>
<a v-if="existMore" @click="more">%i18n:@more%</a>
</main>
@@ -70,4 +70,7 @@ main
margin 0 auto
padding 16px
max-width 700px
+
+ > .post
+ margin-bottom 16px
</style>
diff --git a/src/client/app/desktop/views/pages/home.vue b/src/client/app/desktop/views/pages/home.vue
index e4caa2022e..60b257edb7 100644
--- a/src/client/app/desktop/views/pages/home.vue
+++ b/src/client/app/desktop/views/pages/home.vue
@@ -7,7 +7,6 @@
<script lang="ts">
import Vue from 'vue';
import Progress from '../../../common/scripts/loading';
-import getNoteSummary from '../../../../../renderers/get-note-summary';
export default Vue.extend({
props: {
@@ -16,46 +15,14 @@ export default Vue.extend({
default: 'timeline'
}
},
- data() {
- return {
- connection: null,
- connectionId: null,
- unreadCount: 0
- };
- },
mounted() {
document.title = 'Misskey';
- this.connection = (this as any).os.stream.getConnection();
- this.connectionId = (this as any).os.stream.use();
-
- this.connection.on('note', this.onStreamNote);
- document.addEventListener('visibilitychange', this.onVisibilitychange, false);
-
Progress.start();
},
- beforeDestroy() {
- this.connection.off('note', this.onStreamNote);
- (this as any).os.stream.dispose(this.connectionId);
- document.removeEventListener('visibilitychange', this.onVisibilitychange);
- },
methods: {
loaded() {
Progress.done();
- },
-
- onStreamNote(note) {
- if (document.hidden && note.userId != (this as any).os.i.id) {
- this.unreadCount++;
- document.title = `(${this.unreadCount}) ${getNoteSummary(note)}`;
- }
- },
-
- onVisibilitychange() {
- if (!document.hidden) {
- this.unreadCount = 0;
- document.title = 'Misskey';
- }
}
}
});
diff --git a/src/client/app/desktop/views/pages/index.vue b/src/client/app/desktop/views/pages/index.vue
index 0ea47d913b..5d11fc5423 100644
--- a/src/client/app/desktop/views/pages/index.vue
+++ b/src/client/app/desktop/views/pages/index.vue
@@ -1,5 +1,5 @@
<template>
-<component :is="os.isSignedIn ? 'home' : 'welcome'"></component>
+<component :is="$store.getters.isSignedIn ? 'home' : 'welcome'"></component>
</template>
<script lang="ts">
diff --git a/src/client/app/desktop/views/pages/user/user.header.vue b/src/client/app/desktop/views/pages/user/user.header.vue
index 73af3a4a4c..44910bc7f0 100644
--- a/src/client/app/desktop/views/pages/user/user.header.vue
+++ b/src/client/app/desktop/views/pages/user/user.header.vue
@@ -63,7 +63,7 @@ export default Vue.extend({
},
onBannerClick() {
- if (!(this as any).os.isSignedIn || (this as any).os.i.id != this.user.id) return;
+ if (!this.$store.getters.isSignedIn || this.$store.state.i.id != this.user.id) return;
(this as any).apis.updateBanner().then(i => {
this.user.bannerUrl = i.bannerUrl;
diff --git a/src/client/app/desktop/views/pages/user/user.home.vue b/src/client/app/desktop/views/pages/user/user.home.vue
index 6b242a6129..afaf97dc9e 100644
--- a/src/client/app/desktop/views/pages/user/user.home.vue
+++ b/src/client/app/desktop/views/pages/user/user.home.vue
@@ -4,7 +4,7 @@
<div ref="left">
<x-profile :user="user"/>
<x-photos :user="user"/>
- <x-followers-you-know v-if="os.isSignedIn && os.i.id != user.id" :user="user"/>
+ <x-followers-you-know v-if="$store.getters.isSignedIn && $store.state.i.id != user.id" :user="user"/>
<p v-if="user.host === null">%i18n:@last-used-at%: <b><mk-time :time="user.lastUsedAt"/></b></p>
</div>
</div>
diff --git a/src/client/app/desktop/views/pages/user/user.profile.vue b/src/client/app/desktop/views/pages/user/user.profile.vue
index 29e49f36a6..5aa08f7c85 100644
--- a/src/client/app/desktop/views/pages/user/user.profile.vue
+++ b/src/client/app/desktop/views/pages/user/user.profile.vue
@@ -1,6 +1,6 @@
<template>
<div class="profile">
- <div class="friend-form" v-if="os.isSignedIn && os.i.id != user.id">
+ <div class="friend-form" v-if="$store.getters.isSignedIn && $store.state.i.id != user.id">
<mk-follow-button :user="user" size="big"/>
<p class="followed" v-if="user.isFollowed">%i18n:@follows-you%</p>
<p class="stalk" v-if="user.isFollowing">
diff --git a/src/client/app/desktop/views/pages/user/user.timeline.vue b/src/client/app/desktop/views/pages/user/user.timeline.vue
index 576a285104..812b5b4229 100644
--- a/src/client/app/desktop/views/pages/user/user.timeline.vue
+++ b/src/client/app/desktop/views/pages/user/user.timeline.vue
@@ -21,6 +21,7 @@ const fetchLimit = 10;
export default Vue.extend({
props: ['user'],
+
data() {
return {
fetching: true,
@@ -31,19 +32,23 @@ export default Vue.extend({
date: null
};
},
+
watch: {
mode() {
this.fetch();
}
},
+
mounted() {
document.addEventListener('keydown', this.onDocumentKeydown);
this.fetch(() => this.$emit('loaded'));
},
+
beforeDestroy() {
document.removeEventListener('keydown', this.onDocumentKeydown);
},
+
methods: {
onDocumentKeydown(e) {
if (e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA') {
@@ -52,6 +57,7 @@ export default Vue.extend({
}
}
},
+
fetch(cb?) {
this.fetching = true;
(this.$refs.timeline as any).init(() => new Promise((res, rej) => {
@@ -72,15 +78,19 @@ export default Vue.extend({
}, rej);
}));
},
+
more() {
this.moreFetching = true;
- (this as any).api('users/notes', {
+
+ const promise = (this as any).api('users/notes', {
userId: this.user.id,
limit: fetchLimit + 1,
includeReplies: this.mode == 'with-replies',
withMedia: this.mode == 'with-media',
untilId: (this.$refs.timeline as any).tail().id
- }).then(notes => {
+ });
+
+ promise.then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
} else {
@@ -89,7 +99,10 @@ export default Vue.extend({
notes.forEach(n => (this.$refs.timeline as any).append(n));
this.moreFetching = false;
});
+
+ return promise;
},
+
warp(date) {
this.date = date;
this.fetch();
diff --git a/src/client/app/desktop/views/pages/welcome.vue b/src/client/app/desktop/views/pages/welcome.vue
index 91ad4b61c3..cecd7e3a90 100644
--- a/src/client/app/desktop/views/pages/welcome.vue
+++ b/src/client/app/desktop/views/pages/welcome.vue
@@ -4,9 +4,20 @@
<template v-if="$store.state.device.darkmode">%fa:moon%</template>
<template v-else>%fa:R moon%</template>
</button>
- <main>
- <img :src="$store.state.device.darkmode ? 'assets/title-dark.svg' : 'assets/title.svg'" alt="Misskey">
- <p><button class="signup" @click="signup">%i18n:@signup-button%</button><button class="signin" @click="signin">%i18n:@signin-button%</button></p>
+ <main v-if="about" class="about">
+ <article>
+ <h1>%i18n:common.about-title%</h1>
+ <p v-html="'%i18n:common.about%'"></p>
+ <span class="gotit" @click="about = false">%i18n:@gotit%</span>
+ </article>
+ </main>
+ <main v-else class="index">
+ <img :src="$store.state.device.darkmode ? 'assets/title.dark.svg' : 'assets/title.light.svg'" alt="Misskey">
+ <p class="desc"><b>%i18n:common.misskey%</b> - <span @click="about = true">%i18n:@about%</span></p>
+ <p class="account">
+ <button class="signup" @click="signup">%i18n:@signup-button%</button>
+ <button class="signin" @click="signin">%i18n:@signin-button%</button>
+ </p>
<div class="tl">
<header>%fa:comments R% %i18n:@timeline%<div><span></span><span></span><span></span></div></header>
@@ -33,12 +44,12 @@
<script lang="ts">
import Vue from 'vue';
-import { docsUrl, copyright, lang } from '../../../config';
+import { copyright } from '../../../config';
export default Vue.extend({
data() {
return {
- aboutUrl: `${docsUrl}/${lang}/about`,
+ about: false,
copyright
};
},
@@ -69,13 +80,18 @@ export default Vue.extend({
<style lang="stylus" scoped>
@import '~const.styl'
+@import url(https://fonts.googleapis.com/earlyaccess/notosansjp.css);
+
root(isDark)
display flex
flex-direction column
flex 1
+ background-image isDark ? url('/assets/welcome-bg.dark.svg') : url('/assets/welcome-bg.light.svg')
+ background-size cover
+ background-position center
> button
- position absolute
+ position fixed
z-index 1
top 0
left 0
@@ -87,81 +103,120 @@ root(isDark)
flex 1
padding 64px 0 0 0
text-align center
- color isDark ? #9aa4b3 : #555
- > img
- width 350px
+ &.about
+ font-family 'Noto Sans JP'
+ color isDark ? #fff : #627574
+
+ > article
+ max-width 700px
+ margin 42px auto 0 auto
+ padding 64px 82px
+ background isDark ? #282C37 : #fff
+ box-shadow 0 8px 32px rgba(#000, 0.15)
+
+ > h1
+ margin 0
+ font-weight 900
+
+ > p
+ margin 20px 0
+ line-height 2em
+
+ > .gotit
+ color $theme-color
+ cursor pointer
+
+ &:hover
+ text-decoration underline
+
+ &.index
+ color isDark ? #9aa4b3 : #555
+
+ > img
+ width 350px
+
+ > .desc
+ margin -12px 0 24px 0
+ color isDark ? #fff : #555
+
+ > span
+ color $theme-color
+ cursor pointer
+
+ &:hover
+ text-decoration underline
- > p
- margin 8px 0
- line-height 2em
+ > .account
+ margin 8px 0
+ line-height 2em
- button
- padding 8px 16px
- font-size inherit
+ button
+ padding 8px 16px
+ font-size inherit
- .signup
- color $theme-color
- border solid 2px $theme-color
- border-radius 4px
+ .signup
+ color $theme-color
+ border solid 2px $theme-color
+ border-radius 4px
- &:focus
- box-shadow 0 0 0 3px rgba($theme-color, 0.2)
+ &:focus
+ box-shadow 0 0 0 3px rgba($theme-color, 0.2)
- &:hover
- color $theme-color-foreground
- background $theme-color
+ &:hover
+ color $theme-color-foreground
+ background $theme-color
- &:active
- color $theme-color-foreground
- background darken($theme-color, 10%)
- border-color darken($theme-color, 10%)
+ &:active
+ color $theme-color-foreground
+ background darken($theme-color, 10%)
+ border-color darken($theme-color, 10%)
- .signin
- &:hover
- color isDark ? #fff : #000
+ .signin
+ &:hover
+ color isDark ? #fff : #000
- > .tl
- margin 32px auto 0 auto
- width 410px
- text-align left
- background isDark ? #313543 : #fff
- border-radius 8px
- box-shadow 0 8px 32px rgba(#000, 0.15)
- overflow hidden
+ > .tl
+ margin 32px auto 0 auto
+ width 410px
+ text-align left
+ background isDark ? #313543 : #fff
+ border-radius 8px
+ box-shadow 0 8px 32px rgba(#000, 0.15)
+ overflow hidden
- > header
- z-index 1
- padding 12px 16px
- color isDark ? #e3e5e8 : #888d94
- box-shadow 0 1px 0px rgba(#000, 0.1)
+ > header
+ z-index 1
+ padding 12px 16px
+ color isDark ? #e3e5e8 : #888d94
+ box-shadow 0 1px 0px rgba(#000, 0.1)
- > div
- position absolute
- top 0
- right 0
- padding inherit
+ > div
+ position absolute
+ top 0
+ right 0
+ padding inherit
- > span
- display inline-block
- height 11px
- width 11px
- margin-left 6px
- border-radius 100%
- vertical-align middle
+ > span
+ display inline-block
+ height 11px
+ width 11px
+ margin-left 6px
+ border-radius 100%
+ vertical-align middle
- &:nth-child(1)
- background #5BCC8B
+ &:nth-child(1)
+ background #5BCC8B
- &:nth-child(2)
- background #E6BB46
+ &:nth-child(2)
+ background #E6BB46
- &:nth-child(3)
- background #DF7065
+ &:nth-child(3)
+ background #DF7065
- > .mk-welcome-timeline
- max-height 350px
- overflow auto
+ > .mk-welcome-timeline
+ max-height 350px
+ overflow auto
> footer
font-size 12px
diff --git a/src/client/app/desktop/views/widgets/activity.vue b/src/client/app/desktop/views/widgets/activity.vue
index 1be87f590c..73c6d0ef64 100644
--- a/src/client/app/desktop/views/widgets/activity.vue
+++ b/src/client/app/desktop/views/widgets/activity.vue
@@ -2,7 +2,7 @@
<mk-activity
:design="props.design"
:init-view="props.view"
- :user="os.i"
+ :user="$store.state.i"
@view-changed="viewChanged"/>
</template>
diff --git a/src/client/app/desktop/views/widgets/post-form.vue b/src/client/app/desktop/views/widgets/post-form.vue
index 69b21ad37a..3c4ade0e81 100644
--- a/src/client/app/desktop/views/widgets/post-form.vue
+++ b/src/client/app/desktop/views/widgets/post-form.vue
@@ -3,7 +3,7 @@
<template v-if="props.design == 0">
<p class="title">%fa:pencil-alt%%i18n:@title%</p>
</template>
- <textarea :disabled="posting" v-model="text" @keydown="onKeydown" placeholder="%i18n:@placeholder%"></textarea>
+ <textarea :disabled="posting" v-model="text" @keydown="onKeydown" :placeholder="placeholder"></textarea>
<button @click="post" :disabled="posting">%i18n:@note%</button>
</div>
</template>
@@ -22,6 +22,19 @@ export default define({
text: ''
};
},
+ computed: {
+ placeholder(): string {
+ const xs = [
+ '%i18n:common.note-placeholders.a%',
+ '%i18n:common.note-placeholders.b%',
+ '%i18n:common.note-placeholders.c%',
+ '%i18n:common.note-placeholders.d%',
+ '%i18n:common.note-placeholders.e%',
+ '%i18n:common.note-placeholders.f%'
+ ];
+ return xs[Math.floor(Math.random() * xs.length)];
+ }
+ },
methods: {
func() {
if (this.props.design == 1) {
diff --git a/src/client/app/desktop/views/widgets/profile.vue b/src/client/app/desktop/views/widgets/profile.vue
index 5af5b88e23..7b0fea3729 100644
--- a/src/client/app/desktop/views/widgets/profile.vue
+++ b/src/client/app/desktop/views/widgets/profile.vue
@@ -4,16 +4,16 @@
:data-melt="props.design == 2"
>
<div class="banner"
- :style="os.i.bannerUrl ? `background-image: url(${os.i.bannerUrl}?thumbnail&size=256)` : ''"
+ :style="$store.state.i.bannerUrl ? `background-image: url(${$store.state.i.bannerUrl}?thumbnail&size=256)` : ''"
title="%i18n:@update-banner%"
@click="os.apis.updateBanner"
></div>
- <mk-avatar class="avatar" :user="os.i"
+ <mk-avatar class="avatar" :user="$store.state.i"
@click="os.apis.updateAvatar"
title="%i18n:@update-avatar%"
/>
- <router-link class="name" :to="os.i | userPage">{{ os.i | userName }}</router-link>
- <p class="username">@{{ os.i | acct }}</p>
+ <router-link class="name" :to="$store.state.i | userPage">{{ $store.state.i | userName }}</router-link>
+ <p class="username">@{{ $store.state.i | acct }}</p>
</div>
</template>
diff --git a/src/client/app/init.ts b/src/client/app/init.ts
index 560ab1a096..043f26d0bc 100644
--- a/src/client/app/init.ts
+++ b/src/client/app/init.ts
@@ -67,14 +67,6 @@ const html = document.documentElement;
html.setAttribute('lang', lang);
//#endregion
-//#region Set description meta tag
-const head = document.getElementsByTagName('head')[0];
-const meta = document.createElement('meta');
-meta.setAttribute('name', 'description');
-meta.setAttribute('content', '%i18n:common.misskey%');
-head.appendChild(meta);
-//#endregion
-
// iOSでプライベートモードだとlocalStorageが使えないので既存のメソッドを上書きする
try {
localStorage.setItem('kyoppie', 'yuppie');
@@ -143,8 +135,7 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API)
return {
os,
api: os.api,
- apis: os.apis,
- clientSettings: os.store.state.settings
+ apis: os.apis
};
}
});
diff --git a/src/client/app/mios.ts b/src/client/app/mios.ts
index a5a38a5414..a8da5ddb55 100644
--- a/src/client/app/mios.ts
+++ b/src/client/app/mios.ts
@@ -1,10 +1,9 @@
import Vue from 'vue';
import { EventEmitter } from 'eventemitter3';
-import * as merge from 'object-assign-deep';
import * as uuid from 'uuid';
import initStore from './store';
-import { hostname, apiUrl, swPublickey, version, lang, googleMapsApiKey } from './config';
+import { apiUrl, swPublickey, version, lang, googleMapsApiKey } from './config';
import Progress from './common/scripts/loading';
import Connection from './common/scripts/streaming/stream';
import { HomeStreamManager } from './common/scripts/streaming/home';
@@ -83,18 +82,6 @@ export default class MiOS extends EventEmitter {
}
/**
- * A signing user
- */
- public i: { [x: string]: any };
-
- /**
- * Whether signed in
- */
- public get isSignedIn() {
- return this.i != null;
- }
-
- /**
* Whether is debug mode
*/
public get debug() {
@@ -218,15 +205,8 @@ export default class MiOS extends EventEmitter {
console.error.apply(null, args);
}
- public bakeMe() {
- // ローカルストレージにキャッシュ
- localStorage.setItem('me', JSON.stringify(this.i));
- }
-
public signout() {
- localStorage.removeItem('me');
- localStorage.removeItem('settings');
- document.cookie = `i=; domain=${hostname}; expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
+ this.store.dispatch('logout');
location.href = '/';
}
@@ -242,14 +222,14 @@ export default class MiOS extends EventEmitter {
this.once('signedin', () => {
// Init home stream manager
- this.stream = new HomeStreamManager(this, this.i);
+ this.stream = new HomeStreamManager(this, this.store.state.i);
// Init other stream manager
- this.streams.localTimelineStream = new LocalTimelineStreamManager(this, this.i);
- this.streams.globalTimelineStream = new GlobalTimelineStreamManager(this, this.i);
- this.streams.driveStream = new DriveStreamManager(this, this.i);
- this.streams.messagingIndexStream = new MessagingIndexStreamManager(this, this.i);
- this.streams.othelloStream = new OthelloStreamManager(this, this.i);
+ this.streams.localTimelineStream = new LocalTimelineStreamManager(this, this.store.state.i);
+ this.streams.globalTimelineStream = new GlobalTimelineStreamManager(this, this.store.state.i);
+ this.streams.driveStream = new DriveStreamManager(this, this.store.state.i);
+ this.streams.messagingIndexStream = new MessagingIndexStreamManager(this, this.store.state.i);
+ this.streams.othelloStream = new OthelloStreamManager(this, this.store.state.i);
});
//#endregion
@@ -300,51 +280,29 @@ export default class MiOS extends EventEmitter {
};
// フェッチが完了したとき
- const fetched = me => {
- this.i = me;
-
- // ローカルストレージにキャッシュ
- this.bakeMe();
-
+ const fetched = () => {
this.emit('signedin');
// Finish init
callback();
- //#region Note
-
// Init service worker
if (this.shouldRegisterSw) this.registerSw();
-
- //#endregion
};
- // Get cached account data
- const cachedMe = JSON.parse(localStorage.getItem('me'));
-
- //#region キャッシュされた設定を復元
- const cachedSettings = JSON.parse(localStorage.getItem('settings'));
-
- if (cachedSettings) {
- this.store.dispatch('settings/merge', cachedSettings);
- }
- //#endregion
-
// キャッシュがあったとき
- if (cachedMe) {
- if (cachedMe.token == null) {
+ if (this.store.state.i != null) {
+ if (this.store.state.i.token == null) {
this.signout();
return;
}
// とりあえずキャッシュされたデータでお茶を濁して(?)おいて、
- fetched(cachedMe);
+ fetched();
// 後から新鮮なデータをフェッチ
- fetchme(cachedMe.token, freshData => {
- merge(cachedMe, freshData);
-
- this.store.dispatch('settings/merge', freshData.clientSettings);
+ fetchme(this.store.state.i.token, freshData => {
+ this.store.dispatch('mergeMe', freshData);
});
} else {
// Get token from cookie
@@ -352,9 +310,8 @@ export default class MiOS extends EventEmitter {
fetchme(i, me => {
if (me) {
- this.store.dispatch('settings/merge', me.clientSettings);
-
- fetched(me);
+ this.store.dispatch('login', me);
+ fetched();
} else {
// Finish init
callback();
@@ -375,7 +332,7 @@ export default class MiOS extends EventEmitter {
if (!isSwSupported) return;
// Reject when not signed in to Misskey
- if (!this.isSignedIn) return;
+ if (!this.store.getters.isSignedIn) return;
// When service worker activated
navigator.serviceWorker.ready.then(registration => {
@@ -484,7 +441,7 @@ export default class MiOS extends EventEmitter {
});
} else {
// Append a credential
- if (this.isSignedIn) (data as any).i = this.i.token;
+ if (this.store.getters.isSignedIn) (data as any).i = this.store.state.i.token;
const req = {
id: uuid(),
diff --git a/src/client/app/mobile/script.ts b/src/client/app/mobile/script.ts
index 5418aac090..607ff63711 100644
--- a/src/client/app/mobile/script.ts
+++ b/src/client/app/mobile/script.ts
@@ -36,6 +36,9 @@ import MkNote from './views/pages/note.vue';
import MkSearch from './views/pages/search.vue';
import MkFollowers from './views/pages/followers.vue';
import MkFollowing from './views/pages/following.vue';
+import MkFavorites from './views/pages/favorites.vue';
+import MkUserLists from './views/pages/user-lists.vue';
+import MkUserList from './views/pages/user-list.vue';
import MkSettings from './views/pages/settings.vue';
import MkOthello from './views/pages/othello.vue';
@@ -72,6 +75,9 @@ init((launch) => {
{ path: '/signup', name: 'signup', component: MkSignup },
{ path: '/i/settings', name: 'settings', component: MkSettings },
{ path: '/i/notifications', name: 'notifications', component: MkNotifications },
+ { path: '/i/favorites', name: 'favorites', component: MkFavorites },
+ { path: '/i/lists', name: 'user-lists', component: MkUserLists },
+ { path: '/i/lists/:list', name: 'user-list', component: MkUserList },
{ path: '/i/widgets', name: 'widgets', component: MkWidgets },
{ path: '/i/messaging', name: 'messaging', component: MkMessaging },
{ path: '/i/messaging/:user', component: MkMessagingRoom },
diff --git a/src/client/app/mobile/views/components/drive.file-detail.vue b/src/client/app/mobile/views/components/drive.file-detail.vue
index ddf17d2723..ad29135268 100644
--- a/src/client/app/mobile/views/components/drive.file-detail.vue
+++ b/src/client/app/mobile/views/components/drive.file-detail.vue
@@ -93,7 +93,7 @@ export default Vue.extend({
},
methods: {
rename() {
- const name = window.prompt('名前を変更', this.file.name);
+ const name = window.prompt('%i18n:@rename%', this.file.name);
if (name == null || name == '' || name == this.file.name) return;
(this as any).api('drive/files/update', {
fileId: this.file.id,
diff --git a/src/client/app/mobile/views/components/drive.vue b/src/client/app/mobile/views/components/drive.vue
index 8e35e6c88b..8adf6d8543 100644
--- a/src/client/app/mobile/views/components/drive.vue
+++ b/src/client/app/mobile/views/components/drive.vue
@@ -372,7 +372,7 @@ export default Vue.extend({
},
openContextMenu() {
- const fn = window.prompt('何をしますか?(数字を入力してください): <1 → ファイルをアップロード | 2 → ファイルをURLでアップロード | 3 → フォルダ作成 | 4 → このフォルダ名を変更 | 5 → このフォルダを移動 | 6 → このフォルダを削除>');
+ const fn = window.prompt('%i18n:@prompt%');
if (fn == null || fn == '') return;
switch (fn) {
case '1':
@@ -391,7 +391,7 @@ export default Vue.extend({
this.moveFolder();
break;
case '6':
- alert('ごめんなさい!フォルダの削除は未実装です...。');
+ alert('%i18n:@deletion-alert%');
break;
}
},
@@ -401,7 +401,7 @@ export default Vue.extend({
},
createFolder() {
- const name = window.prompt('フォルダー名');
+ const name = window.prompt('%i18n:@folder-name%');
if (name == null || name == '') return;
(this as any).api('drive/folders/create', {
name: name,
@@ -413,10 +413,10 @@ export default Vue.extend({
renameFolder() {
if (this.folder == null) {
- alert('現在いる場所はルートで、フォルダではないため名前の変更はできません。名前を変更したいフォルダに移動してからやってください。');
+ alert('%i18n:@root-rename-alert%');
return;
}
- const name = window.prompt('フォルダー名', this.folder.name);
+ const name = window.prompt('%i18n:@folder-name%', this.folder.name);
if (name == null || name == '') return;
(this as any).api('drive/folders/update', {
name: name,
@@ -428,7 +428,7 @@ export default Vue.extend({
moveFolder() {
if (this.folder == null) {
- alert('現在いる場所はルートで、フォルダではないため移動はできません。移動したいフォルダに移動してからやってください。');
+ alert('%i18n:@root-move-alert%');
return;
}
(this as any).apis.chooseDriveFolder().then(folder => {
@@ -442,13 +442,13 @@ export default Vue.extend({
},
urlUpload() {
- const url = window.prompt('アップロードしたいファイルのURL');
+ const url = window.prompt('%i18n:@url-prompt%');
if (url == null || url == '') return;
(this as any).api('drive/files/upload_from_url', {
url: url,
folderId: this.folder ? this.folder.id : undefined
});
- alert('アップロードをリクエストしました。アップロードが完了するまで時間がかかる場合があります。');
+ alert('%i18n:@uploading%');
},
onChangeLocalFile() {
diff --git a/src/client/app/mobile/views/components/friends-maker.vue b/src/client/app/mobile/views/components/friends-maker.vue
index ba4abe341f..e0461d2bc2 100644
--- a/src/client/app/mobile/views/components/friends-maker.vue
+++ b/src/client/app/mobile/views/components/friends-maker.vue
@@ -1,13 +1,13 @@
<template>
<div class="mk-friends-maker">
- <p class="title">気になるユーザーをフォロー:</p>
+ <p class="title">%i18n:@title%:</p>
<div class="users" v-if="!fetching && users.length > 0">
<mk-user-card v-for="user in users" :key="user.id" :user="user"/>
</div>
- <p class="empty" v-if="!fetching && users.length == 0">おすすめのユーザーは見つかりませんでした。</p>
- <p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%読み込んでいます<mk-ellipsis/></p>
- <a class="refresh" @click="refresh">もっと見る</a>
- <button class="close" @click="close" title="閉じる">%fa:times%</button>
+ <p class="empty" v-if="!fetching && users.length == 0">%i18n:@empty%</p>
+ <p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:@fetching%<mk-ellipsis/></p>
+ <a class="refresh" @click="refresh">%i18n:@refresh%</a>
+ <button class="close" @click="close" title="%i18n:@close%">%fa:times%</button>
</div>
</template>
diff --git a/src/client/app/mobile/views/components/note-detail.sub.vue b/src/client/app/mobile/views/components/note-detail.sub.vue
deleted file mode 100644
index 3ad5af1719..0000000000
--- a/src/client/app/mobile/views/components/note-detail.sub.vue
+++ /dev/null
@@ -1,101 +0,0 @@
-<template>
-<div class="root sub">
- <mk-avatar class="avatar" :user="note.user"/>
- <div class="main">
- <header>
- <router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
- <span class="username"><mk-acct :user="note.user"/></span>
- <router-link class="time" :to="note | notePage">
- <mk-time :time="note.createdAt"/>
- </router-link>
- </header>
- <div class="body">
- <mk-sub-note-content class="text" :note="note"/>
- </div>
- </div>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-
-export default Vue.extend({
- props: ['note']
-});
-</script>
-
-<style lang="stylus" scoped>
-root(isDark)
- padding 8px
- font-size 0.9em
- background isDark ? #21242d : #fdfdfd
-
- @media (min-width 500px)
- padding 12px
-
- @media (min-width 600px)
- padding 24px 32px
-
- &:after
- content ""
- display block
- clear both
-
- > .avatar
- display block
- float left
- margin 0 12px 0 0
- width 48px
- height 48px
- border-radius 8px
-
- > .main
- float left
- width calc(100% - 60px)
-
- > header
- display flex
- align-items baseline
- margin-bottom 4px
- white-space nowrap
-
- > .name
- display block
- margin 0 .5em 0 0
- padding 0
- overflow hidden
- color isDark ? #fff : #607073
- font-size 1em
- font-weight 700
- text-align left
- text-decoration none
- text-overflow ellipsis
-
- &:hover
- text-decoration underline
-
- > .username
- text-align left
- margin 0 .5em 0 0
- color isDark ? #606984 : #d1d8da
-
- > .time
- margin-left auto
- color isDark ? #606984 : #b2b8bb
-
- > .body
-
- > .text
- cursor default
- margin 0
- padding 0
- font-size 1.1em
- color isDark ? #959ba7 : #717171
-
-.root.sub[data-darkmode]
- root(true)
-
-.root.sub:not([data-darkmode])
- root(false)
-
-</style>
diff --git a/src/client/app/mobile/views/components/note-detail.vue b/src/client/app/mobile/views/components/note-detail.vue
index 244dbb6c03..bdbb8876df 100644
--- a/src/client/app/mobile/views/components/note-detail.vue
+++ b/src/client/app/mobile/views/components/note-detail.vue
@@ -17,7 +17,13 @@
</div>
<div class="renote" v-if="isRenote">
<p>
- <mk-avatar class="avatar" :user="note.user"/>%fa:retweet%<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>がRenote
+ <mk-avatar class="avatar" :user="note.user"/>
+ %fa:retweet%
+ <router-link class="name" :href="note.user | userPage">{{ note.user | userName }}</router-link>
+ <span>{{ '%i18n:@reposted-by%'.substr(0, '%i18n:@reposted-by%'.indexOf('{')) }}</span>
+ <a class="name" :href="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</a>
+ <span>{{ '%i18n:@reposted-by%'.substr('%i18n:@reposted-by%'.indexOf('}') + 1) }}</span>
+ <mk-time :time="note.createdAt"/>
</p>
</div>
<article>
@@ -30,8 +36,9 @@
</header>
<div class="body">
<div class="text">
- <span v-if="p.isHidden" style="opacity: 0.5">(この投稿は非公開です)</span>
- <mk-note-html v-if="p.text" :text="p.text" :i="os.i"/>
+ <span v-if="p.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
+ <span v-if="p.deletedAt" style="opacity: 0.5">(%i18n:@deleted%)</span>
+ <mk-note-html v-if="p.text" :text="p.text" :i="$store.state.i"/>
</div>
<div class="tags" v-if="p.tags && p.tags.length > 0">
<router-link v-for="tag in p.tags" :key="tag" :to="`/search?q=#${tag}`">{{ tag }}</router-link>
@@ -41,7 +48,7 @@
</div>
<mk-poll v-if="p.poll" :note="p"/>
<mk-url-preview v-for="url in urls" :url="url" :key="url"/>
- <a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a>
+ <a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a>
<div class="map" v-if="p.geo" ref="map"></div>
<div class="renote" v-if="p.renote">
<mk-note-preview :note="p.renote"/>
@@ -80,7 +87,7 @@ import parse from '../../../../../text/parse';
import MkNoteMenu from '../../../common/views/components/note-menu.vue';
import MkReactionPicker from '../../../common/views/components/reaction-picker.vue';
-import XSub from './note-detail.sub.vue';
+import XSub from './note.sub.vue';
export default Vue.extend({
components: {
@@ -147,7 +154,7 @@ export default Vue.extend({
// Draw map
if (this.p.geo) {
- const shouldShowMap = (this as any).os.isSignedIn ? (this as any).clientSettings.showMaps : true;
+ const shouldShowMap = this.$store.getters.isSignedIn ? this.$store.state.settings.showMaps : true;
if (shouldShowMap) {
(this as any).os.getGoogleMaps().then(maps => {
const uluru = new maps.LatLng(this.p.geo.coordinates[1], this.p.geo.coordinates[0]);
@@ -165,7 +172,7 @@ export default Vue.extend({
},
methods: {
- fetchContext() {
+ fetchConversation() {
this.conversationFetching = true;
// Fetch conversation
@@ -209,8 +216,6 @@ export default Vue.extend({
root(isDark)
overflow hidden
- margin 0 auto
- padding 0
width 100%
text-align left
background isDark ? #282C37 : #fff
diff --git a/src/client/app/mobile/views/components/note-preview.vue b/src/client/app/mobile/views/components/note-preview.vue
index 8fa57768e0..77ca99e978 100644
--- a/src/client/app/mobile/views/components/note-preview.vue
+++ b/src/client/app/mobile/views/components/note-preview.vue
@@ -5,13 +5,22 @@
<header>
<mk-avatar class="avatar" :user="note.user" v-if="$store.state.device.postStyle == 'smart'"/>
<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
- <span class="is-admin" v-if="note.user.isAdmin">admin</span>
- <span class="is-bot" v-if="note.user.isBot">bot</span>
- <span class="is-cat" v-if="note.user.isCat">cat</span>
+ <span class="is-admin" v-if="note.user.isAdmin">%i18n:@admin%</span>
+ <span class="is-bot" v-if="note.user.isBot">%i18n:@bot%</span>
+ <span class="is-cat" v-if="note.user.isCat">%i18n:@cat%</span>
<span class="username"><mk-acct :user="note.user"/></span>
- <router-link class="time" :to="note | notePage">
- <mk-time :time="note.createdAt"/>
- </router-link>
+ <div class="info">
+ <span class="mobile" v-if="note.viaMobile">%fa:mobile-alt%</span>
+ <router-link class="created-at" :to="note | notePage">
+ <mk-time :time="note.createdAt"/>
+ </router-link>
+ <span class="visibility" v-if="note.visibility != 'public'">
+ <template v-if="note.visibility == 'home'">%fa:home%</template>
+ <template v-if="note.visibility == 'followers'">%fa:unlock%</template>
+ <template v-if="note.visibility == 'specified'">%fa:envelope%</template>
+ <template v-if="note.visibility == 'private'">%fa:lock%</template>
+ </span>
+ </div>
</header>
<div class="body">
<mk-sub-note-content class="text" :note="note"/>
@@ -30,14 +39,16 @@ export default Vue.extend({
<style lang="stylus" scoped>
root(isDark)
+ display flex
margin 0
padding 0
- font-size 0.9em
+ font-size 10px
- &:after
- content ""
- display block
- clear both
+ @media (min-width 350px)
+ font-size 12px
+
+ @media (min-width 500px)
+ font-size 14px
&.smart
> .main
@@ -47,21 +58,31 @@ root(isDark)
align-items center
> .avatar
+ flex-shrink 0
display block
- float left
- margin 0 12px 0 0
- width 48px
- height 48px
+ margin 0 10px 0 0
+ width 40px
+ height 40px
border-radius 8px
+ @media (min-width 350px)
+ margin 0 10px 0 0
+ width 44px
+ height 44px
+
+ @media (min-width 500px)
+ margin 0 12px 0 0
+ width 48px
+ height 48px
+
> .main
- float left
- width calc(100% - 60px)
+ flex 1
+ min-width 0
> header
display flex
align-items baseline
- margin-bottom 4px
+ margin-bottom 2px
white-space nowrap
> .avatar
@@ -86,9 +107,10 @@ root(isDark)
> .is-admin
> .is-bot
> .is-cat
+ align-self center
margin 0 0.5em 0 0
padding 1px 6px
- font-size 10px
+ font-size 0.8em
color isDark ? #758188 : #aaa
border solid 1px isDark ? #57616f : #ddd
border-radius 3px
@@ -103,9 +125,18 @@ root(isDark)
text-overflow ellipsis
color isDark ? #606984 : #d1d8da
- > .time
+ > .info
margin-left auto
- color isDark ? #606984 : #b2b8bb
+ font-size 0.9em
+
+ > *
+ color isDark ? #606984 : #b2b8bb
+
+ > .mobile
+ margin-right 6px
+
+ > .visibility
+ margin-left 6px
> .body
@@ -113,7 +144,6 @@ root(isDark)
cursor default
margin 0
padding 0
- font-size 1.1em
color isDark ? #959ba7 : #717171
.mk-note-preview[data-darkmode]
diff --git a/src/client/app/mobile/views/components/note.sub.vue b/src/client/app/mobile/views/components/note.sub.vue
index 149a78ecde..f487b7647e 100644
--- a/src/client/app/mobile/views/components/note.sub.vue
+++ b/src/client/app/mobile/views/components/note.sub.vue
@@ -5,9 +5,9 @@
<header>
<mk-avatar class="avatar" :user="note.user" v-if="$store.state.device.postStyle == 'smart'"/>
<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
- <span class="is-admin" v-if="note.user.isAdmin">admin</span>
- <span class="is-bot" v-if="note.user.isBot">bot</span>
- <span class="is-cat" v-if="note.user.isCat">cat</span>
+ <span class="is-admin" v-if="note.user.isAdmin">%i18n:@admin%</span>
+ <span class="is-bot" v-if="note.user.isBot">%i18n:@bot%</span>
+ <span class="is-cat" v-if="note.user.isCat">%i18n:@cat%</span>
<span class="username"><mk-acct :user="note.user"/></span>
<div class="info">
<span class="mobile" v-if="note.viaMobile">%fa:mobile-alt%</span>
@@ -33,16 +33,33 @@
import Vue from 'vue';
export default Vue.extend({
- props: ['note']
+ props: {
+ note: {
+ type: Object,
+ required: true
+ },
+ // TODO
+ truncate: {
+ type: Boolean,
+ default: true
+ }
+ }
});
</script>
<style lang="stylus" scoped>
root(isDark)
+ display flex
padding 16px
- font-size 0.9em
+ font-size 10px
background isDark ? #21242d : #fcfcfc
+ @media (min-width 350px)
+ font-size 12px
+
+ @media (min-width 500px)
+ font-size 14px
+
@media (min-width 600px)
padding 24px 32px
@@ -53,30 +70,27 @@ root(isDark)
> header
align-items center
- &:after
- content ""
- display block
- clear both
-
> .avatar
+ flex-shrink 0
display block
- float left
- margin 0 10px 0 0
- width 44px
- height 44px
+ margin 0 8px 0 0
+ width 38px
+ height 38px
border-radius 8px
+ @media (min-width 350px)
+ margin-right 10px
+ width 42px
+ height 42px
+
@media (min-width 500px)
- margin-right 16px
- width 52px
- height 52px
+ margin-right 14px
+ width 50px
+ height 50px
> .main
- float left
- width calc(100% - 54px)
-
- @media (min-width 500px)
- width calc(100% - 68px)
+ flex 1
+ min-width 0
> header
display flex
@@ -109,9 +123,10 @@ root(isDark)
> .is-admin
> .is-bot
> .is-cat
+ align-self center
margin 0 0.5em 0 0
padding 1px 5px
- font-size 10px
+ font-size 0.8em
color isDark ? #758188 : #aaa
border solid 1px isDark ? #57616f : #ddd
border-radius 3px
@@ -139,14 +154,10 @@ root(isDark)
margin-left 6px
> .body
- max-height 128px
- overflow hidden
> .text
- cursor default
margin 0
padding 0
- font-size 1.1em
color isDark ? #959ba7 : #717171
pre
diff --git a/src/client/app/mobile/views/components/note.vue b/src/client/app/mobile/views/components/note.vue
index 2004263d22..34326e12f3 100644
--- a/src/client/app/mobile/views/components/note.vue
+++ b/src/client/app/mobile/views/components/note.vue
@@ -1,6 +1,6 @@
<template>
<div class="note" :class="{ renote: isRenote, smart: $store.state.device.postStyle == 'smart' }">
- <div class="reply-to" v-if="p.reply && (!os.isSignedIn || clientSettings.showReplyTarget)">
+ <div class="reply-to" v-if="p.reply && (!$store.getters.isSignedIn || $store.state.settings.showReplyTarget)">
<x-sub :note="p.reply"/>
</div>
<div class="renote" v-if="isRenote">
@@ -37,13 +37,14 @@
<div class="body">
<p v-if="p.cw != null" class="cw">
<span class="text" v-if="p.cw != ''">{{ p.cw }}</span>
- <span class="toggle" @click="showContent = !showContent">{{ showContent ? '隠す' : 'もっと見る' }}</span>
+ <span class="toggle" @click="showContent = !showContent">{{ showContent ? '%i18n:@less%' : '%i18n:@more%' }}</span>
</p>
<div class="content" v-show="p.cw == null || showContent">
<div class="text">
- <span v-if="p.isHidden" style="opacity: 0.5">(この投稿は非公開です)</span>
+ <span v-if="p.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
+ <span v-if="p.deletedAt" style="opacity: 0.5">(%i18n:@deleted%)</span>
<a class="reply" v-if="p.reply">%fa:reply%</a>
- <mk-note-html v-if="p.text && !canHideText(p)" :text="p.text" :i="os.i" :class="$style.text"/>
+ <mk-note-html v-if="p.text && !canHideText(p)" :text="p.text" :i="$store.state.i" :class="$style.text"/>
<a class="rp" v-if="p.renote != null">RP:</a>
</div>
<div class="media" v-if="p.media.length > 0">
@@ -54,7 +55,7 @@
<router-link v-for="tag in p.tags" :key="tag" :to="`/search?q=#${tag}`">{{ tag }}</router-link>
</div>
<mk-url-preview v-for="url in urls" :url="url" :key="url"/>
- <a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a>
+ <a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a>
<div class="map" v-if="p.geo" ref="map"></div>
<div class="renote" v-if="p.renote">
<mk-note-preview :note="p.renote"/>
@@ -141,7 +142,7 @@ export default Vue.extend({
},
created() {
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection = (this as any).os.stream.getConnection();
this.connectionId = (this as any).os.stream.use();
}
@@ -150,13 +151,13 @@ export default Vue.extend({
mounted() {
this.capture(true);
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection.on('_connected_', this.onStreamConnected);
}
// Draw map
if (this.p.geo) {
- const shouldShowMap = (this as any).os.isSignedIn ? (this as any).clientSettings.showMaps : true;
+ const shouldShowMap = this.$store.getters.isSignedIn ? this.$store.state.settings.showMaps : true;
if (shouldShowMap) {
(this as any).os.getGoogleMaps().then(maps => {
const uluru = new maps.LatLng(this.p.geo.coordinates[1], this.p.geo.coordinates[0]);
@@ -176,7 +177,7 @@ export default Vue.extend({
beforeDestroy() {
this.decapture(true);
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection.off('_connected_', this.onStreamConnected);
(this as any).os.stream.dispose(this.connectionId);
}
@@ -186,7 +187,7 @@ export default Vue.extend({
canHideText,
capture(withHandler = false) {
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection.send({
type: 'capture',
id: this.p.id
@@ -196,7 +197,7 @@ export default Vue.extend({
},
decapture(withHandler = false) {
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection.send({
type: 'decapture',
id: this.p.id
@@ -268,8 +269,6 @@ root(isDark)
&.smart
> article
> .main
- width 100%
-
> header
align-items center
margin-bottom 4px
@@ -327,27 +326,28 @@ root(isDark)
padding-top 8px
> article
+ display flex
padding 16px 16px 9px
@media (min-width 600px)
padding 32px 32px 22px
- &:after
- content ""
- display block
- clear both
-
> .avatar
+ flex-shrink 0
display block
- float left
margin 0 10px 8px 0
- width 48px
- height 48px
+ width 42px
+ height 42px
border-radius 6px
//position -webkit-sticky
//position sticky
//top 62px
+ @media (min-width 350px)
+ width 48px
+ height 48px
+ border-radius 6px
+
@media (min-width 500px)
margin-right 16px
width 58px
@@ -355,11 +355,8 @@ root(isDark)
border-radius 8px
> .main
- float left
- width calc(100% - 58px)
-
- @media (min-width 500px)
- width calc(100% - 74px)
+ flex 1
+ min-width 0
> header
display flex
@@ -389,9 +386,10 @@ root(isDark)
> .is-admin
> .is-bot
> .is-cat
+ align-self center
margin 0 0.5em 0 0
padding 1px 6px
- font-size 12px
+ font-size 0.8em
color isDark ? #758188 : #aaa
border solid 1px isDark ? #57616f : #ddd
border-radius 3px
@@ -420,6 +418,8 @@ root(isDark)
margin-left 6px
> .body
+ @media (min-width 700px)
+ font-size 1.1em
> .cw
cursor default
@@ -427,7 +427,6 @@ root(isDark)
margin 0
padding 0
overflow-wrap break-word
- font-size 1.1em
color isDark ? #fff : #717171
> .text
@@ -453,7 +452,6 @@ root(isDark)
margin 0
padding 0
overflow-wrap break-word
- font-size 1.1em
color isDark ? #fff : #717171
>>> .title
diff --git a/src/client/app/mobile/views/components/notes.vue b/src/client/app/mobile/views/components/notes.vue
index e77698dea9..09cee966a3 100644
--- a/src/client/app/mobile/views/components/notes.vue
+++ b/src/client/app/mobile/views/components/notes.vue
@@ -9,8 +9,8 @@
</div>
<div v-if="!fetching && requestInitPromise != null">
- <p>読み込みに失敗しました。</p>
- <button @click="resolveInitPromise">リトライ</button>
+ <p>%i18n:@failed%</p>
+ <button @click="resolveInitPromise">%i18n:@retry%</button>
</div>
<transition-group name="mk-notes" class="transition">
@@ -121,24 +121,24 @@ export default Vue.extend({
prepend(note, silent = false) {
//#region 弾く
- const isMyNote = note.userId == (this as any).os.i.id;
+ const isMyNote = note.userId == this.$store.state.i.id;
const isPureRenote = note.renoteId != null && note.text == null && note.mediaIds.length == 0 && note.poll == null;
- if ((this as any).clientSettings.showMyRenotes === false) {
+ if (this.$store.state.settings.showMyRenotes === false) {
if (isMyNote && isPureRenote) {
return;
}
}
- if ((this as any).clientSettings.showRenotedMyNotes === false) {
- if (isPureRenote && (note.renote.userId == (this as any).os.i.id)) {
+ if (this.$store.state.settings.showRenotedMyNotes === false) {
+ if (isPureRenote && (note.renote.userId == this.$store.state.i.id)) {
return;
}
}
//#endregion
// 投稿が自分のものではないかつ、タブが非表示またはスクロール位置が最上部ではないならタイトルで通知
- if ((document.hidden || !this.isScrollTop()) && note.userId !== (this as any).os.i.id) {
+ if ((document.hidden || !this.isScrollTop()) && note.userId !== this.$store.state.i.id) {
this.unreadCount++;
document.title = `(${this.unreadCount}) ${getNoteSummary(note)}`;
}
@@ -195,7 +195,7 @@ export default Vue.extend({
this.clearNotification();
}
- if ((this as any).clientSettings.fetchOnScroll !== false) {
+ if (this.$store.state.settings.fetchOnScroll !== false) {
// 親要素が display none だったら弾く
// https://github.com/syuilo/misskey/issues/1569
// http://d.hatena.ne.jp/favril/20091105/1257403319
diff --git a/src/client/app/mobile/views/components/post-form.vue b/src/client/app/mobile/views/components/post-form.vue
index b3b5ffd502..beacb1721b 100644
--- a/src/client/app/mobile/views/components/post-form.vue
+++ b/src/client/app/mobile/views/components/post-form.vue
@@ -5,11 +5,7 @@
<div>
<span class="text-count" :class="{ over: text.length > 1000 }">{{ 1000 - text.length }}</span>
<span class="geo" v-if="geo">%fa:map-marker-alt%</span>
- <button class="submit" :disabled="posting" @click="post">
- <template v-if="reply">%i18n:@reply%</template>
- <template v-else-if="renote">%i18n:@renote%</template>
- <template v-else>%i18n:@submit%</template>
- </button>
+ <button class="submit" :disabled="posting" @click="post">{{ submitText }}</button>
</div>
</header>
<div class="form">
@@ -17,10 +13,10 @@
<mk-note-preview v-if="renote" :note="renote"/>
<div v-if="visibility == 'specified'" class="visibleUsers">
<span v-for="u in visibleUsers">{{ u | userName }}<a @click="removeVisibleUser(u)">[x]</a></span>
- <a @click="addVisibleUser">+ユーザーを追加</a>
+ <a @click="addVisibleUser">+%i18n:@add-visible-user%</a>
</div>
- <input v-show="useCw" v-model="cw" placeholder="内容への注釈 (オプション)">
- <textarea v-model="text" ref="text" :disabled="posting" :placeholder="reply ? '%i18n:@reply-placeholder%' : renote ? '%i18n:@renote-placeholder%' : '%i18n:@note-placeholder%'"></textarea>
+ <input v-show="useCw" v-model="cw" placeholder="%i18n:@cw-placeholder%">
+ <textarea v-model="text" ref="text" :disabled="posting" :placeholder="placeholder"></textarea>
<div class="attaches" v-show="files.length != 0">
<x-draggable class="files" :list="files" :options="{ animation: 150 }">
<div class="file" v-for="file in files" :key="file.id">
@@ -49,6 +45,7 @@ import Vue from 'vue';
import * as XDraggable from 'vuedraggable';
import MkVisibilityChooser from '../../../common/views/components/visibility-chooser.vue';
import getKao from '../../../common/scripts/get-kao';
+import parse from '../../../../../text/parse';
export default Vue.extend({
components: {
@@ -73,11 +70,67 @@ export default Vue.extend({
};
},
+ computed: {
+ draftId(): string {
+ return this.renote
+ ? 'renote:' + this.renote.id
+ : this.reply
+ ? 'reply:' + this.reply.id
+ : 'note';
+ },
+
+ placeholder(): string {
+ const xs = [
+ '%i18n:common.note-placeholders.a%',
+ '%i18n:common.note-placeholders.b%',
+ '%i18n:common.note-placeholders.c%',
+ '%i18n:common.note-placeholders.d%',
+ '%i18n:common.note-placeholders.e%',
+ '%i18n:common.note-placeholders.f%'
+ ];
+ const x = xs[Math.floor(Math.random() * xs.length)];
+
+ return this.renote
+ ? '%i18n:@quote-placeholder%'
+ : this.reply
+ ? '%i18n:@reply-placeholder%'
+ : x;
+ },
+
+ submitText(): string {
+ return this.renote
+ ? '%i18n:@renote%'
+ : this.reply
+ ? '%i18n:@reply%'
+ : '%i18n:@submit%';
+ },
+
+ canPost(): boolean {
+ return !this.posting && (this.text.length != 0 || this.files.length != 0 || this.poll || this.renote);
+ }
+ },
+
mounted() {
if (this.reply && this.reply.user.host != null) {
this.text = `@${this.reply.user.username}@${this.reply.user.host} `;
}
+ if (this.reply && this.reply.text != null) {
+ const ast = parse(this.reply.text);
+
+ ast.filter(t => t.type == 'mention').forEach(x => {
+ const mention = x.host ? `@${x.username}@${x.host}` : `@${x.username}`;
+
+ // 自分は除外
+ if (this.$store.state.i.username == x.username && x.host == null) return;
+
+ // 重複は除外
+ if (this.text.indexOf(`${mention} `) != -1) return;
+
+ this.text += `${mention} `;
+ });
+ }
+
this.$nextTick(() => {
this.focus();
});
@@ -124,14 +177,14 @@ export default Vue.extend({
setGeo() {
if (navigator.geolocation == null) {
- alert('お使いの端末は位置情報に対応していません');
+ alert('%i18n:@location-alert%');
return;
}
navigator.geolocation.getCurrentPosition(pos => {
this.geo = pos.coords;
}, err => {
- alert('エラー: ' + err.message);
+ alert('%i18n:@error%: ' + err.message);
}, {
enableHighAccuracy: true
});
@@ -154,7 +207,7 @@ export default Vue.extend({
addVisibleUser() {
(this as any).apis.input({
- title: 'ユーザー名を入力してください'
+ title: '%i18n:@username-prompt%'
}).then(username => {
(this as any).api('users/show', {
username
@@ -177,7 +230,7 @@ export default Vue.extend({
post() {
this.posting = true;
- const viaMobile = (this as any).clientSettings.disableViaMobile !== true;
+ const viaMobile = this.$store.state.settings.disableViaMobile !== true;
(this as any).api('notes/create', {
text: this.text == '' ? undefined : this.text,
mediaIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
diff --git a/src/client/app/mobile/views/components/sub-note-content.vue b/src/client/app/mobile/views/components/sub-note-content.vue
index cc50977a58..4ad90b97df 100644
--- a/src/client/app/mobile/views/components/sub-note-content.vue
+++ b/src/client/app/mobile/views/components/sub-note-content.vue
@@ -1,13 +1,14 @@
<template>
<div class="mk-sub-note-content">
<div class="body">
- <span v-if="note.isHidden" style="opacity: 0.5">(この投稿は非公開です)</span>
+ <span v-if="note.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
+ <span v-if="note.deletedAt" style="opacity: 0.5">(%i18n:@deleted%)</span>
<a class="reply" v-if="note.replyId">%fa:reply%</a>
- <mk-note-html v-if="note.text" :text="note.text" :i="os.i"/>
+ <mk-note-html v-if="note.text" :text="note.text" :i="$store.state.i"/>
<a class="rp" v-if="note.renoteId">RP: ...</a>
</div>
<details v-if="note.media.length > 0">
- <summary>({{ note.media.length }}個のメディア)</summary>
+ <summary>({{ '%i18n:@media-count%'.replace('{}', note.media.length) }})</summary>
<mk-media-list :media-list="note.media"/>
</details>
<details v-if="note.poll">
diff --git a/src/client/app/mobile/views/components/ui.header.vue b/src/client/app/mobile/views/components/ui.header.vue
index a49462b159..c72b15fb8b 100644
--- a/src/client/app/mobile/views/components/ui.header.vue
+++ b/src/client/app/mobile/views/components/ui.header.vue
@@ -3,10 +3,10 @@
<mk-special-message/>
<div class="main" ref="main">
<div class="backdrop"></div>
- <p ref="welcomeback" v-if="os.isSignedIn">おかえりなさい、<b>{{ os.i | userName }}</b>さん</p>
+ <p ref="welcomeback" v-if="$store.getters.isSignedIn">おかえりなさい、<b>{{ $store.state.i | userName }}</b>さん</p>
<div class="content" ref="mainContainer">
<button class="nav" @click="$parent.isDrawerOpening = true">%fa:bars%</button>
- <template v-if="hasUnreadNotifications || hasUnreadMessagingMessages || hasGameInvitations">%fa:circle%</template>
+ <template v-if="hasUnreadNotification || hasUnreadMessagingMessage || hasGameInvitation">%fa:circle%</template>
<h1>
<slot>Misskey</slot>
</h1>
@@ -25,45 +25,33 @@ export default Vue.extend({
props: ['func'],
data() {
return {
- hasUnreadNotifications: false,
- hasUnreadMessagingMessages: false,
- hasGameInvitations: false,
+ hasGameInvitation: false,
connection: null,
connectionId: null
};
},
+ computed: {
+ hasUnreadNotification(): boolean {
+ return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadNotification;
+ },
+ hasUnreadMessagingMessage(): boolean {
+ return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadMessagingMessage;
+ }
+ },
mounted() {
this.$store.commit('setUiHeaderHeight', 48);
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection = (this as any).os.stream.getConnection();
this.connectionId = (this as any).os.stream.use();
- this.connection.on('read_all_notifications', this.onReadAllNotifications);
- this.connection.on('unread_notification', this.onUnreadNotification);
- this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages);
- this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage);
this.connection.on('othello_invited', this.onOthelloInvited);
this.connection.on('othello_no_invites', this.onOthelloNoInvites);
- // Fetch count of unread notifications
- (this as any).api('notifications/get_unread_count').then(res => {
- if (res.count > 0) {
- this.hasUnreadNotifications = true;
- }
- });
-
- // Fetch count of unread messaging messages
- (this as any).api('messaging/unread').then(res => {
- if (res.count > 0) {
- this.hasUnreadMessagingMessages = true;
- }
- });
-
- const ago = (new Date().getTime() - new Date((this as any).os.i.lastUsedAt).getTime()) / 1000;
+ const ago = (new Date().getTime() - new Date(this.$store.state.i.lastUsedAt).getTime()) / 1000;
const isHisasiburi = ago >= 3600;
- (this as any).os.i.lastUsedAt = new Date();
- (this as any).os.bakeMe();
+ this.$store.state.i.lastUsedAt = new Date();
+
if (isHisasiburi) {
(this.$refs.welcomeback as any).style.display = 'block';
(this.$refs.main as any).style.overflow = 'hidden';
@@ -109,34 +97,18 @@ export default Vue.extend({
}
},
beforeDestroy() {
- if ((this as any).os.isSignedIn) {
- this.connection.off('read_all_notifications', this.onReadAllNotifications);
- this.connection.off('unread_notification', this.onUnreadNotification);
- this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages);
- this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage);
+ if (this.$store.getters.isSignedIn) {
this.connection.off('othello_invited', this.onOthelloInvited);
this.connection.off('othello_no_invites', this.onOthelloNoInvites);
(this as any).os.stream.dispose(this.connectionId);
}
},
methods: {
- onReadAllNotifications() {
- this.hasUnreadNotifications = false;
- },
- onUnreadNotification() {
- this.hasUnreadNotifications = true;
- },
- onReadAllMessagingMessages() {
- this.hasUnreadMessagingMessages = false;
- },
- onUnreadMessagingMessage() {
- this.hasUnreadMessagingMessages = true;
- },
onOthelloInvited() {
- this.hasGameInvitations = true;
+ this.hasGameInvitation = true;
},
onOthelloNoInvites() {
- this.hasGameInvitations = false;
+ this.hasGameInvitation = false;
}
}
});
diff --git a/src/client/app/mobile/views/components/ui.nav.vue b/src/client/app/mobile/views/components/ui.nav.vue
index aa469bd1c8..11a8f7ab97 100644
--- a/src/client/app/mobile/views/components/ui.nav.vue
+++ b/src/client/app/mobile/views/components/ui.nav.vue
@@ -9,27 +9,27 @@
</transition>
<transition name="nav">
<div class="body" v-if="isOpen">
- <router-link class="me" v-if="os.isSignedIn" :to="`/@${os.i.username}`">
- <img class="avatar" :src="`${os.i.avatarUrl}?thumbnail&size=128`" alt="avatar"/>
- <p class="name">{{ os.i | userName }}</p>
+ <router-link class="me" v-if="$store.getters.isSignedIn" :to="`/@${$store.state.i.username}`">
+ <img class="avatar" :src="`${$store.state.i.avatarUrl}?thumbnail&size=128`" alt="avatar"/>
+ <p class="name">{{ $store.state.i | userName }}</p>
</router-link>
<div class="links">
<ul>
- <li><router-link to="/" :data-active="$route.name == 'index'">%fa:home%%i18n:@home%%fa:angle-right%</router-link></li>
- <li><router-link to="/i/notifications" :data-active="$route.name == 'notifications'">%fa:R bell%%i18n:@notifications%<template v-if="hasUnreadNotifications">%fa:circle%</template>%fa:angle-right%</router-link></li>
- <li><router-link to="/i/messaging" :data-active="$route.name == 'messaging'">%fa:R comments%%i18n:@messaging%<template v-if="hasUnreadMessagingMessages">%fa:circle%</template>%fa:angle-right%</router-link></li>
- <li><router-link to="/othello" :data-active="$route.name == 'othello'">%fa:gamepad%ゲーム<template v-if="hasGameInvitations">%fa:circle%</template>%fa:angle-right%</router-link></li>
+ <li><router-link to="/" :data-active="$route.name == 'index'">%fa:home%%i18n:@timeline%%fa:angle-right%</router-link></li>
+ <li><router-link to="/i/notifications" :data-active="$route.name == 'notifications'">%fa:R bell%%i18n:@notifications%<template v-if="hasUnreadNotification">%fa:circle%</template>%fa:angle-right%</router-link></li>
+ <li><router-link to="/i/messaging" :data-active="$route.name == 'messaging'">%fa:R comments%%i18n:@messaging%<template v-if="hasUnreadMessagingMessage">%fa:circle%</template>%fa:angle-right%</router-link></li>
+ <li><router-link to="/othello" :data-active="$route.name == 'othello'">%fa:gamepad%%i18n:@game%<template v-if="hasGameInvitation">%fa:circle%</template>%fa:angle-right%</router-link></li>
</ul>
<ul>
- <li><router-link to="/i/widgets" :data-active="$route.name == 'widgets'">%fa:quidditch%%i18n:@widgets%%fa:angle-right%</router-link></li>
+ <li><router-link to="/i/widgets" :data-active="$route.name == 'widgets'">%fa:R calendar-alt%%i18n:@widgets%%fa:angle-right%</router-link></li>
+ <li><router-link to="/i/favorites" :data-active="$route.name == 'favorites'">%fa:star%%i18n:@favorites%%fa:angle-right%</router-link></li>
+ <li><router-link to="/i/lists" :data-active="$route.name == 'user-lists'">%fa:list%%i18n:@user-lists%%fa:angle-right%</router-link></li>
<li><router-link to="/i/drive" :data-active="$route.name == 'drive'">%fa:cloud%%i18n:@drive%%fa:angle-right%</router-link></li>
</ul>
<ul>
<li><a @click="search">%fa:search%%i18n:@search%%fa:angle-right%</a></li>
- </ul>
- <ul>
<li><router-link to="/i/settings" :data-active="$route.name == 'settings'">%fa:cog%%i18n:@settings%%fa:angle-right%</router-link></li>
- <li @click="dark"><p><template v-if="$store.state.device.darkmode">%fa:moon%</template><template v-else>%fa:R moon%</template><span>ダークモード</span></p></li>
+ <li @click="dark"><p><template v-if="$store.state.device.darkmode">%fa:moon%</template><template v-else>%fa:R moon%</template><span>%i18n:@darkmode%</span></p></li>
</ul>
</div>
<a :href="aboutUrl"><p class="about">%i18n:@about%</p></a>
@@ -46,47 +46,31 @@ export default Vue.extend({
props: ['isOpen'],
data() {
return {
- hasUnreadNotifications: false,
- hasUnreadMessagingMessages: false,
- hasGameInvitations: false,
+ hasGameInvitation: false,
connection: null,
connectionId: null,
aboutUrl: `${docsUrl}/${lang}/about`
};
},
+ computed: {
+ hasUnreadNotification(): boolean {
+ return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadNotification;
+ },
+ hasUnreadMessagingMessage(): boolean {
+ return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadMessagingMessage;
+ }
+ },
mounted() {
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection = (this as any).os.stream.getConnection();
this.connectionId = (this as any).os.stream.use();
- this.connection.on('read_all_notifications', this.onReadAllNotifications);
- this.connection.on('unread_notification', this.onUnreadNotification);
- this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages);
- this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage);
this.connection.on('othello_invited', this.onOthelloInvited);
this.connection.on('othello_no_invites', this.onOthelloNoInvites);
-
- // Fetch count of unread notifications
- (this as any).api('notifications/get_unread_count').then(res => {
- if (res.count > 0) {
- this.hasUnreadNotifications = true;
- }
- });
-
- // Fetch count of unread messaging messages
- (this as any).api('messaging/unread').then(res => {
- if (res.count > 0) {
- this.hasUnreadMessagingMessages = true;
- }
- });
}
},
beforeDestroy() {
- if ((this as any).os.isSignedIn) {
- this.connection.off('read_all_notifications', this.onReadAllNotifications);
- this.connection.off('unread_notification', this.onUnreadNotification);
- this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages);
- this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage);
+ if (this.$store.getters.isSignedIn) {
this.connection.off('othello_invited', this.onOthelloInvited);
this.connection.off('othello_no_invites', this.onOthelloNoInvites);
(this as any).os.stream.dispose(this.connectionId);
@@ -98,23 +82,11 @@ export default Vue.extend({
if (query == null || query == '') return;
this.$router.push('/search?q=' + encodeURIComponent(query));
},
- onReadAllNotifications() {
- this.hasUnreadNotifications = false;
- },
- onUnreadNotification() {
- this.hasUnreadNotifications = true;
- },
- onReadAllMessagingMessages() {
- this.hasUnreadMessagingMessages = false;
- },
- onUnreadMessagingMessage() {
- this.hasUnreadMessagingMessages = true;
- },
onOthelloInvited() {
- this.hasGameInvitations = true;
+ this.hasGameInvitation = true;
},
onOthelloNoInvites() {
- this.hasGameInvitations = false;
+ this.hasGameInvitation = false;
},
dark() {
this.$store.commit('device/set', {
@@ -186,7 +158,10 @@ root(isDark)
&:first-child
margin-top 0
- li
+ &:last-child
+ margin-bottom 0
+
+ > li
display block
font-size 1em
line-height 1em
@@ -209,6 +184,8 @@ root(isDark)
> [data-fa]:first-child
margin-right 0.5em
+ width 20px
+ text-align center
> [data-fa].circle
margin-left 6px
@@ -226,7 +203,7 @@ root(isDark)
opacity 0.5
.about
- margin 0
+ margin 0 0 8px 0
padding 1em 0
text-align center
font-size 0.8em
diff --git a/src/client/app/mobile/views/components/ui.vue b/src/client/app/mobile/views/components/ui.vue
index 325ce9d40e..7e2d39f259 100644
--- a/src/client/app/mobile/views/components/ui.vue
+++ b/src/client/app/mobile/views/components/ui.vue
@@ -8,7 +8,7 @@
<div class="content">
<slot></slot>
</div>
- <mk-stream-indicator v-if="os.isSignedIn"/>
+ <mk-stream-indicator v-if="$store.getters.isSignedIn"/>
</div>
</template>
@@ -32,7 +32,7 @@ export default Vue.extend({
};
},
mounted() {
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection = (this as any).os.stream.getConnection();
this.connectionId = (this as any).os.stream.use();
@@ -40,7 +40,7 @@ export default Vue.extend({
}
},
beforeDestroy() {
- if ((this as any).os.isSignedIn) {
+ if (this.$store.getters.isSignedIn) {
this.connection.off('notification', this.onNotification);
(this as any).os.stream.dispose(this.connectionId);
}
diff --git a/src/client/app/mobile/views/components/user-list-timeline.vue b/src/client/app/mobile/views/components/user-list-timeline.vue
index 59d6abbbc1..2c1564b7ed 100644
--- a/src/client/app/mobile/views/components/user-list-timeline.vue
+++ b/src/client/app/mobile/views/components/user-list-timeline.vue
@@ -12,6 +12,7 @@ const fetchLimit = 10;
export default Vue.extend({
props: ['list'],
+
data() {
return {
fetching: true,
@@ -20,25 +21,36 @@ export default Vue.extend({
connection: null
};
},
+
+ computed: {
+ canFetchMore(): boolean {
+ return !this.moreFetching && !this.fetching && this.existMore;
+ }
+ },
+
watch: {
$route: 'init'
},
+
mounted() {
this.init();
},
+
beforeDestroy() {
this.connection.close();
},
+
methods: {
init() {
if (this.connection) this.connection.close();
- this.connection = new UserListStream((this as any).os, (this as any).os.i, this.list.id);
+ this.connection = new UserListStream((this as any).os, this.$store.state.i, this.list.id);
this.connection.on('note', this.onNote);
this.connection.on('userAdded', this.onUserAdded);
this.connection.on('userRemoved', this.onUserRemoved);
this.fetch();
},
+
fetch() {
this.fetching = true;
@@ -46,8 +58,8 @@ export default Vue.extend({
(this as any).api('notes/user-list-timeline', {
listId: this.list.id,
limit: fetchLimit + 1,
- includeMyRenotes: (this as any).clientSettings.showMyRenotes,
- includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
+ includeMyRenotes: this.$store.state.settings.showMyRenotes,
+ includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
}).then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
@@ -59,16 +71,21 @@ export default Vue.extend({
}, rej);
}));
},
+
more() {
+ if (!this.canFetchMore) return;
+
this.moreFetching = true;
- (this as any).api('notes/user-list-timeline', {
+ const promise = (this as any).api('notes/user-list-timeline', {
listId: this.list.id,
limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id,
- includeMyRenotes: (this as any).clientSettings.showMyRenotes,
- includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
- }).then(notes => {
+ includeMyRenotes: this.$store.state.settings.showMyRenotes,
+ includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
+ });
+
+ promise.then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
} else {
@@ -77,14 +94,19 @@ export default Vue.extend({
notes.forEach(n => (this.$refs.timeline as any).append(n));
this.moreFetching = false;
});
+
+ return promise;
},
+
onNote(note) {
// Prepend a note
(this.$refs.timeline as any).prepend(note);
},
+
onUserAdded() {
this.fetch();
},
+
onUserRemoved() {
this.fetch();
}
diff --git a/src/client/app/mobile/views/components/user-timeline.vue b/src/client/app/mobile/views/components/user-timeline.vue
index aca6f783b8..6be675c0a7 100644
--- a/src/client/app/mobile/views/components/user-timeline.vue
+++ b/src/client/app/mobile/views/components/user-timeline.vue
@@ -59,12 +59,15 @@ export default Vue.extend({
if (!this.canFetchMore) return;
this.moreFetching = true;
- (this as any).api('users/notes', {
+
+ const promise = (this as any).api('users/notes', {
userId: this.user.id,
withMedia: this.withMedia,
limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id
- }).then(notes => {
+ });
+
+ promise.then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
} else {
@@ -73,6 +76,8 @@ export default Vue.extend({
notes.forEach(n => (this.$refs.timeline as any).append(n));
this.moreFetching = false;
});
+
+ return promise;
}
}
});
diff --git a/src/client/app/mobile/views/components/users-list.vue b/src/client/app/mobile/views/components/users-list.vue
index 6175067459..a57b821293 100644
--- a/src/client/app/mobile/views/components/users-list.vue
+++ b/src/client/app/mobile/views/components/users-list.vue
@@ -2,7 +2,7 @@
<div class="mk-users-list">
<nav>
<span :data-active="mode == 'all'" @click="mode = 'all'">%i18n:@all%<span>{{ count }}</span></span>
- <span v-if="os.isSignedIn && youKnowCount" :data-active="mode == 'iknow'" @click="mode = 'iknow'">%i18n:@known%<span>{{ youKnowCount }}</span></span>
+ <span v-if="$store.getters.isSignedIn && youKnowCount" :data-active="mode == 'iknow'" @click="mode = 'iknow'">%i18n:@known%<span>{{ youKnowCount }}</span></span>
</nav>
<div class="users" v-if="!fetching && users.length != 0">
<mk-user-preview v-for="u in users" :user="u" :key="u.id"/>
diff --git a/src/client/app/mobile/views/pages/favorites.vue b/src/client/app/mobile/views/pages/favorites.vue
new file mode 100644
index 0000000000..c4edd9d970
--- /dev/null
+++ b/src/client/app/mobile/views/pages/favorites.vue
@@ -0,0 +1,94 @@
+<template>
+<mk-ui>
+ <span slot="header">%fa:star%%i18n:@title%</span>
+
+ <main>
+ <template v-for="favorite in favorites">
+ <mk-note-detail class="post" :note="favorite.note" :key="favorite.note.id"/>
+ </template>
+ <a v-if="existMore" @click="more">%i18n:@more%</a>
+ </main>
+</mk-ui>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import Progress from '../../../common/scripts/loading';
+
+export default Vue.extend({
+ data() {
+ return {
+ fetching: true,
+ favorites: [],
+ existMore: false,
+ moreFetching: false
+ };
+ },
+ created() {
+ this.fetch();
+ },
+ mounted() {
+ document.title = 'Misskey | %i18n:@notifications%';
+ },
+ methods: {
+ fetch() {
+ Progress.start();
+ this.fetching = true;
+
+ (this as any).api('i/favorites', {
+ limit: 11
+ }).then(favorites => {
+ if (favorites.length == 11) {
+ this.existMore = true;
+ favorites.pop();
+ }
+
+ this.favorites = favorites;
+ this.fetching = false;
+
+ Progress.done();
+ });
+ },
+ more() {
+ this.moreFetching = true;
+ (this as any).api('i/favorites', {
+ limit: 11,
+ maxId: this.favorites[this.favorites.length - 1].id
+ }).then(favorites => {
+ if (favorites.length == 11) {
+ this.existMore = true;
+ favorites.pop();
+ } else {
+ this.existMore = false;
+ }
+
+ this.favorites = this.favorites.concat(favorites);
+ this.moreFetching = false;
+ });
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+@import '~const.styl'
+
+main
+ width 100%
+ max-width 680px
+ margin 0 auto
+ padding 8px
+
+ > .post
+ margin-bottom 8px
+
+ @media (min-width 500px)
+ padding 16px
+
+ > .post
+ margin-bottom 16px
+
+ @media (min-width 600px)
+ padding 32px
+
+</style>
diff --git a/src/client/app/mobile/views/pages/home.timeline.vue b/src/client/app/mobile/views/pages/home.timeline.vue
index 4c1c344db1..364367b940 100644
--- a/src/client/app/mobile/views/pages/home.timeline.vue
+++ b/src/client/app/mobile/views/pages/home.timeline.vue
@@ -38,7 +38,7 @@ export default Vue.extend({
computed: {
alone(): boolean {
- return (this as any).os.i.followingCount == 0;
+ return this.$store.state.i.followingCount == 0;
},
stream(): any {
@@ -92,8 +92,8 @@ export default Vue.extend({
(this as any).api(this.endpoint, {
limit: fetchLimit + 1,
untilDate: this.date ? this.date.getTime() : undefined,
- includeMyRenotes: (this as any).clientSettings.showMyRenotes,
- includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
+ includeMyRenotes: this.$store.state.settings.showMyRenotes,
+ includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
}).then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
@@ -111,12 +111,14 @@ export default Vue.extend({
this.moreFetching = true;
- (this as any).api(this.endpoint, {
+ const promise = (this as any).api(this.endpoint, {
limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id,
- includeMyRenotes: (this as any).clientSettings.showMyRenotes,
- includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
- }).then(notes => {
+ includeMyRenotes: this.$store.state.settings.showMyRenotes,
+ includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
+ });
+
+ promise.then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
} else {
@@ -125,6 +127,8 @@ export default Vue.extend({
notes.forEach(n => (this.$refs.timeline as any).append(n));
this.moreFetching = false;
});
+
+ return promise;
},
onNote(note) {
diff --git a/src/client/app/mobile/views/pages/home.vue b/src/client/app/mobile/views/pages/home.vue
index 5701ff03d5..c0c2ee8ab5 100644
--- a/src/client/app/mobile/views/pages/home.vue
+++ b/src/client/app/mobile/views/pages/home.vue
@@ -5,7 +5,7 @@
<span v-if="src == 'home'">%fa:home%%i18n:@home%</span>
<span v-if="src == 'local'">%fa:R comments%%i18n:@local%</span>
<span v-if="src == 'global'">%fa:globe%%i18n:@global%</span>
- <span v-if="src.startsWith('list')">%fa:list%{{ list.title }}</span>
+ <span v-if="src == 'list'">%fa:list%{{ list.title }}</span>
</span>
<span style="margin-left:8px">
<template v-if="!showNav">%fa:angle-down%</template>
@@ -26,17 +26,17 @@
<span :data-active="src == 'local'" @click="src = 'local'">%fa:R comments% %i18n:@local%</span>
<span :data-active="src == 'global'" @click="src = 'global'">%fa:globe% %i18n:@global%</span>
<template v-if="lists">
- <span v-for="l in lists" :data-active="src == 'list:' + l.id" @click="src = 'list:' + l.id; list = l" :key="l.id">%fa:list% {{ l.title }}</span>
+ <span v-for="l in lists" :data-active="src == 'list' && list == l" @click="src = 'list'; list = l" :key="l.id">%fa:list% {{ l.title }}</span>
</template>
</div>
</div>
</div>
<div class="tl">
- <x-tl v-if="src == 'home'" ref="tl" key="home" src="home" @loaded="onLoaded"/>
+ <x-tl v-if="src == 'home'" ref="tl" key="home" src="home"/>
<x-tl v-if="src == 'local'" ref="tl" key="local" src="local"/>
<x-tl v-if="src == 'global'" ref="tl" key="global" src="global"/>
- <mk-user-list-timeline v-if="src.startsWith('list:')" ref="tl" :key="list.id" :list="list"/>
+ <mk-user-list-timeline v-if="src == 'list'" ref="tl" :key="list.id" :list="list"/>
</div>
</main>
</mk-ui>
@@ -64,6 +64,12 @@ export default Vue.extend({
watch: {
src() {
this.showNav = false;
+ this.saveSrc();
+ },
+
+ list() {
+ this.showNav = false;
+ this.saveSrc();
},
showNav(v) {
@@ -76,7 +82,12 @@ export default Vue.extend({
},
created() {
- if ((this as any).os.i.followingCount == 0) {
+ if (this.$store.state.device.tl) {
+ this.src = this.$store.state.device.tl.src;
+ if (this.src == 'list') {
+ this.list = this.$store.state.device.tl.arg;
+ }
+ } else if (this.$store.state.i.followingCount == 0) {
this.src = 'local';
}
},
@@ -85,6 +96,10 @@ export default Vue.extend({
document.title = 'Misskey';
Progress.start();
+
+ (this.$refs.tl as any).$once('loaded', () => {
+ Progress.done();
+ });
},
methods: {
@@ -92,8 +107,11 @@ export default Vue.extend({
(this as any).apis.post();
},
- onLoaded() {
- Progress.done();
+ saveSrc() {
+ this.$store.commit('device/setTl', {
+ src: this.src,
+ arg: this.list
+ });
},
warp() {
diff --git a/src/client/app/mobile/views/pages/index.vue b/src/client/app/mobile/views/pages/index.vue
index 0ea47d913b..5d11fc5423 100644
--- a/src/client/app/mobile/views/pages/index.vue
+++ b/src/client/app/mobile/views/pages/index.vue
@@ -1,5 +1,5 @@
<template>
-<component :is="os.isSignedIn ? 'home' : 'welcome'"></component>
+<component :is="$store.getters.isSignedIn ? 'home' : 'welcome'"></component>
</template>
<script lang="ts">
diff --git a/src/client/app/mobile/views/pages/notifications.vue b/src/client/app/mobile/views/pages/notifications.vue
index 2e98201caa..64cfa60da0 100644
--- a/src/client/app/mobile/views/pages/notifications.vue
+++ b/src/client/app/mobile/views/pages/notifications.vue
@@ -24,7 +24,7 @@ export default Vue.extend({
const ok = window.confirm('%i18n:@read-all%');
if (!ok) return;
- (this as any).api('notifications/markAsRead_all');
+ (this as any).api('notifications/mark_as_read_all');
},
onFetched() {
Progress.done();
diff --git a/src/client/app/mobile/views/pages/settings.vue b/src/client/app/mobile/views/pages/settings.vue
index 3bb25f88f8..8da7a76633 100644
--- a/src/client/app/mobile/views/pages/settings.vue
+++ b/src/client/app/mobile/views/pages/settings.vue
@@ -17,22 +17,22 @@
</div>
<div>
- <md-switch v-model="clientSettings.circleIcons" @change="onChangeCircleIcons">%i18n:@circle-icons%</md-switch>
+ <md-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons">%i18n:@circle-icons%</md-switch>
</div>
<div>
<div class="md-body-2">%i18n:@timeline%</div>
<div>
- <md-switch v-model="clientSettings.showReplyTarget" @change="onChangeShowReplyTarget">%i18n:@show-reply-target%</md-switch>
+ <md-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget">%i18n:@show-reply-target%</md-switch>
</div>
<div>
- <md-switch v-model="clientSettings.showMyRenotes" @change="onChangeShowMyRenotes">%i18n:@show-my-renotes%</md-switch>
+ <md-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes">%i18n:@show-my-renotes%</md-switch>
</div>
<div>
- <md-switch v-model="clientSettings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</md-switch>
+ <md-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</md-switch>
</div>
</div>
@@ -52,11 +52,11 @@
<md-card-content>
<div>
- <md-switch v-model="clientSettings.fetchOnScroll" @change="onChangeFetchOnScroll">%i18n:@fetch-on-scroll%</md-switch>
+ <md-switch v-model="$store.state.settings.fetchOnScroll" @change="onChangeFetchOnScroll">%i18n:@fetch-on-scroll%</md-switch>
</div>
<div>
- <md-switch v-model="clientSettings.disableViaMobile" @change="onChangeDisableViaMobile">%i18n:@disable-via-mobile%</md-switch>
+ <md-switch v-model="$store.state.settings.disableViaMobile" @change="onChangeDisableViaMobile">%i18n:@disable-via-mobile%</md-switch>
</div>
<div>
@@ -64,7 +64,7 @@
</div>
<div>
- <md-switch v-model="clientSettings.loadRemoteMedia" @change="onChangeLoadRemoteMedia">%i18n:@load-remote-media%</md-switch>
+ <md-switch v-model="$store.state.settings.loadRemoteMedia" @change="onChangeLoadRemoteMedia">%i18n:@load-remote-media%</md-switch>
</div>
<div>
@@ -100,11 +100,11 @@
</md-card-header>
<md-card-content>
- <p class="account" v-if="os.i.twitter"><a :href="`https://twitter.com/${os.i.twitter.screenName}`" target="_blank">@{{ os.i.twitter.screenName }}</a></p>
+ <p class="account" v-if="$store.state.i.twitter"><a :href="`https://twitter.com/${$store.state.i.twitter.screenName}`" target="_blank">@{{ $store.state.i.twitter.screenName }}</a></p>
<p>
- <a :href="`${apiUrl}/connect/twitter`" target="_blank">{{ os.i.twitter ? '%i18n:@twitter-reconnect%' : '%i18n:@twitter-connect%' }}</a>
- <span v-if="os.i.twitter"> or </span>
- <a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="os.i.twitter">%i18n:@twitter-disconnect%</a>
+ <a :href="`${apiUrl}/connect/twitter`" target="_blank">{{ $store.state.i.twitter ? '%i18n:@twitter-reconnect%' : '%i18n:@twitter-connect%' }}</a>
+ <span v-if="$store.state.i.twitter"> or </span>
+ <a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="$store.state.i.twitter">%i18n:@twitter-disconnect%</a>
</p>
</md-card-content>
</md-card>
@@ -156,7 +156,7 @@ export default Vue.extend({
computed: {
name(): string {
- return Vue.filter('userName')((this as any).os.i);
+ return Vue.filter('userName')(this.$store.state.i);
},
darkmode: {
diff --git a/src/client/app/mobile/views/pages/settings/settings.profile.vue b/src/client/app/mobile/views/pages/settings/settings.profile.vue
index c16c44e133..f3444eb1f0 100644
--- a/src/client/app/mobile/views/pages/settings/settings.profile.vue
+++ b/src/client/app/mobile/views/pages/settings/settings.profile.vue
@@ -82,15 +82,15 @@ export default Vue.extend({
},
created() {
- this.name = (this as any).os.i.name || '';
- this.username = (this as any).os.i.username;
- this.location = (this as any).os.i.profile.location;
- this.description = (this as any).os.i.description;
- this.birthday = (this as any).os.i.profile.birthday;
- this.avatarId = (this as any).os.i.avatarId;
- this.bannerId = (this as any).os.i.bannerId;
- this.isBot = (this as any).os.i.isBot;
- this.isCat = (this as any).os.i.isCat;
+ this.name = this.$store.state.i.name || '';
+ this.username = this.$store.state.i.username;
+ this.location = this.$store.state.i.profile.location;
+ this.description = this.$store.state.i.description;
+ this.birthday = this.$store.state.i.profile.birthday;
+ this.avatarId = this.$store.state.i.avatarId;
+ this.bannerId = this.$store.state.i.bannerId;
+ this.isBot = this.$store.state.i.isBot;
+ this.isCat = this.$store.state.i.isCat;
},
methods: {
@@ -99,7 +99,7 @@ export default Vue.extend({
const data = new FormData();
data.append('file', file);
- data.append('i', (this as any).os.i.token);
+ data.append('i', this.$store.state.i.token);
fetch(apiUrl + '/drive/files/create', {
method: 'POST',
@@ -121,7 +121,7 @@ export default Vue.extend({
const data = new FormData();
data.append('file', file);
- data.append('i', (this as any).os.i.token);
+ data.append('i', this.$store.state.i.token);
fetch(apiUrl + '/drive/files/create', {
method: 'POST',
@@ -152,10 +152,10 @@ export default Vue.extend({
isCat: this.isCat
}).then(i => {
this.saving = false;
- (this as any).os.i.avatarId = i.avatarId;
- (this as any).os.i.avatarUrl = i.avatarUrl;
- (this as any).os.i.bannerId = i.bannerId;
- (this as any).os.i.bannerUrl = i.bannerUrl;
+ this.$store.state.i.avatarId = i.avatarId;
+ this.$store.state.i.avatarUrl = i.avatarUrl;
+ this.$store.state.i.bannerId = i.bannerId;
+ this.$store.state.i.bannerUrl = i.bannerUrl;
alert('%i18n:@saved%');
});
diff --git a/src/client/app/mobile/views/pages/user-list.vue b/src/client/app/mobile/views/pages/user-list.vue
new file mode 100644
index 0000000000..1c6a829cd5
--- /dev/null
+++ b/src/client/app/mobile/views/pages/user-list.vue
@@ -0,0 +1,70 @@
+<template>
+<mk-ui>
+ <span slot="header" v-if="!fetching">%fa:list%{{ list.title }}</span>
+
+ <main v-if="!fetching">
+ <ul>
+ <li v-for="user in users" :key="user.id"><router-link :to="user | userPage">{{ user | userName }}</router-link></li>
+ </ul>
+ </main>
+</mk-ui>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import Progress from '../../../common/scripts/loading';
+
+export default Vue.extend({
+ data() {
+ return {
+ fetching: true,
+ list: null,
+ users: null
+ };
+ },
+ watch: {
+ $route: 'fetch'
+ },
+ created() {
+ this.fetch();
+ },
+ methods: {
+ fetch() {
+ Progress.start();
+ this.fetching = true;
+
+ (this as any).api('users/lists/show', {
+ listId: this.$route.params.list
+ }).then(list => {
+ this.list = list;
+ this.fetching = false;
+
+ Progress.done();
+
+ (this as any).api('users/show', {
+ userIds: this.list.userIds
+ }).then(users => {
+ this.users = users;
+ });
+ });
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+@import '~const.styl'
+
+main
+ width 100%
+ max-width 680px
+ margin 0 auto
+ padding 8px
+
+ @media (min-width 500px)
+ padding 16px
+
+ @media (min-width 600px)
+ padding 32px
+
+</style>
diff --git a/src/client/app/mobile/views/pages/user-lists.vue b/src/client/app/mobile/views/pages/user-lists.vue
new file mode 100644
index 0000000000..288295677e
--- /dev/null
+++ b/src/client/app/mobile/views/pages/user-lists.vue
@@ -0,0 +1,68 @@
+<template>
+<mk-ui>
+ <span slot="header">%fa:list%%i18n:@title%</span>
+ <template slot="func"><button @click="fn">%fa:plus%</button></template>
+
+ <main>
+ <ul>
+ <li v-for="list in lists" :key="list.id"><router-link :to="`/i/lists/${list.id}`">{{ list.title }}</router-link></li>
+ </ul>
+ </main>
+</mk-ui>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import Progress from '../../../common/scripts/loading';
+
+export default Vue.extend({
+ data() {
+ return {
+ fetching: true,
+ lists: []
+ };
+ },
+ mounted() {
+ document.title = 'Misskey | %i18n:@title%';
+
+ Progress.start();
+
+ (this as any).api('users/lists/list').then(lists => {
+ this.fetching = false;
+ this.lists = lists;
+
+ Progress.done();
+ });
+ },
+ methods: {
+ fn() {
+ (this as any).apis.input({
+ title: '%i18n:@enter-list-name%',
+ }).then(async title => {
+ const list = await (this as any).api('users/lists/create', {
+ title
+ });
+
+ this.$router.push('/i/lists/' + list.id);
+ });
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+@import '~const.styl'
+
+main
+ width 100%
+ max-width 680px
+ margin 0 auto
+ padding 8px
+
+ @media (min-width 500px)
+ padding 16px
+
+ @media (min-width 600px)
+ padding 32px
+
+</style>
diff --git a/src/client/app/mobile/views/pages/user.vue b/src/client/app/mobile/views/pages/user.vue
index 84fd7eda02..b3b820650c 100644
--- a/src/client/app/mobile/views/pages/user.vue
+++ b/src/client/app/mobile/views/pages/user.vue
@@ -11,7 +11,7 @@
<a class="avatar">
<img :src="user.avatarUrl" alt="avatar"/>
</a>
- <mk-follow-button v-if="os.isSignedIn && os.i.id != user.id" :user="user"/>
+ <mk-follow-button v-if="$store.getters.isSignedIn && $store.state.i.id != user.id" :user="user"/>
</div>
<div class="title">
<h1>{{ user | userName }}</h1>
diff --git a/src/client/app/mobile/views/pages/user/home.vue b/src/client/app/mobile/views/pages/user/home.vue
index d02daf5027..8b57276b17 100644
--- a/src/client/app/mobile/views/pages/user/home.vue
+++ b/src/client/app/mobile/views/pages/user/home.vue
@@ -25,7 +25,7 @@
<x-friends :user="user"/>
</div>
</section>
- <section class="followers-you-know" v-if="os.isSignedIn && os.i.id !== user.id">
+ <section class="followers-you-know" v-if="$store.getters.isSignedIn && $store.state.i.id !== user.id">
<h2>%fa:users%%i18n:@followers-you-know%</h2>
<div>
<x-followers-you-know :user="user"/>
diff --git a/src/client/app/mobile/views/pages/widgets.vue b/src/client/app/mobile/views/pages/widgets.vue
index 03abcabe8f..a0893770e8 100644
--- a/src/client/app/mobile/views/pages/widgets.vue
+++ b/src/client/app/mobile/views/pages/widgets.vue
@@ -8,17 +8,19 @@
<template v-if="customizing">
<header>
<select v-model="widgetAdderSelected">
- <option value="profile">プロフィール</option>
- <option value="calendar">カレンダー</option>
- <option value="activity">アクティビティ</option>
- <option value="rss">RSSリーダー</option>
- <option value="photo-stream">フォトストリーム</option>
- <option value="slideshow">スライドショー</option>
- <option value="version">バージョン</option>
- <option value="server">サーバー情報</option>
- <option value="donation">寄付のお願い</option>
- <option value="nav">ナビゲーション</option>
- <option value="tips">ヒント</option>
+ <option value="profile">%i18n:common.widgets.profile%</option>
+ <option value="analog-clock">%i18n:common.widgets.analog-clock%</option>
+ <option value="calendar">%i18n:common.widgets.calendar%</option>
+ <option value="activity">%i18n:common.widgets.activity%</option>
+ <option value="rss">%i18n:common.widgets.rss%</option>
+ <option value="photo-stream">%i18n:common.widgets.photo-stream%</option>
+ <option value="slideshow">%i18n:common.widgets.slideshow%</option>
+ <option value="version">%i18n:common.widgets.version%</option>
+ <option value="server">%i18n:common.widgets.server%</option>
+ <option value="memo">%i18n:common.widgets.memo%</option>
+ <option value="donation">%i18n:common.widgets.donation%</option>
+ <option value="nav">%i18n:common.widgets.nav%</option>
+ <option value="tips">%i18n:common.widgets.tips%</option>
</select>
<button @click="addWidget">追加</button>
<p><a @click="hint">カスタマイズのヒント</a></p>
diff --git a/src/client/app/mobile/views/widgets/activity.vue b/src/client/app/mobile/views/widgets/activity.vue
index 7763be41f5..85f925ceda 100644
--- a/src/client/app/mobile/views/widgets/activity.vue
+++ b/src/client/app/mobile/views/widgets/activity.vue
@@ -3,7 +3,7 @@
<mk-widget-container :show-header="!props.compact">
<template slot="header">%fa:chart-bar%アクティビティ</template>
<div :class="$style.body">
- <mk-activity :user="os.i"/>
+ <mk-activity :user="$store.state.i"/>
</div>
</mk-widget-container>
</div>
diff --git a/src/client/app/mobile/views/widgets/profile.vue b/src/client/app/mobile/views/widgets/profile.vue
index 59c1ec7c0e..beae1ffa36 100644
--- a/src/client/app/mobile/views/widgets/profile.vue
+++ b/src/client/app/mobile/views/widgets/profile.vue
@@ -2,13 +2,13 @@
<div class="mkw-profile">
<mk-widget-container>
<div :class="$style.banner"
- :style="os.i.bannerUrl ? `background-image: url(${os.i.bannerUrl}?thumbnail&size=256)` : ''"
+ :style="$store.state.i.bannerUrl ? `background-image: url(${$store.state.i.bannerUrl}?thumbnail&size=256)` : ''"
></div>
<img :class="$style.avatar"
- :src="`${os.i.avatarUrl}?thumbnail&size=96`"
+ :src="`${$store.state.i.avatarUrl}?thumbnail&size=96`"
alt="avatar"
/>
- <router-link :class="$style.name" :to="os.i | userPage">{{ os.i | userName }}</router-link>
+ <router-link :class="$style.name" :to="$store.state.i | userPage">{{ $store.state.i | userName }}</router-link>
</mk-widget-container>
</div>
</template>
@@ -56,7 +56,7 @@ export default define({
left 92px
margin 0
line-height 100px
- color #fff
+ color #fff !important // !important is for md
font-weight bold
text-shadow 0 0 8px rgba(#000, 0.5)
diff --git a/src/client/app/store.ts b/src/client/app/store.ts
index e300d31d8d..905ec0501c 100644
--- a/src/client/app/store.ts
+++ b/src/client/app/store.ts
@@ -2,6 +2,7 @@ import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';
import MiOS from './mios';
+import { hostname } from './config';
const defaultSettings = {
home: [],
@@ -15,7 +16,8 @@ const defaultSettings = {
showMyRenotes: true,
showRenotedMyNotes: true,
loadRemoteMedia: true,
- disableViaMobile: false
+ disableViaMobile: false,
+ memo: null
};
const defaultDeviceSettings = {
@@ -33,23 +35,29 @@ const defaultDeviceSettings = {
};
export default (os: MiOS) => new Vuex.Store({
- plugins: [store => {
- store.subscribe((mutation, state) => {
- if (mutation.type.startsWith('settings/')) {
- localStorage.setItem('settings', JSON.stringify(state.settings));
- }
- });
- }, createPersistedState({
- paths: ['device'],
- filter: mut => mut.type.startsWith('device/')
+ plugins: [createPersistedState({
+ paths: ['i', 'device', 'settings']
})],
state: {
+ i: null,
indicate: false,
uiHeaderHeight: 0
},
+ getters: {
+ isSignedIn: state => state.i != null
+ },
+
mutations: {
+ updateI(state, x) {
+ state.i = x;
+ },
+
+ updateIKeyValue(state, x) {
+ state.i[x.key] = x.value;
+ },
+
indicate(state, x) {
state.indicate = x;
},
@@ -59,6 +67,28 @@ export default (os: MiOS) => new Vuex.Store({
}
},
+ actions: {
+ login(ctx, i) {
+ ctx.commit('updateI', i);
+ ctx.dispatch('settings/merge', i.clientSettings);
+ },
+
+ logout(ctx) {
+ ctx.commit('updateI', null);
+ document.cookie = `i=; domain=${hostname}; expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
+ },
+
+ mergeMe(ctx, me) {
+ Object.entries(me).forEach(([key, value]) => {
+ ctx.commit('updateIKeyValue', { key, value });
+ });
+
+ if (me.clientSettings) {
+ ctx.dispatch('settings/merge', me.clientSettings);
+ }
+ },
+ },
+
modules: {
device: {
namespaced: true,
@@ -68,6 +98,13 @@ export default (os: MiOS) => new Vuex.Store({
mutations: {
set(state, x: { key: string; value: any }) {
state[x.key] = x.value;
+ },
+
+ setTl(state, x) {
+ state.tl = {
+ src: x.src,
+ arg: x.arg
+ };
}
}
},
@@ -127,7 +164,7 @@ export default (os: MiOS) => new Vuex.Store({
set(ctx, x) {
ctx.commit('set', x);
- if (os.isSignedIn) {
+ if (ctx.rootGetters.isSignedIn) {
os.api('i/update_client_setting', {
name: x.key,
value: x.value
diff --git a/src/client/assets/title.dark.svg b/src/client/assets/title.dark.svg
new file mode 100644
index 0000000000..10139024ad
--- /dev/null
+++ b/src/client/assets/title.dark.svg
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="614.71039"
+ height="205.08009"
+ viewBox="0 0 162.64213 54.260776"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.1 r15371"
+ sodipodi:docname="misskey.svg"
+ inkscape:export-filename="C:\Users\Takumiya_Cho\Desktop\misskey.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96">
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="simplify"
+ id="path-effect5115"
+ is_visible="true"
+ steps="1"
+ threshold="0.000408163"
+ smooth_angles="360"
+ helper_size="0"
+ simplify_individual_paths="false"
+ simplify_just_coalesce="false"
+ simplifyindividualpaths="false"
+ simplifyJustCoalesce="false" />
+ <inkscape:path-effect
+ effect="simplify"
+ id="path-effect5104"
+ is_visible="true"
+ steps="1"
+ threshold="0.000408163"
+ smooth_angles="360"
+ helper_size="0"
+ simplify_individual_paths="false"
+ simplify_just_coalesce="false"
+ simplifyindividualpaths="false"
+ simplifyJustCoalesce="false" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.9899495"
+ inkscape:cx="370.82839"
+ inkscape:cy="79.043895"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="false"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:snap-center="true"
+ inkscape:snap-page="true"
+ inkscape:window-width="1920"
+ inkscape:window-height="1017"
+ inkscape:window-x="-8"
+ inkscape:window-y="1072"
+ inkscape:window-maximized="1"
+ inkscape:object-paths="true"
+ inkscape:bbox-paths="true"
+ fit-margin-top="50"
+ fit-margin-left="50"
+ fit-margin-bottom="20"
+ fit-margin-right="50" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="レイヤー 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-11.097531,-173.29664)">
+ <g
+ transform="matrix(0.28612302,0,0,0.28612302,17.176981,141.74334)"
+ id="text4489-6"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:141.03404236px;line-height:476.69509888px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#fff;fill-opacity:1;stroke:none;stroke-width:0.92471898px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ aria-label="Mi">
+ <path
+ sodipodi:nodetypes="zccssscssccscczzzccsccsscscsccz"
+ inkscape:connector-curvature="0"
+ id="path5210"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';fill:#fff;fill-opacity:1;stroke-width:0.92471898px"
+ d="m 75.196381,231.17126 c -5.855419,0.0202 -10.885068,-3.50766 -13.2572,-7.61584 -1.266603,-1.79454 -3.772419,-2.43291 -3.807919,0 v 11.2332 c 0,4.51309 -1.645397,8.41504 -4.936191,11.70583 -3.196772,3.19677 -7.098714,4.79516 -11.705826,4.79516 -4.513089,0 -8.415031,-1.59839 -11.705825,-4.79516 -3.196772,-3.29079 -4.795158,-7.19274 -4.795158,-11.70583 v -61.7729 c 0,-3.47884 0.987238,-6.6286 2.961715,-9.44928 2.068499,-2.91471 4.701135,-4.9362 7.897906,-6.06447 1.786431,-0.65816 3.666885,-0.98724 5.641362,-0.98724 5.077225,0 9.308247,1.97448 12.693064,5.92343 1.786431,1.97448 2.820681,3.00873 3.102749,3.10275 0,0 13.408119,16.21319 13.78421,16.49526 0.376091,0.28206 1.480789,2.43848 4.127113,2.43848 2.646324,0 3.89218,-2.15642 4.26827,-2.43848 0.376091,-0.28207 13.784088,-16.49526 13.784088,-16.49526 0.09402,0.094 1.081261,-0.94022 2.961715,-3.10275 3.478837,-3.94895 7.756866,-5.92343 12.834096,-5.92343 1.88045,0 3.76091,0.32908 5.64136,0.98724 3.19677,1.12827 5.7824,3.14976 7.75688,6.06447 2.06849,2.82068 3.10274,5.97044 3.10274,9.44928 v 61.7729 c 0,4.51309 -1.6454,8.41504 -4.93619,11.70583 -3.19677,3.19677 -7.09871,4.79516 -11.70582,4.79516 -4.51309,0 -8.41504,-1.59839 -11.705828,-4.79516 -3.196772,-3.29079 -4.795158,-7.19274 -4.795158,-11.70583 v -11.2332 c -0.277898,-3.06563 -2.987588,-1.13379 -3.948953,0 -2.538613,4.70114 -7.401781,7.59567 -13.2572,7.61584 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path5212"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';fill:#fff;fill-opacity:1;stroke-width:0.92471898px"
+ d="m 145.83461,185.00361 q -5.92343,0 -10.15445,-4.08999 -4.08999,-4.23102 -4.08999,-10.15445 0,-5.92343 4.08999,-10.01342 4.23102,-4.23102 10.15445,-4.23102 5.92343,0 10.15445,4.23102 4.23102,4.08999 4.23102,10.01342 0,5.92343 -4.23102,10.15445 -4.23102,4.08999 -10.15445,4.08999 z m 0.14103,2.82068 q 5.92343,0 10.01342,4.23102 4.23102,4.23102 4.23102,10.15445 v 34.83541 q 0,5.92343 -4.23102,10.15445 -4.08999,4.08999 -10.01342,4.08999 -5.92343,0 -10.15445,-4.08999 -4.23102,-4.23102 -4.23102,-10.15445 v -34.83541 q 0,-5.92343 4.23102,-10.15445 4.23102,-4.23102 10.15445,-4.23102 z" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ id="path5199"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:136.34428406px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#fff;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 72.022691,200.53715 q 0.968125,0.24203 2.420312,0.5244 2.420313,0.40339 3.791824,1.29083 2.581666,1.69422 2.581666,5.08266 0,2.74302 -1.815234,4.47758 -2.097604,2.01693 -5.849089,2.01693 -2.743021,0 -6.131458,-0.76644 -1.089141,-0.24203 -1.774896,-1.08914 -0.645417,-0.84711 -0.645417,-1.89591 0,-1.29083 0.887448,-2.17828 0.927786,-0.92779 2.178281,-0.92779 0.363047,0 0.685756,0.0807 1.169817,0.24203 4.477578,0.60508 0.443724,0 0.968125,-0.0403 0.201693,0 0.201693,-0.24203 0.04034,-0.20169 -0.242032,-0.28237 -1.37151,-0.24203 -2.541328,-0.5244 -1.331172,-0.28237 -1.895911,-0.48406 -1.12948,-0.32271 -1.895912,-0.84711 -2.581667,-1.69422 -2.622005,-5.08266 0,-2.70268 1.855573,-4.47758 2.258958,-2.17828 6.413828,-1.97659 2.783359,0.12102 5.566719,0.7261 1.048802,0.24203 1.734557,1.08914 0.685756,0.84711 0.685756,1.93625 0,1.25049 -0.927787,2.17828 -0.887448,0.88745 -2.178281,0.88745 -0.322709,0 -0.645417,-0.0807 -1.169818,-0.24203 -4.517917,-0.56474 -0.403385,-0.0403 -0.766432,0 -0.322708,0.0403 -0.322708,0.24203 0.04034,0.24203 0.322708,0.32271 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path5201"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:136.34428406px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#fff;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 89.577027,200.53715 q 0.968125,0.24203 2.420312,0.5244 2.420313,0.40339 3.791823,1.29083 2.581667,1.69422 2.581667,5.08266 0,2.74302 -1.815234,4.47758 -2.097604,2.01693 -5.849089,2.01693 -2.743021,0 -6.131458,-0.76644 -1.089141,-0.24203 -1.774896,-1.08914 -0.645417,-0.84711 -0.645417,-1.89591 0,-1.29083 0.887448,-2.17828 0.927786,-0.92779 2.178281,-0.92779 0.363047,0 0.685755,0.0807 1.169818,0.24203 4.477579,0.60508 0.443724,0 0.968125,-0.0403 0.201692,0 0.201692,-0.24203 0.04034,-0.20169 -0.242031,-0.28237 -1.37151,-0.24203 -2.541328,-0.5244 -1.331172,-0.28237 -1.895912,-0.48406 -1.129479,-0.32271 -1.895911,-0.84711 -2.581667,-1.69422 -2.622005,-5.08266 0,-2.70268 1.855573,-4.47758 2.258958,-2.17828 6.413828,-1.97659 2.783359,0.12102 5.566719,0.7261 1.048802,0.24203 1.734557,1.08914 0.685755,0.84711 0.685755,1.93625 0,1.25049 -0.927786,2.17828 -0.887448,0.88745 -2.178281,0.88745 -0.322709,0 -0.645417,-0.0807 -1.169818,-0.24203 -4.517917,-0.56474 -0.403385,-0.0403 -0.766432,0 -0.322708,0.0403 -0.322708,0.24203 0.04034,0.24203 0.322708,0.32271 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path5203"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:136.34428406px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#fff;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 115.65209,203.87137 q 0.12101,0.0807 2.86404,2.78336 1.25049,1.21016 1.25049,2.94471 0,1.61354 -1.16982,2.86404 -1.16982,1.21016 -2.90437,1.21016 -1.65388,0 -2.86404,-1.16982 l -4.03385,-3.91284 q -0.16136,-0.12102 -0.32271,-0.12102 -0.32271,0 -0.32271,1.21016 0,1.69422 -1.21016,2.90438 -1.21015,1.16981 -2.90437,1.16981 -1.69422,0 -2.90438,-1.16981 -1.169807,-1.21016 -1.169807,-2.90438 v -18.79776 q 0,-1.69422 1.169807,-2.86404 1.21016,-1.21015 2.90438,-1.21015 1.69422,0 2.90437,1.21015 1.21016,1.16982 1.21016,2.86404 v 6.29281 q 0,0.40339 0.28237,0.5244 0.24203,0.12102 0.5244,-0.0807 0.16135,-0.0807 4.84063,-3.18675 1.0488,-0.64542 2.25895,-0.64542 2.21862,0 3.42878,1.81524 0.64542,1.0488 0.64542,2.25896 0,2.21862 -1.81524,3.42877 l -2.54133,1.61354 v 0.0403 l -0.0807,0.0403 q -0.56474,0.36305 -0.0403,0.88745 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path5205"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:136.34428406px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#fff;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 131.25181,213.92955 q -4.19521,0 -7.18026,-2.94472 -2.94472,-2.98505 -2.94472,-7.18026 0,-4.15487 2.94472,-7.09958 2.98505,-2.98505 7.18026,-2.98505 4.15487,0 6.97857,2.78335 0.92778,0.92779 0.92778,2.25896 0,1.33118 -0.92778,2.25896 l -4.67928,4.63893 q -1.00846,1.00847 -2.01692,1.00847 -1.45219,0 -2.25896,-0.80677 -0.80677,-0.80677 -0.80677,-2.13795 0,-1.29083 0.92778,-2.21862 l 0.80678,-0.84711 q 0.16135,-0.12101 0.0807,-0.24203 -0.12101,-0.0807 -0.32271,-0.0403 -0.80677,0.20169 -1.37151,0.80677 -1.12948,1.08914 -1.12948,2.622 0,1.5732 1.08915,2.70268 1.12947,1.08914 2.70268,1.08914 1.53286,0 2.622,-1.12947 0.92779,-0.92779 2.25896,-0.92779 1.33117,0 2.25896,0.92779 0.92779,0.92778 0.92779,2.25895 0,1.33118 -0.92779,2.25896 -2.98505,2.94472 -7.13992,2.94472 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path5207"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:136.34428406px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#fff;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 160.51049,198.1433 v 5.60705 q 0,0.56474 -0.0807,1.21016 v 7.38195 q 0,4.51792 -2.74302,7.2206 -2.70268,2.70269 -7.30128,2.70269 -2.66234,0 -4.80028,-1.00847 -2.13795,-0.96812 -2.13795,-3.3481 0,-0.80677 0.36305,-1.53286 0.96812,-2.17828 3.3481,-2.17828 0.56474,0 1.5732,0.32271 1.00847,0.3227 1.65388,0.3227 1.69422,0 2.21862,-0.72609 0.20169,-0.28237 0.0807,-0.44372 -0.16136,-0.24204 -0.56474,-0.16136 -0.68576,0.12102 -1.49253,0.12102 -4.07419,0 -6.97856,-2.90438 -2.90438,-2.90437 -2.90438,-6.97857 v -5.60705 q 0,-1.69422 1.16982,-2.86404 1.21015,-1.21016 2.90437,-1.21016 1.69422,0 2.90438,1.21016 1.21015,1.16982 1.21015,2.86404 v 5.60705 q 0,0.68576 0.48407,1.21016 0.5244,0.48406 1.21015,0.48406 0.7261,0 1.21016,-0.48406 0.48406,-0.5244 0.48406,-1.21016 v -5.60705 q 0,-1.69422 1.21016,-2.86404 1.21015,-1.21016 2.90437,-1.21016 1.69422,0 2.86404,1.21016 1.21016,1.16982 1.21016,2.86404 z" />
+ </g>
+</svg>
diff --git a/src/client/assets/title.light.svg b/src/client/assets/title.light.svg
new file mode 100644
index 0000000000..95ad11c399
--- /dev/null
+++ b/src/client/assets/title.light.svg
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="614.71039"
+ height="205.08009"
+ viewBox="0 0 162.64213 54.260776"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.1 r15371"
+ sodipodi:docname="misskey.svg"
+ inkscape:export-filename="C:\Users\Takumiya_Cho\Desktop\misskey.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96">
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="simplify"
+ id="path-effect5115"
+ is_visible="true"
+ steps="1"
+ threshold="0.000408163"
+ smooth_angles="360"
+ helper_size="0"
+ simplify_individual_paths="false"
+ simplify_just_coalesce="false"
+ simplifyindividualpaths="false"
+ simplifyJustCoalesce="false" />
+ <inkscape:path-effect
+ effect="simplify"
+ id="path-effect5104"
+ is_visible="true"
+ steps="1"
+ threshold="0.000408163"
+ smooth_angles="360"
+ helper_size="0"
+ simplify_individual_paths="false"
+ simplify_just_coalesce="false"
+ simplifyindividualpaths="false"
+ simplifyJustCoalesce="false" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.9899495"
+ inkscape:cx="370.82839"
+ inkscape:cy="79.043895"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="false"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:snap-center="true"
+ inkscape:snap-page="true"
+ inkscape:window-width="1920"
+ inkscape:window-height="1017"
+ inkscape:window-x="-8"
+ inkscape:window-y="1072"
+ inkscape:window-maximized="1"
+ inkscape:object-paths="true"
+ inkscape:bbox-paths="true"
+ fit-margin-top="50"
+ fit-margin-left="50"
+ fit-margin-bottom="20"
+ fit-margin-right="50" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="レイヤー 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-11.097531,-173.29664)">
+ <g
+ transform="matrix(0.28612302,0,0,0.28612302,17.176981,141.74334)"
+ id="text4489-6"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:141.03404236px;line-height:476.69509888px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#212d3a;fill-opacity:1;stroke:none;stroke-width:0.92471898px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ aria-label="Mi">
+ <path
+ sodipodi:nodetypes="zccssscssccscczzzccsccsscscsccz"
+ inkscape:connector-curvature="0"
+ id="path5210"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';fill:#212d3a;fill-opacity:1;stroke-width:0.92471898px"
+ d="m 75.196381,231.17126 c -5.855419,0.0202 -10.885068,-3.50766 -13.2572,-7.61584 -1.266603,-1.79454 -3.772419,-2.43291 -3.807919,0 v 11.2332 c 0,4.51309 -1.645397,8.41504 -4.936191,11.70583 -3.196772,3.19677 -7.098714,4.79516 -11.705826,4.79516 -4.513089,0 -8.415031,-1.59839 -11.705825,-4.79516 -3.196772,-3.29079 -4.795158,-7.19274 -4.795158,-11.70583 v -61.7729 c 0,-3.47884 0.987238,-6.6286 2.961715,-9.44928 2.068499,-2.91471 4.701135,-4.9362 7.897906,-6.06447 1.786431,-0.65816 3.666885,-0.98724 5.641362,-0.98724 5.077225,0 9.308247,1.97448 12.693064,5.92343 1.786431,1.97448 2.820681,3.00873 3.102749,3.10275 0,0 13.408119,16.21319 13.78421,16.49526 0.376091,0.28206 1.480789,2.43848 4.127113,2.43848 2.646324,0 3.89218,-2.15642 4.26827,-2.43848 0.376091,-0.28207 13.784088,-16.49526 13.784088,-16.49526 0.09402,0.094 1.081261,-0.94022 2.961715,-3.10275 3.478837,-3.94895 7.756866,-5.92343 12.834096,-5.92343 1.88045,0 3.76091,0.32908 5.64136,0.98724 3.19677,1.12827 5.7824,3.14976 7.75688,6.06447 2.06849,2.82068 3.10274,5.97044 3.10274,9.44928 v 61.7729 c 0,4.51309 -1.6454,8.41504 -4.93619,11.70583 -3.19677,3.19677 -7.09871,4.79516 -11.70582,4.79516 -4.51309,0 -8.41504,-1.59839 -11.705828,-4.79516 -3.196772,-3.29079 -4.795158,-7.19274 -4.795158,-11.70583 v -11.2332 c -0.277898,-3.06563 -2.987588,-1.13379 -3.948953,0 -2.538613,4.70114 -7.401781,7.59567 -13.2572,7.61584 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path5212"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';fill:#212d3a;fill-opacity:1;stroke-width:0.92471898px"
+ d="m 145.83461,185.00361 q -5.92343,0 -10.15445,-4.08999 -4.08999,-4.23102 -4.08999,-10.15445 0,-5.92343 4.08999,-10.01342 4.23102,-4.23102 10.15445,-4.23102 5.92343,0 10.15445,4.23102 4.23102,4.08999 4.23102,10.01342 0,5.92343 -4.23102,10.15445 -4.23102,4.08999 -10.15445,4.08999 z m 0.14103,2.82068 q 5.92343,0 10.01342,4.23102 4.23102,4.23102 4.23102,10.15445 v 34.83541 q 0,5.92343 -4.23102,10.15445 -4.08999,4.08999 -10.01342,4.08999 -5.92343,0 -10.15445,-4.08999 -4.23102,-4.23102 -4.23102,-10.15445 v -34.83541 q 0,-5.92343 4.23102,-10.15445 4.23102,-4.23102 10.15445,-4.23102 z" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ id="path5199"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:136.34428406px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#212d3a;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 72.022691,200.53715 q 0.968125,0.24203 2.420312,0.5244 2.420313,0.40339 3.791824,1.29083 2.581666,1.69422 2.581666,5.08266 0,2.74302 -1.815234,4.47758 -2.097604,2.01693 -5.849089,2.01693 -2.743021,0 -6.131458,-0.76644 -1.089141,-0.24203 -1.774896,-1.08914 -0.645417,-0.84711 -0.645417,-1.89591 0,-1.29083 0.887448,-2.17828 0.927786,-0.92779 2.178281,-0.92779 0.363047,0 0.685756,0.0807 1.169817,0.24203 4.477578,0.60508 0.443724,0 0.968125,-0.0403 0.201693,0 0.201693,-0.24203 0.04034,-0.20169 -0.242032,-0.28237 -1.37151,-0.24203 -2.541328,-0.5244 -1.331172,-0.28237 -1.895911,-0.48406 -1.12948,-0.32271 -1.895912,-0.84711 -2.581667,-1.69422 -2.622005,-5.08266 0,-2.70268 1.855573,-4.47758 2.258958,-2.17828 6.413828,-1.97659 2.783359,0.12102 5.566719,0.7261 1.048802,0.24203 1.734557,1.08914 0.685756,0.84711 0.685756,1.93625 0,1.25049 -0.927787,2.17828 -0.887448,0.88745 -2.178281,0.88745 -0.322709,0 -0.645417,-0.0807 -1.169818,-0.24203 -4.517917,-0.56474 -0.403385,-0.0403 -0.766432,0 -0.322708,0.0403 -0.322708,0.24203 0.04034,0.24203 0.322708,0.32271 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path5201"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:136.34428406px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#212d3a;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 89.577027,200.53715 q 0.968125,0.24203 2.420312,0.5244 2.420313,0.40339 3.791823,1.29083 2.581667,1.69422 2.581667,5.08266 0,2.74302 -1.815234,4.47758 -2.097604,2.01693 -5.849089,2.01693 -2.743021,0 -6.131458,-0.76644 -1.089141,-0.24203 -1.774896,-1.08914 -0.645417,-0.84711 -0.645417,-1.89591 0,-1.29083 0.887448,-2.17828 0.927786,-0.92779 2.178281,-0.92779 0.363047,0 0.685755,0.0807 1.169818,0.24203 4.477579,0.60508 0.443724,0 0.968125,-0.0403 0.201692,0 0.201692,-0.24203 0.04034,-0.20169 -0.242031,-0.28237 -1.37151,-0.24203 -2.541328,-0.5244 -1.331172,-0.28237 -1.895912,-0.48406 -1.129479,-0.32271 -1.895911,-0.84711 -2.581667,-1.69422 -2.622005,-5.08266 0,-2.70268 1.855573,-4.47758 2.258958,-2.17828 6.413828,-1.97659 2.783359,0.12102 5.566719,0.7261 1.048802,0.24203 1.734557,1.08914 0.685755,0.84711 0.685755,1.93625 0,1.25049 -0.927786,2.17828 -0.887448,0.88745 -2.178281,0.88745 -0.322709,0 -0.645417,-0.0807 -1.169818,-0.24203 -4.517917,-0.56474 -0.403385,-0.0403 -0.766432,0 -0.322708,0.0403 -0.322708,0.24203 0.04034,0.24203 0.322708,0.32271 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path5203"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:136.34428406px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#212d3a;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 115.65209,203.87137 q 0.12101,0.0807 2.86404,2.78336 1.25049,1.21016 1.25049,2.94471 0,1.61354 -1.16982,2.86404 -1.16982,1.21016 -2.90437,1.21016 -1.65388,0 -2.86404,-1.16982 l -4.03385,-3.91284 q -0.16136,-0.12102 -0.32271,-0.12102 -0.32271,0 -0.32271,1.21016 0,1.69422 -1.21016,2.90438 -1.21015,1.16981 -2.90437,1.16981 -1.69422,0 -2.90438,-1.16981 -1.169807,-1.21016 -1.169807,-2.90438 v -18.79776 q 0,-1.69422 1.169807,-2.86404 1.21016,-1.21015 2.90438,-1.21015 1.69422,0 2.90437,1.21015 1.21016,1.16982 1.21016,2.86404 v 6.29281 q 0,0.40339 0.28237,0.5244 0.24203,0.12102 0.5244,-0.0807 0.16135,-0.0807 4.84063,-3.18675 1.0488,-0.64542 2.25895,-0.64542 2.21862,0 3.42878,1.81524 0.64542,1.0488 0.64542,2.25896 0,2.21862 -1.81524,3.42877 l -2.54133,1.61354 v 0.0403 l -0.0807,0.0403 q -0.56474,0.36305 -0.0403,0.88745 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path5205"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:136.34428406px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#212d3a;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 131.25181,213.92955 q -4.19521,0 -7.18026,-2.94472 -2.94472,-2.98505 -2.94472,-7.18026 0,-4.15487 2.94472,-7.09958 2.98505,-2.98505 7.18026,-2.98505 4.15487,0 6.97857,2.78335 0.92778,0.92779 0.92778,2.25896 0,1.33118 -0.92778,2.25896 l -4.67928,4.63893 q -1.00846,1.00847 -2.01692,1.00847 -1.45219,0 -2.25896,-0.80677 -0.80677,-0.80677 -0.80677,-2.13795 0,-1.29083 0.92778,-2.21862 l 0.80678,-0.84711 q 0.16135,-0.12101 0.0807,-0.24203 -0.12101,-0.0807 -0.32271,-0.0403 -0.80677,0.20169 -1.37151,0.80677 -1.12948,1.08914 -1.12948,2.622 0,1.5732 1.08915,2.70268 1.12947,1.08914 2.70268,1.08914 1.53286,0 2.622,-1.12947 0.92779,-0.92779 2.25896,-0.92779 1.33117,0 2.25896,0.92779 0.92779,0.92778 0.92779,2.25895 0,1.33118 -0.92779,2.25896 -2.98505,2.94472 -7.13992,2.94472 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path5207"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:136.34428406px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill:#212d3a;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 160.51049,198.1433 v 5.60705 q 0,0.56474 -0.0807,1.21016 v 7.38195 q 0,4.51792 -2.74302,7.2206 -2.70268,2.70269 -7.30128,2.70269 -2.66234,0 -4.80028,-1.00847 -2.13795,-0.96812 -2.13795,-3.3481 0,-0.80677 0.36305,-1.53286 0.96812,-2.17828 3.3481,-2.17828 0.56474,0 1.5732,0.32271 1.00847,0.3227 1.65388,0.3227 1.69422,0 2.21862,-0.72609 0.20169,-0.28237 0.0807,-0.44372 -0.16136,-0.24204 -0.56474,-0.16136 -0.68576,0.12102 -1.49253,0.12102 -4.07419,0 -6.97856,-2.90438 -2.90438,-2.90437 -2.90438,-6.97857 v -5.60705 q 0,-1.69422 1.16982,-2.86404 1.21015,-1.21016 2.90437,-1.21016 1.69422,0 2.90438,1.21016 1.21015,1.16982 1.21015,2.86404 v 5.60705 q 0,0.68576 0.48407,1.21016 0.5244,0.48406 1.21015,0.48406 0.7261,0 1.21016,-0.48406 0.48406,-0.5244 0.48406,-1.21016 v -5.60705 q 0,-1.69422 1.21016,-2.86404 1.21015,-1.21016 2.90437,-1.21016 1.69422,0 2.86404,1.21016 1.21016,1.16982 1.21016,2.86404 z" />
+ </g>
+</svg>
diff --git a/src/client/assets/welcome-bg.dark.svg b/src/client/assets/welcome-bg.dark.svg
new file mode 100644
index 0000000000..1866170327
--- /dev/null
+++ b/src/client/assets/welcome-bg.dark.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="900"><path d="M667,476L630,367L567,460Z" fill="#121931" stroke="#121931" stroke-width="1.51"/><path d="M630,367L576,311L567,460Z" fill="#121c31" stroke="#121c31" stroke-width="1.51"/><path d="M567,460L631,579L667,476Z" fill="#121731" stroke="#121731" stroke-width="1.51"/><path d="M567,460L556,584L631,579Z" fill="#131830" stroke="#131830" stroke-width="1.51"/><path d="M437,475L556,584L567,460Z" fill="#121a31" stroke="#121a31" stroke-width="1.51"/><path d="M667,476L773,349L630,367Z" fill="#121831" stroke="#121831" stroke-width="1.51"/><path d="M630,367L580,255L576,311Z" fill="#122031" stroke="#122031" stroke-width="1.51"/><path d="M813,438L773,349L667,476Z" fill="#121530" stroke="#121530" stroke-width="1.51"/><path d="M576,311L437,475L567,460Z" fill="#111d31" stroke="#111d31" stroke-width="1.51"/><path d="M642,193L580,255L630,367Z" fill="#112131" stroke="#112131" stroke-width="1.51"/><path d="M800,574L813,438L667,476Z" fill="#121330" stroke="#121330" stroke-width="1.51"/><path d="M400,299L437,475L576,311Z" fill="#122231" stroke="#122231" stroke-width="1.51"/><path d="M556,584L583,647L631,579Z" fill="#14162f" stroke="#14162f" stroke-width="1.51"/><path d="M631,579L800,574L667,476Z" fill="#121430" stroke="#121430" stroke-width="1.51"/><path d="M423,693L583,647L556,584Z" fill="#14192f" stroke="#14192f" stroke-width="1.51"/><path d="M653,680L800,574L631,579Z" fill="#13132f" stroke="#13132f" stroke-width="1.51"/><path d="M773,349L642,193L630,367Z" fill="#111d31" stroke="#111d31" stroke-width="1.51"/><path d="M813,438L874,423L773,349Z" fill="#131630" stroke="#131630" stroke-width="1.51"/><path d="M773,349L789,203L642,193Z" fill="#121f31" stroke="#121f31" stroke-width="1.51"/><path d="M906,568L874,423L813,438Z" fill="#13122f" stroke="#13122f" stroke-width="1.51"/><path d="M583,647L653,680L631,579Z" fill="#14152e" stroke="#14152e" stroke-width="1.51"/><path d="M449,219L400,299L576,311Z" fill="#112631" stroke="#112631" stroke-width="1.51"/><path d="M449,219L576,311L580,255Z" fill="#112431" stroke="#112431" stroke-width="1.51"/><path d="M437,475L411,599L556,584Z" fill="#131c30" stroke="#131c30" stroke-width="1.51"/><path d="M556,765L666,768L653,680Z" fill="#15142d" stroke="#15142d" stroke-width="1.51"/><path d="M327,557L411,599L437,475Z" fill="#131f30" stroke="#131f30" stroke-width="1.51"/><path d="M572,116L449,219L580,255Z" fill="#102731" stroke="#102731" stroke-width="1.51"/><path d="M920,229L789,203L773,349Z" fill="#131d30" stroke="#131d30" stroke-width="1.51"/><path d="M874,423L909,355L773,349Z" fill="#131730" stroke="#131730" stroke-width="1.51"/><path d="M1018,299L909,355L1040,413Z" fill="#14172e" stroke="#14172e" stroke-width="1.51"/><path d="M642,193L572,116L580,255Z" fill="#112631" stroke="#112631" stroke-width="1.51"/><path d="M802,140L639,121L642,193Z" fill="#112531" stroke="#112531" stroke-width="1.51"/><path d="M800,574L906,568L813,438Z" fill="#13122f" stroke="#13122f" stroke-width="1.51"/><path d="M860,653L906,568L800,574Z" fill="#14112e" stroke="#14112e" stroke-width="1.51"/><path d="M653,680L792,696L800,574Z" fill="#14112e" stroke="#14112e" stroke-width="1.51"/><path d="M639,121L572,116L642,193Z" fill="#102731" stroke="#102731" stroke-width="1.51"/><path d="M280,464L327,557L437,475Z" fill="#122131" stroke="#122131" stroke-width="1.51"/><path d="M792,696L860,653L800,574Z" fill="#15102d" stroke="#15102d" stroke-width="1.51"/><path d="M315,686L423,693L411,599Z" fill="#141d2f" stroke="#141d2f" stroke-width="1.51"/><path d="M411,599L423,693L556,584Z" fill="#141b2f" stroke="#141b2f" stroke-width="1.51"/><path d="M653,680L666,768L792,696Z" fill="#14112d" stroke="#14112d" stroke-width="1.51"/><path d="M400,299L298,362L437,475Z" fill="#112431" stroke="#112431" stroke-width="1.51"/><path d="M289,189L298,362L400,299Z" fill="#0f2a31" stroke="#0f2a31" stroke-width="1.51"/><path d="M556,765L653,680L583,647Z" fill="#15152e" stroke="#15152e" stroke-width="1.51"/><path d="M789,203L802,140L642,193Z" fill="#112231" stroke="#112231" stroke-width="1.51"/><path d="M920,229L802,140L789,203Z" fill="#132130" stroke="#132130" stroke-width="1.51"/><path d="M423,693L556,765L583,647Z" fill="#15182e" stroke="#15182e" stroke-width="1.51"/><path d="M298,362L280,464L437,475Z" fill="#112331" stroke="#112331" stroke-width="1.51"/><path d="M909,355L920,229L773,349Z" fill="#131a30" stroke="#131a30" stroke-width="1.51"/><path d="M1018,299L920,229L909,355Z" fill="#141a2f" stroke="#141a2f" stroke-width="1.51"/><path d="M675,877L748,809L666,768Z" fill="#17112d" stroke="#17112d" stroke-width="1.51"/><path d="M423,693L443,781L556,765Z" fill="#16192e" stroke="#16192e" stroke-width="1.51"/><path d="M336,786L443,781L423,693Z" fill="#161c2d" stroke="#161c2d" stroke-width="1.51"/><path d="M792,696L924,797L860,653Z" fill="#150e2c" stroke="#150e2c" stroke-width="1.51"/><path d="M666,768L748,809L792,696Z" fill="#150f2d" stroke="#150f2d" stroke-width="1.51"/><path d="M675,877L666,768L556,765Z" fill="#17132d" stroke="#17132d" stroke-width="1.51"/><path d="M327,557L315,686L411,599Z" fill="#141f2f" stroke="#141f2f" stroke-width="1.51"/><path d="M224,597L315,686L327,557Z" fill="#14222f" stroke="#14222f" stroke-width="1.51"/><path d="M566,23L421,77L572,116Z" fill="#132a2e" stroke="#132a2e" stroke-width="1.51"/><path d="M572,116L421,77L449,219Z" fill="#0e2d31" stroke="#0e2d31" stroke-width="1.51"/><path d="M449,219L289,189L400,299Z" fill="#0f2b31" stroke="#0f2b31" stroke-width="1.51"/><path d="M566,23L572,116L639,121Z" fill="#13282f" stroke="#13282f" stroke-width="1.51"/><path d="M644,-20L566,23L639,121Z" fill="#16272d" stroke="#16272d" stroke-width="1.51"/><path d="M328,133L289,189L449,219Z" fill="#0d2f31" stroke="#0d2f31" stroke-width="1.51"/><path d="M171,486L224,597L280,464Z" fill="#13232f" stroke="#13232f" stroke-width="1.51"/><path d="M1040,413L909,355L874,423Z" fill="#14152f" stroke="#14152f" stroke-width="1.51"/><path d="M920,229L902,89L802,140Z" fill="#132230" stroke="#132230" stroke-width="1.51"/><path d="M1020,585L906,568L1018,660Z" fill="#150f2c" stroke="#150f2c" stroke-width="1.51"/><path d="M1020,585L1040,413L906,568Z" fill="#14102d" stroke="#14102d" stroke-width="1.51"/><path d="M906,568L1040,413L874,423Z" fill="#13122f" stroke="#13122f" stroke-width="1.51"/><path d="M421,77L328,133L449,219Z" fill="#0d2f31" stroke="#0d2f31" stroke-width="1.51"/><path d="M1018,299L987,217L920,229Z" fill="#141d2f" stroke="#141d2f" stroke-width="1.51"/><path d="M755,-6L644,-20L639,121Z" fill="#16242d" stroke="#16242d" stroke-width="1.51"/><path d="M1018,660L906,568L860,653Z" fill="#15102c" stroke="#15102c" stroke-width="1.51"/><path d="M190,365L280,464L298,362Z" fill="#102731" stroke="#102731" stroke-width="1.51"/><path d="M280,464L224,597L327,557Z" fill="#122330" stroke="#122330" stroke-width="1.51"/><path d="M225,235L190,365L298,362Z" fill="#102b31" stroke="#102b31" stroke-width="1.51"/><path d="M1009,122L902,89L920,229Z" fill="#14222f" stroke="#14222f" stroke-width="1.51"/><path d="M289,189L225,235L298,362Z" fill="#0d2e31" stroke="#0d2e31" stroke-width="1.51"/><path d="M185,70L225,235L289,189Z" fill="#0c3330" stroke="#0c3330" stroke-width="1.51"/><path d="M527,877L675,877L556,765Z" fill="#19152d" stroke="#19152d" stroke-width="1.51"/><path d="M976,767L1018,660L860,653Z" fill="#160e2c" stroke="#160e2c" stroke-width="1.51"/><path d="M566,23L439,-17L421,77Z" fill="#152c2c" stroke="#152c2c" stroke-width="1.51"/><path d="M755,-6L639,121L802,140Z" fill="#14242f" stroke="#14242f" stroke-width="1.51"/><path d="M190,365L171,486L280,464Z" fill="#132430" stroke="#132430" stroke-width="1.51"/><path d="M902,89L755,-6L802,140Z" fill="#15232e" stroke="#15232e" stroke-width="1.51"/><path d="M924,797L792,696L748,809Z" fill="#160e2c" stroke="#160e2c" stroke-width="1.51"/><path d="M1020,585L1106,477L1040,413Z" fill="#14102d" stroke="#14102d" stroke-width="1.51"/><path d="M443,781L527,877L556,765Z" fill="#17182d" stroke="#17182d" stroke-width="1.51"/><path d="M427,924L527,877L443,781Z" fill="#1b192d" stroke="#1b192d" stroke-width="1.51"/><path d="M315,686L336,786L423,693Z" fill="#151e2e" stroke="#151e2e" stroke-width="1.51"/><path d="M201,784L336,786L315,686Z" fill="#16202d" stroke="#16202d" stroke-width="1.51"/><path d="M779,911L924,797L748,809Z" fill="#190e2c" stroke="#190e2c" stroke-width="1.51"/><path d="M421,77L296,-6L328,133Z" fill="#10312e" stroke="#10312e" stroke-width="1.51"/><path d="M328,133L185,70L289,189Z" fill="#093431" stroke="#093431" stroke-width="1.51"/><path d="M545,-110L439,-17L566,23Z" fill="#18292a" stroke="#18292a" stroke-width="1.51"/><path d="M1098,562L1106,477L1020,585Z" fill="#150f2d" stroke="#150f2d" stroke-width="1.51"/><path d="M1040,413L1149,365L1018,299Z" fill="#15162e" stroke="#15162e" stroke-width="1.51"/><path d="M1135,188L1009,122L987,217Z" fill="#14202e" stroke="#14202e" stroke-width="1.51"/><path d="M224,597L189,651L315,686Z" fill="#15222e" stroke="#15222e" stroke-width="1.51"/><path d="M122,584L189,651L224,597Z" fill="#16212d" stroke="#16212d" stroke-width="1.51"/><path d="M1095,646L1098,562L1020,585Z" fill="#160e2c" stroke="#160e2c" stroke-width="1.51"/><path d="M924,797L976,767L860,653Z" fill="#160d2b" stroke="#160d2b" stroke-width="1.51"/><path d="M1095,646L1020,585L1018,660Z" fill="#160e2b" stroke="#160e2b" stroke-width="1.51"/><path d="M902,89L855,-47L755,-6Z" fill="#18222b" stroke="#18222b" stroke-width="1.51"/><path d="M987,217L1009,122L920,229Z" fill="#14202f" stroke="#14202f" stroke-width="1.51"/><path d="M1135,188L987,217L1018,299Z" fill="#141c2e" stroke="#141c2e" stroke-width="1.51"/><path d="M675,877L779,911L748,809Z" fill="#1a102d" stroke="#1a102d" stroke-width="1.51"/><path d="M924,797L1032,900L976,767Z" fill="#190d2a" stroke="#190d2a" stroke-width="1.51"/><path d="M758,1032L779,911L675,877Z" fill="#1d102d" stroke="#1d102d" stroke-width="1.51"/><path d="M1153,782L1095,646L1018,660Z" fill="#170c2b" stroke="#170c2b" stroke-width="1.51"/><path d="M1262,481L1149,365L1106,477Z" fill="#15102d" stroke="#15102d" stroke-width="1.51"/><path d="M171,486L122,584L224,597Z" fill="#16222d" stroke="#16222d" stroke-width="1.51"/><path d="M70,425L122,584L171,486Z" fill="#17232c" stroke="#17232c" stroke-width="1.51"/><path d="M70,425L171,486L190,365Z" fill="#15242e" stroke="#15242e" stroke-width="1.51"/><path d="M527,877L566,1030L675,877Z" fill="#1d152d" stroke="#1d152d" stroke-width="1.51"/><path d="M336,786L350,882L443,781Z" fill="#181d2d" stroke="#181d2d" stroke-width="1.51"/><path d="M201,784L350,882L336,786Z" fill="#18202d" stroke="#18202d" stroke-width="1.51"/><path d="M201,784L315,686L189,651Z" fill="#15212d" stroke="#15212d" stroke-width="1.51"/><path d="M1106,477L1149,365L1040,413Z" fill="#14122d" stroke="#14122d" stroke-width="1.51"/><path d="M1262,481L1106,477L1098,562Z" fill="#150e2c" stroke="#150e2c" stroke-width="1.51"/><path d="M689,-114L545,-110L644,-20Z" fill="#1b2427" stroke="#1b2427" stroke-width="1.51"/><path d="M644,-20L545,-110L566,23Z" fill="#19272a" stroke="#19272a" stroke-width="1.51"/><path d="M1028,16L855,-47L902,89Z" fill="#19212a" stroke="#19212a" stroke-width="1.51"/><path d="M350,882L427,924L443,781Z" fill="#1b1c2d" stroke="#1b1c2d" stroke-width="1.51"/><path d="M439,-17L296,-6L421,77Z" fill="#142e2c" stroke="#142e2c" stroke-width="1.51"/><path d="M225,235L80,349L190,365Z" fill="#132a2e" stroke="#132a2e" stroke-width="1.51"/><path d="M689,-114L644,-20L755,-6Z" fill="#192229" stroke="#192229" stroke-width="1.51"/><path d="M439,-17L324,-108L296,-6Z" fill="#172e29" stroke="#172e29" stroke-width="1.51"/><path d="M753,-160L689,-114L755,-6Z" fill="#1c2127" stroke="#1c2127" stroke-width="1.51"/><path d="M90,203L80,349L225,235Z" fill="#132d2d" stroke="#132d2d" stroke-width="1.51"/><path d="M102,767L201,784L189,651Z" fill="#18202b" stroke="#18202b" stroke-width="1.51"/><path d="M80,349L70,425L190,365Z" fill="#16262d" stroke="#16262d" stroke-width="1.51"/><path d="M1009,122L1028,16L902,89Z" fill="#16212c" stroke="#16212c" stroke-width="1.51"/><path d="M1149,365L1135,188L1018,299Z" fill="#15192e" stroke="#15192e" stroke-width="1.51"/><path d="M296,-6L185,70L328,133Z" fill="#0f332e" stroke="#0f332e" stroke-width="1.51"/><path d="M779,911L893,937L924,797Z" fill="#1b0e2b" stroke="#1b0e2b" stroke-width="1.51"/><path d="M976,767L1153,782L1018,660Z" fill="#170c2a" stroke="#170c2a" stroke-width="1.51"/><path d="M758,1032L893,937L779,911Z" fill="#1f0f2c" stroke="#1f0f2c" stroke-width="1.51"/><path d="M1131,95L1028,16L1009,122Z" fill="#17212c" stroke="#17212c" stroke-width="1.51"/><path d="M855,-47L753,-160L755,-6Z" fill="#1b2128" stroke="#1b2128" stroke-width="1.51"/><path d="M123,103L90,203L225,235Z" fill="#11312e" stroke="#11312e" stroke-width="1.51"/><path d="M80,349L-14,363L70,425Z" fill="#18252b" stroke="#18252b" stroke-width="1.51"/><path d="M1028,16L881,-96L855,-47Z" fill="#1b2028" stroke="#1b2028" stroke-width="1.51"/><path d="M185,70L123,103L225,235Z" fill="#0e342e" stroke="#0e342e" stroke-width="1.51"/><path d="M118,-15L123,103L185,70Z" fill="#15322a" stroke="#15322a" stroke-width="1.51"/><path d="M296,-6L182,-12L185,70Z" fill="#13322a" stroke="#13322a" stroke-width="1.51"/><path d="M545,-110L463,-146L439,-17Z" fill="#1a2927" stroke="#1a2927" stroke-width="1.51"/><path d="M753,-160L463,-146L545,-110Z" fill="#1d2525" stroke="#1d2525" stroke-width="1.51"/><path d="M753,-160L545,-110L689,-114Z" fill="#1d2226" stroke="#1d2226" stroke-width="1.51"/><path d="M122,584L64,646L189,651Z" fill="#18212b" stroke="#18212b" stroke-width="1.51"/><path d="M-55,555L64,646L122,584Z" fill="#1a2029" stroke="#1a2029" stroke-width="1.51"/><path d="M465,1018L566,1030L527,877Z" fill="#20182d" stroke="#20182d" stroke-width="1.51"/><path d="M465,1018L527,877L427,924Z" fill="#1f1a2d" stroke="#1f1a2d" stroke-width="1.51"/><path d="M465,1018L427,924L298,1048Z" fill="#211c2d" stroke="#211c2d" stroke-width="1.51"/><path d="M881,-96L753,-160L855,-47Z" fill="#1c2026" stroke="#1c2026" stroke-width="1.51"/><path d="M1248,72L1131,95L1135,188Z" fill="#16212d" stroke="#16212d" stroke-width="1.51"/><path d="M1135,188L1131,95L1009,122Z" fill="#15222e" stroke="#15222e" stroke-width="1.51"/><path d="M298,1048L427,924L350,882Z" fill="#1f1e2d" stroke="#1f1e2d" stroke-width="1.51"/><path d="M463,-146L324,-108L439,-17Z" fill="#1a2c27" stroke="#1a2c27" stroke-width="1.51"/><path d="M696,1054L758,1032L675,877Z" fill="#20102d" stroke="#20102d" stroke-width="1.51"/><path d="M201,784L170,884L350,882Z" fill="#1b212d" stroke="#1b212d" stroke-width="1.51"/><path d="M64,646L102,767L189,651Z" fill="#18202a" stroke="#18202a" stroke-width="1.51"/><path d="M913,1005L1032,900L893,937Z" fill="#1f0d2b" stroke="#1f0d2b" stroke-width="1.51"/><path d="M893,937L1032,900L924,797Z" fill="#1c0d2b" stroke="#1c0d2b" stroke-width="1.51"/><path d="M207,-137L182,-12L296,-6Z" fill="#173127" stroke="#173127" stroke-width="1.51"/><path d="M566,1030L696,1054L675,877Z" fill="#20132d" stroke="#20132d" stroke-width="1.51"/><path d="M298,1048L696,1054L566,1030Z" fill="#23182d" stroke="#23182d" stroke-width="1.51"/><path d="M1089,882L1153,782L976,767Z" fill="#1a0b2a" stroke="#1a0b2a" stroke-width="1.51"/><path d="M1255,588L1262,481L1098,562Z" fill="#160d2c" stroke="#160d2c" stroke-width="1.51"/><path d="M70,425L-21,485L122,584Z" fill="#19222b" stroke="#19222b" stroke-width="1.51"/><path d="M-5,194L-14,363L80,349Z" fill="#18292a" stroke="#18292a" stroke-width="1.51"/><path d="M-5,194L80,349L90,203Z" fill="#162d2b" stroke="#162d2b" stroke-width="1.51"/><path d="M-5,194L90,203L123,103Z" fill="#13312b" stroke="#13312b" stroke-width="1.51"/><path d="M1255,588L1098,562L1095,646Z" fill="#170d2b" stroke="#170d2b" stroke-width="1.51"/><path d="M1149,365L1263,231L1135,188Z" fill="#161a2d" stroke="#161a2d" stroke-width="1.51"/><path d="M102,767L170,884L201,784Z" fill="#1b202a" stroke="#1b202a" stroke-width="1.51"/><path d="M758,1032L913,1005L893,937Z" fill="#200e2c" stroke="#200e2c" stroke-width="1.51"/><path d="M990,1060L913,1005L758,1032Z" fill="#220e2b" stroke="#220e2b" stroke-width="1.51"/><path d="M64,646L-24,765L102,767Z" fill="#1b1f27" stroke="#1b1f27" stroke-width="1.51"/><path d="M-14,363L-21,485L70,425Z" fill="#192329" stroke="#192329" stroke-width="1.51"/><path d="M1094,1029L1089,882L1032,900Z" fill="#1f0b2a" stroke="#1f0b2a" stroke-width="1.51"/><path d="M1032,900L1089,882L976,767Z" fill="#1b0c2a" stroke="#1b0c2a" stroke-width="1.51"/><path d="M1248,648L1255,588L1095,646Z" fill="#170c2a" stroke="#170c2a" stroke-width="1.51"/><path d="M1318,235L1271,354L1377,345Z" fill="#1b182d" stroke="#1b182d" stroke-width="1.51"/><path d="M1262,481L1271,354L1149,365Z" fill="#17122d" stroke="#17122d" stroke-width="1.51"/><path d="M1253,799L1248,648L1153,782Z" fill="#190a29" stroke="#190a29" stroke-width="1.51"/><path d="M1153,782L1248,648L1095,646Z" fill="#180b2a" stroke="#180b2a" stroke-width="1.51"/><path d="M1131,95L1110,-28L1028,16Z" fill="#192029" stroke="#192029" stroke-width="1.51"/><path d="M1028,16L971,-156L881,-96Z" fill="#1c1f26" stroke="#1c1f26" stroke-width="1.51"/><path d="M881,-96L971,-156L753,-160Z" fill="#1e1f24" stroke="#1e1f24" stroke-width="1.51"/><path d="M1248,72L1110,-28L1131,95Z" fill="#191f29" stroke="#191f29" stroke-width="1.51"/><path d="M1271,354L1263,231L1149,365Z" fill="#17172d" stroke="#17172d" stroke-width="1.51"/><path d="M-121,448L-55,555L-21,485Z" fill="#1c2027" stroke="#1c2027" stroke-width="1.51"/><path d="M-38,73L-5,194L123,103Z" fill="#153229" stroke="#153229" stroke-width="1.51"/><path d="M182,-12L118,-15L185,70Z" fill="#163228" stroke="#163228" stroke-width="1.51"/><path d="M207,-137L118,-15L182,-12Z" fill="#193125" stroke="#193125" stroke-width="1.51"/><path d="M1110,-28L971,-156L1028,16Z" fill="#1c1f26" stroke="#1c1f26" stroke-width="1.51"/><path d="M465,1018L298,1048L566,1030Z" fill="#231b2d" stroke="#231b2d" stroke-width="1.51"/><path d="M170,884L228,990L350,882Z" fill="#1e212d" stroke="#1e212d" stroke-width="1.51"/><path d="M93,915L228,990L170,884Z" fill="#20202a" stroke="#20202a" stroke-width="1.51"/><path d="M-21,485L-55,555L122,584Z" fill="#1a2129" stroke="#1a2129" stroke-width="1.51"/><path d="M102,767L93,915L170,884Z" fill="#1e2029" stroke="#1e2029" stroke-width="1.51"/><path d="M-121,448L-21,485L-14,363Z" fill="#1b2228" stroke="#1b2228" stroke-width="1.51"/><path d="M228,990L298,1048L350,882Z" fill="#21212d" stroke="#21212d" stroke-width="1.51"/><path d="M-55,555L-35,672L64,646Z" fill="#1b1f27" stroke="#1b1f27" stroke-width="1.51"/><path d="M324,-108L207,-137L296,-6Z" fill="#183127" stroke="#183127" stroke-width="1.51"/><path d="M463,-146L207,-137L324,-108Z" fill="#1a2e25" stroke="#1a2e25" stroke-width="1.51"/><path d="M73,-154L207,-137L463,-146Z" fill="#1a3024" stroke="#1a3024" stroke-width="1.51"/><path d="M-24,765L93,915L102,767Z" fill="#1d1f27" stroke="#1d1f27" stroke-width="1.51"/><path d="M228,990L72,1047L298,1048Z" fill="#25212b" stroke="#25212b" stroke-width="1.51"/><path d="M1110,-28L1136,-111L971,-156Z" fill="#1e1e24" stroke="#1e1e24" stroke-width="1.51"/><path d="M1263,231L1248,72L1135,188Z" fill="#171f2d" stroke="#171f2d" stroke-width="1.51"/><path d="M1263,231L1348,116L1248,72Z" fill="#1a212d" stroke="#1a212d" stroke-width="1.51"/><path d="M1271,354L1318,235L1263,231Z" fill="#19192d" stroke="#19192d" stroke-width="1.51"/><path d="M1377,345L1271,354L1386,431Z" fill="#1b142d" stroke="#1b142d" stroke-width="1.51"/><path d="M1355,543L1262,481L1255,588Z" fill="#190e2c" stroke="#190e2c" stroke-width="1.51"/><path d="M-132,680L-24,765L-35,672Z" fill="#1e1e25" stroke="#1e1e25" stroke-width="1.51"/><path d="M-35,672L-24,765L64,646Z" fill="#1c1e27" stroke="#1c1e27" stroke-width="1.51"/><path d="M913,1005L990,1060L1032,900Z" fill="#200d2a" stroke="#200d2a" stroke-width="1.51"/><path d="M1218,912L1253,799L1153,782Z" fill="#1c0a29" stroke="#1c0a29" stroke-width="1.51"/><path d="M696,1054L990,1060L758,1032Z" fill="#220f2c" stroke="#220f2c" stroke-width="1.51"/><path d="M-136,1054L990,1060L696,1054Z" fill="#24182d" stroke="#24182d" stroke-width="1.51"/><path d="M1218,912L1153,782L1089,882Z" fill="#1c0a29" stroke="#1c0a29" stroke-width="1.51"/><path d="M1248,648L1355,543L1255,588Z" fill="#190d2b" stroke="#190d2b" stroke-width="1.51"/><path d="M1367,710L1355,543L1248,648Z" fill="#1b0c2a" stroke="#1b0c2a" stroke-width="1.51"/><path d="M-55,555L-132,680L-35,672Z" fill="#1d1e25" stroke="#1d1e25" stroke-width="1.51"/><path d="M-131,315L-121,448L-14,363Z" fill="#1c2426" stroke="#1c2426" stroke-width="1.51"/><path d="M1246,-36L1136,-111L1110,-28Z" fill="#1d1e25" stroke="#1d1e25" stroke-width="1.51"/><path d="M118,-15L-38,73L123,103Z" fill="#183128" stroke="#183128" stroke-width="1.51"/><path d="M-5,194L-131,315L-14,363Z" fill="#1a2928" stroke="#1a2928" stroke-width="1.51"/><path d="M-39,7L-38,73L118,-15Z" fill="#1a3025" stroke="#1a3025" stroke-width="1.51"/><path d="M1324,-3L1246,-36L1248,72Z" fill="#1e1f28" stroke="#1e1f28" stroke-width="1.51"/><path d="M1386,431L1271,354L1262,481Z" fill="#19112d" stroke="#19112d" stroke-width="1.51"/><path d="M990,1060L1094,1029L1032,900Z" fill="#210c2a" stroke="#210c2a" stroke-width="1.51"/><path d="M-124,219L-131,315L-5,194Z" fill="#1a2b26" stroke="#1a2b26" stroke-width="1.51"/><path d="M1355,543L1386,431L1262,481Z" fill="#1b0f2c" stroke="#1b0f2c" stroke-width="1.51"/><path d="M1094,1029L1218,912L1089,882Z" fill="#1f0a29" stroke="#1f0a29" stroke-width="1.51"/><path d="M1253,799L1367,710L1248,648Z" fill="#1b0b29" stroke="#1b0b29" stroke-width="1.51"/><path d="M-38,73L-124,219L-5,194Z" fill="#183027" stroke="#183027" stroke-width="1.51"/><path d="M1248,72L1246,-36L1110,-28Z" fill="#1b1f27" stroke="#1b1f27" stroke-width="1.51"/><path d="M1348,116L1263,231L1318,235Z" fill="#1a1e2d" stroke="#1a1e2d" stroke-width="1.51"/><path d="M-38,73L-167,117L-124,219Z" fill="#193125" stroke="#193125" stroke-width="1.51"/><path d="M-7,-152L-39,7L118,-15Z" fill="#1d3021" stroke="#1d3021" stroke-width="1.51"/><path d="M1465,118L1348,116L1318,235Z" fill="#1d202d" stroke="#1d202d" stroke-width="1.51"/><path d="M-121,448L-165,529L-55,555Z" fill="#1d1f25" stroke="#1d1f25" stroke-width="1.51"/><path d="M-131,315L-165,529L-121,448Z" fill="#1d2125" stroke="#1d2125" stroke-width="1.51"/><path d="M-167,117L-165,529L-131,315Z" fill="#1d2724" stroke="#1d2724" stroke-width="1.51"/><path d="M1476,551L1473,419L1386,431Z" fill="#1e102d" stroke="#1e102d" stroke-width="1.51"/><path d="M1335,825L1367,710L1253,799Z" fill="#1d0a29" stroke="#1d0a29" stroke-width="1.51"/><path d="M-165,529L-132,680L-55,555Z" fill="#1e1f24" stroke="#1e1f24" stroke-width="1.51"/><path d="M-24,765L-15,943L93,915Z" fill="#211e26" stroke="#211e26" stroke-width="1.51"/><path d="M753,-160L73,-154L463,-146Z" fill="#1c2a24" stroke="#1c2a24" stroke-width="1.51"/><path d="M207,-137L73,-154L118,-15Z" fill="#1b3023" stroke="#1b3023" stroke-width="1.51"/><path d="M1218,912L1335,825L1253,799Z" fill="#1e0a29" stroke="#1e0a29" stroke-width="1.51"/><path d="M1344,904L1335,825L1218,912Z" fill="#200a29" stroke="#200a29" stroke-width="1.51"/><path d="M-175,829L-15,943L-24,765Z" fill="#211d23" stroke="#211d23" stroke-width="1.51"/><path d="M93,915L72,1047L228,990Z" fill="#242029" stroke="#242029" stroke-width="1.51"/><path d="M1094,1029L1223,992L1218,912Z" fill="#210a29" stroke="#210a29" stroke-width="1.51"/><path d="M1339,1016L1223,992L1094,1029Z" fill="#230a29" stroke="#230a29" stroke-width="1.51"/><path d="M1348,116L1324,-3L1248,72Z" fill="#1d202a" stroke="#1d202a" stroke-width="1.51"/><path d="M1246,-36L1241,-144L1136,-111Z" fill="#1f1d23" stroke="#1f1d23" stroke-width="1.51"/><path d="M-15,943L72,1047L93,915Z" fill="#241f27" stroke="#241f27" stroke-width="1.51"/><path d="M298,1048L-136,1054L696,1054Z" fill="#24212d" stroke="#24212d" stroke-width="1.51"/><path d="M1384,-153L1241,-144L1246,-36Z" fill="#211d23" stroke="#211d23" stroke-width="1.51"/><path d="M1136,-111L1241,-144L971,-156Z" fill="#1f1c22" stroke="#1f1c22" stroke-width="1.51"/><path d="M-124,219L-167,117L-131,315Z" fill="#1b2c25" stroke="#1b2c25" stroke-width="1.51"/><path d="M-117,3L-167,117L-38,73Z" fill="#1c3022" stroke="#1c3022" stroke-width="1.51"/><path d="M-117,3L-38,73L-39,7Z" fill="#1c3022" stroke="#1c3022" stroke-width="1.51"/><path d="M1501,228L1465,118L1318,235Z" fill="#1f1e2d" stroke="#1f1e2d" stroke-width="1.51"/><path d="M1348,116L1465,118L1324,-3Z" fill="#1f202b" stroke="#1f202b" stroke-width="1.51"/><path d="M1386,431L1476,362L1377,345Z" fill="#1d142d" stroke="#1d142d" stroke-width="1.51"/><path d="M1476,551L1386,431L1355,543Z" fill="#1d0e2c" stroke="#1d0e2c" stroke-width="1.51"/><path d="M1476,551L1355,543L1459,701Z" fill="#1e0d2b" stroke="#1e0d2b" stroke-width="1.51"/><path d="M-110,-95L-117,3L-39,7Z" fill="#1f2e1e" stroke="#1f2e1e" stroke-width="1.51"/><path d="M1473,419L1476,362L1386,431Z" fill="#1e132d" stroke="#1e132d" stroke-width="1.51"/><path d="M73,-154L-7,-152L118,-15Z" fill="#1e2f20" stroke="#1e2f20" stroke-width="1.51"/><path d="M1459,701L1355,543L1367,710Z" fill="#1d0c2a" stroke="#1d0c2a" stroke-width="1.51"/><path d="M1579,184L1501,228L1612,342Z" fill="#231c2d" stroke="#231c2d" stroke-width="1.51"/><path d="M1467,827L1459,701L1367,710Z" fill="#1f0a29" stroke="#1f0a29" stroke-width="1.51"/><path d="M1223,992L1344,904L1218,912Z" fill="#220a29" stroke="#220a29" stroke-width="1.51"/><path d="M-15,943L-43,1000L72,1047Z" fill="#261e25" stroke="#261e25" stroke-width="1.51"/><path d="M-145,939L-43,1000L-15,943Z" fill="#261e23" stroke="#261e23" stroke-width="1.51"/><path d="M1467,827L1367,710L1335,825Z" fill="#1f0a29" stroke="#1f0a29" stroke-width="1.51"/><path d="M-167,117L-175,829L-165,529Z" fill="#1e1f24" stroke="#1e1f24" stroke-width="1.51"/><path d="M-165,529L-175,829L-132,680Z" fill="#1f1d22" stroke="#1f1d22" stroke-width="1.51"/><path d="M-132,680L-175,829L-24,765Z" fill="#1e1c22" stroke="#1e1c22" stroke-width="1.51"/><path d="M1501,228L1318,235L1377,345Z" fill="#1d1a2d" stroke="#1d1a2d" stroke-width="1.51"/><path d="M1324,-3L1384,-153L1246,-36Z" fill="#211e25" stroke="#211e25" stroke-width="1.51"/><path d="M1476,362L1501,228L1377,345Z" fill="#1f182d" stroke="#1f182d" stroke-width="1.51"/><path d="M1567,465L1476,362L1473,419Z" fill="#20122d" stroke="#20122d" stroke-width="1.51"/><path d="M-7,-152L-110,-95L-39,7Z" fill="#1f2e1e" stroke="#1f2e1e" stroke-width="1.51"/><path d="M-117,3L-110,-95L-167,117Z" fill="#1e2f1f" stroke="#1e2f1f" stroke-width="1.51"/><path d="M-175,829L-145,939L-15,943Z" fill="#241d22" stroke="#241d22" stroke-width="1.51"/><path d="M1344,904L1467,827L1335,825Z" fill="#210a29" stroke="#210a29" stroke-width="1.51"/><path d="M1223,992L1339,1016L1344,904Z" fill="#240a29" stroke="#240a29" stroke-width="1.51"/><path d="M990,1060L1339,1016L1094,1029Z" fill="#220b29" stroke="#220b29" stroke-width="1.51"/><path d="M1484,941L1467,827L1344,904Z" fill="#240a29" stroke="#240a29" stroke-width="1.51"/><path d="M1582,529L1567,465L1476,551Z" fill="#210e2c" stroke="#210e2c" stroke-width="1.51"/><path d="M1476,551L1567,465L1473,419Z" fill="#200f2c" stroke="#200f2c" stroke-width="1.51"/><path d="M1582,529L1476,551L1577,710Z" fill="#220d2b" stroke="#220d2b" stroke-width="1.51"/><path d="M1481,-21L1324,-3L1465,118Z" fill="#222029" stroke="#222029" stroke-width="1.51"/><path d="M1481,-21L1384,-153L1324,-3Z" fill="#231e25" stroke="#231e25" stroke-width="1.51"/><path d="M1241,-144L1384,-153L971,-156Z" fill="#201c21" stroke="#201c21" stroke-width="1.51"/><path d="M971,-156L1384,-153L753,-160Z" fill="#1f1d22" stroke="#1f1d22" stroke-width="1.51"/><path d="M1577,710L1476,551L1459,701Z" fill="#210d2a" stroke="#210d2a" stroke-width="1.51"/><path d="M1501,228L1476,362L1612,342Z" fill="#21182d" stroke="#21182d" stroke-width="1.51"/><path d="M1579,184L1465,118L1501,228Z" fill="#211f2d" stroke="#211f2d" stroke-width="1.51"/><path d="M1568,-35L1481,-21L1465,118Z" fill="#252028" stroke="#252028" stroke-width="1.51"/><path d="M-175,829L-136,1054L-145,939Z" fill="#271d21" stroke="#271d21" stroke-width="1.51"/><path d="M-145,939L-136,1054L-43,1000Z" fill="#281d22" stroke="#281d22" stroke-width="1.51"/><path d="M-43,1000L-136,1054L72,1047Z" fill="#291f24" stroke="#291f24" stroke-width="1.51"/><path d="M72,1047L-136,1054L298,1048Z" fill="#272028" stroke="#272028" stroke-width="1.51"/><path d="M1612,342L1476,362L1567,465Z" fill="#21132d" stroke="#21132d" stroke-width="1.51"/><path d="M1582,529L1612,342L1567,465Z" fill="#22102d" stroke="#22102d" stroke-width="1.51"/><path d="M1582,529L1577,710L1612,342Z" fill="#220f2c" stroke="#220f2c" stroke-width="1.51"/><path d="M1565,807L1577,710L1459,701Z" fill="#210a29" stroke="#210a29" stroke-width="1.51"/><path d="M1565,807L1459,701L1467,827Z" fill="#210a29" stroke="#210a29" stroke-width="1.51"/><path d="M1456,1026L1484,941L1344,904Z" fill="#270a29" stroke="#270a29" stroke-width="1.51"/><path d="M1577,908L1565,807L1467,827Z" fill="#250a29" stroke="#250a29" stroke-width="1.51"/><path d="M1484,941L1577,908L1467,827Z" fill="#260a29" stroke="#260a29" stroke-width="1.51"/><path d="M1339,1016L1456,1026L1344,904Z" fill="#260a29" stroke="#260a29" stroke-width="1.51"/><path d="M990,1060L1456,1026L1339,1016Z" fill="#250a29" stroke="#250a29" stroke-width="1.51"/><path d="M1481,-21L1493,-148L1384,-153Z" fill="#261d23" stroke="#261d23" stroke-width="1.51"/><path d="M1568,-35L1493,-148L1481,-21Z" fill="#271e25" stroke="#271e25" stroke-width="1.51"/><path d="M1579,184L1618,111L1465,118Z" fill="#23222d" stroke="#23222d" stroke-width="1.51"/><path d="M1612,342L1618,111L1579,184Z" fill="#241e2d" stroke="#241e2d" stroke-width="1.51"/><path d="M1618,111L1568,-35L1465,118Z" fill="#25212a" stroke="#25212a" stroke-width="1.51"/><path d="M1568,1003L1577,908L1484,941Z" fill="#2a0a29" stroke="#2a0a29" stroke-width="1.51"/><path d="M1565,807L1577,908L1577,710Z" fill="#240a29" stroke="#240a29" stroke-width="1.51"/><path d="M1577,710L1577,908L1612,342Z" fill="#230d2a" stroke="#230d2a" stroke-width="1.51"/><path d="M1456,1026L1568,1003L1484,941Z" fill="#2a0a29" stroke="#2a0a29" stroke-width="1.51"/><path d="M1568,-35L1582,-127L1493,-148Z" fill="#281e23" stroke="#281e23" stroke-width="1.51"/><path d="M1618,111L1582,-127L1568,-35Z" fill="#281f26" stroke="#281f26" stroke-width="1.51"/></svg> \ No newline at end of file
diff --git a/src/client/assets/welcome-bg.light.svg b/src/client/assets/welcome-bg.light.svg
new file mode 100644
index 0000000000..ebccb648ea
--- /dev/null
+++ b/src/client/assets/welcome-bg.light.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="900"><path d="M741,416L678,396L681,478Z" fill="#f4f4f3" stroke="#f4f4f3" stroke-width="1.51"/><path d="M681,478L777,499L741,416Z" fill="#f2f3f2" stroke="#f2f3f2" stroke-width="1.51"/><path d="M678,396L605,487L681,478Z" fill="#f3f3f2" stroke="#f3f3f2" stroke-width="1.51"/><path d="M681,478L683,560L777,499Z" fill="#edf1ee" stroke="#edf1ee" stroke-width="1.51"/><path d="M760,327L659,322L678,396Z" fill="#f1f1ef" stroke="#f1f1ef" stroke-width="1.51"/><path d="M678,396L571,389L605,487Z" fill="#f2f2f0" stroke="#f2f2f0" stroke-width="1.51"/><path d="M741,416L760,327L678,396Z" fill="#f3f2f1" stroke="#f3f2f1" stroke-width="1.51"/><path d="M854,398L760,327L741,416Z" fill="#eef0ec" stroke="#eef0ec" stroke-width="1.51"/><path d="M605,487L683,560L681,478Z" fill="#edf0ec" stroke="#edf0ec" stroke-width="1.51"/><path d="M659,322L571,389L678,396Z" fill="#f1f1ee" stroke="#f1f1ee" stroke-width="1.51"/><path d="M683,560L783,568L777,499Z" fill="#e7eee9" stroke="#e7eee9" stroke-width="1.51"/><path d="M777,499L854,398L741,416Z" fill="#eef2ef" stroke="#eef2ef" stroke-width="1.51"/><path d="M844,505L854,398L777,499Z" fill="#eaefeb" stroke="#eaefeb" stroke-width="1.51"/><path d="M783,568L844,505L777,499Z" fill="#e6ece7" stroke="#e6ece7" stroke-width="1.51"/><path d="M659,322L596,308L571,389Z" fill="#f0f0eb" stroke="#f0f0eb" stroke-width="1.51"/><path d="M597,246L596,308L659,322Z" fill="#efeee9" stroke="#efeee9" stroke-width="1.51"/><path d="M605,487L579,600L683,560Z" fill="#e7ede7" stroke="#e7ede7" stroke-width="1.51"/><path d="M571,389L512,495L605,487Z" fill="#f1f1ee" stroke="#f1f1ee" stroke-width="1.51"/><path d="M492,390L512,495L571,389Z" fill="#f0f0ec" stroke="#f0f0ec" stroke-width="1.51"/><path d="M760,327L745,238L659,322Z" fill="#f1f0ed" stroke="#f1f0ed" stroke-width="1.51"/><path d="M852,301L745,238L760,327Z" fill="#ebede7" stroke="#ebede7" stroke-width="1.51"/><path d="M512,495L579,600L605,487Z" fill="#e9ede7" stroke="#e9ede7" stroke-width="1.51"/><path d="M764,652L848,599L783,568Z" fill="#dce7de" stroke="#dce7de" stroke-width="1.51"/><path d="M854,398L852,301L760,327Z" fill="#eaeee8" stroke="#eaeee8" stroke-width="1.51"/><path d="M513,332L492,390L571,389Z" fill="#efeeea" stroke="#efeeea" stroke-width="1.51"/><path d="M596,308L513,332L571,389Z" fill="#efefe9" stroke="#efefe9" stroke-width="1.51"/><path d="M521,240L513,332L596,308Z" fill="#edede6" stroke="#edede6" stroke-width="1.51"/><path d="M655,216L597,246L659,322Z" fill="#eeeee8" stroke="#eeeee8" stroke-width="1.51"/><path d="M783,568L848,599L844,505Z" fill="#e0e9e1" stroke="#e0e9e1" stroke-width="1.51"/><path d="M844,505L926,479L854,398Z" fill="#e7ede8" stroke="#e7ede8" stroke-width="1.51"/><path d="M764,652L783,568L683,560Z" fill="#e2eae3" stroke="#e2eae3" stroke-width="1.51"/><path d="M745,238L655,216L659,322Z" fill="#efefea" stroke="#efefea" stroke-width="1.51"/><path d="M691,673L764,652L683,560Z" fill="#e0e9e1" stroke="#e0e9e1" stroke-width="1.51"/><path d="M930,580L926,479L844,505Z" fill="#dee8e0" stroke="#dee8e0" stroke-width="1.51"/><path d="M854,398L924,327L852,301Z" fill="#e5ebe3" stroke="#e5ebe3" stroke-width="1.51"/><path d="M926,479L932,405L854,398Z" fill="#e5ece6" stroke="#e5ece6" stroke-width="1.51"/><path d="M579,600L691,673L683,560Z" fill="#e1e9e1" stroke="#e1e9e1" stroke-width="1.51"/><path d="M852,301L854,250L745,238Z" fill="#e8ebe4" stroke="#e8ebe4" stroke-width="1.51"/><path d="M745,238L695,139L655,216Z" fill="#eeede7" stroke="#eeede7" stroke-width="1.51"/><path d="M932,252L854,250L852,301Z" fill="#e3e9df" stroke="#e3e9df" stroke-width="1.51"/><path d="M932,405L924,327L854,398Z" fill="#e4ebe3" stroke="#e4ebe3" stroke-width="1.51"/><path d="M512,495L484,563L579,600Z" fill="#e5ebe3" stroke="#e5ebe3" stroke-width="1.51"/><path d="M579,600L598,675L691,673Z" fill="#dce6dc" stroke="#dce6dc" stroke-width="1.51"/><path d="M424,483L484,563L512,495Z" fill="#e9ece5" stroke="#e9ece5" stroke-width="1.51"/><path d="M523,666L598,675L579,600Z" fill="#dbe6da" stroke="#dbe6da" stroke-width="1.51"/><path d="M597,246L521,240L596,308Z" fill="#edede6" stroke="#edede6" stroke-width="1.51"/><path d="M403,323L433,428L492,390Z" fill="#eeede7" stroke="#eeede7" stroke-width="1.51"/><path d="M509,138L521,240L597,246Z" fill="#ebeae2" stroke="#ebeae2" stroke-width="1.51"/><path d="M492,390L433,428L512,495Z" fill="#f0efec" stroke="#f0efec" stroke-width="1.51"/><path d="M403,323L492,390L513,332Z" fill="#edede7" stroke="#edede7" stroke-width="1.51"/><path d="M848,599L930,580L844,505Z" fill="#dce7dd" stroke="#dce7dd" stroke-width="1.51"/><path d="M926,479L1021,423L932,405Z" fill="#e1e9e2" stroke="#e1e9e2" stroke-width="1.51"/><path d="M914,673L930,580L848,599Z" fill="#d3e2d5" stroke="#d3e2d5" stroke-width="1.51"/><path d="M433,428L424,483L512,495Z" fill="#eeefe9" stroke="#eeefe9" stroke-width="1.51"/><path d="M439,658L523,666L484,563Z" fill="#dce5d9" stroke="#dce5d9" stroke-width="1.51"/><path d="M484,563L523,666L579,600Z" fill="#dee7dd" stroke="#dee7dd" stroke-width="1.51"/><path d="M764,652L859,684L848,599Z" fill="#d6e4d8" stroke="#d6e4d8" stroke-width="1.51"/><path d="M841,752L859,684L764,652Z" fill="#d0e0d3" stroke="#d0e0d3" stroke-width="1.51"/><path d="M771,770L764,652L691,673Z" fill="#d6e4d9" stroke="#d6e4d9" stroke-width="1.51"/><path d="M781,131L695,139L745,238Z" fill="#ecece5" stroke="#ecece5" stroke-width="1.51"/><path d="M924,327L932,252L852,301Z" fill="#e2e8df" stroke="#e2e8df" stroke-width="1.51"/><path d="M1000,247L932,252L924,327Z" fill="#dde6da" stroke="#dde6da" stroke-width="1.51"/><path d="M781,131L745,238L854,250Z" fill="#e8eae3" stroke="#e8eae3" stroke-width="1.51"/><path d="M655,216L610,125L597,246Z" fill="#ecece4" stroke="#ecece4" stroke-width="1.51"/><path d="M869,153L781,131L854,250Z" fill="#e4e8de" stroke="#e4e8de" stroke-width="1.51"/><path d="M521,240L403,323L513,332Z" fill="#ecebe4" stroke="#ecebe4" stroke-width="1.51"/><path d="M342,409L347,500L424,483Z" fill="#edede7" stroke="#edede7" stroke-width="1.51"/><path d="M930,580L1009,511L926,479Z" fill="#d9e6db" stroke="#d9e6db" stroke-width="1.51"/><path d="M932,405L1014,332L924,327Z" fill="#dfe8de" stroke="#dfe8de" stroke-width="1.51"/><path d="M1044,592L1009,511L930,580Z" fill="#d1e1d4" stroke="#d1e1d4" stroke-width="1.51"/><path d="M859,684L914,673L848,599Z" fill="#d1e1d4" stroke="#d1e1d4" stroke-width="1.51"/><path d="M1009,511L1021,423L926,479Z" fill="#dde7de" stroke="#dde7de" stroke-width="1.51"/><path d="M424,483L415,588L484,563Z" fill="#e5eae1" stroke="#e5eae1" stroke-width="1.51"/><path d="M347,500L415,588L424,483Z" fill="#e6eae1" stroke="#e6eae1" stroke-width="1.51"/><path d="M695,139L610,125L655,216Z" fill="#ecebe3" stroke="#ecebe3" stroke-width="1.51"/><path d="M521,240L403,213L403,323Z" fill="#eaeae1" stroke="#eaeae1" stroke-width="1.51"/><path d="M659,40L610,125L695,139Z" fill="#ebe7df" stroke="#ebe7df" stroke-width="1.51"/><path d="M598,675L697,764L691,673Z" fill="#d6e3d8" stroke="#d6e3d8" stroke-width="1.51"/><path d="M859,684L935,739L914,673Z" fill="#c9ddcd" stroke="#c9ddcd" stroke-width="1.51"/><path d="M523,666L582,742L598,675Z" fill="#d5e2d5" stroke="#d5e2d5" stroke-width="1.51"/><path d="M504,768L582,742L523,666Z" fill="#d1e0d1" stroke="#d1e0d1" stroke-width="1.51"/><path d="M582,742L697,764L598,675Z" fill="#d3e1d4" stroke="#d3e1d4" stroke-width="1.51"/><path d="M932,252L869,153L854,250Z" fill="#e1e7dd" stroke="#e1e7dd" stroke-width="1.51"/><path d="M1021,423L1014,332L932,405Z" fill="#dde7dd" stroke="#dde7dd" stroke-width="1.51"/><path d="M932,252L934,126L869,153Z" fill="#dee5d9" stroke="#dee5d9" stroke-width="1.51"/><path d="M697,764L771,770L691,673Z" fill="#d4e2d6" stroke="#d4e2d6" stroke-width="1.51"/><path d="M415,588L439,658L484,563Z" fill="#dee6da" stroke="#dee6da" stroke-width="1.51"/><path d="M771,770L841,752L764,652Z" fill="#cfe0d2" stroke="#cfe0d2" stroke-width="1.51"/><path d="M610,125L509,138L597,246Z" fill="#eaeae1" stroke="#eaeae1" stroke-width="1.51"/><path d="M1014,332L1000,247L924,327Z" fill="#dce6da" stroke="#dce6da" stroke-width="1.51"/><path d="M342,409L424,483L433,428Z" fill="#eeeee9" stroke="#eeeee9" stroke-width="1.51"/><path d="M415,588L317,676L439,658Z" fill="#d9e2d4" stroke="#d9e2d4" stroke-width="1.51"/><path d="M403,323L342,409L433,428Z" fill="#edece5" stroke="#edece5" stroke-width="1.51"/><path d="M318,300L342,409L403,323Z" fill="#ebebe2" stroke="#ebebe2" stroke-width="1.51"/><path d="M438,164L403,213L521,240Z" fill="#e9e9df" stroke="#e9e9df" stroke-width="1.51"/><path d="M1009,511L1102,487L1021,423Z" fill="#d7e5da" stroke="#d7e5da" stroke-width="1.51"/><path d="M1021,423L1106,419L1014,332Z" fill="#d9e4d9" stroke="#d9e4d9" stroke-width="1.51"/><path d="M1039,662L1044,592L930,580Z" fill="#cbddce" stroke="#cbddce" stroke-width="1.51"/><path d="M1039,662L930,580L914,673Z" fill="#ccdecf" stroke="#ccdecf" stroke-width="1.51"/><path d="M509,138L438,164L521,240Z" fill="#e9e9de" stroke="#e9e9de" stroke-width="1.51"/><path d="M841,752L935,739L859,684Z" fill="#c8dccc" stroke="#c8dccc" stroke-width="1.51"/><path d="M848,838L935,739L841,752Z" fill="#c3d9c8" stroke="#c3d9c8" stroke-width="1.51"/><path d="M439,658L504,768L523,666Z" fill="#d4e1d2" stroke="#d4e1d2" stroke-width="1.51"/><path d="M582,742L595,833L697,764Z" fill="#ceded0" stroke="#ceded0" stroke-width="1.51"/><path d="M697,764L752,857L771,770Z" fill="#cdded2" stroke="#cdded2" stroke-width="1.51"/><path d="M1000,247L934,126L932,252Z" fill="#dbe4d7" stroke="#dbe4d7" stroke-width="1.51"/><path d="M869,153L847,70L781,131Z" fill="#e4e5da" stroke="#e4e5da" stroke-width="1.51"/><path d="M754,40L659,40L695,139Z" fill="#ece5de" stroke="#ece5de" stroke-width="1.51"/><path d="M925,70L847,70L869,153Z" fill="#dfe1d5" stroke="#dfe1d5" stroke-width="1.51"/><path d="M610,125L596,39L509,138Z" fill="#e9e5dc" stroke="#e9e5dc" stroke-width="1.51"/><path d="M754,40L695,139L781,131Z" fill="#eae7df" stroke="#eae7df" stroke-width="1.51"/><path d="M509,138L481,39L438,164Z" fill="#e7e4d9" stroke="#e7e4d9" stroke-width="1.51"/><path d="M847,70L754,40L781,131Z" fill="#e6e3da" stroke="#e6e3da" stroke-width="1.51"/><path d="M439,658L431,757L504,768Z" fill="#d0dece" stroke="#d0dece" stroke-width="1.51"/><path d="M347,500L320,574L415,588Z" fill="#e2e8dd" stroke="#e2e8dd" stroke-width="1.51"/><path d="M252,484L320,574L347,500Z" fill="#e5e8de" stroke="#e5e8de" stroke-width="1.51"/><path d="M1044,592L1102,487L1009,511Z" fill="#d0e1d4" stroke="#d0e1d4" stroke-width="1.51"/><path d="M1014,332L1093,313L1000,247Z" fill="#d7e2d5" stroke="#d7e2d5" stroke-width="1.51"/><path d="M403,213L318,300L403,323Z" fill="#e9e9df" stroke="#e9e9df" stroke-width="1.51"/><path d="M342,409L252,484L347,500Z" fill="#ecece5" stroke="#ecece5" stroke-width="1.51"/><path d="M336,215L318,300L403,213Z" fill="#e8e8dd" stroke="#e8e8dd" stroke-width="1.51"/><path d="M1102,487L1106,419L1021,423Z" fill="#d8e5da" stroke="#d8e5da" stroke-width="1.51"/><path d="M1000,247L1035,167L934,126Z" fill="#d8e2d3" stroke="#d8e2d3" stroke-width="1.51"/><path d="M935,739L1039,662L914,673Z" fill="#c5dbc9" stroke="#c5dbc9" stroke-width="1.51"/><path d="M1044,592L1121,583L1102,487Z" fill="#cbdece" stroke="#cbdece" stroke-width="1.51"/><path d="M516,826L595,833L582,742Z" fill="#cbdcce" stroke="#cbdcce" stroke-width="1.51"/><path d="M771,770L848,838L841,752Z" fill="#c7dbcc" stroke="#c7dbcc" stroke-width="1.51"/><path d="M659,40L596,39L610,125Z" fill="#eae3db" stroke="#eae3db" stroke-width="1.51"/><path d="M661,-27L596,39L659,40Z" fill="#eadfd7" stroke="#eadfd7" stroke-width="1.51"/><path d="M1106,419L1093,313L1014,332Z" fill="#d6e3d6" stroke="#d6e3d6" stroke-width="1.51"/><path d="M504,768L516,826L582,742Z" fill="#ccddcd" stroke="#ccddcd" stroke-width="1.51"/><path d="M317,676L431,757L439,658Z" fill="#d2dfcf" stroke="#d2dfcf" stroke-width="1.51"/><path d="M595,833L691,858L697,764Z" fill="#cbddd1" stroke="#cbddd1" stroke-width="1.51"/><path d="M691,858L752,857L697,764Z" fill="#ccddd2" stroke="#ccddd2" stroke-width="1.51"/><path d="M353,127L403,213L438,164Z" fill="#e7e6db" stroke="#e7e6db" stroke-width="1.51"/><path d="M353,127L336,215L403,213Z" fill="#e6e6da" stroke="#e6e6da" stroke-width="1.51"/><path d="M752,857L848,838L771,770Z" fill="#c7dacd" stroke="#c7dacd" stroke-width="1.51"/><path d="M935,739L1021,771L1039,662Z" fill="#bfd7c3" stroke="#bfd7c3" stroke-width="1.51"/><path d="M934,126L925,70L869,153Z" fill="#dde1d5" stroke="#dde1d5" stroke-width="1.51"/><path d="M1121,236L1035,167L1000,247Z" fill="#d4e0d0" stroke="#d4e0d0" stroke-width="1.51"/><path d="M857,-32L751,-25L754,40Z" fill="#e6dcd3" stroke="#e6dcd3" stroke-width="1.51"/><path d="M1020,81L925,70L934,126Z" fill="#d9ddce" stroke="#d9ddce" stroke-width="1.51"/><path d="M426,848L516,826L504,768Z" fill="#c8d9ca" stroke="#c8d9ca" stroke-width="1.51"/><path d="M595,833L598,906L691,858Z" fill="#c7d9cd" stroke="#c7d9cd" stroke-width="1.51"/><path d="M1114,656L1121,583L1044,592Z" fill="#c4d9c8" stroke="#c4d9c8" stroke-width="1.51"/><path d="M1102,487L1185,403L1106,419Z" fill="#d3e2d6" stroke="#d3e2d6" stroke-width="1.51"/><path d="M239,415L342,409L232,341Z" fill="#ebeae1" stroke="#ebeae1" stroke-width="1.51"/><path d="M239,415L252,484L342,409Z" fill="#ecebe4" stroke="#ecebe4" stroke-width="1.51"/><path d="M320,574L317,676L415,588Z" fill="#dbe3d6" stroke="#dbe3d6" stroke-width="1.51"/><path d="M265,661L317,676L320,574Z" fill="#d8e1d2" stroke="#d8e1d2" stroke-width="1.51"/><path d="M481,907L598,906L516,826Z" fill="#c4d7ca" stroke="#c4d7ca" stroke-width="1.51"/><path d="M596,39L481,39L509,138Z" fill="#e8e2d8" stroke="#e8e2d8" stroke-width="1.51"/><path d="M232,341L342,409L318,300Z" fill="#eae9e1" stroke="#eae9e1" stroke-width="1.51"/><path d="M1039,662L1114,656L1044,592Z" fill="#c3d9c7" stroke="#c3d9c7" stroke-width="1.51"/><path d="M1003,828L1021,771L935,739Z" fill="#bad4c0" stroke="#bad4c0" stroke-width="1.51"/><path d="M754,40L751,-25L659,40Z" fill="#ebe1da" stroke="#ebe1da" stroke-width="1.51"/><path d="M596,39L496,-7L481,39Z" fill="#e8ddd4" stroke="#e8ddd4" stroke-width="1.51"/><path d="M857,-32L754,40L847,70Z" fill="#e4ddd3" stroke="#e4ddd3" stroke-width="1.51"/><path d="M425,40L353,127L438,164Z" fill="#e6e3d7" stroke="#e6e3d7" stroke-width="1.51"/><path d="M247,249L232,341L318,300Z" fill="#e8e6dc" stroke="#e8e6dc" stroke-width="1.51"/><path d="M751,-25L661,-27L659,40Z" fill="#ebded7" stroke="#ebded7" stroke-width="1.51"/><path d="M1093,313L1121,236L1000,247Z" fill="#d3e0d1" stroke="#d3e0d1" stroke-width="1.51"/><path d="M1035,167L1020,81L934,126Z" fill="#d6decf" stroke="#d6decf" stroke-width="1.51"/><path d="M1213,315L1121,236L1093,313Z" fill="#cedecd" stroke="#cedecd" stroke-width="1.51"/><path d="M1185,403L1093,313L1106,419Z" fill="#d2e1d3" stroke="#d2e1d3" stroke-width="1.51"/><path d="M1093,741L1114,656L1039,662Z" fill="#bcd5c1" stroke="#bcd5c1" stroke-width="1.51"/><path d="M247,249L318,300L336,215Z" fill="#e7e7dc" stroke="#e7e7dc" stroke-width="1.51"/><path d="M1114,139L1020,81L1035,167Z" fill="#d1dccb" stroke="#d1dccb" stroke-width="1.51"/><path d="M925,70L857,-32L847,70Z" fill="#dfdcd0" stroke="#dfdcd0" stroke-width="1.51"/><path d="M661,-27L577,-27L596,39Z" fill="#e9ddd4" stroke="#e9ddd4" stroke-width="1.51"/><path d="M426,848L504,768L431,757Z" fill="#cadaca" stroke="#cadaca" stroke-width="1.51"/><path d="M516,826L598,906L595,833Z" fill="#c6d9cc" stroke="#c6d9cc" stroke-width="1.51"/><path d="M691,858L757,921L752,857Z" fill="#c7dacf" stroke="#c7dacf" stroke-width="1.51"/><path d="M840,910L941,859L848,838Z" fill="#bcd4c5" stroke="#bcd4c5" stroke-width="1.51"/><path d="M496,-7L425,40L481,39Z" fill="#e7dcd2" stroke="#e7dcd2" stroke-width="1.51"/><path d="M481,39L425,40L438,164Z" fill="#e7e1d6" stroke="#e7e1d6" stroke-width="1.51"/><path d="M147,423L252,484L239,415Z" fill="#ece7e0" stroke="#ece7e0" stroke-width="1.51"/><path d="M164,575L241,587L252,484Z" fill="#e1e1d7" stroke="#e1e1d7" stroke-width="1.51"/><path d="M252,484L241,587L320,574Z" fill="#e1e5da" stroke="#e1e5da" stroke-width="1.51"/><path d="M265,661L319,736L317,676Z" fill="#d1ddcc" stroke="#d1ddcc" stroke-width="1.51"/><path d="M317,676L319,736L431,757Z" fill="#cfddcb" stroke="#cfddcb" stroke-width="1.51"/><path d="M1187,514L1102,487L1121,583Z" fill="#caddcd" stroke="#caddcd" stroke-width="1.51"/><path d="M1187,514L1185,403L1102,487Z" fill="#cfe0d3" stroke="#cfe0d3" stroke-width="1.51"/><path d="M848,838L941,859L935,739Z" fill="#bdd5c5" stroke="#bdd5c5" stroke-width="1.51"/><path d="M840,910L848,838L752,857Z" fill="#c1d7ca" stroke="#c1d7ca" stroke-width="1.51"/><path d="M577,-27L496,-7L596,39Z" fill="#e8dcd3" stroke="#e8dcd3" stroke-width="1.51"/><path d="M687,939L757,921L691,858Z" fill="#c5d9cf" stroke="#c5d9cf" stroke-width="1.51"/><path d="M241,587L265,661L320,574Z" fill="#dae2d3" stroke="#dae2d3" stroke-width="1.51"/><path d="M225,125L336,215L353,127Z" fill="#e5e4d7" stroke="#e5e4d7" stroke-width="1.51"/><path d="M225,125L247,249L336,215Z" fill="#e6e4d7" stroke="#e6e4d7" stroke-width="1.51"/><path d="M1184,577L1187,514L1121,583Z" fill="#c5dac9" stroke="#c5dac9" stroke-width="1.51"/><path d="M953,-21L857,-32L925,70Z" fill="#dcd8cb" stroke="#dcd8cb" stroke-width="1.51"/><path d="M751,-25L666,-95L661,-27Z" fill="#ebdad4" stroke="#ebdad4" stroke-width="1.51"/><path d="M661,-27L591,-101L577,-27Z" fill="#e9d9d0" stroke="#e9d9d0" stroke-width="1.51"/><path d="M757,921L840,910L752,857Z" fill="#c1d6cb" stroke="#c1d6cb" stroke-width="1.51"/><path d="M319,736L426,848L431,757Z" fill="#c9dac8" stroke="#c9dac8" stroke-width="1.51"/><path d="M1021,771L1093,741L1039,662Z" fill="#bad5bf" stroke="#bad5bf" stroke-width="1.51"/><path d="M941,859L1003,828L935,739Z" fill="#bad3c1" stroke="#bad3c1" stroke-width="1.51"/><path d="M1043,903L1003,828L941,859Z" fill="#b2cfbd" stroke="#b2cfbd" stroke-width="1.51"/><path d="M1110,818L1093,741L1021,771Z" fill="#b3d0b9" stroke="#b3d0b9" stroke-width="1.51"/><path d="M1114,656L1184,577L1121,583Z" fill="#c1d8c5" stroke="#c1d8c5" stroke-width="1.51"/><path d="M870,1015L917,930L840,910Z" fill="#b5cfc3" stroke="#b5cfc3" stroke-width="1.51"/><path d="M598,906L687,939L691,858Z" fill="#c5d8cd" stroke="#c5d8cd" stroke-width="1.51"/><path d="M683,991L687,939L598,906Z" fill="#c1d5cb" stroke="#c1d5cb" stroke-width="1.51"/><path d="M1184,688L1184,577L1114,656Z" fill="#bbd4c0" stroke="#bbd4c0" stroke-width="1.51"/><path d="M1016,-5L953,-21L925,70Z" fill="#d8d6c7" stroke="#d8d6c7" stroke-width="1.51"/><path d="M1121,236L1114,139L1035,167Z" fill="#d0ddcb" stroke="#d0ddcb" stroke-width="1.51"/><path d="M1190,163L1114,139L1121,236Z" fill="#ccdbc7" stroke="#ccdbc7" stroke-width="1.51"/><path d="M425,40L336,72L353,127Z" fill="#e5dfd3" stroke="#e5dfd3" stroke-width="1.51"/><path d="M343,-19L336,72L425,40Z" fill="#e5dbcf" stroke="#e5dbcf" stroke-width="1.51"/><path d="M426,848L481,907L516,826Z" fill="#c4d6c8" stroke="#c4d6c8" stroke-width="1.51"/><path d="M400,933L481,907L426,848Z" fill="#c1d4c6" stroke="#c1d4c6" stroke-width="1.51"/><path d="M1016,-5L925,70L1020,81Z" fill="#d6d8c9" stroke="#d6d8c9" stroke-width="1.51"/><path d="M1185,403L1213,315L1093,313Z" fill="#cedecf" stroke="#cedecf" stroke-width="1.51"/><path d="M1273,400L1213,315L1185,403Z" fill="#ccdccf" stroke="#ccdccf" stroke-width="1.51"/><path d="M1273,400L1185,403L1293,477Z" fill="#ccddd1" stroke="#ccddd1" stroke-width="1.51"/><path d="M577,-27L492,-108L496,-7Z" fill="#e7d7ce" stroke="#e7d7ce" stroke-width="1.51"/><path d="M496,-7L420,-42L425,40Z" fill="#e6dace" stroke="#e6dace" stroke-width="1.51"/><path d="M772,-110L666,-95L751,-25Z" fill="#ead8d2" stroke="#ead8d2" stroke-width="1.51"/><path d="M772,-110L751,-25L857,-32Z" fill="#e5d7ce" stroke="#e5d7ce" stroke-width="1.51"/><path d="M840,910L917,930L941,859Z" fill="#b7d1c2" stroke="#b7d1c2" stroke-width="1.51"/><path d="M1195,761L1184,688L1093,741Z" fill="#b1d0b7" stroke="#b1d0b7" stroke-width="1.51"/><path d="M754,1005L840,910L757,921Z" fill="#bdd4c9" stroke="#bdd4c9" stroke-width="1.51"/><path d="M1090,57L1016,-5L1020,81Z" fill="#d2d5c4" stroke="#d2d5c4" stroke-width="1.51"/><path d="M864,-125L772,-110L857,-32Z" fill="#e1d2c9" stroke="#e1d2c9" stroke-width="1.51"/><path d="M1114,139L1090,57L1020,81Z" fill="#cfd8c6" stroke="#cfd8c6" stroke-width="1.51"/><path d="M1184,73L1090,57L1114,139Z" fill="#cbd5c2" stroke="#cbd5c2" stroke-width="1.51"/><path d="M1293,477L1185,403L1187,514Z" fill="#ccded2" stroke="#ccded2" stroke-width="1.51"/><path d="M1093,741L1184,688L1114,656Z" fill="#b7d3bc" stroke="#b7d3bc" stroke-width="1.51"/><path d="M1110,818L1021,771L1003,828Z" fill="#b3d0bb" stroke="#b3d0bb" stroke-width="1.51"/><path d="M666,-95L591,-101L661,-27Z" fill="#e9d7cf" stroke="#e9d7cf" stroke-width="1.51"/><path d="M864,-125L857,-32L932,-133Z" fill="#ddcfc4" stroke="#ddcfc4" stroke-width="1.51"/><path d="M666,-95L772,-110L591,-101Z" fill="#e9d5ce" stroke="#e9d5ce" stroke-width="1.51"/><path d="M232,341L147,423L239,415Z" fill="#ebe6dd" stroke="#ebe6dd" stroke-width="1.51"/><path d="M241,587L157,669L265,661Z" fill="#d6ddcd" stroke="#d6ddcd" stroke-width="1.51"/><path d="M141,302L147,423L232,341Z" fill="#eae3d9" stroke="#eae3d9" stroke-width="1.51"/><path d="M165,251L232,341L247,249Z" fill="#e7e3d8" stroke="#e7e3d8" stroke-width="1.51"/><path d="M136,501L164,575L252,484Z" fill="#e4e1d7" stroke="#e4e1d7" stroke-width="1.51"/><path d="M265,661L243,762L319,736Z" fill="#cedac8" stroke="#cedac8" stroke-width="1.51"/><path d="M319,736L311,858L426,848Z" fill="#c6d7c6" stroke="#c6d7c6" stroke-width="1.51"/><path d="M492,-108L420,-42L496,-7Z" fill="#e6d6cb" stroke="#e6d6cb" stroke-width="1.51"/><path d="M1213,315L1208,214L1121,236Z" fill="#cbdbca" stroke="#cbdbca" stroke-width="1.51"/><path d="M687,939L754,1005L757,921Z" fill="#c0d6cd" stroke="#c0d6cd" stroke-width="1.51"/><path d="M606,1030L683,991L598,906Z" fill="#bed3c9" stroke="#bed3c9" stroke-width="1.51"/><path d="M1043,903L1110,818L1003,828Z" fill="#afcdb9" stroke="#afcdb9" stroke-width="1.51"/><path d="M170,746L243,762L265,661Z" fill="#cdd7c5" stroke="#cdd7c5" stroke-width="1.51"/><path d="M1208,214L1190,163L1121,236Z" fill="#cadac8" stroke="#cadac8" stroke-width="1.51"/><path d="M225,125L353,127L336,72Z" fill="#e4e1d3" stroke="#e4e1d3" stroke-width="1.51"/><path d="M225,125L165,251L247,249Z" fill="#e5e1d4" stroke="#e5e1d4" stroke-width="1.51"/><path d="M86,589L136,501L62,472Z" fill="#e3dcd2" stroke="#e3dcd2" stroke-width="1.51"/><path d="M147,423L136,501L252,484Z" fill="#eae4dd" stroke="#eae4dd" stroke-width="1.51"/><path d="M255,61L225,125L336,72Z" fill="#e4ddcf" stroke="#e4ddcf" stroke-width="1.51"/><path d="M683,991L754,1005L687,939Z" fill="#c0d5cc" stroke="#c0d5cc" stroke-width="1.51"/><path d="M516,1028L606,1030L598,906Z" fill="#bcd1c7" stroke="#bcd1c7" stroke-width="1.51"/><path d="M243,762L311,858L319,736Z" fill="#c7d7c4" stroke="#c7d7c4" stroke-width="1.51"/><path d="M1293,477L1187,514L1292,592Z" fill="#c3d8ca" stroke="#c3d8ca" stroke-width="1.51"/><path d="M1213,315L1302,245L1208,214Z" fill="#c7d9c9" stroke="#c7d9c9" stroke-width="1.51"/><path d="M165,251L141,302L232,341Z" fill="#e8e1d7" stroke="#e8e1d7" stroke-width="1.51"/><path d="M420,-42L343,-19L425,40Z" fill="#e5d8cd" stroke="#e5d8cd" stroke-width="1.51"/><path d="M412,-112L343,-19L420,-42Z" fill="#e4d4c8" stroke="#e4d4c8" stroke-width="1.51"/><path d="M1014,1027L1043,903L917,930Z" fill="#accaba" stroke="#accaba" stroke-width="1.51"/><path d="M917,930L1043,903L941,859Z" fill="#b2cebd" stroke="#b2cebd" stroke-width="1.51"/><path d="M311,858L400,933L426,848Z" fill="#c1d4c4" stroke="#c1d4c4" stroke-width="1.51"/><path d="M343,-19L255,61L336,72Z" fill="#e4dbcd" stroke="#e4dbcd" stroke-width="1.51"/><path d="M225,125L146,150L165,251Z" fill="#e5ded1" stroke="#e5ded1" stroke-width="1.51"/><path d="M591,-101L492,-108L577,-27Z" fill="#e7d5cc" stroke="#e7d5cc" stroke-width="1.51"/><path d="M772,-110L492,-108L591,-101Z" fill="#e8d4cc" stroke="#e8d4cc" stroke-width="1.51"/><path d="M932,-133L857,-32L953,-21Z" fill="#dbd1c5" stroke="#dbd1c5" stroke-width="1.51"/><path d="M772,-110L864,-125L492,-108Z" fill="#ead5ce" stroke="#ead5ce" stroke-width="1.51"/><path d="M243,762L256,859L311,858Z" fill="#c4d4c2" stroke="#c4d4c2" stroke-width="1.51"/><path d="M164,575L157,669L241,587Z" fill="#dadcce" stroke="#dadcce" stroke-width="1.51"/><path d="M86,589L157,669L164,575Z" fill="#d9d9cb" stroke="#d9d9cb" stroke-width="1.51"/><path d="M1200,836L1195,761L1110,818Z" fill="#aacab3" stroke="#aacab3" stroke-width="1.51"/><path d="M1110,818L1195,761L1093,741Z" fill="#afceb6" stroke="#afceb6" stroke-width="1.51"/><path d="M1292,592L1187,514L1184,577Z" fill="#c1d8c7" stroke="#c1d8c7" stroke-width="1.51"/><path d="M1292,592L1184,577L1287,654Z" fill="#b9d3c1" stroke="#b9d3c1" stroke-width="1.51"/><path d="M516,1028L598,906L481,907Z" fill="#bfd3c7" stroke="#bfd3c7" stroke-width="1.51"/><path d="M683,991L606,1030L754,1005Z" fill="#bcd2ca" stroke="#bcd2ca" stroke-width="1.51"/><path d="M754,1005L870,1015L840,910Z" fill="#b7d0c6" stroke="#b7d0c6" stroke-width="1.51"/><path d="M606,1030L870,1015L754,1005Z" fill="#bad2ca" stroke="#bad2ca" stroke-width="1.51"/><path d="M1022,-108L932,-133L953,-21Z" fill="#d7cdbf" stroke="#d7cdbf" stroke-width="1.51"/><path d="M1090,57L1087,-29L1016,-5Z" fill="#d0d1c0" stroke="#d0d1c0" stroke-width="1.51"/><path d="M1190,163L1184,73L1114,139Z" fill="#c9d7c3" stroke="#c9d7c3" stroke-width="1.51"/><path d="M1259,129L1184,73L1190,163Z" fill="#c6d4c2" stroke="#c6d4c2" stroke-width="1.51"/><path d="M1259,129L1190,163L1208,214Z" fill="#c6d7c5" stroke="#c6d7c5" stroke-width="1.51"/><path d="M1191,-40L1087,-29L1090,57Z" fill="#cbcdba" stroke="#cbcdba" stroke-width="1.51"/><path d="M1273,400L1301,336L1213,315Z" fill="#c9dacd" stroke="#c9dacd" stroke-width="1.51"/><path d="M1367,403L1301,336L1273,400Z" fill="#c7d9cd" stroke="#c7d9cd" stroke-width="1.51"/><path d="M1287,654L1184,577L1184,688Z" fill="#b8d3bf" stroke="#b8d3bf" stroke-width="1.51"/><path d="M1293,477L1367,403L1273,400Z" fill="#c8dbd0" stroke="#c8dbd0" stroke-width="1.51"/><path d="M178,821L256,859L243,762Z" fill="#c4d2bf" stroke="#c4d2bf" stroke-width="1.51"/><path d="M311,858L334,941L400,933Z" fill="#bed1c2" stroke="#bed1c2" stroke-width="1.51"/><path d="M157,669L170,746L265,661Z" fill="#d0d8c6" stroke="#d0d8c6" stroke-width="1.51"/><path d="M348,-127L412,-112L492,-108Z" fill="#e4cfc4" stroke="#e4cfc4" stroke-width="1.51"/><path d="M1022,-108L953,-21L1016,-5Z" fill="#d5cfc0" stroke="#d5cfc0" stroke-width="1.51"/><path d="M238,-42L163,72L255,61Z" fill="#e3d5c8" stroke="#e3d5c8" stroke-width="1.51"/><path d="M492,-108L412,-112L420,-42Z" fill="#e5d2c7" stroke="#e5d2c7" stroke-width="1.51"/><path d="M348,-127L492,-108L864,-125Z" fill="#e7d2c9" stroke="#e7d2c9" stroke-width="1.51"/><path d="M418,1011L481,907L400,933Z" fill="#bcd1c4" stroke="#bcd1c4" stroke-width="1.51"/><path d="M418,1011L516,1028L481,907Z" fill="#bad0c4" stroke="#bad0c4" stroke-width="1.51"/><path d="M260,932L334,941L311,858Z" fill="#bed1c1" stroke="#bed1c1" stroke-width="1.51"/><path d="M163,72L146,150L225,125Z" fill="#e4dacc" stroke="#e4dacc" stroke-width="1.51"/><path d="M63,247L75,313L141,302Z" fill="#e7dcd1" stroke="#e7dcd1" stroke-width="1.51"/><path d="M163,72L225,125L255,61Z" fill="#e3dacc" stroke="#e3dacc" stroke-width="1.51"/><path d="M1283,769L1287,654L1184,688Z" fill="#afcdb7" stroke="#afcdb7" stroke-width="1.51"/><path d="M1301,336L1302,245L1213,315Z" fill="#c7d9ca" stroke="#c7d9ca" stroke-width="1.51"/><path d="M1119,-104L1022,-108L1087,-29Z" fill="#cec9b7" stroke="#cec9b7" stroke-width="1.51"/><path d="M1087,-29L1022,-108L1016,-5Z" fill="#d1cdbd" stroke="#d1cdbd" stroke-width="1.51"/><path d="M136,501L86,589L164,575Z" fill="#e0dbd0" stroke="#e0dbd0" stroke-width="1.51"/><path d="M157,669L65,684L170,746Z" fill="#cfd3c1" stroke="#cfd3c1" stroke-width="1.51"/><path d="M62,472L136,501L147,423Z" fill="#eae1d9" stroke="#eae1d9" stroke-width="1.51"/><path d="M75,313L147,423L141,302Z" fill="#e9dfd6" stroke="#e9dfd6" stroke-width="1.51"/><path d="M1195,761L1283,769L1184,688Z" fill="#acccb5" stroke="#acccb5" stroke-width="1.51"/><path d="M1043,903L1124,911L1110,818Z" fill="#aac9b5" stroke="#aac9b5" stroke-width="1.51"/><path d="M1124,989L1124,911L1043,903Z" fill="#a5c6b3" stroke="#a5c6b3" stroke-width="1.51"/><path d="M63,247L141,302L165,251Z" fill="#e7ddd2" stroke="#e7ddd2" stroke-width="1.51"/><path d="M1191,-40L1119,-104L1087,-29Z" fill="#cac8b5" stroke="#cac8b5" stroke-width="1.51"/><path d="M1302,245L1259,129L1208,214Z" fill="#c5d7c5" stroke="#c5d7c5" stroke-width="1.51"/><path d="M60,406L62,472L147,423Z" fill="#ebe0d8" stroke="#ebe0d8" stroke-width="1.51"/><path d="M334,941L418,1011L400,933Z" fill="#bbcfc2" stroke="#bbcfc2" stroke-width="1.51"/><path d="M1124,911L1200,836L1110,818Z" fill="#a7c9b2" stroke="#a7c9b2" stroke-width="1.51"/><path d="M870,1015L950,1026L917,930Z" fill="#afccbe" stroke="#afccbe" stroke-width="1.51"/><path d="M606,1030L950,1026L870,1015Z" fill="#b5cec5" stroke="#b5cec5" stroke-width="1.51"/><path d="M75,313L60,406L147,423Z" fill="#e9ded6" stroke="#e9ded6" stroke-width="1.51"/><path d="M53,774L178,821L170,746Z" fill="#c7cebb" stroke="#c7cebb" stroke-width="1.51"/><path d="M170,746L178,821L243,762Z" fill="#c7d2bf" stroke="#c7d2bf" stroke-width="1.51"/><path d="M256,859L260,932L311,858Z" fill="#bfd1c0" stroke="#bfd1c0" stroke-width="1.51"/><path d="M334,941L312,1020L418,1011Z" fill="#b8cdc0" stroke="#b8cdc0" stroke-width="1.51"/><path d="M146,150L63,247L165,251Z" fill="#e5dccf" stroke="#e5dccf" stroke-width="1.51"/><path d="M238,-42L255,61L343,-19Z" fill="#e3d6c9" stroke="#e3d6c9" stroke-width="1.51"/><path d="M147,938L260,932L256,859Z" fill="#bdcdbc" stroke="#bdcdbc" stroke-width="1.51"/><path d="M412,-112L348,-127L343,-19Z" fill="#e3d1c5" stroke="#e3d1c5" stroke-width="1.51"/><path d="M932,-133L348,-127L864,-125Z" fill="#ead4cd" stroke="#ead4cd" stroke-width="1.51"/><path d="M-12,302L-6,427L60,406Z" fill="#e9d9d1" stroke="#e9d9d1" stroke-width="1.51"/><path d="M76,150L63,247L146,150Z" fill="#e4d9cc" stroke="#e4d9cc" stroke-width="1.51"/><path d="M249,-116L238,-42L343,-19Z" fill="#e2d1c4" stroke="#e2d1c4" stroke-width="1.51"/><path d="M1345,669L1350,584L1292,592Z" fill="#b5d0bf" stroke="#b5d0bf" stroke-width="1.51"/><path d="M1292,592L1350,584L1293,477Z" fill="#bdd5c6" stroke="#bdd5c6" stroke-width="1.51"/><path d="M1301,336L1367,325L1302,245Z" fill="#c4d7c9" stroke="#c4d7c9" stroke-width="1.51"/><path d="M1345,669L1292,592L1287,654Z" fill="#b3cfbd" stroke="#b3cfbd" stroke-width="1.51"/><path d="M1382,498L1367,403L1293,477Z" fill="#c6d9cf" stroke="#c6d9cf" stroke-width="1.51"/><path d="M1389,78L1261,67L1259,129Z" fill="#c1cebd" stroke="#c1cebd" stroke-width="1.51"/><path d="M950,1026L1014,1027L917,930Z" fill="#abc9bb" stroke="#abc9bb" stroke-width="1.51"/><path d="M1280,824L1195,761L1200,836Z" fill="#a7c8b1" stroke="#a7c8b1" stroke-width="1.51"/><path d="M606,1030L1014,1027L950,1026Z" fill="#b0ccc1" stroke="#b0ccc1" stroke-width="1.51"/><path d="M1280,824L1283,769L1195,761Z" fill="#a7c8b1" stroke="#a7c8b1" stroke-width="1.51"/><path d="M1187,933L1200,836L1124,911Z" fill="#a3c6b0" stroke="#a3c6b0" stroke-width="1.51"/><path d="M1259,129L1261,67L1184,73Z" fill="#c5d1be" stroke="#c5d1be" stroke-width="1.51"/><path d="M1354,168L1259,129L1302,245Z" fill="#c2d4c3" stroke="#c2d4c3" stroke-width="1.51"/><path d="M1367,403L1367,325L1301,336Z" fill="#c4d7cb" stroke="#c4d7cb" stroke-width="1.51"/><path d="M265,1033L312,1020L260,932Z" fill="#b6cbbd" stroke="#b6cbbd" stroke-width="1.51"/><path d="M86,589L65,684L157,669Z" fill="#d5d5c5" stroke="#d5d5c5" stroke-width="1.51"/><path d="M4,663L65,684L86,589Z" fill="#d5d2c2" stroke="#d5d2c2" stroke-width="1.51"/><path d="M-23,562L86,589L62,472Z" fill="#e1d7cd" stroke="#e1d7cd" stroke-width="1.51"/><path d="M1191,-40L1090,57L1184,73Z" fill="#c9cfbb" stroke="#c9cfbb" stroke-width="1.51"/><path d="M1022,-108L1119,-104L932,-133Z" fill="#d2c8b9" stroke="#d2c8b9" stroke-width="1.51"/><path d="M1261,67L1191,-40L1184,73Z" fill="#c6cdba" stroke="#c6cdba" stroke-width="1.51"/><path d="M1367,403L1456,317L1367,325Z" fill="#c1d5ca" stroke="#c1d5ca" stroke-width="1.51"/><path d="M1350,584L1382,498L1293,477Z" fill="#bfd5c9" stroke="#bfd5c9" stroke-width="1.51"/><path d="M1433,478L1382,498L1450,600Z" fill="#bad2c6" stroke="#bad2c6" stroke-width="1.51"/><path d="M1283,769L1345,669L1287,654Z" fill="#adcbb7" stroke="#adcbb7" stroke-width="1.51"/><path d="M163,72L76,150L146,150Z" fill="#e3d8ca" stroke="#e3d8ca" stroke-width="1.51"/><path d="M81,44L76,150L163,72Z" fill="#e3d4c6" stroke="#e3d4c6" stroke-width="1.51"/><path d="M1367,325L1367,247L1302,245Z" fill="#c2d5c7" stroke="#c2d5c7" stroke-width="1.51"/><path d="M1456,317L1367,247L1367,325Z" fill="#bfd3c7" stroke="#bfd3c7" stroke-width="1.51"/><path d="M1283,769L1382,751L1345,669Z" fill="#a7c8b3" stroke="#a7c8b3" stroke-width="1.51"/><path d="M1124,989L1187,933L1124,911Z" fill="#a0c4af" stroke="#a0c4af" stroke-width="1.51"/><path d="M1014,1027L1124,989L1043,903Z" fill="#a5c6b4" stroke="#a5c6b4" stroke-width="1.51"/><path d="M1299,904L1280,824L1200,836Z" fill="#a1c4af" stroke="#a1c4af" stroke-width="1.51"/><path d="M260,932L312,1020L334,941Z" fill="#b9cebf" stroke="#b9cebf" stroke-width="1.51"/><path d="M418,1011L312,1020L516,1028Z" fill="#b7cdc1" stroke="#b7cdc1" stroke-width="1.51"/><path d="M265,1033L260,932L177,999Z" fill="#b6c9ba" stroke="#b6c9ba" stroke-width="1.51"/><path d="M60,406L-6,427L62,472Z" fill="#eadcd5" stroke="#eadcd5" stroke-width="1.51"/><path d="M-12,302L60,406L75,313Z" fill="#e8dad1" stroke="#e8dad1" stroke-width="1.51"/><path d="M-12,302L75,313L63,247Z" fill="#e6d9ce" stroke="#e6d9ce" stroke-width="1.51"/><path d="M1367,247L1354,168L1302,245Z" fill="#c1d3c4" stroke="#c1d3c4" stroke-width="1.51"/><path d="M1261,67L1273,-26L1191,-40Z" fill="#c4c9b7" stroke="#c4c9b7" stroke-width="1.51"/><path d="M238,-42L175,-47L163,72Z" fill="#e2d0c3" stroke="#e2d0c3" stroke-width="1.51"/><path d="M348,-127L249,-116L343,-19Z" fill="#e2d0c3" stroke="#e2d0c3" stroke-width="1.51"/><path d="M249,-116L175,-47L238,-42Z" fill="#e1cdbf" stroke="#e1cdbf" stroke-width="1.51"/><path d="M-6,427L-23,477L62,472Z" fill="#eadbd4" stroke="#eadbd4" stroke-width="1.51"/><path d="M-94,493L-23,477L-6,427Z" fill="#e9d7d0" stroke="#e9d7d0" stroke-width="1.51"/><path d="M-18,229L-12,302L63,247Z" fill="#e5d6cb" stroke="#e5d6cb" stroke-width="1.51"/><path d="M-18,229L63,247L76,150Z" fill="#e4d6ca" stroke="#e4d6ca" stroke-width="1.51"/><path d="M65,684L53,774L170,746Z" fill="#cbcebc" stroke="#cbcebc" stroke-width="1.51"/><path d="M7,751L53,774L65,684Z" fill="#cacbb8" stroke="#cacbb8" stroke-width="1.51"/><path d="M-23,562L4,663L86,589Z" fill="#d9d2c5" stroke="#d9d2c5" stroke-width="1.51"/><path d="M175,-47L81,44L163,72Z" fill="#e2d0c2" stroke="#e2d0c2" stroke-width="1.51"/><path d="M-23,477L-23,562L62,472Z" fill="#e5d7ce" stroke="#e5d7ce" stroke-width="1.51"/><path d="M1382,498L1433,478L1367,403Z" fill="#c3d7ce" stroke="#c3d7ce" stroke-width="1.51"/><path d="M1367,247L1469,163L1354,168Z" fill="#bdd1c2" stroke="#bdd1c2" stroke-width="1.51"/><path d="M1450,600L1382,498L1350,584Z" fill="#b7d1c3" stroke="#b7d1c3" stroke-width="1.51"/><path d="M1450,600L1350,584L1345,669Z" fill="#b1cdbd" stroke="#b1cdbd" stroke-width="1.51"/><path d="M1362,-22L1273,-26L1261,67Z" fill="#c0c7b6" stroke="#c0c7b6" stroke-width="1.51"/><path d="M1191,-40L1204,-112L1119,-104Z" fill="#c7c4b1" stroke="#c7c4b1" stroke-width="1.51"/><path d="M312,1020L265,1033L516,1028Z" fill="#b5cbbf" stroke="#b5cbbf" stroke-width="1.51"/><path d="M516,1028L265,1033L606,1030Z" fill="#b7cdc2" stroke="#b7cdc2" stroke-width="1.51"/><path d="M606,1030L1286,1032L1014,1027Z" fill="#a8c7b9" stroke="#a8c7b9" stroke-width="1.51"/><path d="M147,938L256,859L178,821Z" fill="#c0cdbc" stroke="#c0cdbc" stroke-width="1.51"/><path d="M1259,-90L1204,-112L1191,-40Z" fill="#c5c3b0" stroke="#c5c3b0" stroke-width="1.51"/><path d="M1119,-104L1204,-112L932,-133Z" fill="#cdc5b4" stroke="#cdc5b4" stroke-width="1.51"/><path d="M53,774L86,858L178,821Z" fill="#c4cbb8" stroke="#c4cbb8" stroke-width="1.51"/><path d="M64,907L86,858L-13,828Z" fill="#c0c4b3" stroke="#c0c4b3" stroke-width="1.51"/><path d="M86,858L147,938L178,821Z" fill="#c0c9b8" stroke="#c0c9b8" stroke-width="1.51"/><path d="M-12,302L-87,319L-6,427Z" fill="#e8d5cd" stroke="#e8d5cd" stroke-width="1.51"/><path d="M-31,141L-18,229L76,150Z" fill="#e3d3c7" stroke="#e3d3c7" stroke-width="1.51"/><path d="M1014,1027L1181,1013L1124,989Z" fill="#9ec2b0" stroke="#9ec2b0" stroke-width="1.51"/><path d="M1124,989L1181,1013L1187,933Z" fill="#9dc1ad" stroke="#9dc1ad" stroke-width="1.51"/><path d="M1187,933L1299,904L1200,836Z" fill="#a0c3ae" stroke="#a0c3ae" stroke-width="1.51"/><path d="M1353,843L1283,769L1280,824Z" fill="#a2c4af" stroke="#a2c4af" stroke-width="1.51"/><path d="M1353,843L1382,751L1283,769Z" fill="#a2c5af" stroke="#a2c5af" stroke-width="1.51"/><path d="M1286,1032L1299,904L1187,933Z" fill="#99bfab" stroke="#99bfab" stroke-width="1.51"/><path d="M-13,828L7,751L-96,769Z" fill="#c6c4b1" stroke="#c6c4b1" stroke-width="1.51"/><path d="M4,663L7,751L65,684Z" fill="#cecdbb" stroke="#cecdbb" stroke-width="1.51"/><path d="M1362,-22L1259,-90L1273,-26Z" fill="#c1c3b1" stroke="#c1c3b1" stroke-width="1.51"/><path d="M1476,404L1456,317L1367,403Z" fill="#c0d4ca" stroke="#c0d4ca" stroke-width="1.51"/><path d="M1461,680L1450,600L1345,669Z" fill="#accab9" stroke="#accab9" stroke-width="1.51"/><path d="M1433,478L1476,404L1367,403Z" fill="#c2d6cd" stroke="#c2d6cd" stroke-width="1.51"/><path d="M1273,-26L1259,-90L1191,-40Z" fill="#c4c4b2" stroke="#c4c4b2" stroke-width="1.51"/><path d="M1389,78L1259,129L1354,168Z" fill="#bfd0bf" stroke="#bfd0bf" stroke-width="1.51"/><path d="M147,938L177,999L260,932Z" fill="#b9c8b9" stroke="#b9c8b9" stroke-width="1.51"/><path d="M71,1004L177,999L147,938Z" fill="#b7c3b4" stroke="#b7c3b4" stroke-width="1.51"/><path d="M64,907L147,938L86,858Z" fill="#bdc6b5" stroke="#bdc6b5" stroke-width="1.51"/><path d="M1299,904L1353,843L1280,824Z" fill="#9ec2ae" stroke="#9ec2ae" stroke-width="1.51"/><path d="M1382,751L1461,680L1345,669Z" fill="#a7c8b5" stroke="#a7c8b5" stroke-width="1.51"/><path d="M1469,163L1389,78L1354,168Z" fill="#bccfbe" stroke="#bccfbe" stroke-width="1.51"/><path d="M1532,489L1476,404L1433,478Z" fill="#bed4cc" stroke="#bed4cc" stroke-width="1.51"/><path d="M-10,82L-31,141L76,150Z" fill="#e2d1c3" stroke="#e2d1c3" stroke-width="1.51"/><path d="M-18,229L-87,319L-12,302Z" fill="#e6d4c9" stroke="#e6d4c9" stroke-width="1.51"/><path d="M-23,477L-94,493L-23,562Z" fill="#e3d4cb" stroke="#e3d4cb" stroke-width="1.51"/><path d="M-10,82L76,150L81,44Z" fill="#e2d0c2" stroke="#e2d0c2" stroke-width="1.51"/><path d="M-10,82L81,44L-6,-8Z" fill="#e1cabc" stroke="#e1cabc" stroke-width="1.51"/><path d="M1456,317L1469,252L1367,247Z" fill="#bdd2c5" stroke="#bdd2c5" stroke-width="1.51"/><path d="M1534,335L1469,252L1456,317Z" fill="#bbd0c5" stroke="#bbd0c5" stroke-width="1.51"/><path d="M-13,828L86,858L53,774Z" fill="#c3c7b5" stroke="#c3c7b5" stroke-width="1.51"/><path d="M58,-47L81,44L175,-47Z" fill="#e1cabd" stroke="#e1cabd" stroke-width="1.51"/><path d="M-93,222L-87,319L-18,229Z" fill="#e5d1c6" stroke="#e5d1c6" stroke-width="1.51"/><path d="M-23,562L-120,600L4,663Z" fill="#d8cec0" stroke="#d8cec0" stroke-width="1.51"/><path d="M249,-116L139,-128L175,-47Z" fill="#e1c8bb" stroke="#e1c8bb" stroke-width="1.51"/><path d="M348,-127L139,-128L249,-116Z" fill="#e1c9bc" stroke="#e1c9bc" stroke-width="1.51"/><path d="M932,-133L139,-128L348,-127Z" fill="#e5cfc5" stroke="#e5cfc5" stroke-width="1.51"/><path d="M-114,385L-94,493L-6,427Z" fill="#ead6ce" stroke="#ead6ce" stroke-width="1.51"/><path d="M7,751L-13,828L53,774Z" fill="#c6c7b4" stroke="#c6c7b4" stroke-width="1.51"/><path d="M1450,600L1532,489L1433,478Z" fill="#b7d0c5" stroke="#b7d0c5" stroke-width="1.51"/><path d="M1469,733L1461,680L1382,751Z" fill="#a3c5b1" stroke="#a3c5b1" stroke-width="1.51"/><path d="M94,-100L58,-47L175,-47Z" fill="#e1c6b9" stroke="#e1c6b9" stroke-width="1.51"/><path d="M1450,46L1362,-22L1389,78Z" fill="#bbc6b6" stroke="#bbc6b6" stroke-width="1.51"/><path d="M1389,78L1362,-22L1261,67Z" fill="#bfc9b8" stroke="#bfc9b8" stroke-width="1.51"/><path d="M139,-128L94,-100L175,-47Z" fill="#e0c5b8" stroke="#e0c5b8" stroke-width="1.51"/><path d="M-102,683L7,751L4,663Z" fill="#cec9b8" stroke="#cec9b8" stroke-width="1.51"/><path d="M-87,319L-114,385L-6,427Z" fill="#e8d4cc" stroke="#e8d4cc" stroke-width="1.51"/><path d="M-93,222L-114,385L-87,319Z" fill="#e6d1c7" stroke="#e6d1c7" stroke-width="1.51"/><path d="M1469,252L1469,163L1367,247Z" fill="#bcd0c2" stroke="#bcd0c2" stroke-width="1.51"/><path d="M1540,251L1469,163L1469,252Z" fill="#b8cec1" stroke="#b8cec1" stroke-width="1.51"/><path d="M-89,147L-31,141L-115,69Z" fill="#e1cbbe" stroke="#e1cbbe" stroke-width="1.51"/><path d="M-89,147L-93,222L-31,141Z" fill="#e2cec1" stroke="#e2cec1" stroke-width="1.51"/><path d="M-31,141L-93,222L-18,229Z" fill="#e3d1c4" stroke="#e3d1c4" stroke-width="1.51"/><path d="M1547,584L1532,489L1450,600Z" fill="#b1cdc1" stroke="#b1cdc1" stroke-width="1.51"/><path d="M1467,836L1469,733L1382,751Z" fill="#9ec2ae" stroke="#9ec2ae" stroke-width="1.51"/><path d="M1467,836L1382,751L1353,843Z" fill="#9dc1ad" stroke="#9dc1ad" stroke-width="1.51"/><path d="M1476,404L1534,335L1456,317Z" fill="#bcd1c7" stroke="#bcd1c7" stroke-width="1.51"/><path d="M1547,584L1450,600L1543,644Z" fill="#abc9bb" stroke="#abc9bb" stroke-width="1.51"/><path d="M58,-47L-6,-8L81,44Z" fill="#e1c7ba" stroke="#e1c7ba" stroke-width="1.51"/><path d="M0,-128L-6,-8L58,-47Z" fill="#e0c1b4" stroke="#e0c1b4" stroke-width="1.51"/><path d="M1299,904L1375,939L1353,843Z" fill="#99beac" stroke="#99beac" stroke-width="1.51"/><path d="M1181,1013L1286,1032L1187,933Z" fill="#98beab" stroke="#98beab" stroke-width="1.51"/><path d="M1014,1027L1286,1032L1181,1013Z" fill="#99beac" stroke="#99beac" stroke-width="1.51"/><path d="M265,1033L1286,1032L606,1030Z" fill="#bbd2cb" stroke="#bbd2cb" stroke-width="1.51"/><path d="M-94,493L-120,600L-23,562Z" fill="#dfcfc5" stroke="#dfcfc5" stroke-width="1.51"/><path d="M-114,385L-120,600L-94,493Z" fill="#e5d1c9" stroke="#e5d1c9" stroke-width="1.51"/><path d="M-120,600L-102,683L4,663Z" fill="#d4cabb" stroke="#d4cabb" stroke-width="1.51"/><path d="M1550,388L1534,335L1476,404Z" fill="#bbd1c8" stroke="#bbd1c8" stroke-width="1.51"/><path d="M-115,69L-31,141L-10,82Z" fill="#e1cabd" stroke="#e1cabd" stroke-width="1.51"/><path d="M-93,222L-115,69L-114,385Z" fill="#e3cdc2" stroke="#e3cdc2" stroke-width="1.51"/><path d="M1354,990L1375,939L1299,904Z" fill="#95bcaa" stroke="#95bcaa" stroke-width="1.51"/><path d="M1469,163L1450,46L1389,78Z" fill="#b9caba" stroke="#b9caba" stroke-width="1.51"/><path d="M1472,-5L1450,46L1521,65Z" fill="#b7c3b4" stroke="#b7c3b4" stroke-width="1.51"/><path d="M-19,934L64,907L-13,828Z" fill="#bec1b0" stroke="#bec1b0" stroke-width="1.51"/><path d="M-19,934L71,1004L64,907Z" fill="#b9bfb0" stroke="#b9bfb0" stroke-width="1.51"/><path d="M64,907L71,1004L147,938Z" fill="#b9c2b3" stroke="#b9c2b3" stroke-width="1.51"/><path d="M177,999L71,1004L265,1033Z" fill="#b5c4b6" stroke="#b5c4b6" stroke-width="1.51"/><path d="M1534,335L1540,251L1469,252Z" fill="#b8cec3" stroke="#b8cec3" stroke-width="1.51"/><path d="M1532,489L1550,388L1476,404Z" fill="#bcd3cb" stroke="#bcd3cb" stroke-width="1.51"/><path d="M1286,1032L1354,990L1299,904Z" fill="#94bcaa" stroke="#94bcaa" stroke-width="1.51"/><path d="M1543,644L1461,680L1532,755Z" fill="#a2c4b2" stroke="#a2c4b2" stroke-width="1.51"/><path d="M1543,644L1450,600L1461,680Z" fill="#a9c8b9" stroke="#a9c8b9" stroke-width="1.51"/><path d="M1532,489L1547,584L1550,388Z" fill="#b7d0c7" stroke="#b7d0c7" stroke-width="1.51"/><path d="M1467,836L1353,843L1457,919Z" fill="#97bdaa" stroke="#97bdaa" stroke-width="1.51"/><path d="M1550,388L1540,251L1534,335Z" fill="#b8cfc5" stroke="#b8cfc5" stroke-width="1.51"/><path d="M-102,683L-96,769L7,751Z" fill="#cac5b2" stroke="#cac5b2" stroke-width="1.51"/><path d="M-120,600L-96,769L-102,683Z" fill="#d0c6b5" stroke="#d0c6b5" stroke-width="1.51"/><path d="M1457,919L1353,843L1375,939Z" fill="#96bcab" stroke="#96bcab" stroke-width="1.51"/><path d="M1532,755L1461,680L1469,733Z" fill="#a0c3b0" stroke="#a0c3b0" stroke-width="1.51"/><path d="M1362,-22L1371,-117L1259,-90Z" fill="#bfbfae" stroke="#bfbfae" stroke-width="1.51"/><path d="M1259,-90L1371,-117L1204,-112Z" fill="#c1bead" stroke="#c1bead" stroke-width="1.51"/><path d="M1204,-112L1371,-117L932,-133Z" fill="#c7c1ae" stroke="#c7c1ae" stroke-width="1.51"/><path d="M1440,-114L1371,-117L1362,-22Z" fill="#bbbcac" stroke="#bbbcac" stroke-width="1.51"/><path d="M-88,822L-19,934L-13,828Z" fill="#c0bfae" stroke="#c0bfae" stroke-width="1.51"/><path d="M-96,769L-88,822L-13,828Z" fill="#c4c1ae" stroke="#c4c1ae" stroke-width="1.51"/><path d="M1521,65L1450,46L1469,163Z" fill="#b7c8b9" stroke="#b7c8b9" stroke-width="1.51"/><path d="M1450,46L1472,-5L1362,-22Z" fill="#bac2b3" stroke="#bac2b3" stroke-width="1.51"/><path d="M1467,836L1532,755L1469,733Z" fill="#9ac0ac" stroke="#9ac0ac" stroke-width="1.51"/><path d="M1530,858L1532,755L1467,836Z" fill="#96bdaa" stroke="#96bdaa" stroke-width="1.51"/><path d="M-85,-17L-115,69L-10,82Z" fill="#e0c5b8" stroke="#e0c5b8" stroke-width="1.51"/><path d="M-89,147L-115,69L-93,222Z" fill="#e1ccbf" stroke="#e1ccbf" stroke-width="1.51"/><path d="M-114,385L-115,69L-120,600Z" fill="#e7d0c8" stroke="#e7d0c8" stroke-width="1.51"/><path d="M-85,-17L-10,82L-6,-8Z" fill="#e0c4b8" stroke="#e0c4b8" stroke-width="1.51"/><path d="M1466,1010L1457,919L1375,939Z" fill="#8fb8a8" stroke="#8fb8a8" stroke-width="1.51"/><path d="M94,-100L0,-128L58,-47Z" fill="#dfc0b3" stroke="#dfc0b3" stroke-width="1.51"/><path d="M139,-128L0,-128L94,-100Z" fill="#dfbfb3" stroke="#dfbfb3" stroke-width="1.51"/><path d="M932,-133L0,-128L139,-128Z" fill="#e3cdc1" stroke="#e3cdc1" stroke-width="1.51"/><path d="M1556,125L1521,65L1469,163Z" fill="#b5c8ba" stroke="#b5c8ba" stroke-width="1.51"/><path d="M-80,-93L-85,-17L-6,-8Z" fill="#dfbeb1" stroke="#dfbeb1" stroke-width="1.51"/><path d="M1540,251L1556,125L1469,163Z" fill="#b6ccbe" stroke="#b6ccbe" stroke-width="1.51"/><path d="M1550,388L1556,125L1540,251Z" fill="#b6cdc2" stroke="#b6cdc2" stroke-width="1.51"/><path d="M1547,584L1556,125L1550,388Z" fill="#b9cfc7" stroke="#b9cfc7" stroke-width="1.51"/><path d="M-107,936L-24,996L-19,934Z" fill="#b8baab" stroke="#b8baab" stroke-width="1.51"/><path d="M-19,934L-24,996L71,1004Z" fill="#b7bcad" stroke="#b7bcad" stroke-width="1.51"/><path d="M71,1004L-106,993L265,1033Z" fill="#b4beb0" stroke="#b4beb0" stroke-width="1.51"/><path d="M1472,-5L1440,-114L1362,-22Z" fill="#babeae" stroke="#babeae" stroke-width="1.51"/><path d="M1536,-22L1440,-114L1472,-5Z" fill="#b7bcad" stroke="#b7bcad" stroke-width="1.51"/><path d="M1536,-22L1472,-5L1521,65Z" fill="#b5c0b1" stroke="#b5c0b1" stroke-width="1.51"/><path d="M1457,919L1530,858L1467,836Z" fill="#93bba9" stroke="#93bba9" stroke-width="1.51"/><path d="M1532,755L1530,858L1543,644Z" fill="#9abfac" stroke="#9abfac" stroke-width="1.51"/><path d="M1543,644L1531,1032L1547,584Z" fill="#99bfac" stroke="#99bfac" stroke-width="1.51"/><path d="M0,-128L-80,-93L-6,-8Z" fill="#dfbdb0" stroke="#dfbdb0" stroke-width="1.51"/><path d="M-85,-17L-80,-93L-115,69Z" fill="#dfbeb1" stroke="#dfbeb1" stroke-width="1.51"/><path d="M-88,822L-107,936L-19,934Z" fill="#bdbcab" stroke="#bdbcab" stroke-width="1.51"/><path d="M-96,769L-107,936L-88,822Z" fill="#c1bdab" stroke="#c1bdab" stroke-width="1.51"/><path d="M-120,600L-107,936L-96,769Z" fill="#c6c0ad" stroke="#c6c0ad" stroke-width="1.51"/><path d="M1556,125L1536,-22L1521,65Z" fill="#b3c2b4" stroke="#b3c2b4" stroke-width="1.51"/><path d="M1457,919L1530,924L1530,858Z" fill="#8fb8a8" stroke="#8fb8a8" stroke-width="1.51"/><path d="M1354,990L1466,1010L1375,939Z" fill="#8fb8a8" stroke="#8fb8a8" stroke-width="1.51"/><path d="M1286,1032L1466,1010L1354,990Z" fill="#8eb7a7" stroke="#8eb7a7" stroke-width="1.51"/><path d="M1466,1010L1530,924L1457,919Z" fill="#8cb6a7" stroke="#8cb6a7" stroke-width="1.51"/><path d="M1530,858L1530,924L1543,644Z" fill="#95bcaa" stroke="#95bcaa" stroke-width="1.51"/><path d="M-107,936L-106,993L-24,996Z" fill="#b7b7a8" stroke="#b7b7a8" stroke-width="1.51"/><path d="M-24,996L-106,993L71,1004Z" fill="#b5b9ab" stroke="#b5b9ab" stroke-width="1.51"/><path d="M-120,600L-106,993L-107,936Z" fill="#c1bcab" stroke="#c1bcab" stroke-width="1.51"/><path d="M1466,1010L1531,1032L1530,924Z" fill="#88b3a4" stroke="#88b3a4" stroke-width="1.51"/><path d="M1530,924L1531,1032L1543,644Z" fill="#91b9a8" stroke="#91b9a8" stroke-width="1.51"/><path d="M1286,1032L1531,1032L1466,1010Z" fill="#8ab4a5" stroke="#8ab4a5" stroke-width="1.51"/><path d="M265,1033L1531,1032L1286,1032Z" fill="#a3c4b4" stroke="#a3c4b4" stroke-width="1.51"/><path d="M1536,-22L1554,-129L1440,-114Z" fill="#b5b8a9" stroke="#b5b8a9" stroke-width="1.51"/><path d="M1440,-114L1554,-129L1371,-117Z" fill="#b7b7a8" stroke="#b7b7a8" stroke-width="1.51"/><path d="M1371,-117L1554,-129L932,-133Z" fill="#c1bdab" stroke="#c1bdab" stroke-width="1.51"/><path d="M1556,125L1554,-129L1536,-22Z" fill="#b3bdaf" stroke="#b3bdaf" stroke-width="1.51"/></svg> \ No newline at end of file
diff --git a/src/client/assets/welcome-bg.svg b/src/client/assets/welcome-bg.svg
deleted file mode 100644
index ba8cd8dc0a..0000000000
--- a/src/client/assets/welcome-bg.svg
+++ /dev/null
@@ -1,579 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="1920"
- height="1080"
- viewBox="0 0 507.99999 285.75001"
- version="1.1"
- id="svg8"
- inkscape:version="0.92.1 r15371"
- sodipodi:docname="welcome-bg.svg">
- <defs
- id="defs2">
- <pattern
- inkscape:collect="always"
- xlink:href="#Checkerboard"
- id="pattern7194"
- patternTransform="scale(1.3152942)" />
- <linearGradient
- id="linearGradient7169"
- inkscape:collect="always">
- <stop
- id="stop7165"
- offset="0"
- style="stop-color:#eaeaea;stop-opacity:1" />
- <stop
- id="stop7167"
- offset="1"
- style="stop-color:#000000;stop-opacity:1" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient7044">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop7040" />
- <stop
- style="stop-color:#ffffff;stop-opacity:1"
- offset="1"
- id="stop7042" />
- </linearGradient>
- <pattern
- inkscape:collect="always"
- xlink:href="#Checkerboard"
- id="pattern7010"
- patternTransform="matrix(1.673813,0,0,1.673813,-177.6001,-146.38611)" />
- <pattern
- inkscape:stockid="Checkerboard"
- id="Checkerboard"
- patternTransform="translate(0,0) scale(10,10)"
- height="2"
- width="2"
- patternUnits="userSpaceOnUse"
- inkscape:collect="always"
- inkscape:isstock="true">
- <rect
- id="rect6201"
- height="1"
- width="1"
- y="0"
- x="0"
- style="fill:black;stroke:none" />
- <rect
- id="rect6203"
- height="1"
- width="1"
- y="1"
- x="1"
- style="fill:black;stroke:none" />
- </pattern>
- <linearGradient
- id="linearGradient5406"
- osb:paint="solid">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop5404" />
- </linearGradient>
- <pattern
- patternUnits="userSpaceOnUse"
- width="15.999999"
- height="16.000025"
- patternTransform="matrix(0.26458333,0,0,0.26458333,-16.933332,263.1333)"
- id="pattern6465">
- <path
- d="m 8.0000542,8.0000126 h 7.9998878 c 3e-5,0 5.7e-5,3.78e-5 5.7e-5,3.78e-5 V 15.99995 c 0,3.7e-5 -2.7e-5,7.5e-5 -5.7e-5,7.5e-5 H 8.0000542 c -3.03e-5,0 -5.67e-5,-3.8e-5 -5.67e-5,-7.5e-5 V 8.0000504 c 0,0 2.64e-5,-3.78e-5 5.67e-5,-3.78e-5 z M 5.6692913e-5,0 H 7.9999408 c 3.02e-5,0 5.67e-5,3.7795275e-5 5.67e-5,7.5590551e-5 V 7.999937 c 0,3.78e-5 -2.65e-5,7.56e-5 -5.67e-5,7.56e-5 H 5.6692913e-5 C 2.2677165e-5,8.0000126 0,7.9999748 0,7.999937 V 7.5590551e-5 C 0,3.7795276e-5 2.2677165e-5,0 5.6692913e-5,0 Z"
- style="opacity:1;fill:#db1545;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:15.99999905;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect6445-2"
- inkscape:connector-curvature="0" />
- </pattern>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient7044"
- id="linearGradient6476"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.223659,0,0,2.5556636,-579.27357,808.39)"
- x1="86.490868"
- y1="-216.62756"
- x2="176.77992"
- y2="-216.62756" />
- <mask
- maskUnits="userSpaceOnUse"
- id="mask6472">
- <rect
- transform="rotate(-90)"
- y="-0.91986513"
- x="-300.45657"
- height="511.36566"
- width="291.06116"
- id="rect6474"
- style="opacity:1;fill:url(#linearGradient6476);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.92238116;stroke-miterlimit:4;stroke-dasharray:none" />
- </mask>
- <pattern
- patternUnits="userSpaceOnUse"
- width="2340.7208"
- height="2340.7236"
- patternTransform="matrix(0.26458333,0,0,0.26458333,-63.499801,-58.601683)"
- id="pattern7142">
- <path
- d="m 1170.3684,1170.3628 h 1170.3448 c 0,0 0.01,0 0.01,0 v 1170.3457 c 0,0 0,0.011 -0.01,0.011 H 1170.3684 c 0,0 -0.01,0 -0.01,-0.011 v -1170.344 c 0,0 0,0 0.01,0 z M 0.00869291,1.1338583e-5 H 1170.352 c 0,0 0.01,0.0052913414 0.01,0.01096063142 V 1170.3511 c 0,0 0,0.011 -0.01,0.011 H 0.00869291 C 0.00340157,1170.3625 0,1170.3549 0,1170.3511 V 0.01096063 C 0,0.00566929 0.00312945,0 0.00869291,0 Z"
- style="opacity:1;fill:#763971;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2340.72119141;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path7135"
- inkscape:connector-curvature="0" />
- </pattern>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient7169"
- id="linearGradient7157"
- x1="-3.631536"
- y1="155.11069"
- x2="511.52777"
- y2="155.11069"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(2.184742,0,0,6.5696504,-17.948376,-1979.8074)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient7169"
- id="linearGradient7200"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0.57804632,0,0,1.73822,6.5011419,-523.82404)"
- x1="-3.631536"
- y1="155.11069"
- x2="511.52777"
- y2="155.11069" />
- <mask
- maskUnits="userSpaceOnUse"
- id="mask7196">
- <rect
- transform="rotate(90)"
- y="-512.56537"
- x="4.4019437"
- height="516.7157"
- width="297.78595"
- id="rect7198"
- style="opacity:1;fill:url(#linearGradient7200);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.1217103;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- </mask>
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#1e1d65"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.84705882"
- inkscape:pageshadow="2"
- inkscape:zoom="0.79170474"
- inkscape:cx="1093.7227"
- inkscape:cy="695.27372"
- inkscape:document-units="mm"
- inkscape:current-layer="layer5"
- showgrid="true"
- units="px"
- inkscape:pagecheckerboard="false"
- inkscape:window-width="1920"
- inkscape:window-height="1017"
- inkscape:window-x="-8"
- inkscape:window-y="1072"
- inkscape:window-maximized="1"
- objecttolerance="1"
- guidetolerance="10000"
- gridtolerance="10000"
- inkscape:snap-bbox="true"
- inkscape:bbox-paths="true"
- inkscape:bbox-nodes="true"
- inkscape:snap-bbox-edge-midpoints="true"
- inkscape:snap-bbox-midpoints="true"
- showguides="false"
- inkscape:lockguides="true">
- <inkscape:grid
- type="xygrid"
- id="grid6443"
- spacingx="2.1166667"
- spacingy="2.1166667"
- empspacing="4"
- color="#3f3fff"
- opacity="0.1254902"
- enabled="false" />
- <sodipodi:guide
- position="-69.219003,3.872392"
- orientation="1,0"
- id="guide6508"
- inkscape:locked="true" />
- </sodipodi:namedview>
- <metadata
- id="metadata5">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="レイヤー 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-11.249983)"
- style="display:inline"
- sodipodi:insensitive="true">
- <rect
- style="display:inline;opacity:0.2;fill:url(#pattern7194);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.11666656;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect7178"
- width="568.07599"
- height="367.82269"
- x="-37.871731"
- y="-52.665051"
- mask="url(#mask7196)" />
- </g>
- <g
- inkscape:groupmode="layer"
- id="layer2"
- inkscape:label="レイヤー 2"
- style="display:inline">
- <rect
- transform="translate(0,-11.249983)"
- style="opacity:0.5;fill:none;stroke:none;stroke-width:140.99996948"
- width="596.8999"
- height="596.90082"
- x="-63.49987"
- y="-58.600021"
- id="rect6468"
- mask="url(#mask6472)" />
- <path
- transform="translate(0,-11.249983)"
- sodipodi:type="star"
- style="fill:#000000;fill-opacity:0.09661835;fill-rule:nonzero;stroke:none;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none"
- id="path6921"
- sodipodi:sides="4"
- sodipodi:cx="117.63232"
- sodipodi:cy="102.13793"
- sodipodi:r1="5.7652407"
- sodipodi:r2="2.8826203"
- sodipodi:arg1="1.4464413"
- sodipodi:arg2="2.2318395"
- inkscape:flatsided="false"
- inkscape:rounded="0"
- inkscape:randomized="0"
- d="m 118.34741,107.85865 -2.48485,-3.44532 -3.95096,-1.56031 3.44531,-2.48485 1.56032,-3.950959 2.48484,3.445318 3.95097,1.560311 -3.44532,2.48485 z"
- inkscape:transform-center-x="1.481982e-006"
- inkscape:transform-center-y="-1.1450451e-006" />
- <path
- transform="translate(0,-11.249983)"
- sodipodi:type="star"
- style="fill:#000000;fill-opacity:0.09661835;fill-rule:nonzero;stroke:none;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none"
- id="path6923"
- sodipodi:sides="4"
- sodipodi:cx="317.5"
- sodipodi:cy="75.679596"
- sodipodi:r1="3.949214"
- sodipodi:r2="1.974607"
- sodipodi:arg1="1.6614562"
- sodipodi:arg2="2.4468544"
- inkscape:flatsided="false"
- inkscape:rounded="0"
- inkscape:randomized="0"
- d="m 317.14246,79.612591 -1.1594,-2.668882 -2.41606,-1.621658 2.66889,-1.15939 1.62165,-2.41606 1.1594,2.668882 2.41606,1.621658 -2.66889,1.15939 z"
- inkscape:transform-center-x="4.0000001e-006" />
- <path
- transform="translate(0,-11.249983)"
- sodipodi:type="star"
- style="fill:#000000;fill-opacity:0.09661835;fill-rule:nonzero;stroke:none;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none"
- id="path6925"
- sodipodi:sides="4"
- sodipodi:cx="230.97409"
- sodipodi:cy="57.802349"
- sodipodi:r1="2.2613134"
- sodipodi:r2="1.1306567"
- sodipodi:arg1="1.2490458"
- sodipodi:arg2="2.0344439"
- inkscape:flatsided="false"
- inkscape:rounded="0"
- inkscape:randomized="0"
- d="m 231.68918,59.947619 -1.22073,-1.13398 -1.63963,-0.2962 1.13398,-1.220735 0.2962,-1.639625 1.22074,1.13398 1.63962,0.2962 -1.13398,1.220735 z"
- inkscape:transform-center-x="2.9099099e-006" />
- <path
- transform="translate(0,-11.249983)"
- sodipodi:type="star"
- style="fill:#000000;fill-opacity:0.09661835;fill-rule:nonzero;stroke:none;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none"
- id="path6927"
- sodipodi:sides="4"
- sodipodi:cx="260.65033"
- sodipodi:cy="106.42847"
- sodipodi:r1="1.59899"
- sodipodi:r2="0.79949504"
- sodipodi:arg1="2.0344439"
- sodipodi:arg2="2.8198421"
- inkscape:flatsided="false"
- inkscape:rounded="0"
- inkscape:randomized="0"
- d="m 259.93524,107.85865 -0.0434,-1.17736 -0.67171,-0.96791 1.17736,-0.0434 0.96791,-0.67171 0.0434,1.17735 0.67171,0.96792 -1.17736,0.0434 z"
- inkscape:transform-center-x="3.2837838e-006"
- inkscape:transform-center-y="-1.1990991e-006" />
- <path
- sodipodi:type="star"
- style="fill:#000000;fill-opacity:0.09661835;fill-rule:nonzero;stroke:none;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none"
- id="path6925-2"
- sodipodi:sides="4"
- sodipodi:cx="87.956078"
- sodipodi:cy="127.16609"
- sodipodi:r1="2.2613134"
- sodipodi:r2="1.1306567"
- sodipodi:arg1="1.2490458"
- sodipodi:arg2="2.0344439"
- inkscape:flatsided="false"
- inkscape:rounded="0"
- inkscape:randomized="0"
- d="m 88.671168,129.31136 -1.220735,-1.13398 -1.639626,-0.2962 1.13398,-1.22073 0.296201,-1.63963 1.220735,1.13398 1.639625,0.2962 -1.13398,1.22074 z"
- inkscape:transform-center-x="2.4830149e-006"
- transform="matrix(0.91666666,0,0,1,7.1509006,-11.249983)" />
- <ellipse
- style="opacity:0.68000034;fill:#6e76a3;fill-opacity:1;stroke:none;stroke-width:0.06383465"
- id="path5313-3-7"
- cx="178.44102"
- cy="110.95996"
- rx="21.691566"
- ry="5.0825601"
- transform="rotate(-1.570553,-410.38805,-5.6250559)" />
- <ellipse
- style="opacity:0.68000034;fill:#6e76a3;fill-opacity:1;stroke:none;stroke-width:0.08063243"
- id="path5313-3-7-5"
- cx="200.1326"
- cy="116.80371"
- rx="27.399597"
- ry="6.4200115"
- transform="rotate(-1.570553,-410.38805,-5.6250559)" />
- <ellipse
- style="opacity:0.68000034;fill:#6e76a3;fill-opacity:1;stroke:none;stroke-width:0.06734787"
- id="path5313-3-7-2"
- cx="-429.23041"
- cy="90.631134"
- rx="24.144913"
- ry="5.0825605"
- transform="matrix(-0.99537478,-0.09606802,-0.09606802,0.99537478,0,-11.249983)" />
- <ellipse
- style="opacity:0.68000034;fill:#6e76a3;fill-opacity:1;stroke:none;stroke-width:0.08507013"
- id="path5313-3-7-5-9"
- cx="-405.08548"
- cy="96.474884"
- rx="30.498529"
- ry="6.4200115"
- transform="matrix(-0.99537478,-0.09606802,-0.09606802,0.99537478,0,-11.249983)" />
- <ellipse
- style="opacity:0.68000034;fill:#6e76a3;fill-opacity:1;stroke:none;stroke-width:0.05208009"
- id="path5313-3-7-2-9"
- cx="-46.428764"
- cy="163.90004"
- rx="18.893074"
- ry="3.884198"
- transform="matrix(-0.99073724,0.13579293,0.14607844,0.98927301,0,-11.249983)" />
- <ellipse
- style="opacity:0.68000034;fill:#6e76a3;fill-opacity:1;stroke:none;stroke-width:0.06578472"
- id="path5313-3-7-5-9-1"
- cx="-27.535677"
- cy="168.36595"
- rx="23.864695"
- ry="4.9063048"
- transform="matrix(-0.99073724,0.13579293,0.14607844,0.98927301,0,-11.249983)" />
- <path
- transform="translate(0,-11.249983)"
- sodipodi:type="star"
- style="fill:#000000;fill-opacity:0.09661835;fill-rule:nonzero;stroke:none;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none"
- id="path6923-9"
- sodipodi:sides="4"
- sodipodi:cx="459.82239"
- sodipodi:cy="139.8455"
- sodipodi:r1="3.949214"
- sodipodi:r2="1.9746071"
- sodipodi:arg1="1.6614562"
- sodipodi:arg2="2.4468544"
- inkscape:flatsided="false"
- inkscape:rounded="0"
- inkscape:randomized="0"
- d="m 459.46484,143.7785 -1.15939,-2.66888 -2.41606,-1.62166 2.66889,-1.15939 1.62165,-2.41606 1.15939,2.66888 2.41606,1.62166 -2.66888,1.15939 z"
- inkscape:transform-center-x="4.0000001e-006" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.81509405;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path5229"
- cx="192.18326"
- cy="74.677902"
- r="2.7216933" />
- <path
- sodipodi:type="star"
- style="fill:#ffffff;fill-opacity:0.09661835;fill-rule:nonzero;stroke:none;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none"
- id="path6923-8"
- sodipodi:sides="4"
- sodipodi:cx="53.989292"
- sodipodi:cy="88.908768"
- sodipodi:r1="3.949214"
- sodipodi:r2="1.9746071"
- sodipodi:arg1="1.6614562"
- sodipodi:arg2="2.4468544"
- inkscape:flatsided="false"
- inkscape:rounded="0"
- inkscape:randomized="0"
- d="m 53.631747,92.841763 -1.15939,-2.668883 -2.41606,-1.621657 2.668883,-1.159391 1.621657,-2.41606 1.15939,2.668883 2.416061,1.621658 -2.668883,1.15939 z"
- inkscape:transform-center-x="2.0634674e-006"
- transform="matrix(0.61390676,-0.48689202,0.48689202,0.61390676,-23.159158,48.648961)"
- inkscape:transform-center-y="1.4320049e-006" />
- <path
- sodipodi:type="star"
- style="fill:#ffffff;fill-opacity:0.09661835;fill-rule:nonzero;stroke:none;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none"
- id="path6923-8-3"
- sodipodi:sides="4"
- sodipodi:cx="53.989292"
- sodipodi:cy="88.908768"
- sodipodi:r1="3.949214"
- sodipodi:r2="1.9746071"
- sodipodi:arg1="1.6614562"
- sodipodi:arg2="2.4468544"
- inkscape:flatsided="false"
- inkscape:rounded="0"
- inkscape:randomized="0"
- d="m 53.631747,92.841763 -1.15939,-2.668883 -2.41606,-1.621657 2.668883,-1.159391 1.621657,-2.41606 1.15939,2.668883 2.416061,1.621658 -2.668883,1.15939 z"
- inkscape:transform-center-x="3.0260172e-006"
- transform="matrix(0.58032639,0.43093706,-0.43093706,0.58032639,446.58431,23.35553)"
- inkscape:transform-center-y="-1.3594204e-006" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28035584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path5229-6"
- cx="347.17841"
- cy="36.709366"
- r="0.9361406" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28035584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path5229-6-5"
- cx="116.0927"
- cy="42.136036"
- r="0.9361406" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.15;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.55002564;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path5229-0"
- cx="456.28247"
- cy="47.488548"
- r="1.8365992" />
- </g>
- <g
- inkscape:groupmode="layer"
- id="layer5"
- inkscape:label="レイヤー 4"
- style="display:none">
- <path
- transform="translate(0,-11.249983)"
- style="display:inline;fill:#ffff7c;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none"
- d="m 377.25876,69.781182 a 18.234796,18.234796 0 0 1 8.1747,15.19442 18.234796,18.234796 0 0 1 -18.23455,18.235058 18.234796,18.234796 0 0 1 -10.14098,-3.08921 20.380066,20.380066 0 0 0 17.64905,10.2402 20.380066,20.380066 0 0 0 20.38015,-20.380152 20.380066,20.380066 0 0 0 -17.82837,-20.200316 z"
- id="path6914"
- inkscape:connector-curvature="0" />
- </g>
- <g
- inkscape:groupmode="layer"
- id="layer4"
- inkscape:label="レイヤー 3"
- style="display:none">
- <circle
- style="display:inline;opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.36438358;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path5306"
- cx="168.31279"
- cy="2.1908164"
- r="36.253109" />
- <path
- style="display:inline;opacity:0.1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.39123487px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 201.1259,19.428383 2.66976,2.617062 1.21734,-1.978474 -0.34264,5.194221 -4.15215,2.110811 1.0283,-1.928856 -2.76172,-2.210044 z"
- id="path5168"
- inkscape:connector-curvature="0" />
- <path
- style="display:inline;opacity:0.1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.89719725px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 196.25421,26.631949 6.0286,8.817373 -3.70059,3.384671 -1.84127,-4.638447 -2.48924,2.916491 -2.23471,-6.507119 z"
- id="path5174"
- inkscape:connector-curvature="0" />
- <path
- style="display:inline;opacity:0.1;fill:#000500;fill-opacity:1;stroke:none;stroke-width:0.05121958px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 187.00695,34.050482 1.26268,2.214392 1.44195,-0.54357 1.31981,0.86123 0.21375,1.739039 -1.36828,1.61618 -1.80409,0.265403 -1.1589,-1.059687 -0.23516,-1.721875 1.11047,-0.916698 -0.43413,-0.680502 -0.4102,0.997264 0.74387,1.070883 -0.49255,1.027197 -1.26776,0.228606 -0.5501,-0.871237 0.15467,-0.82956 0.93559,-0.424446 0.58058,-1.450625 -0.75664,-1.131455 z"
- id="path6985"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccccccccccccccccc" />
- <path
- style="display:inline;opacity:0.1;fill:#000016;fill-opacity:1;stroke:none;stroke-width:0.04695854px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 203.23593,14.367789 4.43345,3.766934 0.87976,-0.995725 0.46812,0.475437 -0.80488,0.995031 0.83731,0.705238 0.86731,-0.962102 0.50998,0.516259 -0.87206,0.921255 0.99505,0.941692 -0.44277,0.42746 -0.91483,-0.900095 -0.8367,0.879711 -0.43031,-0.474867 0.78065,-0.831436 -0.86665,-0.779727 -0.81136,0.912638 -0.55866,-0.483362 0.8179,-0.927279 -4.48211,-3.638676 z"
- id="path6891-8"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccccccccccccccccc" />
- <path
- style="display:inline;opacity:0.05;fill:#000016;fill-opacity:1;stroke:none;stroke-width:0.58045781px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 204.43932,-5.3971152 6.34563,7.5781721 -3.73895,4.9604312 0.33681,4.6546149 -5.20345,5.793617 c 2.83273,-8.049795 3.31033,-11.8140092 3.09986,-18.9271334 z"
- id="path5208"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccc" />
- <path
- style="display:inline;opacity:0.1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.11183073px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 205.60259,0.56695919 1.24493,0.127049 0.0916,-0.59592195 0.28719,0.07174803 -0.065,0.56786179 0.62071,0.0788993 -0.0423,0.36840374 -0.62423,-0.048236 -0.0804,0.8381885 0.52004,0.075191 -0.0192,0.3709729 -0.5764,-0.058257 -0.10087,0.8125312 0.54747,0.039404 -0.04,0.4153104 -0.5593,-0.071919 -0.0636,0.6224815 -0.3736,0.00386 0.0816,-0.6437327 -1.20305,-0.1533942 0.0499,-0.3674909 1.2006,0.1064631 0.11092,-0.7647515 -1.19622,-0.1448386 0.027,-0.3701253 1.23042,0.1176518 0.12327,-0.8721654 -1.26199,-0.1134749 z"
- id="path7229"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccccccccccccccccccccccccc" />
- <path
- style="display:inline;opacity:0.1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.16325578px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 204.68821,9.1424652 1.78173,-0.049987 -1.44996,0.7563273 1.12166,0.7127945 -1.34099,0.0029 0.93885,1.309289 -1.59949,-0.942185 z"
- id="path7212-4-6"
- inkscape:connector-curvature="0" />
- <path
- style="display:inline;opacity:0.05;fill:#000016;fill-opacity:1;stroke:none;stroke-width:0.71902335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 180.87434,36.932251 -8.12162,8.095249 -6.61262,-3.934427 -5.68596,1.043018 -7.6496,-6.371879 c 10.33078,4.527622 19.43137,4.062311 28.0698,1.168039 z"
- id="path5208-6"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccc" />
- <path
- style="display:inline;opacity:0.1;fill:#000016;fill-opacity:1;stroke:none;stroke-width:0.04569969px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 156.79314,37.138611 -0.83209,5.600235 1.27513,0.214749 -0.15211,0.631281 -1.23602,-0.153244 -0.15211,1.0545 1.24093,0.221743 -0.16427,0.686859 -1.20964,-0.246683 -0.26626,1.306416 -0.58089,-0.145968 0.27316,-1.218758 -1.15712,-0.238846 0.17092,-0.599741 1.08842,0.21735 0.19853,-1.117028 -1.17126,-0.200972 0.11204,-0.710141 1.18676,0.198837 0.70106,-5.574493 z"
- id="path6891-8-9"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccccccccccccccccc" />
- <path
- style="display:inline;opacity:0.1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.84177661px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 143.96364,29.933272 -4.59686,9.216397 3.65156,2.834687 1.22043,-4.692866 2.51661,2.524357 1.39851,-6.542721 z"
- id="path5174-1"
- inkscape:connector-curvature="0" />
- <path
- style="display:inline;opacity:0.1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.56489706px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 142.60658,28.70585 -2.96842,6.930652 -3.79379,-3.925042 4.56394,-5.124749 z"
- id="path5285"
- inkscape:connector-curvature="0" />
- <path
- style="display:inline;opacity:0.1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.35393918px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 137.9306,23.319484 -3.42616,1.224261 1.2143,1.906916 -4.40128,-2.508612 -0.0822,-4.53226 1.25123,1.720316 3.10894,-1.477793 z"
- id="path5168-0"
- inkscape:connector-curvature="0" />
- <path
- style="display:inline;opacity:0.1;fill:#000500;fill-opacity:1;stroke:none;stroke-width:0.0498465px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 132.55595,11.444656 -2.31852,0.882408 0.30663,1.468015 -1.02588,1.140069 -1.70428,-0.05499 -1.34908,-1.557886 0.015,-1.774566 1.1926,-0.955614 1.69096,0.03182 0.7151,1.205156 0.71942,-0.315492 -0.89748,-0.543864 -1.14121,0.554849 -0.91394,-0.627513 -0.0299,-1.2533405 0.92017,-0.3984462 0.77453,0.2730438 0.26797,0.9632459 1.30792,0.775623 1.20137,-0.558052 z"
- id="path6985-7"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccccccccccccccccc" />
- <path
- style="display:inline;opacity:0.1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.15882961px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 131.32384,2.4817954 -1.6313,-0.4305236 1.16551,1.0474206 -1.19547,0.453907 1.23564,0.290212 -1.16202,1.0740836 1.68796,-0.5749329 z"
- id="path7212-4-6-8"
- inkscape:connector-curvature="0" />
- <path
- style="display:inline;opacity:0.05;fill:#000016;fill-opacity:1;stroke:none;stroke-width:0.55575538px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 137.04207,-21.420699 -7.13207,5.035868 1.31743,5.70794 -2.10914,4.1341529 2.26645,6.93249012 c 0.67636,-8.23493742 2.69888,-15.39599902 5.65733,-21.81045102 z"
- id="path5208-4"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccc" />
- </g>
-</svg>
diff --git a/src/client/assets/welcome-fg.svg b/src/client/assets/welcome-fg.svg
deleted file mode 100644
index 5c795c3027..0000000000
--- a/src/client/assets/welcome-fg.svg
+++ /dev/null
@@ -1,380 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="1920"
- height="1080"
- viewBox="0 0 507.99999 285.75001"
- version="1.1"
- id="svg8"
- inkscape:version="0.92.1 r15371"
- sodipodi:docname="welcome-fg.svg">
- <defs
- id="defs2">
- <linearGradient
- inkscape:collect="always"
- id="linearGradient7044">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop7040" />
- <stop
- style="stop-color:#ffffff;stop-opacity:1"
- offset="1"
- id="stop7042" />
- </linearGradient>
- <pattern
- inkscape:collect="always"
- xlink:href="#Checkerboard"
- id="pattern7010"
- patternTransform="matrix(1.673813,0,0,1.673813,-177.6001,-146.38611)" />
- <pattern
- inkscape:stockid="Checkerboard"
- id="Checkerboard"
- patternTransform="translate(0,0) scale(10,10)"
- height="2"
- width="2"
- patternUnits="userSpaceOnUse"
- inkscape:collect="always">
- <rect
- id="rect6201"
- height="1"
- width="1"
- y="0"
- x="0"
- style="fill:black;stroke:none" />
- <rect
- id="rect6203"
- height="1"
- width="1"
- y="1"
- x="1"
- style="fill:black;stroke:none" />
- </pattern>
- <linearGradient
- id="linearGradient5406"
- osb:paint="solid">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop5404" />
- </linearGradient>
- <pattern
- patternUnits="userSpaceOnUse"
- width="15.999999"
- height="16.000025"
- patternTransform="matrix(0.26458333,0,0,0.26458333,-16.933332,263.1333)"
- id="pattern6465">
- <path
- d="m 8.0000542,8.0000126 h 7.9998878 c 3e-5,0 5.7e-5,3.78e-5 5.7e-5,3.78e-5 V 15.99995 c 0,3.7e-5 -2.7e-5,7.5e-5 -5.7e-5,7.5e-5 H 8.0000542 c -3.03e-5,0 -5.67e-5,-3.8e-5 -5.67e-5,-7.5e-5 V 8.0000504 c 0,0 2.64e-5,-3.78e-5 5.67e-5,-3.78e-5 z M 5.6692913e-5,0 H 7.9999408 c 3.02e-5,0 5.67e-5,3.7795275e-5 5.67e-5,7.5590551e-5 V 7.999937 c 0,3.78e-5 -2.65e-5,7.56e-5 -5.67e-5,7.56e-5 H 5.6692913e-5 C 2.2677165e-5,8.0000126 0,7.9999748 0,7.999937 V 7.5590551e-5 C 0,3.7795276e-5 2.2677165e-5,0 5.6692913e-5,0 Z"
- style="opacity:1;fill:#db1545;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:15.99999905;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect6445-2"
- inkscape:connector-curvature="0" />
- </pattern>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient7044"
- id="linearGradient6476"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.223659,0,0,2.5556636,-579.27357,808.39)"
- x1="86.490868"
- y1="-216.62756"
- x2="176.77992"
- y2="-216.62756" />
- <mask
- maskUnits="userSpaceOnUse"
- id="mask6472">
- <rect
- transform="rotate(-90)"
- y="-0.91986513"
- x="-300.45657"
- height="511.36566"
- width="291.06116"
- id="rect6474"
- style="opacity:1;fill:url(#linearGradient6476);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.92238116;stroke-miterlimit:4;stroke-dasharray:none" />
- </mask>
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#1e1d65"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.84705882"
- inkscape:pageshadow="2"
- inkscape:zoom="0.6363961"
- inkscape:cx="720.54406"
- inkscape:cy="371.58659"
- inkscape:document-units="mm"
- inkscape:current-layer="layer1"
- showgrid="true"
- units="px"
- inkscape:pagecheckerboard="true"
- inkscape:window-width="1920"
- inkscape:window-height="1057"
- inkscape:window-x="1912"
- inkscape:window-y="1143"
- inkscape:window-maximized="1"
- objecttolerance="1"
- guidetolerance="10000"
- gridtolerance="10000"
- inkscape:snap-bbox="true"
- inkscape:bbox-paths="true"
- inkscape:bbox-nodes="true"
- inkscape:snap-bbox-edge-midpoints="true"
- inkscape:snap-bbox-midpoints="true"
- showguides="false">
- <inkscape:grid
- type="xygrid"
- id="grid6443"
- spacingx="2.1166667"
- spacingy="2.1166667"
- empspacing="4"
- color="#3f3fff"
- opacity="0.1254902"
- enabled="false" />
- <sodipodi:guide
- position="-69.219003,3.872392"
- orientation="1,0"
- id="guide6508"
- inkscape:locked="false" />
- </sodipodi:namedview>
- <metadata
- id="metadata5">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:groupmode="layer"
- id="layer2"
- inkscape:label="Back"
- style="display:inline">
- <path
- style="fill:#253276;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 500.58203,825.29688 -54.2207,18.9121 18.91406,56.74219 -45.39258,10.08594 -11.34765,-39.08789 -46.6543,12.60937 13.87109,34.04493 -55.48047,15.13086 -12.60937,-44.13086 -47.91406,13.86914 13.86914,44.13086 -32.78321,11.3496 17.65235,35.30469 278.66211,-63.04492 z m -11.0957,26.45312 0.44726,11.5918 -12.03711,2.67382 -3.5664,-9.80664 z m 4.90429,24.51953 0.89258,9.80859 -9.36328,2.67383 -4.45703,-9.36133 z m -201.5,32.09766 v 11.14453 l -8.4707,1.7832 -4.9043,-8.91601 z"
- id="path4522"
- inkscape:connector-curvature="0"
- transform="scale(0.26458333)" />
- <path
- transform="translate(0,-11.249983)"
- style="fill:#253276;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 381.65643,238.28361 -47.37344,16.34717 116.09827,29.02457 -14.01186,-23.68672 -31.02626,-0.33362 z"
- id="path4520"
- inkscape:connector-curvature="0" />
- </g>
- <g
- inkscape:label="Ground"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-11.249983)"
- style="display:inline">
- <circle
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:1.99730551"
- id="path5392"
- cx="253.06117"
- cy="887.61829"
- r="642.68146" />
- </g>
- <g
- inkscape:groupmode="layer"
- id="layer3"
- inkscape:label="Front">
- <path
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:1.00157475;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 565.38867,666.80078 -115.20508,24.36914 70.24414,231.09766 121.20118,-18.97656 8.61523,-148.01368 -76.28906,21.625 z m -30.15234,38.82813 3.09765,47.0625 -11.44531,2.49414 -9.14062,-46.10743 z m -26.41211,5.20898 10.30664,46.03906 -9.47852,2.06641 -17.14257,-44.88672 z m 41.45508,65.93945 2.80078,44.04493 -12.50391,3.40234 L 532.1543,781.75 Z m -25.15039,6.90039 9.4414,42.18165 -9.54297,2.59765 -13.99804,-40.91015 z m 85.48242,50.83789 1,42.35938 -22.15235,4.89648 -4.53906,-41.66406 z m -54.21485,10.16797 4.54102,41.66211 -7.67188,1.89649 -8.07421,-40.73047 z m -16.66992,4.20899 9.05469,40.45703 -8.88477,2.19727 -12.02734,-39.66016 z"
- id="path5398"
- transform="scale(0.26458333)"
- inkscape:connector-curvature="0" />
- <path
- transform="translate(0,-11.249983)"
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 329.51477,199.15082 -32.04286,18.26817 12.8142,1.28619 -6.02656,28.18505 32.94792,3.49531 0.51681,-27.76301 11.91226,1.00737 z m -14.10711,25.93826 6.27123,0.90288 -1.15019,5.4805 -6.00929,-0.898 z m 13.58524,2.09643 0.42171,5.50053 -6.35262,-0.44337 1.22618,-5.67857 z m -15.04127,5.73678 6.21844,0.90138 -1.87301,4.94347 -5.07899,-0.81761 z m 8.80707,1.53673 6.3403,1.10313 0.43128,4.98637 -7.83808,-1.19409 z"
- id="path6874"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccccccccccccccccccccccccc" />
- <path
- transform="translate(0,-11.249983)"
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 366.28967,254.78298 7.49431,-30.40441 -7.41388,-2.66046 1.18763,-3.36104 7.21205,2.27141 1.38362,-5.73044 -7.20912,-2.66047 1.28561,-3.65794 7.01313,2.7643 2.17341,-7.01022 3.35519,1.48161 -2.1734,6.51147 6.70747,2.66046 -1.28564,3.16213 -6.31255,-2.46154 -1.68638,6.02735 6.80837,2.46447 -0.9887,3.84808 -6.90052,-2.47031 -6.71038,30.41026 z"
- id="path6891"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccccccccccccccccc" />
- <path
- transform="translate(0,-11.249983)"
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 74.047433,217.56203 -1.20251,0.65577 2.314585,6.84299 -4.564578,1.31517 13.625009,41.10395 21.186821,-5.50251 -7.183542,-43.56323 -22.044649,6.35259 z m 16.734379,10.06088 1.478463,10.23607 -8.339026,1.96939 -3.82509,-9.42992 z m 3.780131,14.55519 0.781863,9.82627 -7.001121,1.81797 -3.593063,-9.29297 z"
- id="path6944"
- inkscape:connector-curvature="0" />
- <path
- transform="translate(0,-11.249983)"
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:0.24600939px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 43.603475,280.06036 -10.564819,-28.58824 -6.574764,2.28618 -0.916385,-3.37337 6.23111,-2.47535 -2.011396,-5.37101 -6.431418,2.16468 -1.002197,-3.66725 6.348194,-1.96596 -2.123972,-6.85578 3.11982,-0.81419 1.86458,6.45975 6.080155,-1.86705 0.744318,3.27357 -5.700174,1.79072 1.953823,5.78639 6.048884,-2.08256 1.308957,3.64208 -6.116434,2.13257 11.116753,28.12778 z"
- id="path6891-8"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccccccccccccccccc" />
- <path
- transform="translate(0,-11.249983)"
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 411.98753,264.70523 3.91734,-12.57157 -7.13355,-3.53259 -1.396,-8.02014 5.81668,-6.93436 10.92618,-0.52461 7.35863,5.88054 0.0806,8.11138 -5.67524,6.95564 -7.37536,-0.96565 -1.04168,4.03744 5.21293,-1.96321 1.42492,-6.58308 5.61592,-1.7579 5.33002,3.98422 -1.35343,5.14755 -3.67857,2.33882 -4.89966,-2.03926 -7.52592,2.91667 -1.60892,6.84465 z"
- id="path6985"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccccccccccccccccc" />
- <path
- transform="translate(0,-11.249983)"
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:0.27861062px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 438.77767,272.41521 -0.009,-2.99656 1.24656,2.44908 1.28337,-1.87551 -0.0534,2.25473 2.30831,-1.55949 -1.70125,2.67579 z"
- id="path7212"
- inkscape:connector-curvature="0" />
- <path
- transform="translate(0,-11.249983)"
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:0.29395995px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 387.1467,259.13862 -0.3913,-3.17093 1.60741,2.46066 1.09423,-2.12083 0.23196,2.39229 2.19942,-1.8946 -1.42637,3.01207 z"
- id="path7212-4"
- inkscape:connector-curvature="0" />
- <path
- transform="translate(0,-11.249983)"
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 457.96894,278.42384 1.02302,-2.77836 -1.31183,-0.56021 0.33336,-0.616 1.26318,0.48291 0.54568,-1.37607 0.81934,0.31324 -0.47741,1.4022 1.87364,0.67714 0.47795,-1.14765 0.83893,0.26207 -0.47245,1.28672 1.80283,0.70884 0.41215,-1.23149 0.92825,0.33529 -0.49337,1.23952 1.38917,0.51162 -0.21081,0.85845 -1.42731,-0.56527 -1.05878,2.6669 -0.81279,-0.33034 0.94975,-2.68892 -1.68742,-0.7038 -1.03512,2.65627 -0.83236,-0.27915 0.99293,-2.75061 -1.92628,-0.79522 -1.00194,2.82543 z"
- id="path7229"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccccccccccccccccccccccccc" />
- <path
- transform="translate(0,-11.249983)"
- id="path7233"
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:0.3185696px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 73.482785,265.42476 4.944364,-1.72314 -0.207904,-0.52164 -2.012479,0.86151 -0.0213,-0.63037 -0.837931,0.3339 0.324488,0.46118 -2.371778,0.68852 z m 0.497305,0.21764 4.223597,-1.35549 0.556753,4.37406 -2.879727,0.92419 z"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccccccccccc" />
- <path
- transform="translate(0,-11.249983)"
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 156.55184,206.61884 0.47605,-0.20403 1.0201,8.90891 -0.47605,0.20402 z"
- id="path7236"
- inkscape:connector-curvature="0" />
- <path
- transform="translate(0,-11.249983)"
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 160.97229,209.47512 0.20402,4.96451 0.47605,-0.068 0.068,-5.03251 z"
- id="path7238"
- inkscape:connector-curvature="0" />
- <path
- transform="translate(0,-11.249983)"
- style="fill:#172062;fill-opacity:1;stroke:none;stroke-width:0.34364724px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 23.838748,287.33572 -2.186787,-3.04882 3.027872,1.63785 -0.07842,-2.79635 1.585239,2.33549 1.177306,-3.18042 0.241718,3.90016 z"
- id="path7212-4-6"
- inkscape:connector-curvature="0" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.5;fill:#ff0016;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.11666656;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535"
- cx="120.03474"
- cy="193.66763"
- r="2.5126758" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.5;fill:#ff0016;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.11666656;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535-2"
- cx="97.333473"
- cy="218.84901"
- r="2.5126758" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.5;fill:#ff0016;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.11666656;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535-24"
- cx="70.128021"
- cy="226.19046"
- r="2.5126758" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.25;fill:#ff0016;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.41842699;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535-25"
- cx="118.05532"
- cy="234.83446"
- r="1.6838019" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.5;fill:#ffbe16;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.3186785;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535-9"
- cx="110.59546"
- cy="252.2408"
- r="1.5653913" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.5;fill:#ffbe16;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.3186785;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535-9-7"
- cx="122.43651"
- cy="242.53113"
- r="1.5653913" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.5;fill:#ffbe16;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.3186785;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535-9-2"
- cx="64.415337"
- cy="265.26596"
- r="1.5653913" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.1;fill:#ff0016;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6.44323444;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535-24-4"
- cx="69.61615"
- cy="226.18503"
- r="7.648705" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.1;fill:#ff0016;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6.44323444;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535-24-4-4"
- cx="97.333473"
- cy="218.84901"
- r="7.648705" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.1;fill:#ff0016;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6.44323444;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535-24-4-2"
- cx="119.52941"
- cy="193.50121"
- r="7.648705" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.02999998;fill:#ffbe16;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.13750315;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535-9-2-6"
- cx="64.415337"
- cy="265.26596"
- r="4.9115925" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.02999998;fill:#ffbe16;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.13750315;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535-9-2-6-7"
- cx="110.59546"
- cy="252.2408"
- r="4.9115925" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.02999998;fill:#ffbe16;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.13750315;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535-9-2-6-3"
- cx="122.43651"
- cy="242.53113"
- r="4.9115925" />
- <circle
- transform="translate(0,-11.249983)"
- style="opacity:0.05;fill:#ff0016;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6.44323444;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4535-24-4-4-8"
- cx="117.52492"
- cy="234.88242"
- r="7.648705" />
- </g>
-</svg>