2018-02-13 06:56:11 +00:00
|
|
|
<template>
|
2018-02-26 19:36:16 +00:00
|
|
|
<div class="mk-messaging-form"
|
2018-02-26 21:25:17 +00:00
|
|
|
@dragover.stop="onDragover"
|
|
|
|
@drop.stop="onDrop"
|
2018-02-26 19:36:16 +00:00
|
|
|
>
|
2018-02-25 04:05:55 +00:00
|
|
|
<textarea
|
|
|
|
v-model="text"
|
|
|
|
ref="textarea"
|
|
|
|
@keypress="onKeypress"
|
|
|
|
@paste="onPaste"
|
2018-11-09 04:47:22 +00:00
|
|
|
:placeholder="$t('input-message-here')"
|
2018-12-15 23:45:10 +00:00
|
|
|
v-autocomplete="{ model: 'text' }"
|
2018-02-25 04:05:55 +00:00
|
|
|
></textarea>
|
2018-02-26 17:10:52 +00:00
|
|
|
<div class="file" @click="file = null" v-if="file">{{ file.name }}</div>
|
|
|
|
<mk-uploader ref="uploader" @uploaded="onUploaded"/>
|
2018-11-08 18:44:35 +00:00
|
|
|
<button class="send" @click="send" :disabled="!canSend || sending" :title="$t('send')">
|
2018-11-05 16:40:11 +00:00
|
|
|
<template v-if="!sending"><fa icon="paper-plane"/></template><template v-if="sending"><fa icon="spinner .spin"/></template>
|
2018-02-13 06:56:11 +00:00
|
|
|
</button>
|
2018-11-08 18:44:35 +00:00
|
|
|
<button class="attach-from-local" @click="chooseFile" :title="$t('attach-from-local')">
|
2018-11-05 16:40:11 +00:00
|
|
|
<fa icon="upload"/>
|
2018-02-13 06:56:11 +00:00
|
|
|
</button>
|
2018-11-08 18:44:35 +00:00
|
|
|
<button class="attach-from-drive" @click="chooseFileFromDrive" :title="$t('attach-from-drive')">
|
2018-11-05 16:40:11 +00:00
|
|
|
<fa :icon="['far', 'folder-open']"/>
|
2018-02-13 06:56:11 +00:00
|
|
|
</button>
|
2018-02-26 17:10:52 +00:00
|
|
|
<input ref="file" type="file" @change="onChangeFile"/>
|
2018-02-13 06:56:11 +00:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
|
|
import Vue from 'vue';
|
2018-11-08 18:44:35 +00:00
|
|
|
import i18n from '../../../i18n';
|
2018-02-24 17:57:19 +00:00
|
|
|
import * as autosize from 'autosize';
|
2019-07-08 04:46:31 +00:00
|
|
|
import { formatTimeString } from '../../../../../misc/format-time-string';
|
2018-02-24 17:57:19 +00:00
|
|
|
|
2018-02-13 06:56:11 +00:00
|
|
|
export default Vue.extend({
|
2018-11-08 18:44:35 +00:00
|
|
|
i18n: i18n('common/views/components/messaging-room.form.vue'),
|
2019-05-18 11:36:33 +00:00
|
|
|
props: {
|
|
|
|
user: {
|
|
|
|
type: Object,
|
|
|
|
requird: false,
|
|
|
|
},
|
|
|
|
group: {
|
|
|
|
type: Object,
|
|
|
|
requird: false,
|
|
|
|
},
|
|
|
|
},
|
2018-02-13 06:56:11 +00:00
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
text: null,
|
2018-02-18 14:51:41 +00:00
|
|
|
file: null,
|
2018-02-13 06:56:11 +00:00
|
|
|
sending: false
|
|
|
|
};
|
|
|
|
},
|
2018-02-25 13:56:23 +00:00
|
|
|
computed: {
|
|
|
|
draftId(): string {
|
2019-05-18 11:36:33 +00:00
|
|
|
return this.user ? 'user:' + this.user.id : 'group:' + this.group.id;
|
2018-02-26 17:10:52 +00:00
|
|
|
},
|
|
|
|
canSend(): boolean {
|
|
|
|
return (this.text != null && this.text != '') || this.file != null;
|
2018-02-26 19:36:16 +00:00
|
|
|
},
|
|
|
|
room(): any {
|
|
|
|
return this.$parent;
|
2018-02-25 13:56:23 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
text() {
|
|
|
|
this.saveDraft();
|
|
|
|
},
|
|
|
|
file() {
|
|
|
|
this.saveDraft();
|
2018-02-26 19:36:16 +00:00
|
|
|
|
|
|
|
if (this.room.isBottom()) {
|
|
|
|
this.room.scrollToBottom();
|
|
|
|
}
|
2018-02-25 13:56:23 +00:00
|
|
|
}
|
|
|
|
},
|
2018-02-24 17:57:19 +00:00
|
|
|
mounted() {
|
|
|
|
autosize(this.$refs.textarea);
|
2018-02-25 13:56:23 +00:00
|
|
|
|
|
|
|
// 書きかけの投稿を復元
|
|
|
|
const draft = JSON.parse(localStorage.getItem('message_drafts') || '{}')[this.draftId];
|
|
|
|
if (draft) {
|
|
|
|
this.text = draft.data.text;
|
|
|
|
this.file = draft.data.file;
|
|
|
|
}
|
2018-02-24 17:57:19 +00:00
|
|
|
},
|
2018-02-13 06:56:11 +00:00
|
|
|
methods: {
|
2019-07-08 04:46:31 +00:00
|
|
|
async onPaste(e: ClipboardEvent) {
|
2018-02-13 06:56:11 +00:00
|
|
|
const data = e.clipboardData;
|
|
|
|
const items = data.items;
|
2018-02-26 19:36:16 +00:00
|
|
|
|
|
|
|
if (items.length == 1) {
|
|
|
|
if (items[0].kind == 'file') {
|
2019-07-08 04:46:31 +00:00
|
|
|
const file = items[0].getAsFile();
|
|
|
|
const lio = file.name.lastIndexOf('.');
|
|
|
|
const ext = lio >= 0 ? file.name.slice(lio) : '';
|
|
|
|
const formatted = `${formatTimeString(new Date(file.lastModified), this.$store.state.settings.pastedFileName).replace(/{{number}}/g, '1')}${ext}`;
|
|
|
|
const name = this.$store.state.settings.pasteDialog
|
|
|
|
? await this.$root.dialog({
|
|
|
|
title: this.$t('@.post-form.enter-file-name'),
|
|
|
|
input: {
|
|
|
|
default: formatted
|
|
|
|
},
|
|
|
|
allowEmpty: false
|
|
|
|
}).then(({ canceled, result }) => canceled ? false : result)
|
|
|
|
: formatted;
|
|
|
|
if (name) this.upload(file, name);
|
2018-02-26 19:36:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (items[0].kind == 'file') {
|
2019-04-16 04:05:10 +00:00
|
|
|
this.$root.dialog({
|
|
|
|
type: 'error',
|
|
|
|
text: this.$t('only-one-file-attached')
|
|
|
|
});
|
2018-02-26 19:36:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
onDragover(e) {
|
2018-02-26 21:25:17 +00:00
|
|
|
const isFile = e.dataTransfer.items[0].kind == 'file';
|
|
|
|
const isDriveFile = e.dataTransfer.types[0] == 'mk_drive_file';
|
|
|
|
if (isFile || isDriveFile) {
|
|
|
|
e.preventDefault();
|
|
|
|
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
|
|
|
}
|
2018-02-26 19:36:16 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
onDrop(e): void {
|
|
|
|
// ファイルだったら
|
|
|
|
if (e.dataTransfer.files.length == 1) {
|
2018-02-26 21:25:17 +00:00
|
|
|
e.preventDefault();
|
2018-02-26 19:36:16 +00:00
|
|
|
this.upload(e.dataTransfer.files[0]);
|
|
|
|
return;
|
|
|
|
} else if (e.dataTransfer.files.length > 1) {
|
2018-02-26 21:25:17 +00:00
|
|
|
e.preventDefault();
|
2019-04-16 04:05:10 +00:00
|
|
|
this.$root.dialog({
|
|
|
|
type: 'error',
|
|
|
|
text: this.$t('only-one-file-attached')
|
|
|
|
});
|
2018-02-26 19:36:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-26 21:25:17 +00:00
|
|
|
//#region ドライブのファイル
|
|
|
|
const driveFile = e.dataTransfer.getData('mk_drive_file');
|
|
|
|
if (driveFile != null && driveFile != '') {
|
|
|
|
this.file = JSON.parse(driveFile);
|
|
|
|
e.preventDefault();
|
2018-02-13 06:56:11 +00:00
|
|
|
}
|
2018-02-26 21:25:17 +00:00
|
|
|
//#endregion
|
2018-02-13 06:56:11 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
onKeypress(e) {
|
2018-07-20 17:07:50 +00:00
|
|
|
if ((e.which == 10 || e.which == 13) && e.ctrlKey && this.canSend) {
|
2018-02-13 06:56:11 +00:00
|
|
|
this.send();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
chooseFile() {
|
|
|
|
(this.$refs.file as any).click();
|
|
|
|
},
|
|
|
|
|
|
|
|
chooseFileFromDrive() {
|
2018-11-09 07:00:29 +00:00
|
|
|
this.$chooseDriveFile({
|
2018-02-18 14:51:41 +00:00
|
|
|
multiple: false
|
|
|
|
}).then(file => {
|
|
|
|
this.file = file;
|
2018-02-13 06:56:11 +00:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2018-02-26 17:10:52 +00:00
|
|
|
onChangeFile() {
|
|
|
|
this.upload((this.$refs.file as any).files[0]);
|
|
|
|
},
|
|
|
|
|
2019-07-08 04:46:31 +00:00
|
|
|
upload(file: File, name?: string) {
|
|
|
|
(this.$refs.uploader as any).upload(file, this.$store.state.settings.uploadFolder, name);
|
2018-02-26 17:10:52 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
onUploaded(file) {
|
|
|
|
this.file = file;
|
2018-02-18 14:56:25 +00:00
|
|
|
},
|
2018-02-18 14:51:41 +00:00
|
|
|
|
2018-02-13 06:56:11 +00:00
|
|
|
send() {
|
|
|
|
this.sending = true;
|
2018-11-08 23:13:34 +00:00
|
|
|
this.$root.api('messaging/messages/create', {
|
2019-05-18 11:36:33 +00:00
|
|
|
userId: this.user ? this.user.id : undefined,
|
|
|
|
groupId: this.group ? this.group.id : undefined,
|
2018-02-26 17:10:52 +00:00
|
|
|
text: this.text ? this.text : undefined,
|
2018-03-29 05:48:47 +00:00
|
|
|
fileId: this.file ? this.file.id : undefined
|
2018-02-13 06:56:11 +00:00
|
|
|
}).then(message => {
|
|
|
|
this.clear();
|
|
|
|
}).catch(err => {
|
|
|
|
console.error(err);
|
|
|
|
}).then(() => {
|
|
|
|
this.sending = false;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
clear() {
|
|
|
|
this.text = '';
|
2018-02-18 14:56:25 +00:00
|
|
|
this.file = null;
|
2018-02-25 13:56:23 +00:00
|
|
|
this.deleteDraft();
|
|
|
|
},
|
|
|
|
|
|
|
|
saveDraft() {
|
|
|
|
const data = JSON.parse(localStorage.getItem('message_drafts') || '{}');
|
|
|
|
|
|
|
|
data[this.draftId] = {
|
2018-03-29 05:48:47 +00:00
|
|
|
updatedAt: new Date(),
|
2018-02-25 13:56:23 +00:00
|
|
|
data: {
|
|
|
|
text: this.text,
|
|
|
|
file: this.file
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
localStorage.setItem('message_drafts', JSON.stringify(data));
|
|
|
|
},
|
|
|
|
|
|
|
|
deleteDraft() {
|
|
|
|
const data = JSON.parse(localStorage.getItem('message_drafts') || '{}');
|
|
|
|
|
|
|
|
delete data[this.draftId];
|
|
|
|
|
|
|
|
localStorage.setItem('message_drafts', JSON.stringify(data));
|
|
|
|
},
|
2018-02-13 06:56:11 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="stylus" scoped>
|
2018-09-28 10:59:19 +00:00
|
|
|
.mk-messaging-form
|
2018-02-13 06:56:11 +00:00
|
|
|
> textarea
|
|
|
|
cursor auto
|
|
|
|
display block
|
|
|
|
width 100%
|
|
|
|
min-width 100%
|
|
|
|
max-width 100%
|
|
|
|
height 64px
|
|
|
|
margin 0
|
|
|
|
padding 8px
|
2018-02-24 17:57:19 +00:00
|
|
|
resize none
|
2018-02-13 06:56:11 +00:00
|
|
|
font-size 1em
|
2018-09-27 13:50:34 +00:00
|
|
|
color var(--inputText)
|
2018-02-13 06:56:11 +00:00
|
|
|
outline none
|
|
|
|
border none
|
2018-09-28 10:59:19 +00:00
|
|
|
border-top solid 1px var(--faceDivider)
|
2018-02-13 06:56:11 +00:00
|
|
|
border-radius 0
|
|
|
|
box-shadow none
|
|
|
|
background transparent
|
|
|
|
|
2018-02-26 17:10:52 +00:00
|
|
|
> .file
|
|
|
|
padding 8px
|
|
|
|
color #444
|
|
|
|
background #eee
|
|
|
|
cursor pointer
|
|
|
|
|
2018-02-13 06:56:11 +00:00
|
|
|
> .send
|
|
|
|
position absolute
|
|
|
|
bottom 0
|
|
|
|
right 0
|
|
|
|
margin 0
|
|
|
|
padding 10px 14px
|
|
|
|
font-size 1em
|
|
|
|
color #aaa
|
|
|
|
transition color 0.1s ease
|
|
|
|
|
|
|
|
&:hover
|
2018-09-26 11:19:35 +00:00
|
|
|
color var(--primary)
|
2018-02-13 06:56:11 +00:00
|
|
|
|
|
|
|
&:active
|
2018-09-26 11:19:35 +00:00
|
|
|
color var(--primaryDarken10)
|
2018-02-13 06:56:11 +00:00
|
|
|
transition color 0s ease
|
|
|
|
|
|
|
|
.files
|
|
|
|
display block
|
|
|
|
margin 0
|
|
|
|
padding 0 8px
|
|
|
|
list-style none
|
|
|
|
|
|
|
|
&:after
|
|
|
|
content ''
|
|
|
|
display block
|
|
|
|
clear both
|
|
|
|
|
|
|
|
> li
|
|
|
|
display block
|
|
|
|
float left
|
|
|
|
margin 4px
|
|
|
|
padding 0
|
|
|
|
width 64px
|
|
|
|
height 64px
|
|
|
|
background-color #eee
|
|
|
|
background-repeat no-repeat
|
|
|
|
background-position center center
|
|
|
|
background-size cover
|
|
|
|
cursor move
|
|
|
|
|
|
|
|
&:hover
|
|
|
|
> .remove
|
|
|
|
display block
|
|
|
|
|
|
|
|
> .remove
|
|
|
|
display none
|
|
|
|
position absolute
|
|
|
|
right -6px
|
|
|
|
top -6px
|
|
|
|
margin 0
|
|
|
|
padding 0
|
|
|
|
background transparent
|
|
|
|
outline none
|
|
|
|
border none
|
|
|
|
border-radius 0
|
|
|
|
box-shadow none
|
|
|
|
cursor pointer
|
|
|
|
|
|
|
|
.attach-from-local
|
|
|
|
.attach-from-drive
|
|
|
|
margin 0
|
|
|
|
padding 10px 14px
|
|
|
|
font-size 1em
|
|
|
|
font-weight normal
|
|
|
|
text-decoration none
|
|
|
|
color #aaa
|
|
|
|
transition color 0.1s ease
|
|
|
|
|
|
|
|
&:hover
|
2018-09-26 11:19:35 +00:00
|
|
|
color var(--primary)
|
2018-02-13 06:56:11 +00:00
|
|
|
|
|
|
|
&:active
|
2018-09-26 11:19:35 +00:00
|
|
|
color var(--primaryDarken10)
|
2018-02-13 06:56:11 +00:00
|
|
|
transition color 0s ease
|
|
|
|
|
|
|
|
input[type=file]
|
|
|
|
display none
|
|
|
|
|
|
|
|
</style>
|