Improve usability
This commit is contained in:
		
							parent
							
								
									90de725a07
								
							
						
					
					
						commit
						c4a59c3912
					
				
					 3 changed files with 105 additions and 7 deletions
				
			
		| 
						 | 
					@ -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
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue