diff --git a/src/web/app/app.vue b/src/web/app/app.vue index 497d47003f..321e003930 100644 --- a/src/web/app/app.vue +++ b/src/web/app/app.vue @@ -1,3 +1,3 @@ <template> - <router-view></router-view> + <router-view id="app"></router-view> </template> diff --git a/src/web/app/common/mios.ts b/src/web/app/common/mios.ts index a37c5d6f78..e3a66f5b11 100644 --- a/src/web/app/common/mios.ts +++ b/src/web/app/common/mios.ts @@ -1,3 +1,4 @@ +import Vue from 'vue'; import { EventEmitter } from 'eventemitter3'; import api from './scripts/api'; import signout from './scripts/signout'; @@ -8,6 +9,8 @@ import ServerStreamManager from './scripts/streaming/server-stream-manager'; import RequestsStreamManager from './scripts/streaming/requests-stream-manager'; import MessagingIndexStreamManager from './scripts/streaming/messaging-index-stream-manager'; +import Err from '../common/views/components/connect-failed.vue'; + //#region environment variables declare const _VERSION_: string; declare const _LANG_: string; @@ -214,8 +217,10 @@ export default class MiOS extends EventEmitter { // When failure .catch(() => { // Render the error screen - //document.body.innerHTML = '<mk-error />'; - //riot.mount('*'); + document.body.innerHTML = '<div id="err"></div>'; + new Vue({ + render: createEl => createEl(Err) + }).$mount('#err'); Progress.done(); }); diff --git a/src/web/app/common/views/components/connect-failed.troubleshooter.vue b/src/web/app/common/views/components/connect-failed.troubleshooter.vue index 49396d1584..bede504b58 100644 --- a/src/web/app/common/views/components/connect-failed.troubleshooter.vue +++ b/src/web/app/common/views/components/connect-failed.troubleshooter.vue @@ -41,8 +41,8 @@ export default Vue.extend({ return { network: navigator.onLine, end: false, - internet: false, - server: false + internet: null, + server: null }; }, mounted() { diff --git a/src/web/app/mobile/views/pages/welcome.vue b/src/web/app/mobile/views/pages/welcome.vue index 959d8cfcad..84e5ae5507 100644 --- a/src/web/app/mobile/views/pages/welcome.vue +++ b/src/web/app/mobile/views/pages/welcome.vue @@ -1,5 +1,146 @@ <template> -<div> - <mk-signin/> +<div class="welcome"> + <h1><b>Misskey</b>へようこそ</h1> + <p>Twitter風ミニブログSNS、Misskeyへようこそ。思ったことを投稿したり、タイムラインでみんなの投稿を読むこともできます。</p> + <div class="form"> + <p>ログイン</p> + <div> + <form @submit.prevent="onSubmit"> + <input v-model="username" type="text" pattern="^[a-zA-Z0-9-]+$" placeholder="ユーザー名" autofocus required @change="onUsernameChange"/> + <input v-model="password" type="password" placeholder="パスワード" required/> + <input v-if="user && user.two_factor_enabled" v-model="token" type="number" placeholder="トークン" required/> + <button type="submit" :disabled="signing">{{ signing ? 'ログインしています' : 'ログイン' }}</button> + </form> + <div> + <a :href="`${apiUrl}/signin/twitter`">Twitterでログイン</a> + </div> + </div> + </div> + <a href="/signup">アカウントを作成する</a> </div> </template> + +<script lang="ts"> +import Vue from 'vue'; +import { apiUrl } from '../../../config'; + +export default Vue.extend({ + data() { + return { + signing: false, + user: null, + username: '', + password: '', + token: '', + apiUrl + }; + }, + mounted() { + document.documentElement.style.background = '#293946'; + }, + methods: { + onUsernameChange() { + (this as any).api('users/show', { + username: this.username + }).then(user => { + this.user = user; + }); + }, + onSubmit() { + this.signing = true; + + (this as any).api('signin', { + username: this.username, + password: this.password, + token: this.user && this.user.two_factor_enabled ? this.token : undefined + }).then(() => { + location.reload(); + }).catch(() => { + alert('something happened'); + this.signing = false; + }); + } + } +}); +</script> + +<style lang="stylus" scoped> +.welcome + padding 16px + margin 0 auto + max-width 500px + + h1 + margin 0 + padding 8px + font-size 1.5em + font-weight normal + color #c3c6ca + + & + p + margin 0 0 16px 0 + padding 0 8px 0 8px + color #949fa9 + + .form + background #fff + border solid 1px rgba(0, 0, 0, 0.2) + border-radius 8px + overflow hidden + + & + a + display block + margin-top 16px + text-align center + + > p + margin 0 + padding 12px 20px + color #555 + background #f5f5f5 + border-bottom solid 1px #ddd + + > div + + > form + padding 16px + border-bottom solid 1px #ddd + + input + display block + padding 12px + margin 0 0 16px 0 + width 100% + font-size 1em + color rgba(0, 0, 0, 0.7) + background #fff + outline none + border solid 1px #ddd + border-radius 4px + + button + display block + width 100% + padding 10px + margin 0 + color #333 + font-size 1em + text-align center + text-decoration none + text-shadow 0 1px 0 rgba(255, 255, 255, 0.9) + background-image linear-gradient(#fafafa, #eaeaea) + border 1px solid #ddd + border-bottom-color #cecece + border-radius 4px + + &:active + background-color #767676 + background-image none + border-color #444 + box-shadow 0 1px 3px rgba(0, 0, 0, 0.075), inset 0 0 5px rgba(0, 0, 0, 0.2) + + > div + padding 16px + text-align center + +</style> diff --git a/webpack/module/rules/base64.ts b/webpack/module/rules/base64.ts deleted file mode 100644 index c2f6b9339e..0000000000 --- a/webpack/module/rules/base64.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Replace base64 symbols - */ - -import * as fs from 'fs'; - -export default () => ({ - enforce: 'pre', - test: /\.(vue|js)$/, - exclude: /node_modules/, - loader: 'string-replace-loader', - query: { - search: /%base64:(.+?)%/g, - replace: (_, key) => { - return fs.readFileSync(__dirname + '/../../../src/web/' + key, 'base64'); - } - } -}); diff --git a/webpack/webpack.config.ts b/webpack/webpack.config.ts index bd8c6d1205..76d2980788 100644 --- a/webpack/webpack.config.ts +++ b/webpack/webpack.config.ts @@ -2,6 +2,7 @@ * webpack configuration */ +import * as fs from 'fs'; const minify = require('html-minifier').minify; import I18nReplacer from '../src/common/build/i18n'; import { pattern as faPattern, replacement as faReplacement } from '../src/common/build/fa'; @@ -19,7 +20,11 @@ global['collapseSpacesReplacement'] = html => { collapseWhitespace: true, collapseInlineTagWhitespace: true, keepClosingSlash: true - }); + }).replace(/\t/g, ''); +}; + +global['base64replacement'] = (_, key) => { + return fs.readFileSync(__dirname + '/../src/web/' + key, 'base64'); }; module.exports = Object.keys(langs).map(lang => { @@ -59,6 +64,12 @@ module.exports = Object.keys(langs).map(lang => { cssSourceMap: false, preserveWhitespace: false } + }, { + loader: 'replace', + query: { + search: /%base64:(.+?)%/g.toString(), + replace: 'base64replacement' + } }, { loader: 'webpack-replace-loader', options: {