From 5209a584a2ed76057ec5edc351cf155154f3f68f Mon Sep 17 00:00:00 2001 From: syuilo <syuilotan@yahoo.co.jp> Date: Sat, 1 Sep 2018 20:47:49 +0900 Subject: [PATCH] Better post form --- package.json | 2 +- src/client/app/app.styl | 14 +- src/client/app/app.vue | 5 +- .../app/desktop/views/pages/welcome.vue | 16 +-- src/client/app/init.ts | 7 +- src/client/app/mobile/api/post.ts | 23 +++ src/client/app/mobile/script.ts | 3 +- .../mobile/views/components/note-detail.vue | 28 +--- .../app/mobile/views/components/note.vue | 28 +--- .../views/components/post-form-dialog.vue | 131 ++++++++++++++++++ src/client/app/mobile/views/pages/home.vue | 10 +- 11 files changed, 184 insertions(+), 83 deletions(-) create mode 100644 src/client/app/mobile/api/post.ts create mode 100644 src/client/app/mobile/views/components/post-form-dialog.vue diff --git a/package.json b/package.json index afdd47b3ce..4c88e02a45 100644 --- a/package.json +++ b/package.json @@ -210,12 +210,12 @@ "vue": "2.5.17", "vue-chartjs": "3.4.0", "vue-cropperjs": "2.2.1", + "vue-js-modal": "1.3.25", "vue-json-tree-view": "2.1.4", "vue-loader": "15.4.1", "vue-router": "3.0.1", "vue-style-loader": "4.1.2", "vue-template-compiler": "2.5.17", - "vue-thin-modal": "1.1.1", "vuedraggable": "2.16.0", "vuex": "3.0.1", "vuex-persistedstate": "2.5.4", diff --git a/src/client/app/app.styl b/src/client/app/app.styl index aaa0d34c71..3911f83a61 100644 --- a/src/client/app/app.styl +++ b/src/client/app/app.styl @@ -6,6 +6,10 @@ html &, * cursor progress !important +html + // iOSのため + overflow auto + body overflow-wrap break-word @@ -126,13 +130,3 @@ pre [data-fa] display inline-block - -.modal-backdrop - z-index 10000 !important - -.modal-content-wrapper - z-index 10001 !important - -.modal-content - padding 0 !important - background-color transparent !important diff --git a/src/client/app/app.vue b/src/client/app/app.vue index 011eb14661..7a46e7dea0 100644 --- a/src/client/app/app.vue +++ b/src/client/app/app.vue @@ -1,6 +1,3 @@ <template> -<div> - <router-view id="app"></router-view> - <modal-portal/> -</div> +<router-view id="app"></router-view> </template> diff --git a/src/client/app/desktop/views/pages/welcome.vue b/src/client/app/desktop/views/pages/welcome.vue index 37c776130e..ae9bf7e678 100644 --- a/src/client/app/desktop/views/pages/welcome.vue +++ b/src/client/app/desktop/views/pages/welcome.vue @@ -38,11 +38,9 @@ <mk-welcome-timeline :max="20"/> </div> - <modal name="signup"> - <div :class="$style.modal"> - <header :class="$style.signupFormHeader">%i18n:@signup%</header> - <mk-signup :class="$style.signupForm"/> - </div> + <modal name="signup" width="500px" height="auto" scrollable> + <header :class="$style.signupFormHeader">%i18n:@signup%</header> + <mk-signup :class="$style.signupForm"/> </modal> </div> </template> @@ -91,10 +89,10 @@ export default Vue.extend({ this.$refs.pointer.style.left = x.left + 'px'; }, signup() { - this.$modal.push('signup'); + this.$modal.show('signup'); }, signin() { - this.$modal.push('signin'); + this.$modal.show('signin'); }, dark() { this.$store.commit('device/set', { @@ -268,10 +266,6 @@ root(isDark) </style> <style lang="stylus" module> -.modal - width 500px - background #fff !important - .signupForm padding 24px 48px 48px 48px diff --git a/src/client/app/init.ts b/src/client/app/init.ts index 0b22509870..82924e92e3 100644 --- a/src/client/app/init.ts +++ b/src/client/app/init.ts @@ -10,8 +10,7 @@ import VAnimateCss from 'v-animate-css'; import Element from 'element-ui'; import ElementLocaleEn from 'element-ui/lib/locale/lang/en'; import ElementLocaleJa from 'element-ui/lib/locale/lang/ja'; -import VueThinModal from 'vue-thin-modal'; -import 'vue-thin-modal/dist/vue-thin-modal.css'; +import VModal from 'vue-js-modal'; import App from './app.vue'; import checkForUpdate from './common/scripts/check-for-update'; @@ -30,9 +29,7 @@ Vue.use(VueRouter); Vue.use(TreeView); Vue.use(VAnimateCss); Vue.use(Element, { locale: elementLocale }); -Vue.use(VueThinModal, { - autoMountPortal: false -}); +Vue.use(VModal); // Register global directives require('./common/views/directives'); diff --git a/src/client/app/mobile/api/post.ts b/src/client/app/mobile/api/post.ts new file mode 100644 index 0000000000..5c0f0af852 --- /dev/null +++ b/src/client/app/mobile/api/post.ts @@ -0,0 +1,23 @@ +import PostForm from '../views/components/post-form-dialog.vue'; + +export default (os) => (opts) => { + const o = opts || {}; + + document.documentElement.style.overflow = 'hidden'; + + function recover() { + document.documentElement.style.overflow = 'auto'; + } + + const vm = new PostForm({ + parent: os.app, + propsData: { + reply: o.reply, + renote: o.renote + } + }).$mount(); + vm.$once('cancel', recover); + vm.$once('posted', recover); + document.body.appendChild(vm.$el); + (vm as any).focus(); +}; diff --git a/src/client/app/mobile/script.ts b/src/client/app/mobile/script.ts index edc2b35529..5b9d45462a 100644 --- a/src/client/app/mobile/script.ts +++ b/src/client/app/mobile/script.ts @@ -14,6 +14,7 @@ import chooseDriveFolder from './api/choose-drive-folder'; import chooseDriveFile from './api/choose-drive-file'; import dialog from './api/dialog'; import input from './api/input'; +import post from './api/post'; import notify from './api/notify'; import MkIndex from './views/pages/index.vue'; @@ -90,7 +91,7 @@ init((launch) => { chooseDriveFile, dialog: dialog(os), input, - post: () => alert('deprecated'), + post: post(os), notify })); }, true); diff --git a/src/client/app/mobile/views/components/note-detail.vue b/src/client/app/mobile/views/components/note-detail.vue index 8a0305cedd..786e57bb22 100644 --- a/src/client/app/mobile/views/components/note-detail.vue +++ b/src/client/app/mobile/views/components/note-detail.vue @@ -75,19 +75,11 @@ <div class="replies" v-if="!compact"> <x-sub v-for="note in replies" :key="note.id" :note="note"/> </div> - - <modal :name="replyFormId"> - <mk-post-form @posted="replyFormClosed" @cancel="replyFormClosed" :reply="p"/> - </modal> - <modal :name="renoteFormId"> - <mk-post-form @posted="renoteFormClosed" @cancel="renoteFormClosed" :renote="p"/> - </modal> </div> </template> <script lang="ts"> import Vue from 'vue'; -import * as uuid from 'uuid'; import parse from '../../../../../mfm/parse'; import MkNoteMenu from '../../../common/views/components/note-menu.vue'; @@ -113,9 +105,7 @@ export default Vue.extend({ return { conversation: [], conversationFetching: false, - replies: [], - replyFormId: uuid(), - renoteFormId: uuid() + replies: [] }; }, @@ -195,19 +185,15 @@ export default Vue.extend({ }, reply() { - this.$modal.push(this.replyFormId); - }, - - replyFormClosed() { - this.$modal.pop(); + (this as any).apis.post({ + reply: this.p + }); }, renote() { - this.$modal.push(this.renoteFormId); - }, - - renoteFormClosed() { - this.$modal.pop(); + (this as any).apis.post({ + renote: this.p + }); }, react() { diff --git a/src/client/app/mobile/views/components/note.vue b/src/client/app/mobile/views/components/note.vue index 4bf4eb34e3..d0cea135f9 100644 --- a/src/client/app/mobile/views/components/note.vue +++ b/src/client/app/mobile/views/components/note.vue @@ -60,19 +60,11 @@ </footer> </div> </article> - - <modal :name="replyFormId"> - <mk-post-form @posted="replyFormClosed" @cancel="replyFormClosed" :reply="p"/> - </modal> - <modal :name="renoteFormId"> - <mk-post-form @posted="renoteFormClosed" @cancel="renoteFormClosed" :renote="p"/> - </modal> </div> </template> <script lang="ts"> import Vue from 'vue'; -import * as uuid from 'uuid'; import parse from '../../../../../mfm/parse'; import MkNoteMenu from '../../../common/views/components/note-menu.vue'; @@ -90,9 +82,7 @@ export default Vue.extend({ return { showContent: false, connection: null, - connectionId: null, - replyFormId: uuid(), - renoteFormId: uuid() + connectionId: null }; }, @@ -205,19 +195,15 @@ export default Vue.extend({ }, reply() { - this.$modal.push(this.replyFormId); - }, - - replyFormClosed() { - this.$modal.pop(); + (this as any).apis.post({ + reply: this.p + }); }, renote() { - this.$modal.push(this.renoteFormId); - }, - - renoteFormClosed() { - this.$modal.pop(); + (this as any).apis.post({ + renote: this.p + }); }, react() { diff --git a/src/client/app/mobile/views/components/post-form-dialog.vue b/src/client/app/mobile/views/components/post-form-dialog.vue new file mode 100644 index 0000000000..6fe9249321 --- /dev/null +++ b/src/client/app/mobile/views/components/post-form-dialog.vue @@ -0,0 +1,131 @@ +<template> +<div class="ulveipglmagnxfgvitaxyszerjwiqmwl"> + <div class="bg" ref="bg" @click="onBgClick"></div> + <div class="main" ref="main" @click.self="onBgClick"> + <mk-post-form ref="form" + :reply="reply" + :renote="renote" + :initial-text="initialText" + :instant="instant" + @posted="onPosted" + @cancel="onCanceled"/> + </div> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import * as anime from 'animejs'; + +export default Vue.extend({ + props: { + reply: { + type: Object, + required: false + }, + renote: { + type: Object, + required: false + }, + initialText: { + type: String, + required: false + }, + instant: { + type: Boolean, + required: false, + default: false + } + }, + + mounted() { + this.$nextTick(() => { + (this.$refs.bg as any).style.pointerEvents = 'auto'; + anime({ + targets: this.$refs.bg, + opacity: 1, + duration: 100, + easing: 'linear' + }); + + anime({ + targets: this.$refs.main, + opacity: 1, + translateY: [-16, 0], + duration: 300, + easing: 'easeOutQuad' + }); + }); + }, + + methods: { + focus() { + this.$refs.form.focus(); + }, + + close() { + (this.$refs.bg as any).style.pointerEvents = 'none'; + anime({ + targets: this.$refs.bg, + opacity: 0, + duration: 300, + easing: 'linear' + }); + + (this.$refs.main as any).style.pointerEvents = 'none'; + anime({ + targets: this.$refs.main, + opacity: 0, + translateY: 16, + duration: 300, + easing: 'easeOutQuad', + complete: () => this.$destroy() + }); + }, + + onBgClick() { + this.$emit('cancel'); + this.close(); + }, + + onPosted() { + this.$emit('posted'); + this.close(); + }, + + onCanceled() { + this.$emit('cancel'); + this.close(); + } + } +}); +</script> + +<style lang="stylus" scoped> +.ulveipglmagnxfgvitaxyszerjwiqmwl + > .bg + display block + position fixed + z-index 10000 + top 0 + left 0 + width 100% + height 100% + background rgba(#000, 0.7) + opacity 0 + pointer-events none + + > .main + display block + position fixed + z-index 10000 + top 0 + left 0 + right 0 + height 100% + overflow auto + margin 0 auto 0 auto + opacity 0 + transform translateY(-16px) + +</style> diff --git a/src/client/app/mobile/views/pages/home.vue b/src/client/app/mobile/views/pages/home.vue index a03fa03c5f..706c9cd28b 100644 --- a/src/client/app/mobile/views/pages/home.vue +++ b/src/client/app/mobile/views/pages/home.vue @@ -42,10 +42,6 @@ <mk-user-list-timeline v-if="src == 'list'" ref="tl" :key="list.id" :list="list"/> </div> </main> - - <modal name="postForm"> - <mk-post-form @posted="postFormClosed" @cancel="postFormClosed"/> - </modal> </mk-ui> </template> @@ -111,11 +107,7 @@ export default Vue.extend({ methods: { fn() { - this.$modal.push('postForm'); - }, - - postFormClosed() { - this.$modal.pop(); + (this as any).apis.post(); }, saveSrc() {