mirror of
https://iceshrimp.dev/limepotato/jormungandr-bite.git
synced 2024-11-23 02:17:40 -07:00
Improve usability
This commit is contained in:
parent
519c8749ac
commit
e4ac2a4f50
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…
Reference in a new issue