This commit is contained in:
syuilo 2018-02-11 12:08:43 +09:00
parent 7664354187
commit 92826c406a
12 changed files with 113 additions and 74 deletions

View file

@ -11,7 +11,7 @@ const loadLang = lang => yaml.safeLoad(
const native = loadLang('ja'); const native = loadLang('ja');
const langs = { const langs = {
'en': loadLang('en'), //'en': loadLang('en'),
'ja': native 'ja': native
}; };

View file

@ -1,40 +0,0 @@
<mk-forkit><a href="https://github.com/syuilo/misskey" target="_blank" title="%i18n:common.tags.mk-forkit.open-github-link%" aria-label="%i18n:common.tags.mk-forkit.open-github-link%">
<svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="aria-hidden">
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
<path class="octo-arm" d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor"></path>
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor"></path>
</svg></a>
<style lang="stylus" scoped>
:scope
display block
position absolute
top 0
right 0
> a
display block
> svg
display block
//fill #151513
//color #fff
fill $theme-color
color $theme-color-foreground
.octo-arm
transform-origin 130px 106px
&:hover
.octo-arm
animation octocat-wave 560ms ease-in-out
@keyframes octocat-wave
0%, 100%
transform rotate(0)
20%, 60%
transform rotate(-25deg)
40%, 80%
transform rotate(10deg)
</style>
</mk-forkit>

View file

@ -0,0 +1,40 @@
<template>
<a class="a" href="https://github.com/syuilo/misskey" target="_blank" title="%i18n:common.tags.mk-forkit.open-github-link%" aria-label="%i18n:common.tags.mk-forkit.open-github-link%">
<svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="aria-hidden">
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
<path class="octo-arm" d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor"></path>
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor"></path>
</svg>
</a>
</template>
<style lang="stylus" scoped>
.a
display block
position absolute
top 0
right 0
> svg
display block
//fill #151513
//color #fff
fill $theme-color
color $theme-color-foreground
.octo-arm
transform-origin 130px 106px
&:hover
.octo-arm
animation octocat-wave 560ms ease-in-out
@keyframes octocat-wave
0%, 100%
transform rotate(0)
20%, 60%
transform rotate(-25deg)
40%, 80%
transform rotate(10deg)
</style>

View file

@ -2,6 +2,8 @@ import Vue from 'vue';
import signin from './signin.vue'; import signin from './signin.vue';
import signup from './signup.vue'; import signup from './signup.vue';
import forkit from './forkit.vue';
Vue.component('mk-signin', signin); Vue.component('mk-signin', signin);
Vue.component('mk-signup', signup); Vue.component('mk-signup', signup);
Vue.component('mk-forkit', forkit);

View file

@ -13,20 +13,22 @@
</form> </form>
</template> </template>
<script> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
export default Vue.extend({ export default Vue.extend({
props: ['os'],
data() { data() {
return { return {
signing: false, signing: false,
user: null user: null,
username: '',
password: '',
token: ''
}; };
}, },
methods: { methods: {
onUsernameChange() { onUsernameChange() {
this.os.api('users/show', { this.$root.$data.os.api('users/show', {
username: this.username username: this.username
}).then(user => { }).then(user => {
this.user = user; this.user = user;
@ -35,7 +37,7 @@ export default Vue.extend({
onSubmit() { onSubmit() {
this.signing = true; this.signing = true;
this.os.api('signin', { this.$root.$data.os.api('signin', {
username: this.username, username: this.username,
password: this.password, password: this.password,
token: this.user && this.user.two_factor_enabled ? this.token : undefined token: this.user && this.user.two_factor_enabled ? this.token : undefined

View file

@ -2,8 +2,8 @@
<form class="mk-signup" @submit.prevent="onSubmit" autocomplete="off"> <form class="mk-signup" @submit.prevent="onSubmit" autocomplete="off">
<label class="username"> <label class="username">
<p class="caption">%fa:at%%i18n:common.tags.mk-signup.username%</p> <p class="caption">%fa:at%%i18n:common.tags.mk-signup.username%</p>
<input v-model="username" type="text" pattern="^[a-zA-Z0-9-]{3,20}$" placeholder="a~z、A~Z、0~9、-" autocomplete="off" required @keyup="onChangeUsername"/> <input v-model="username" type="text" pattern="^[a-zA-Z0-9-]{3,20}$" placeholder="a~z、A~Z、0~9、-" autocomplete="off" required @input="onChangeUsername"/>
<p class="profile-page-url-preview" v-if="username != '' && username-state != 'invalidFormat' && username-state != 'minRange' && username-state != 'maxRange'">{ _URL_ + '/' + refs.username.value }</p> <p class="profile-page-url-preview" v-if="shouldShowProfileUrl">{{ `${url}/${username}` }}</p>
<p class="info" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%%i18n:common.tags.mk-signup.checking%</p> <p class="info" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%%i18n:common.tags.mk-signup.checking%</p>
<p class="info" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.available%</p> <p class="info" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.available%</p>
<p class="info" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.unavailable%</p> <p class="info" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.unavailable%</p>
@ -14,8 +14,8 @@
</label> </label>
<label class="password"> <label class="password">
<p class="caption">%fa:lock%%i18n:common.tags.mk-signup.password%</p> <p class="caption">%fa:lock%%i18n:common.tags.mk-signup.password%</p>
<input v-model="password" type="password" placeholder="%i18n:common.tags.mk-signup.password-placeholder%" autocomplete="off" required @keyup="onChangePassword"/> <input v-model="password" type="password" placeholder="%i18n:common.tags.mk-signup.password-placeholder%" autocomplete="off" required @input="onChangePassword"/>
<div class="meter" v-if="passwordStrength != ''" :data-strength="passwordStrength"> <div class="meter" v-show="passwordStrength != ''" :data-strength="passwordStrength">
<div class="value" ref="passwordMetar"></div> <div class="value" ref="passwordMetar"></div>
</div> </div>
<p class="info" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.weak-password%</p> <p class="info" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.weak-password%</p>
@ -24,13 +24,13 @@
</label> </label>
<label class="retype-password"> <label class="retype-password">
<p class="caption">%fa:lock%%i18n:common.tags.mk-signup.password%(%i18n:common.tags.mk-signup.retype%)</p> <p class="caption">%fa:lock%%i18n:common.tags.mk-signup.password%(%i18n:common.tags.mk-signup.retype%)</p>
<input v-model="retypedPassword" type="password" placeholder="%i18n:common.tags.mk-signup.retype-placeholder%" autocomplete="off" required @keyup="onChangePasswordRetype"/> <input v-model="retypedPassword" type="password" placeholder="%i18n:common.tags.mk-signup.retype-placeholder%" autocomplete="off" required @input="onChangePasswordRetype"/>
<p class="info" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.password-matched%</p> <p class="info" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.password-matched%</p>
<p class="info" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.password-not-matched%</p> <p class="info" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:common.tags.mk-signup.password-not-matched%</p>
</label> </label>
<label class="recaptcha"> <label class="recaptcha">
<p class="caption"><template v-if="recaptchaed">%fa:toggle-on%</template><template v-if="!recaptchaed">%fa:toggle-off%</template>%i18n:common.tags.mk-signup.recaptcha%</p> <p class="caption"><template v-if="recaptchaed">%fa:toggle-on%</template><template v-if="!recaptchaed">%fa:toggle-off%</template>%i18n:common.tags.mk-signup.recaptcha%</p>
<div v-if="recaptcha" class="g-recaptcha" data-callback="onRecaptchaed" data-expired-callback="onRecaptchaExpired" :data-sitekey="recaptchaSitekey"></div> <div class="g-recaptcha" data-callback="onRecaptchaed" data-expired-callback="onRecaptchaExpired" :data-sitekey="recaptchaSitekey"></div>
</label> </label>
<label class="agree-tou"> <label class="agree-tou">
<input name="agree-tou" type="checkbox" autocomplete="off" required/> <input name="agree-tou" type="checkbox" autocomplete="off" required/>
@ -43,15 +43,15 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
const getPasswordStrength = require('syuilo-password-strength'); const getPasswordStrength = require('syuilo-password-strength');
import { docsUrl, lang, recaptchaSitekey } from '../../../config'; import { url, docsUrl, lang, recaptchaSitekey } from '../../../config';
export default Vue.extend({ export default Vue.extend({
props: ['os'],
data() { data() {
return { return {
username: '', username: '',
password: '', password: '',
retypedPassword: '', retypedPassword: '',
url,
touUrl: `${docsUrl}/${lang}/tou`, touUrl: `${docsUrl}/${lang}/tou`,
recaptchaSitekey, recaptchaSitekey,
recaptchaed: false, recaptchaed: false,
@ -60,6 +60,14 @@ export default Vue.extend({
passwordRetypeState: null passwordRetypeState: null
} }
}, },
computed: {
shouldShowProfileUrl(): boolean {
return (this.username != '' &&
this.usernameState != 'invalid-format' &&
this.usernameState != 'min-range' &&
this.usernameState != 'max-range');
}
},
methods: { methods: {
onChangeUsername() { onChangeUsername() {
if (this.username == '') { if (this.username == '') {
@ -80,7 +88,7 @@ export default Vue.extend({
this.usernameState = 'wait'; this.usernameState = 'wait';
this.os.api('username/available', { this.$root.$data.os.api('username/available', {
username: this.username username: this.username
}).then(result => { }).then(result => {
this.usernameState = result.available ? 'ok' : 'unavailable'; this.usernameState = result.available ? 'ok' : 'unavailable';
@ -107,12 +115,12 @@ export default Vue.extend({
this.passwordRetypeState = this.password == this.retypedPassword ? 'match' : 'not-match'; this.passwordRetypeState = this.password == this.retypedPassword ? 'match' : 'not-match';
}, },
onSubmit() { onSubmit() {
this.os.api('signup', { this.$root.$data.os.api('signup', {
username: this.username, username: this.username,
password: this.password, password: this.password,
'g-recaptcha-response': (window as any).grecaptcha.getResponse() 'g-recaptcha-response': (window as any).grecaptcha.getResponse()
}).then(() => { }).then(() => {
this.os.api('signin', { this.$root.$data.os.api('signin', {
username: this.username, username: this.username,
password: this.password password: this.password
}).then(() => { }).then(() => {

View file

@ -1,11 +1,21 @@
declare const _HOST_: string; declare const _HOST_: string;
declare const _URL_: string; declare const _URL_: string;
declare const _API_URL_: string;
declare const _DOCS_URL_: string; declare const _DOCS_URL_: string;
declare const _LANG_: string; declare const _LANG_: string;
declare const _RECAPTCHA_SITEKEY_: string; declare const _RECAPTCHA_SITEKEY_: string;
declare const _SW_PUBLICKEY_: string;
declare const _THEME_COLOR_: string;
declare const _COPYRIGHT_: string;
declare const _VERSION_: string;
export const host = _HOST_; export const host = _HOST_;
export const url = _URL_; export const url = _URL_;
export const apiUrl = _API_URL_;
export const docsUrl = _DOCS_URL_; export const docsUrl = _DOCS_URL_;
export const lang = _LANG_; export const lang = _LANG_;
export const recaptchaSitekey = _RECAPTCHA_SITEKEY_; export const recaptchaSitekey = _RECAPTCHA_SITEKEY_;
export const swPublickey = _SW_PUBLICKEY_;
export const themeColor = _THEME_COLOR_;
export const copyright = _COPYRIGHT_;
export const version = _VERSION_;

View file

@ -15,12 +15,17 @@ import MkIndex from './views/pages/index.vue';
/** /**
* init * init
*/ */
init(async (os, launch) => { init(async (launch) => {
/** /**
* Fuck AD Block * Fuck AD Block
*/ */
fuckAdBlock(); fuckAdBlock();
// Register components
require('./views/components');
const app = launch();
/** /**
* Init Notification * Init Notification
*/ */
@ -31,17 +36,12 @@ init(async (os, launch) => {
} }
if ((Notification as any).permission == 'granted') { if ((Notification as any).permission == 'granted') {
registerNotifications(os.stream); registerNotifications(app.$data.os.stream);
} }
} }
// Register components
require('./views/components');
const app = launch();
app.$router.addRoutes([{ app.$router.addRoutes([{
path: '/', component: MkIndex, props: { os } path: '/', component: MkIndex
}]); }]);
}, true); }, true);

View file

@ -1,5 +1,5 @@
<template> <template>
<component v-bind:is="os.isSignedIn ? 'home' : 'welcome'"></component> <component v-bind:is="$root.$data.os.isSignedIn ? 'home' : 'welcome'"></component>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -8,7 +8,6 @@ import HomeView from './home.vue';
import WelcomeView from './welcome.vue'; import WelcomeView from './welcome.vue';
export default Vue.extend({ export default Vue.extend({
props: ['os'],
components: { components: {
home: HomeView, home: HomeView,
welcome: WelcomeView welcome: WelcomeView

View file

@ -19,7 +19,11 @@
</footer> </footer>
<modal name="signup" width="500px" height="auto" scrollable> <modal name="signup" width="500px" height="auto" scrollable>
<header :class="$style.signupFormHeader">新規登録</header> <header :class="$style.signupFormHeader">新規登録</header>
<mk-signup :class="$style.signupForm"></mk-signup> <mk-signup :class="$style.signupForm"/>
</modal>
<modal name="signin" width="500px" height="auto" scrollable>
<header :class="$style.signinFormHeader">ログイン</header>
<mk-signin :class="$style.signinForm"/>
</modal> </modal>
</div> </div>
</template> </template>
@ -31,6 +35,9 @@ export default Vue.extend({
methods: { methods: {
signup() { signup() {
this.$modal.show('signup'); this.$modal.show('signup');
},
signin() {
this.$modal.show('signin');
} }
} }
}); });
@ -139,4 +146,14 @@ export default Vue.extend({
font-size 1.5em font-size 1.5em
color #777 color #777
border-bottom solid 1px #eee border-bottom solid 1px #eee
.signinForm
padding 24px 48px 48px 48px
.signinFormHeader
padding 48px 0 12px 0
margin: 0 48px
font-size 1.5em
color #777
border-bottom solid 1px #eee
</style> </style>

View file

@ -63,7 +63,7 @@ if (localStorage.getItem('should-refresh') == 'true') {
} }
// MiOSを初期化してコールバックする // MiOSを初期化してコールバックする
export default (callback: (os: MiOS, launch: () => Vue) => void, sw = false) => { export default (callback: (launch: () => Vue) => void, sw = false) => {
const mios = new MiOS(sw); const mios = new MiOS(sw);
mios.init(() => { mios.init(() => {
@ -75,6 +75,9 @@ export default (callback: (os: MiOS, launch: () => Vue) => void, sw = false) =>
const launch = () => { const launch = () => {
return new Vue({ return new Vue({
data: {
os: mios
},
router: new VueRouter({ router: new VueRouter({
mode: 'history' mode: 'history'
}), }),
@ -83,7 +86,7 @@ export default (callback: (os: MiOS, launch: () => Vue) => void, sw = false) =>
}; };
try { try {
callback(mios, launch); callback(launch);
} catch (e) { } catch (e) {
panic(e); panic(e);
} }

View file

@ -7,16 +7,14 @@ import './style.styl';
require('./tags'); require('./tags');
import init from '../init'; import init from '../init';
import route from './router';
import MiOS from '../common/mios';
/** /**
* init * init
*/ */
init((mios: MiOS) => { init((launch) => {
// http://qiita.com/junya/items/3ff380878f26ca447f85 // http://qiita.com/junya/items/3ff380878f26ca447f85
document.body.setAttribute('ontouchstart', ''); document.body.setAttribute('ontouchstart', '');
// Start routing // Start routing
route(mios); //route(mios);
}, true); }, true);