summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-06-14 14:52:37 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-06-14 14:52:37 +0900
commita1ae832129e8bfe8c082064349e2b9973be5f0e5 (patch)
treee143eb1a039179794bd6f23b65bdbc88e549a317 /src
parentwip (diff)
downloadmisskey-a1ae832129e8bfe8c082064349e2b9973be5f0e5.tar.gz
misskey-a1ae832129e8bfe8c082064349e2b9973be5f0e5.tar.bz2
misskey-a1ae832129e8bfe8c082064349e2b9973be5f0e5.zip
wip
Diffstat (limited to 'src')
-rw-r--r--src/client/app/common/views/components/index.ts12
-rw-r--r--src/client/app/common/views/components/signup.vue182
-rw-r--r--src/client/app/common/views/components/ui/button.vue (renamed from src/client/app/common/views/components/material/button.vue)8
-rw-r--r--src/client/app/common/views/components/ui/form.vue28
-rw-r--r--src/client/app/common/views/components/ui/group.vue23
-rw-r--r--src/client/app/common/views/components/ui/input.vue215
-rw-r--r--src/client/app/common/views/components/ui/switch.vue199
-rw-r--r--src/client/app/common/views/components/ui/textarea.vue (renamed from src/client/app/common/views/components/material/input.vue)74
-rw-r--r--src/client/app/mobile/views/pages/settings.vue170
-rw-r--r--src/client/app/mobile/views/pages/settings/settings.profile.vue83
-rw-r--r--src/client/app/mobile/views/pages/signup.vue2
-rw-r--r--src/client/app/mobile/views/pages/welcome.vue8
12 files changed, 658 insertions, 346 deletions
diff --git a/src/client/app/common/views/components/index.ts b/src/client/app/common/views/components/index.ts
index 5dc466857c..060af388b3 100644
--- a/src/client/app/common/views/components/index.ts
+++ b/src/client/app/common/views/components/index.ts
@@ -29,8 +29,12 @@ import fileTypeIcon from './file-type-icon.vue';
import Switch from './switch.vue';
import Othello from './othello.vue';
import welcomeTimeline from './welcome-timeline.vue';
-import uiInput from './material/input.vue';
-import uiButton from './material/button.vue';
+import uiInput from './ui/input.vue';
+import uiButton from './ui/button.vue';
+import uiGroup from './ui/group.vue';
+import uiForm from './ui/form.vue';
+import uiTextarea from './ui/textarea.vue';
+import uiSwitch from './ui/switch.vue';
Vue.component('mk-analog-clock', analogClock);
Vue.component('mk-menu', menu);
@@ -63,3 +67,7 @@ Vue.component('mk-othello', Othello);
Vue.component('mk-welcome-timeline', welcomeTimeline);
Vue.component('ui-input', uiInput);
Vue.component('ui-button', uiButton);
+Vue.component('ui-group', uiGroup);
+Vue.component('ui-form', uiForm);
+Vue.component('ui-textarea', uiTextarea);
+Vue.component('ui-switch', uiSwitch);
diff --git a/src/client/app/common/views/components/signup.vue b/src/client/app/common/views/components/signup.vue
index 3adb10f2c3..d1621a4848 100644
--- a/src/client/app/common/views/components/signup.vue
+++ b/src/client/app/common/views/components/signup.vue
@@ -1,50 +1,40 @@
<template>
<form class="mk-signup" @submit.prevent="onSubmit" autocomplete="off">
- <label class="username">
- <ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" autocomplete="off" required @input="onChangeUsername">
- <span>%i18n:@username%</span>
- <span slot="prefix">@</span>
- <span slot="suffix">@{{ host }}</span>
- <p slot="text" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%%i18n:@checking%</p>
- <p slot="text" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw%%i18n:@available%</p>
- <p slot="text" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@unavailable%</p>
- <p slot="text" v-if="usernameState == 'error'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@error%</p>
- <p slot="text" v-if="usernameState == 'invalid-format'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@invalid-format%</p>
- <p slot="text" v-if="usernameState == 'min-range'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@too-short%</p>
- <p slot="text" v-if="usernameState == 'max-range'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@too-long%</p>
- </ui-input>
- </label>
- <label class="password">
- <ui-input v-model="password" type="password" autocomplete="off" required @input="onChangePassword">
- <span>%i18n:@password%</span>
- <span slot="prefix">%fa:lock%</span>
- <div slot="text">
-
- </div>
- </ui-input>
- <div class="meter" v-show="passwordStrength != ''" :data-strength="passwordStrength">
- <div class="value" ref="passwordMetar"></div>
+ <ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" autocomplete="off" required @input="onChangeUsername">
+ <span>%i18n:@username%</span>
+ <span slot="prefix">@</span>
+ <span slot="suffix">@{{ host }}</span>
+ <p slot="text" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw% %i18n:@checking%</p>
+ <p slot="text" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw% %i18n:@available%</p>
+ <p slot="text" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@unavailable%</p>
+ <p slot="text" v-if="usernameState == 'error'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@error%</p>
+ <p slot="text" v-if="usernameState == 'invalid-format'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@invalid-format%</p>
+ <p slot="text" v-if="usernameState == 'min-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-short%</p>
+ <p slot="text" v-if="usernameState == 'max-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-long%</p>
+ </ui-input>
+ <ui-input v-model="password" type="password" autocomplete="off" required @input="onChangePassword" :with-password-meter="true">
+ <span>%i18n:@password%</span>
+ <span slot="prefix">%fa:lock%</span>
+ <div slot="text">
+ <p slot="text" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@weak-password%</p>
+ <p slot="text" v-if="passwordStrength == 'medium'" style="color:#3CB7B5">%fa:check .fw% %i18n:@normal-password%</p>
+ <p slot="text" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw% %i18n:@strong-password%</p>
</div>
- <p class="info" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@weak-password%</p>
- <p class="info" v-if="passwordStrength == 'medium'" style="color:#3CB7B5">%fa:check .fw%%i18n:@normal-password%</p>
- <p class="info" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw%%i18n:@strong-password%</p>
- </label>
- <label class="retype-password">
- <ui-input v-model="retypedPassword" type="password" autocomplete="off" required @input="onChangePasswordRetype">
- <span>%i18n:@password% (%i18n:@retype%)</span>
- <span slot="prefix">%fa:lock%</span>
- </ui-input>
- <p class="info" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw%%i18n:@password-matched%</p>
- <p class="info" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw%%i18n:@password-not-matched%</p>
- </label>
- <label class="recaptcha">
- <div class="g-recaptcha" :data-sitekey="recaptchaSitekey"></div>
- </label>
- <label class="agree-tou">
+ </ui-input>
+ <ui-input v-model="retypedPassword" type="password" autocomplete="off" required @input="onChangePasswordRetype">
+ <span>%i18n:@password% (%i18n:@retype%)</span>
+ <span slot="prefix">%fa:lock%</span>
+ <div slot="text">
+ <p slot="text" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw% %i18n:@password-matched%</p>
+ <p slot="text" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@password-not-matched%</p>
+ </div>
+ </ui-input>
+ <div class="g-recaptcha" :data-sitekey="recaptchaSitekey" style="margin: 16px 0;"></div>
+ <label class="agree-tou" style="display: block; margin: 16px 0;">
<input name="agree-tou" type="checkbox" autocomplete="off" required/>
<p><a :href="touUrl" target="_blank">利用規約</a>に同意する</p>
</label>
- <button type="submit">%i18n:@create%</button>
+ <ui-button type="submit">%i18n:@create%</ui-button>
</form>
</template>
@@ -112,7 +102,6 @@ export default Vue.extend({
const strength = getPasswordStrength(this.password);
this.passwordStrength = strength > 0.7 ? 'high' : strength > 0.3 ? 'medium' : 'low';
- (this.$refs.passwordMetar as any).style.width = `${strength * 100}%`;
},
onChangePasswordRetype() {
if (this.retypedPassword == '') {
@@ -156,100 +145,6 @@ export default Vue.extend({
.mk-signup
min-width 302px
- label
- display block
- margin 0 0 16px 0
-
- > .caption
- margin 0 0 4px 0
- color #828888
- font-size 0.95em
-
- > [data-fa]
- margin-right 0.25em
- color #96adac
-
- > .info
- display block
- margin 4px 0
- font-size 0.8em
-
- > [data-fa]
- margin-right 0.3em
-
- &.username
- .profile-page-url-preview
- display block
- margin 4px 8px 0 4px
- font-size 0.8em
- color #888
-
- &:empty
- display none
-
- &:not(:empty) + .info
- margin-top 0
-
- &.password
- .meter
- display block
- margin-top 8px
- width 100%
- height 8px
-
- &[data-strength='']
- display none
-
- &[data-strength='low']
- > .value
- background #d73612
-
- &[data-strength='medium']
- > .value
- background #d7ca12
-
- &[data-strength='high']
- > .value
- background #61bb22
-
- > .value
- display block
- width 0%
- height 100%
- background transparent
- border-radius 4px
- transition all 0.1s ease
-
- [type=text], [type=password]
- user-select text
- display inline-block
- cursor auto
- padding 0 12px
- margin 0
- width 100%
- line-height 44px
- font-size 1em
- color #333 !important
- background #fff !important
- outline none
- border solid 1px rgba(#000, 0.1)
- border-radius 4px
- box-shadow 0 0 0 114514px #fff inset
- transition all .3s ease
-
- &:hover
- border-color rgba(#000, 0.2)
- transition all .1s ease
-
- &:focus
- color $theme-color !important
- border-color $theme-color
- box-shadow 0 0 0 1024px #fff inset, 0 0 0 4px rgba($theme-color, 10%)
- transition all 0s ease
-
- &:disabled
- opacity 0.5
-
.agree-tou
padding 4px
border-radius 4px
@@ -267,19 +162,4 @@ export default Vue.extend({
display inline
color #555
- button
- margin 0
- padding 16px
- width 100%
- font-size 1em
- color #fff
- background $theme-color
- border-radius 3px
-
- &:hover
- background lighten($theme-color, 5%)
-
- &:active
- background darken($theme-color, 5%)
-
</style>
diff --git a/src/client/app/common/views/components/material/button.vue b/src/client/app/common/views/components/ui/button.vue
index 8dacedbac6..57747fd469 100644
--- a/src/client/app/common/views/components/material/button.vue
+++ b/src/client/app/common/views/components/ui/button.vue
@@ -25,7 +25,7 @@ export default Vue.extend({
> button
display block
width 100%
- margin 32px 0 16px 0
+ margin 0
padding 0
color $theme-color-foreground
font-weight bold
@@ -37,4 +37,10 @@ export default Vue.extend({
outline none
box-shadow none
+ &:hover
+ background lighten($theme-color, 5%)
+
+ &:active
+ background darken($theme-color, 5%)
+
</style>
diff --git a/src/client/app/common/views/components/ui/form.vue b/src/client/app/common/views/components/ui/form.vue
new file mode 100644
index 0000000000..0893af1bce
--- /dev/null
+++ b/src/client/app/common/views/components/ui/form.vue
@@ -0,0 +1,28 @@
+<template>
+<div class="ui-form">
+ <fieldset :disabled="disabled">
+ <slot></slot>
+ </fieldset>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+export default Vue.extend({
+ props: {
+ disabled: {
+ type: String,
+ required: false
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+@import '~const.styl'
+
+.ui-form
+ > fieldset
+ border none
+
+</style>
diff --git a/src/client/app/common/views/components/ui/group.vue b/src/client/app/common/views/components/ui/group.vue
new file mode 100644
index 0000000000..fb29458ce8
--- /dev/null
+++ b/src/client/app/common/views/components/ui/group.vue
@@ -0,0 +1,23 @@
+<template>
+<div class="ui-group">
+ <header>
+ <slot name="title"></slot>
+ </header>
+
+ <slot></slot>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+export default Vue.extend({});
+</script>
+
+<style lang="stylus" scoped>
+@import '~const.styl'
+
+.ui-group
+ > header
+ font-weight bold
+
+</style>
diff --git a/src/client/app/common/views/components/ui/input.vue b/src/client/app/common/views/components/ui/input.vue
new file mode 100644
index 0000000000..7461aac7fe
--- /dev/null
+++ b/src/client/app/common/views/components/ui/input.vue
@@ -0,0 +1,215 @@
+<template>
+<div class="ui-input" :class="{ focused, filled }">
+ <div class="input" @click="focus">
+ <div class="password-meter" v-if="withPasswordMeter" v-show="passwordStrength != ''" :data-strength="passwordStrength">
+ <div class="value" ref="passwordMetar"></div>
+ </div>
+ <span class="label" ref="label"><slot></slot></span>
+ <div class="prefix" ref="prefix"><slot name="prefix"></slot></div>
+ <input ref="input"
+ :type="type"
+ :value="value"
+ :required="required"
+ :readonly="readonly"
+ :pattern="pattern"
+ :autocomplete="autocomplete"
+ @input="$emit('input', $event.target.value)"
+ @focus="focused = true"
+ @blur="focused = false">
+ <div class="suffix"><slot name="suffix"></slot></div>
+ </div>
+ <div class="text"><slot name="text"></slot></div>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+const getPasswordStrength = require('syuilo-password-strength');
+
+export default Vue.extend({
+ props: {
+ value: {
+ required: false
+ },
+ type: {
+ type: String,
+ required: false
+ },
+ required: {
+ type: Boolean,
+ required: false
+ },
+ readonly: {
+ type: Boolean,
+ required: false
+ },
+ pattern: {
+ type: String,
+ required: false
+ },
+ autocomplete: {
+ type: String,
+ required: false
+ },
+ withPasswordMeter: {
+ type: Boolean,
+ required: false,
+ default: false
+ }
+ },
+ data() {
+ return {
+ focused: false,
+ passwordStrength: ''
+ }
+ },
+ computed: {
+ filled(): boolean {
+ return this.value != '' && this.value != null;
+ }
+ },
+ watch: {
+ value(v) {
+ if (this.withPasswordMeter) {
+ if (v == '') {
+ this.passwordStrength = '';
+ return;
+ }
+
+ const strength = getPasswordStrength(v);
+ this.passwordStrength = strength > 0.7 ? 'high' : strength > 0.3 ? 'medium' : 'low';
+ (this.$refs.passwordMetar as any).style.width = `${strength * 100}%`;
+ }
+ }
+ },
+ mounted() {
+ if (this.$refs.prefix) {
+ this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px';
+ }
+ },
+ methods: {
+ focus() {
+ this.$refs.input.focus();
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+@import '~const.styl'
+
+.ui-input
+ margin 32px 0
+
+ > .input
+ display flex
+ padding 6px 12px
+ background rgba(#000, 0.035)
+ border-radius 6px
+
+ > .password-meter
+ position absolute
+ top 0
+ left 0
+ width 100%
+ height 100%
+ border-radius 6px
+ overflow hidden
+ opacity 0.3
+
+ &[data-strength='']
+ display none
+
+ &[data-strength='low']
+ > .value
+ background #d73612
+
+ &[data-strength='medium']
+ > .value
+ background #d7ca12
+
+ &[data-strength='high']
+ > .value
+ background #61bb22
+
+ > .value
+ display block
+ width 0%
+ height 100%
+ background transparent
+ border-radius 6px
+ transition all 0.1s ease
+
+ > .label
+ position absolute
+ top 6px
+ left 0
+ pointer-events none
+ transition 0.4s cubic-bezier(0.25, 0.8, 0.25, 1)
+ transition-duration 0.3s
+ font-size 16px
+ line-height 32px
+ color rgba(#000, 0.54)
+ pointer-events none
+ //will-change transform
+ transform-origin top left
+ transform scale(1)
+
+ > input
+ display block
+ flex 1
+ width 100%
+ padding 0
+ font inherit
+ font-weight bold
+ font-size 16px
+ line-height 32px
+ background transparent
+ border none
+ border-radius 0
+ outline none
+ box-shadow none
+
+ > .prefix
+ > .suffix
+ display block
+ align-self center
+ justify-self center
+ font-size 16px
+ line-height 32px
+ color rgba(#000, 0.54)
+ pointer-events none
+
+ > *
+ display block
+ min-width 16px
+
+ > .prefix
+ padding-right 4px
+
+ > .suffix
+ padding-left 4px
+
+ > .text
+ margin 6px 0
+ font-size 13px
+
+ *
+ margin 0
+
+ &.focused
+ > .input
+ background rgba(#000, 0.05)
+
+ > .label
+ color $theme-color
+
+ &.focused
+ &.filled
+ > .input
+ > .label
+ top -24px
+ left 0 !important
+ transform scale(0.8)
+
+</style>
diff --git a/src/client/app/common/views/components/ui/switch.vue b/src/client/app/common/views/components/ui/switch.vue
new file mode 100644
index 0000000000..2cac6262f1
--- /dev/null
+++ b/src/client/app/common/views/components/ui/switch.vue
@@ -0,0 +1,199 @@
+<template>
+<div
+ class="ui-switch"
+ :class="{ disabled, checked }"
+ role="switch"
+ :aria-checked="checked"
+ :aria-disabled="disabled"
+ @click="switchValue"
+ @mouseover="mouseenter"
+>
+ <input
+ type="checkbox"
+ @change="handleChange"
+ ref="input"
+ :disabled="disabled"
+ @keydown.enter="switchValue"
+ >
+ <span class="button">
+ <span :style="{ transform }"></span>
+ </span>
+ <span class="label">
+ <span :aria-hidden="!checked"><slot></slot></span>
+ <p :aria-hidden="!checked">
+ <slot name="text"></slot>
+ </p>
+ </span>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+export default Vue.extend({
+ props: {
+ value: {
+ type: Boolean,
+ default: false
+ },
+ disabled: {
+ type: Boolean,
+ default: false
+ }
+ },/*
+ created() {
+ if (!~[true, false].indexOf(this.value)) {
+ this.$emit('input', false);
+ }
+ },*/
+ computed: {
+ checked(): boolean {
+ return this.value;
+ },
+ transform(): string {
+ return this.checked ? 'translate3d(14px, 0, 0)' : '';
+ }
+ },
+ watch: {
+ value() {
+ (this.$el).style.transition = 'all 0.3s';
+ (this.$refs.input as any).checked = this.checked;
+ }
+ },
+ mounted() {
+ (this.$refs.input as any).checked = this.checked;
+ },
+ methods: {
+ mouseenter() {
+ (this.$el).style.transition = 'all 0s';
+ },
+ handleChange() {
+ (this.$el).style.transition = 'all 0.3s';
+ this.$emit('input', !this.checked);
+ this.$emit('change', !this.checked);
+ this.$nextTick(() => {
+ // set input's checked property
+ // in case parent refuses to change component's value
+ (this.$refs.input as any).checked = this.checked;
+ });
+ },
+ switchValue() {
+ !this.disabled && this.handleChange();
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+@import '~const.styl'
+
+root(isDark)
+ display flex
+ margin 16px 0
+ cursor pointer
+ transition all 0.3s
+
+ > *
+ user-select none
+
+ &.disabled
+ opacity 0.6
+ cursor not-allowed
+
+ &.checked
+ > .button
+ background-color $theme-color
+ border-color $theme-color
+
+ > .label
+ > span
+ color $theme-color
+
+ &:hover
+ > .label
+ > span
+ color darken($theme-color, 10%)
+
+ > .button
+ background darken($theme-color, 10%)
+ border-color darken($theme-color, 10%)
+
+ &:hover
+ > .label
+ > span
+ color isDark ? #fff : #2e3338
+
+ > .button
+ $color = isDark ? #15181d : #ced2da
+ background $color
+ border-color $color
+
+ > input
+ position absolute
+ width 0
+ height 0
+ opacity 0
+ margin 0
+
+ &:focus + .button
+ &:after
+ content ""
+ pointer-events none
+ position absolute
+ top -5px
+ right -5px
+ bottom -5px
+ left -5px
+ border 2px solid rgba($theme-color, 0.3)
+ border-radius 14px
+
+ > .button
+ $color = isDark ? #1c1f25 : #dcdfe6
+
+ display inline-block
+ margin 0
+ width 46px
+ min-width 46px
+ height 32px
+ min-height 32px
+ background $color
+ border 1px solid $color
+ outline none
+ border-radius 6px
+ transition inherit
+
+ > *
+ position absolute
+ top 1px
+ left 1px
+ border-radius 6px
+ transition transform 0.3s
+ width 28px
+ height 28px
+ background-color #fff
+
+ > .label
+ margin-left 8px
+ display block
+ font-size 16px
+ cursor pointer
+ transition inherit
+
+ > span
+ display block
+ line-height 32px
+ font-weight bold
+ color isDark ? #c4ccd2 : #4a535a
+ transition inherit
+
+ > p
+ margin 0
+ //font-size 90%
+ color isDark ? #78858e : #9daab3
+
+.ui-switch[data-darkmode]
+ root(true)
+
+.ui-switch:not([data-darkmode])
+ root(false)
+
+</style>
diff --git a/src/client/app/common/views/components/material/input.vue b/src/client/app/common/views/components/ui/textarea.vue
index 6564b3aa6c..0a9f60f1bc 100644
--- a/src/client/app/common/views/components/material/input.vue
+++ b/src/client/app/common/views/components/ui/textarea.vue
@@ -1,17 +1,17 @@
<template>
-<div class="ui-input" :class="{ focused, filled }">
+<div class="ui-textarea" :class="{ focused, filled }">
<div class="input">
<span class="label" ref="label"><slot></slot></span>
- <div class="prefix" ref="prefix" @click="focus"><slot name="prefix"></slot></div>
- <input ref="input"
- :type="type"
+ <textarea ref="input"
:value="value"
:required="required"
:readonly="readonly"
+ :pattern="pattern"
+ :autocomplete="autocomplete"
@input="$emit('input', $event.target.value)"
@focus="focused = true"
@blur="focused = false">
- <div class="suffix" @click="focus"><slot name="suffix"></slot></div>
+ </textarea>
</div>
<div class="text"><slot name="text"></slot></div>
</div>
@@ -19,15 +19,13 @@
<script lang="ts">
import Vue from 'vue';
+const getPasswordStrength = require('syuilo-password-strength');
+
export default Vue.extend({
props: {
value: {
required: false
},
- type: {
- type: String,
- required: false
- },
required: {
type: Boolean,
required: false
@@ -35,11 +33,20 @@ export default Vue.extend({
readonly: {
type: Boolean,
required: false
+ },
+ pattern: {
+ type: String,
+ required: false
+ },
+ autocomplete: {
+ type: String,
+ required: false
}
},
data() {
return {
- focused: false
+ focused: false,
+ passwordStrength: ''
}
},
computed: {
@@ -47,9 +54,6 @@ export default Vue.extend({
return this.value != '' && this.value != null;
}
},
- mounted() {
- this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px';
- },
methods: {
focus() {
this.$refs.input.focus();
@@ -61,20 +65,18 @@ export default Vue.extend({
<style lang="stylus" scoped>
@import '~const.styl'
-.ui-input
- margin-bottom 16px
- padding-top 16px
+.ui-textarea
+ margin 32px 0
> .input
- display flex
- padding 6px 12px
+ padding 12px
background rgba(#000, 0.035)
border-radius 6px
> .label
position absolute
top 6px
- left 0
+ left 12px
pointer-events none
transition 0.4s cubic-bezier(0.25, 0.8, 0.25, 1)
transition-duration 0.3s
@@ -82,42 +84,29 @@ export default Vue.extend({
line-height 32px
color rgba(#000, 0.54)
pointer-events none
+ //will-change transform
+ transform-origin top left
+ transform scale(1)
- > input
+ > textarea
display block
- flex 1
width 100%
+ min-height 100px
padding 0
font inherit
font-weight bold
font-size 16px
- line-height 32px
background transparent
border none
border-radius 0
outline none
box-shadow none
- > .prefix
- > .suffix
- display block
- align-self center
- justify-self center
- font-size 16px
- line-height 32px
- color rgba(#000, 0.54)
-
- > .prefix
- padding-right 4px
-
- > .suffix
- padding-left 4px
-
> .text
- margin 8px 0
- font-size 14px
+ margin 6px 0
+ font-size 13px
- > p
+ *
margin 0
&.focused
@@ -131,9 +120,8 @@ export default Vue.extend({
&.filled
> .input
> .label
- top -20px
+ top -24px
left 0 !important
- font-size 12px
- line-height 20px
+ transform scale(0.8)
</style>
diff --git a/src/client/app/mobile/views/pages/settings.vue b/src/client/app/mobile/views/pages/settings.vue
index 8da7a76633..716f7afc0c 100644
--- a/src/client/app/mobile/views/pages/settings.vue
+++ b/src/client/app/mobile/views/pages/settings.vue
@@ -6,125 +6,105 @@
<div>
<x-profile/>
- <md-card>
- <md-card-header>
- <div class="md-title">%fa:palette% %i18n:@design%</div>
- </md-card-header>
+ <ui-group>
+ <div slot="title">%fa:palette% %i18n:@design%</div>
+
+ <div>
+ <ui-switch v-model="darkmode">%i18n:@dark-mode%</ui-switch>
+ </div>
+
+ <div>
+ <ui-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons">%i18n:@circle-icons%</ui-switch>
+ </div>
+
+ <div>
+ <div class="md-body-2">%i18n:@timeline%</div>
- <md-card-content>
<div>
- <md-switch v-model="darkmode">%i18n:@dark-mode%</md-switch>
+ <ui-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget">%i18n:@show-reply-target%</ui-switch>
</div>
<div>
- <md-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons">%i18n:@circle-icons%</md-switch>
+ <ui-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes">%i18n:@show-my-renotes%</ui-switch>
</div>
<div>
- <div class="md-body-2">%i18n:@timeline%</div>
-
- <div>
- <md-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget">%i18n:@show-reply-target%</md-switch>
- </div>
-
- <div>
- <md-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes">%i18n:@show-my-renotes%</md-switch>
- </div>
-
- <div>
- <md-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</md-switch>
- </div>
+ <ui-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</ui-switch>
</div>
+ </div>
- <div>
- <div class="md-body-2">%i18n:@post-style%</div>
+ <div>
+ <div class="md-body-2">%i18n:@post-style%</div>
- <md-radio v-model="postStyle" value="standard">%i18n:@post-style-standard%</md-radio>
- <md-radio v-model="postStyle" value="smart">%i18n:@post-style-smart%</md-radio>
- </div>
- </md-card-content>
- </md-card>
+ <md-radio v-model="postStyle" value="standard">%i18n:@post-style-standard%</md-radio>
+ <md-radio v-model="postStyle" value="smart">%i18n:@post-style-smart%</md-radio>
+ </div>
+ </ui-group>
- <md-card>
- <md-card-header>
- <div class="md-title">%fa:cog% %i18n:@behavior%</div>
- </md-card-header>
+ <ui-group>
+ <div slot="title">%fa:cog% %i18n:@behavior%</div>
- <md-card-content>
- <div>
- <md-switch v-model="$store.state.settings.fetchOnScroll" @change="onChangeFetchOnScroll">%i18n:@fetch-on-scroll%</md-switch>
- </div>
+ <div>
+ <ui-switch v-model="$store.state.settings.fetchOnScroll" @change="onChangeFetchOnScroll">%i18n:@fetch-on-scroll%</ui-switch>
+ </div>
- <div>
- <md-switch v-model="$store.state.settings.disableViaMobile" @change="onChangeDisableViaMobile">%i18n:@disable-via-mobile%</md-switch>
- </div>
+ <div>
+ <ui-switch v-model="$store.state.settings.disableViaMobile" @change="onChangeDisableViaMobile">%i18n:@disable-via-mobile%</ui-switch>
+ </div>
- <div>
- <md-switch v-model="loadRawImages">%i18n:@load-raw-images%</md-switch>
- </div>
+ <div>
+ <ui-switch v-model="loadRawImages">%i18n:@load-raw-images%</ui-switch>
+ </div>
- <div>
- <md-switch v-model="$store.state.settings.loadRemoteMedia" @change="onChangeLoadRemoteMedia">%i18n:@load-remote-media%</md-switch>
- </div>
+ <div>
+ <ui-switch v-model="$store.state.settings.loadRemoteMedia" @change="onChangeLoadRemoteMedia">%i18n:@load-remote-media%</ui-switch>
+ </div>
- <div>
- <md-switch v-model="lightmode">%i18n:@i-am-under-limited-internet%</md-switch>
- </div>
- </md-card-content>
- </md-card>
+ <div>
+ <ui-switch v-model="lightmode">%i18n:@i-am-under-limited-internet%</ui-switch>
+ </div>
+ </ui-group>
- <md-card>
- <md-card-header>
- <div class="md-title">%fa:language% %i18n:@lang%</div>
- </md-card-header>
+ <ui-group>
+ <div slot="title">%fa:language% %i18n:@lang%</div>
- <md-card-content>
- <md-field>
- <md-select v-model="lang" placeholder="%i18n:@auto%">
- <md-optgroup label="%i18n:@recommended%">
- <md-option value="">%i18n:@auto%</md-option>
- </md-optgroup>
+ <md-field>
+ <md-select v-model="lang" placeholder="%i18n:@auto%">
+ <md-optgroup label="%i18n:@recommended%">
+ <md-option value="">%i18n:@auto%</md-option>
+ </md-optgroup>
- <md-optgroup label="%i18n:@specify-language%">
- <md-option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</md-option>
- </md-optgroup>
- </md-select>
- </md-field>
- <span class="md-helper-text">%fa:info-circle% %i18n:@lang-tip%</span>
- </md-card-content>
- </md-card>
+ <md-optgroup label="%i18n:@specify-language%">
+ <md-option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</md-option>
+ </md-optgroup>
+ </md-select>
+ </md-field>
+ <span class="md-helper-text">%fa:info-circle% %i18n:@lang-tip%</span>
+ </ui-group>
- <md-card>
- <md-card-header>
- <div class="md-title">%fa:B twitter% %i18n:@twitter%</div>
- </md-card-header>
+ <ui-group>
+ <div slot="title">%fa:B twitter% %i18n:@twitter%</div>
- <md-card-content>
- <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">{{ $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>
+ <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">{{ $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>
+ </ui-group>
- <md-card>
- <md-card-header>
- <div class="md-title">%fa:sync-alt% %i18n:@update%</div>
- </md-card-header>
+ <ui-group>
+ <div slot="title">%fa:sync-alt% %i18n:@update%</div>
- <md-card-content>
- <div>%i18n:@version% <i>{{ version }}</i></div>
- <template v-if="latestVersion !== undefined">
- <div>%i18n:@latest-version% <i>{{ latestVersion ? latestVersion : version }}</i></div>
- </template>
- <md-button class="md-raised md-primary" @click="checkForUpdate" :disabled="checkingForUpdate">
- <template v-if="checkingForUpdate">%i18n:@update-checking%<mk-ellipsis/></template>
- <template v-else>%i18n:@check-for-updates%</template>
- </md-button>
- </md-card-content>
- </md-card>
+ <div>%i18n:@version% <i>{{ version }}</i></div>
+ <template v-if="latestVersion !== undefined">
+ <div>%i18n:@latest-version% <i>{{ latestVersion ? latestVersion : version }}</i></div>
+ </template>
+ <md-button class="md-raised md-primary" @click="checkForUpdate" :disabled="checkingForUpdate">
+ <template v-if="checkingForUpdate">%i18n:@update-checking%<mk-ellipsis/></template>
+ <template v-else>%i18n:@check-for-updates%</template>
+ </md-button>
+ </ui-group>
</div>
<p><small>ver {{ version }} ({{ codename }})</small></p>
</main>
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 f3444eb1f0..73d876d14e 100644
--- a/src/client/app/mobile/views/pages/settings/settings.profile.vue
+++ b/src/client/app/mobile/views/pages/settings/settings.profile.vue
@@ -1,62 +1,47 @@
<template>
- <md-card>
- <md-card-header>
- <div class="md-title">%fa:pencil-alt% %i18n:@title%</div>
- </md-card-header>
+<ui-group>
+ <div slot="title">%fa:pencil-alt% %i18n:@title%</div>
- <md-card-content>
- <md-field>
- <label>%i18n:@name%</label>
- <md-input v-model="name" :disabled="saving" md-counter="30"/>
- </md-field>
+ <ui-form :disabled="saving">
+ <ui-input v-model="name" :max="30">
+ <span>%i18n:@name%</span>
+ </ui-input>
- <md-field>
- <label>%i18n:@account%</label>
- <span class="md-prefix">@</span>
- <md-input v-model="username" readonly></md-input>
- <span class="md-suffix">@{{ host }}</span>
- </md-field>
+ <ui-input v-model="username" readonly>
+ <span>%i18n:@account%</span>
+ <span slot="prefix">@</span>
+ <span slot="suffix">@{{ host }}</span>
+ </ui-input>
- <md-field>
- <md-icon>%fa:map-marker-alt%</md-icon>
- <label>%i18n:@location%</label>
- <md-input v-model="location" :disabled="saving"/>
- </md-field>
+ <ui-input v-model="location">
+ <span>%i18n:@location%</span>
+ <span slot="prefix">%fa:map-marker-alt%</span>
+ </ui-input>
- <md-field>
- <md-icon>%fa:birthday-cake%</md-icon>
- <label>%i18n:@birthday%</label>
- <md-input type="date" v-model="birthday" :disabled="saving"/>
- </md-field>
+ <ui-input v-model="birthday" type="date">
+ <span>%i18n:@birthday%</span>
+ <span slot="prefix">%fa:birthday-cake%</span>
+ </ui-input>
- <md-field>
- <label>%i18n:@description%</label>
- <md-textarea v-model="description" :disabled="saving" md-counter="500"/>
- </md-field>
+ <ui-textarea v-model="description" :max="500">
+ <span>%i18n:@description%</span>
+ </ui-textarea>
- <md-field>
- <label>%i18n:@avatar%</label>
- <md-file @md-change="onAvatarChange"/>
- </md-field>
+ <ui-input type="file" @change="onAvatarChange">
+ <span>%i18n:@avatar%</span>
+ <span slot="prefix">%fa:picture-o%</span>
+ </ui-input>
- <md-field>
- <label>%i18n:@banner%</label>
- <md-file @md-change="onBannerChange"/>
- </md-field>
+ <ui-input type="file" @change="onBannerChange">
+ <span>%i18n:@banner%</span>
+ <span slot="prefix">%fa:picture-o%</span>
+ </ui-input>
- <md-dialog-alert
- :md-active.sync="uploading"
- md-content="%18n:!@uploading%"/>
+ <ui-switch v-model="isCat">%i18n:@is-cat%</ui-switch>
- <div>
- <md-switch v-model="isCat">%i18n:@is-cat%</md-switch>
- </div>
- </md-card-content>
-
- <md-card-actions>
- <md-button class="md-primary" :disabled="saving" @click="save">%i18n:@save%</md-button>
- </md-card-actions>
- </md-card>
+ <ui-button @click="save">%i18n:@save%</ui-button>
+ </ui-form>
+</ui-group>
</template>
<script lang="ts">
diff --git a/src/client/app/mobile/views/pages/signup.vue b/src/client/app/mobile/views/pages/signup.vue
index f2b29bca60..47384e2b3c 100644
--- a/src/client/app/mobile/views/pages/signup.vue
+++ b/src/client/app/mobile/views/pages/signup.vue
@@ -18,7 +18,7 @@ export default Vue.extend({});
h1
margin 0
- padding 8px
+ padding 8px 0 0 0
font-size 1.5em
font-weight bold
color #444
diff --git a/src/client/app/mobile/views/pages/welcome.vue b/src/client/app/mobile/views/pages/welcome.vue
index 01b20aa472..3b37a185bd 100644
--- a/src/client/app/mobile/views/pages/welcome.vue
+++ b/src/client/app/mobile/views/pages/welcome.vue
@@ -10,16 +10,16 @@
</div>
<div class="login">
<form @submit.prevent="onSubmit">
- <ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" placeholder="ユーザー名" autofocus required @change="onUsernameChange">
+ <ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" autofocus required @change="onUsernameChange">
<span>ユーザー名</span>
<span slot="prefix">@</span>
<span slot="suffix">@{{ host }}</span>
</ui-input>
- <ui-input v-model="password" type="password" placeholder="パスワード" required>
+ <ui-input v-model="password" type="password" required>
<span>パスワード</span>
<span slot="prefix">%fa:lock%</span>
</ui-input>
- <ui-input v-if="user && user.twoFactorEnabled" v-model="token" type="number" placeholder="トークン" required/>
+ <ui-input v-if="user && user.twoFactorEnabled" v-model="token" type="number" required/>
<ui-button type="submit" :disabled="signing">{{ signing ? 'ログインしています' : 'ログイン' }}</ui-button>
</form>
<div>
@@ -113,7 +113,7 @@ export default Vue.extend({
> .about
margin-top 16px
padding 16px
- color #444
+ color #555
background #fff
border-radius 6px