Improve usability

This commit is contained in:
syuilo 2018-02-27 04:36:16 +09:00
parent 90de725a07
commit c4a59c3912
3 changed files with 105 additions and 7 deletions

View file

@ -1,5 +1,8 @@
<template> <template>
<div class="mk-messaging-form"> <div class="mk-messaging-form"
@dragover.prevent.stop="onDragover"
@drop.prevent.stop="onDrop"
>
<textarea <textarea
v-model="text" v-model="text"
ref="textarea" ref="textarea"
@ -42,6 +45,9 @@ export default Vue.extend({
}, },
canSend(): boolean { canSend(): boolean {
return (this.text != null && this.text != '') || this.file != null; return (this.text != null && this.text != '') || this.file != null;
},
room(): any {
return this.$parent;
} }
}, },
watch: { watch: {
@ -50,6 +56,10 @@ export default Vue.extend({
}, },
file() { file() {
this.saveDraft(); this.saveDraft();
if (this.room.isBottom()) {
this.room.scrollToBottom();
}
} }
}, },
mounted() { mounted() {
@ -66,10 +76,46 @@ export default Vue.extend({
onPaste(e) { onPaste(e) {
const data = e.clipboardData; const data = e.clipboardData;
const items = data.items; const items = data.items;
for (const item of items) {
if (item.kind == 'file') { if (items.length == 1) {
//this.upload(item.getAsFile()); 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
} }
}, },

View file

@ -1,5 +1,8 @@
<template> <template>
<div class="mk-messaging-room"> <div class="mk-messaging-room"
@dragover.prevent.stop="onDragover"
@drop.prevent.stop="onDrop"
>
<div class="stream"> <div class="stream">
<p class="init" v-if="init">%fa:spinner .spin%%i18n:common.loading%</p> <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> <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> </div>
<footer> <footer>
<div ref="notifications" class="notifications"></div> <div ref="notifications" class="notifications"></div>
<x-form :user="user"/> <x-form :user="user" ref="form"/>
</footer> </footer>
</div> </div>
</template> </template>
@ -32,7 +35,9 @@ export default Vue.extend({
XMessage, XMessage,
XForm XForm
}, },
props: ['user', 'isNaked'], props: ['user', 'isNaked'],
data() { data() {
return { return {
init: true, init: true,
@ -42,6 +47,7 @@ export default Vue.extend({
connection: null connection: null
}; };
}, },
computed: { computed: {
_messages(): any[] { _messages(): any[] {
return (this.messages as any).map(message => { return (this.messages as any).map(message => {
@ -51,6 +57,10 @@ export default Vue.extend({
message._datetext = `${month}${date}`; message._datetext = `${month}${date}`;
return message; return message;
}); });
},
form(): any {
return this.$refs.form;
} }
}, },
@ -67,6 +77,7 @@ export default Vue.extend({
this.scrollToBottom(); this.scrollToBottom();
}); });
}, },
beforeDestroy() { beforeDestroy() {
this.connection.off('message', this.onMessage); this.connection.off('message', this.onMessage);
this.connection.off('read', this.onRead); this.connection.off('read', this.onRead);
@ -74,7 +85,39 @@ export default Vue.extend({
document.removeEventListener('visibilitychange', this.onVisibilitychange); document.removeEventListener('visibilitychange', this.onVisibilitychange);
}, },
methods: { 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() { fetchMessages() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const max = this.existMoreMessages ? 20 : 10; const max = this.existMoreMessages ? 20 : 10;
@ -96,12 +139,14 @@ export default Vue.extend({
}); });
}); });
}, },
fetchMoreMessages() { fetchMoreMessages() {
this.fetchingMoreMessages = true; this.fetchingMoreMessages = true;
this.fetchMessages().then(() => { this.fetchMessages().then(() => {
this.fetchingMoreMessages = false; this.fetchingMoreMessages = false;
}); });
}, },
onMessage(message) { onMessage(message) {
const isBottom = this.isBottom(); const isBottom = this.isBottom();
@ -123,6 +168,7 @@ export default Vue.extend({
this.notify('%i18n:common.tags.mk-messaging-room.new-message%'); this.notify('%i18n:common.tags.mk-messaging-room.new-message%');
} }
}, },
onRead(ids) { onRead(ids) {
if (!Array.isArray(ids)) ids = [ids]; if (!Array.isArray(ids)) ids = [ids];
ids.forEach(id => { ids.forEach(id => {
@ -132,6 +178,7 @@ export default Vue.extend({
} }
}); });
}, },
isBottom() { isBottom() {
const asobi = 64; const asobi = 64;
const current = this.isNaked const current = this.isNaked
@ -142,6 +189,7 @@ export default Vue.extend({
: this.$el.scrollHeight; : this.$el.scrollHeight;
return current > (max - asobi); return current > (max - asobi);
}, },
scrollToBottom() { scrollToBottom() {
if (this.isNaked) { if (this.isNaked) {
window.scroll(0, document.body.offsetHeight); window.scroll(0, document.body.offsetHeight);
@ -149,6 +197,7 @@ export default Vue.extend({
this.$el.scrollTop = this.$el.scrollHeight; this.$el.scrollTop = this.$el.scrollHeight;
} }
}, },
notify(message) { notify(message) {
const n = document.createElement('p') as any; const n = document.createElement('p') as any;
n.innerHTML = '%fa:arrow-circle-down%' + message; n.innerHTML = '%fa:arrow-circle-down%' + message;
@ -163,6 +212,7 @@ export default Vue.extend({
setTimeout(() => n.parentNode.removeChild(n), 1000); setTimeout(() => n.parentNode.removeChild(n), 1000);
}, 4000); }, 4000);
}, },
onVisibilitychange() { onVisibilitychange() {
if (document.hidden) return; if (document.hidden) return;
this.messages.forEach(message => { this.messages.forEach(message => {

View file

@ -190,7 +190,9 @@ export default Vue.extend({
this.files.push(obj.file); this.files.push(obj.file);
this.$emit('change-attached-media', this.files); this.$emit('change-attached-media', this.files);
} }
} catch (e) { } } catch (e) {
// not a json, so noop
}
}, },
post() { post() {
this.posting = true; this.posting = true;