From c4a59c3912c7ec031d235ba4278ce2d7bc3bc073 Mon Sep 17 00:00:00 2001 From: syuilo <syuilotan@yahoo.co.jp> Date: Tue, 27 Feb 2018 04:36:16 +0900 Subject: [PATCH] Improve usability --- .../views/components/messaging-room.form.vue | 54 +++++++++++++++++-- .../views/components/messaging-room.vue | 54 ++++++++++++++++++- .../desktop/views/components/post-form.vue | 4 +- 3 files changed, 105 insertions(+), 7 deletions(-) diff --git a/src/web/app/common/views/components/messaging-room.form.vue b/src/web/app/common/views/components/messaging-room.form.vue index 48ccaa4d27..3698ccd5b2 100644 --- a/src/web/app/common/views/components/messaging-room.form.vue +++ b/src/web/app/common/views/components/messaging-room.form.vue @@ -1,5 +1,8 @@ <template> -<div class="mk-messaging-form"> +<div class="mk-messaging-form" + @dragover.prevent.stop="onDragover" + @drop.prevent.stop="onDrop" +> <textarea v-model="text" ref="textarea" @@ -42,6 +45,9 @@ export default Vue.extend({ }, canSend(): boolean { return (this.text != null && this.text != '') || this.file != null; + }, + room(): any { + return this.$parent; } }, watch: { @@ -50,6 +56,10 @@ export default Vue.extend({ }, file() { this.saveDraft(); + + if (this.room.isBottom()) { + this.room.scrollToBottom(); + } } }, mounted() { @@ -66,10 +76,46 @@ export default Vue.extend({ onPaste(e) { const data = e.clipboardData; const items = data.items; - for (const item of items) { - if (item.kind == 'file') { - //this.upload(item.getAsFile()); + + if (items.length == 1) { + if (items[0].kind == 'file') { + this.upload(items[0].getAsFile()); } + } else { + if (items[0].kind == 'file') { + alert('メッセージに添付できるのはひとつのファイルのみです'); + } + } + }, + + onDragover(e) { + e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move'; + }, + + onDrop(e): void { + // ファイルだったら + if (e.dataTransfer.files.length == 1) { + this.upload(e.dataTransfer.files[0]); + return; + } else if (e.dataTransfer.files.length > 1) { + alert('メッセージに添付できるのはひとつのファイルのみです'); + return; + } + + // データ取得 + const data = e.dataTransfer.getData('text'); + if (data == null) return; + + try { + // パース + const obj = JSON.parse(data); + + // (ドライブの)ファイルだったら + if (obj.type == 'file') { + this.file = obj.file; + } + } catch (e) { + // not a json, so noop } }, diff --git a/src/web/app/common/views/components/messaging-room.vue b/src/web/app/common/views/components/messaging-room.vue index 310b56f6fc..fb67d126cb 100644 --- a/src/web/app/common/views/components/messaging-room.vue +++ b/src/web/app/common/views/components/messaging-room.vue @@ -1,5 +1,8 @@ <template> -<div class="mk-messaging-room"> +<div class="mk-messaging-room" + @dragover.prevent.stop="onDragover" + @drop.prevent.stop="onDrop" +> <div class="stream"> <p class="init" v-if="init">%fa:spinner .spin%%i18n:common.loading%</p> <p class="empty" v-if="!init && messages.length == 0">%fa:info-circle%%i18n:common.tags.mk-messaging-room.empty%</p> @@ -16,7 +19,7 @@ </div> <footer> <div ref="notifications" class="notifications"></div> - <x-form :user="user"/> + <x-form :user="user" ref="form"/> </footer> </div> </template> @@ -32,7 +35,9 @@ export default Vue.extend({ XMessage, XForm }, + props: ['user', 'isNaked'], + data() { return { init: true, @@ -42,6 +47,7 @@ export default Vue.extend({ connection: null }; }, + computed: { _messages(): any[] { return (this.messages as any).map(message => { @@ -51,6 +57,10 @@ export default Vue.extend({ message._datetext = `${month}月 ${date}日`; return message; }); + }, + + form(): any { + return this.$refs.form; } }, @@ -67,6 +77,7 @@ export default Vue.extend({ this.scrollToBottom(); }); }, + beforeDestroy() { this.connection.off('message', this.onMessage); this.connection.off('read', this.onRead); @@ -74,7 +85,39 @@ export default Vue.extend({ document.removeEventListener('visibilitychange', this.onVisibilitychange); }, + methods: { + onDragover(e) { + e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move'; + }, + + onDrop(e): void { + // ファイルだったら + if (e.dataTransfer.files.length == 1) { + this.form.upload(e.dataTransfer.files[0]); + return; + } else if (e.dataTransfer.files.length > 1) { + alert('メッセージに添付できるのはひとつのファイルのみです'); + return; + } + + // データ取得 + const data = e.dataTransfer.getData('text'); + if (data == null) return; + + try { + // パース + const obj = JSON.parse(data); + + // (ドライブの)ファイルだったら + if (obj.type == 'file') { + this.form.file = obj.file; + } + } catch (e) { + // not a json, so noop + } + }, + fetchMessages() { return new Promise((resolve, reject) => { const max = this.existMoreMessages ? 20 : 10; @@ -96,12 +139,14 @@ export default Vue.extend({ }); }); }, + fetchMoreMessages() { this.fetchingMoreMessages = true; this.fetchMessages().then(() => { this.fetchingMoreMessages = false; }); }, + onMessage(message) { const isBottom = this.isBottom(); @@ -123,6 +168,7 @@ export default Vue.extend({ this.notify('%i18n:common.tags.mk-messaging-room.new-message%'); } }, + onRead(ids) { if (!Array.isArray(ids)) ids = [ids]; ids.forEach(id => { @@ -132,6 +178,7 @@ export default Vue.extend({ } }); }, + isBottom() { const asobi = 64; const current = this.isNaked @@ -142,6 +189,7 @@ export default Vue.extend({ : this.$el.scrollHeight; return current > (max - asobi); }, + scrollToBottom() { if (this.isNaked) { window.scroll(0, document.body.offsetHeight); @@ -149,6 +197,7 @@ export default Vue.extend({ this.$el.scrollTop = this.$el.scrollHeight; } }, + notify(message) { const n = document.createElement('p') as any; n.innerHTML = '%fa:arrow-circle-down%' + message; @@ -163,6 +212,7 @@ export default Vue.extend({ setTimeout(() => n.parentNode.removeChild(n), 1000); }, 4000); }, + onVisibilitychange() { if (document.hidden) return; this.messages.forEach(message => { diff --git a/src/web/app/desktop/views/components/post-form.vue b/src/web/app/desktop/views/components/post-form.vue index ecb686a109..4d43d98d75 100644 --- a/src/web/app/desktop/views/components/post-form.vue +++ b/src/web/app/desktop/views/components/post-form.vue @@ -190,7 +190,9 @@ export default Vue.extend({ this.files.push(obj.file); this.$emit('change-attached-media', this.files); } - } catch (e) { } + } catch (e) { + // not a json, so noop + } }, post() { this.posting = true;