diff options
Diffstat (limited to 'src/client')
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> |