diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2021-05-31 13:06:40 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2021-05-31 13:06:40 +0900 |
| commit | 929e5455149fd770c53dc03dabd9572f586772c1 (patch) | |
| tree | c34d7f85b0a7b324f412b2a6bb4168574da30f6f /src/client/components | |
| parent | Merge branch 'develop' (diff) | |
| parent | 12.82.0 (diff) | |
| download | misskey-929e5455149fd770c53dc03dabd9572f586772c1.tar.gz misskey-929e5455149fd770c53dc03dabd9572f586772c1.tar.bz2 misskey-929e5455149fd770c53dc03dabd9572f586772c1.zip | |
Merge branch 'develop'
Diffstat (limited to 'src/client/components')
| -rw-r--r-- | src/client/components/date-separated-list.vue | 4 | ||||
| -rw-r--r-- | src/client/components/drive.file.vue | 24 | ||||
| -rw-r--r-- | src/client/components/drive.vue | 4 | ||||
| -rw-r--r-- | src/client/components/follow-button.vue | 2 | ||||
| -rw-r--r-- | src/client/components/image-viewer.vue | 2 | ||||
| -rw-r--r-- | src/client/components/media-caption.vue | 238 | ||||
| -rw-r--r-- | src/client/components/media-image.vue | 4 | ||||
| -rw-r--r-- | src/client/components/notification.vue | 2 | ||||
| -rw-r--r-- | src/client/components/notifications.vue | 8 | ||||
| -rw-r--r-- | src/client/components/post-form-attaches.vue | 25 | ||||
| -rw-r--r-- | src/client/components/timeline.vue | 20 |
11 files changed, 311 insertions, 22 deletions
diff --git a/src/client/components/date-separated-list.vue b/src/client/components/date-separated-list.vue index 34085cc070..6a0c7f29f2 100644 --- a/src/client/components/date-separated-list.vue +++ b/src/client/components/date-separated-list.vue @@ -1,11 +1,11 @@ <script lang="ts"> -import { defineComponent, h, TransitionGroup } from 'vue'; +import { defineComponent, h, PropType, TransitionGroup } from 'vue'; import MkAd from '@client/components/global/ad.vue'; export default defineComponent({ props: { items: { - type: Array, + type: Array as PropType<{ id: string; createdAt: string; _shouldInsertAd_: boolean; }[]>, required: true, }, direction: { diff --git a/src/client/components/drive.file.vue b/src/client/components/drive.file.vue index 37b1afc1b3..3d20de23e9 100644 --- a/src/client/components/drive.file.vue +++ b/src/client/components/drive.file.vue @@ -87,6 +87,10 @@ export default defineComponent({ text: this.file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive, icon: this.file.isSensitive ? 'fas fa-eye' : 'fas fa-eye-slash', action: this.toggleSensitive + }, { + text: this.$ts.describeFile, + icon: 'fas fa-i-cursor', + action: this.describe }, null, { text: this.$ts.copyUrl, icon: 'fas fa-link', @@ -150,6 +154,26 @@ export default defineComponent({ }); }, + describe() { + os.popup(import('@client/components/media-caption.vue'), { + title: this.$ts.describeFile, + input: { + placeholder: this.$ts.inputNewDescription, + default: this.file.comment !== null ? this.file.comment : '', + }, + image: this.file + }, { + done: result => { + if (!result || result.canceled) return; + let comment = result.result; + os.api('drive/files/update', { + fileId: this.file.id, + comment: comment.length == 0 ? null : comment + }); + } + }, 'closed'); + }, + toggleSensitive() { os.api('drive/files/update', { fileId: this.file.id, diff --git a/src/client/components/drive.vue b/src/client/components/drive.vue index 06f9cf7806..ca637e3f3d 100644 --- a/src/client/components/drive.vue +++ b/src/client/components/drive.vue @@ -139,7 +139,7 @@ export default defineComponent({ }); } - this.connection = os.stream.useSharedConnection('drive'); + this.connection = os.stream.useChannel('drive'); this.connection.on('fileCreated', this.onStreamDriveFileCreated); this.connection.on('fileUpdated', this.onStreamDriveFileUpdated); @@ -301,7 +301,7 @@ export default defineComponent({ } }).then(({ canceled, result: url }) => { if (canceled) return; - os.api('drive/files/upload_from_url', { + os.api('drive/files/upload-from-url', { url: url, folderId: this.folder ? this.folder.id : undefined }); diff --git a/src/client/components/follow-button.vue b/src/client/components/follow-button.vue index 7199183c66..49bf678491 100644 --- a/src/client/components/follow-button.vue +++ b/src/client/components/follow-button.vue @@ -71,7 +71,7 @@ export default defineComponent({ }, mounted() { - this.connection = os.stream.useSharedConnection('main'); + this.connection = os.stream.useChannel('main'); this.connection.on('follow', this.onFollowChange); this.connection.on('unfollow', this.onFollowChange); diff --git a/src/client/components/image-viewer.vue b/src/client/components/image-viewer.vue index ec22bd98ec..7701ae926f 100644 --- a/src/client/components/image-viewer.vue +++ b/src/client/components/image-viewer.vue @@ -2,7 +2,7 @@ <MkModal ref="modal" @click="$refs.modal.close()" @closed="$emit('closed')"> <div class="xubzgfga"> <header>{{ image.name }}</header> - <img :src="image.url" :alt="image.name" :title="image.name" @click="$refs.modal.close()"/> + <img :src="image.url" :alt="image.comment" :title="image.comment" @click="$refs.modal.close()"/> <footer> <span>{{ image.type }}</span> <span>{{ bytes(image.size) }}</span> diff --git a/src/client/components/media-caption.vue b/src/client/components/media-caption.vue new file mode 100644 index 0000000000..690927d4c5 --- /dev/null +++ b/src/client/components/media-caption.vue @@ -0,0 +1,238 @@ +<template> + <MkModal ref="modal" @click="done(true)" @closed="$emit('closed')"> + <div class="container"> + <div class="fullwidth top-caption"> + <div class="mk-dialog"> + <header v-if="title"><Mfm :text="title"/></header> + <textarea autofocus v-model="inputValue" :placeholder="input.placeholder" @keydown="onInputKeydown"></textarea> + <div class="buttons" v-if="(showOkButton || showCancelButton)"> + <MkButton inline @click="ok" primary>{{ $ts.ok }}</MkButton> + <MkButton inline @click="cancel" >{{ $ts.cancel }}</MkButton> + </div> + </div> + </div> + <div class="hdrwpsaf fullwidth"> + <header>{{ image.name }}</header> + <img :src="image.url" :alt="image.comment" :title="image.comment" @click="$refs.modal.close()"/> + <footer> + <span>{{ image.type }}</span> + <span>{{ bytes(image.size) }}</span> + <span v-if="image.properties && image.properties.width">{{ number(image.properties.width) }}px × {{ number(image.properties.height) }}px</span> + </footer> + </div> + </div> + </MkModal> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import MkModal from '@client/components/ui/modal.vue'; +import MkButton from '@client/components/ui/button.vue'; +import bytes from '@client/filters/bytes'; +import number from '@client/filters/number'; + +export default defineComponent({ + components: { + MkModal, + MkButton, + }, + + props: { + image: { + type: Object, + required: true, + }, + title: { + type: String, + required: false + }, + input: { + required: true + }, + showOkButton: { + type: Boolean, + default: true + }, + showCancelButton: { + type: Boolean, + default: true + }, + cancelableByBgClick: { + type: Boolean, + default: true + }, + }, + + emits: ['done', 'closed'], + + data() { + return { + inputValue: this.input.default ? this.input.default : null + }; + }, + + mounted() { + document.addEventListener('keydown', this.onKeydown); + }, + + beforeUnmount() { + document.removeEventListener('keydown', this.onKeydown); + }, + + methods: { + bytes, + number, + + done(canceled, result?) { + this.$emit('done', { canceled, result }); + this.$refs.modal.close(); + }, + + async ok() { + if (!this.showOkButton) return; + + const result = this.inputValue; + this.done(false, result); + }, + + cancel() { + this.done(true); + }, + + onBgClick() { + if (this.cancelableByBgClick) { + this.cancel(); + } + }, + + onKeydown(e) { + if (e.which === 27) { // ESC + this.cancel(); + } + }, + + onInputKeydown(e) { + if (e.which === 13) { // Enter + if (e.ctrlKey) { + e.preventDefault(); + e.stopPropagation(); + this.ok(); + } + } + } + } +}); +</script> + +<style lang="scss" scoped> +.container { + display: flex; + width: 100%; + height: 100%; + flex-direction: row; +} +@media (max-width: 850px) { + .container { + flex-direction: column; + } + .top-caption { + padding-bottom: 8px; + } +} +.fullwidth { + width: 100%; + margin: auto; +} +.mk-dialog { + position: relative; + padding: 32px; + min-width: 320px; + max-width: 480px; + box-sizing: border-box; + text-align: center; + background: var(--panel); + border-radius: var(--radius); + margin: auto; + + > header { + margin: 0 0 8px 0; + font-weight: bold; + font-size: 20px; + } + + > .buttons { + margin-top: 16px; + + > * { + margin: 0 8px; + } + } + + > textarea { + display: block; + box-sizing: border-box; + padding: 0 24px; + margin: 0; + width: 100%; + font-size: 16px; + border: none; + border-radius: 0; + background: transparent; + color: var(--fg); + font-family: inherit; + max-width: 100%; + min-width: 100%; + min-height: 90px; + + &:focus { + outline: none; + } + + &:disabled { + opacity: 0.5; + } + } +} +.hdrwpsaf { + display: flex; + flex-direction: column; + height: 100%; + + > header, + > footer { + align-self: center; + display: inline-block; + padding: 6px 9px; + font-size: 90%; + background: rgba(0, 0, 0, 0.5); + border-radius: 6px; + color: #fff; + } + + > header { + margin-bottom: 8px; + opacity: 0.9; + } + + > img { + display: block; + flex: 1; + min-height: 0; + object-fit: contain; + width: 100%; + cursor: zoom-out; + image-orientation: from-image; + } + + > footer { + margin-top: 8px; + opacity: 0.8; + + > span + span { + margin-left: 0.5em; + padding-left: 0.5em; + border-left: solid 1px rgba(255, 255, 255, 0.5); + } + } +} +</style> diff --git a/src/client/components/media-image.vue b/src/client/components/media-image.vue index 267e4debd2..863eb10272 100644 --- a/src/client/components/media-image.vue +++ b/src/client/components/media-image.vue @@ -1,6 +1,6 @@ <template> <div class="qjewsnkg" v-if="hide" @click="hide = false"> - <ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.name"/> + <ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.comment" :alt="image.comment"/> <div class="text"> <div> <b><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b> @@ -14,7 +14,7 @@ :title="image.name" @click.prevent="onClick" > - <ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.name" :title="image.name" :cover="false"/> + <ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.comment" :title="image.comment" :cover="false"/> <div class="gif" v-if="image.type === 'image/gif'">GIF</div> </a> <i class="fas fa-eye-slash" @click="hide = true"></i> diff --git a/src/client/components/notification.vue b/src/client/components/notification.vue index 9badd7a708..c7063b0aa2 100644 --- a/src/client/components/notification.vue +++ b/src/client/components/notification.vue @@ -109,7 +109,7 @@ export default defineComponent({ this.readObserver.observe(this.$el); - this.connection = os.stream.useSharedConnection('main'); + this.connection = os.stream.useChannel('main'); this.connection.on('readAllNotifications', () => this.readObserver.unobserve(this.$el)); } }, diff --git a/src/client/components/notifications.vue b/src/client/components/notifications.vue index 161419f891..092c00f14e 100644 --- a/src/client/components/notifications.vue +++ b/src/client/components/notifications.vue @@ -12,10 +12,10 @@ <XNotification v-else :notification="notification" :with-time="true" :full="true" class="_panel notification" :key="notification.id"/> </XList> - <button class="_buttonPrimary" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" v-show="more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }"> + <MkButton primary style="margin: var(--margin) auto;" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" v-show="more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }"> <template v-if="!moreFetching">{{ $ts.loadMore }}</template> <template v-if="moreFetching"><MkLoading inline/></template> - </button> + </MkButton> </div> </transition> </template> @@ -28,12 +28,14 @@ import XList from './date-separated-list.vue'; import XNote from './note.vue'; import { notificationTypes } from '../../types'; import * as os from '@client/os'; +import MkButton from '@client/components/ui/button.vue'; export default defineComponent({ components: { XNotification, XList, XNote, + MkButton, }, mixins: [ @@ -87,7 +89,7 @@ export default defineComponent({ }, mounted() { - this.connection = os.stream.useSharedConnection('main'); + this.connection = os.stream.useChannel('main'); this.connection.on('notification', this.onNotification); }, diff --git a/src/client/components/post-form-attaches.vue b/src/client/components/post-form-attaches.vue index f832ea87b5..27e20fdfa8 100644 --- a/src/client/components/post-form-attaches.vue +++ b/src/client/components/post-form-attaches.vue @@ -89,6 +89,27 @@ export default defineComponent({ file.name = result; }); }, + + async describe(file) { + os.popup(import("@client/components/media-caption.vue"), { + title: this.$ts.describeFile, + input: { + placeholder: this.$ts.inputNewDescription, + default: file.comment !== null ? file.comment : "", + }, + image: file + }, { + done: result => { + if (!result || result.canceled) return; + let comment = result.result; + os.api('drive/files/update', { + fileId: file.id, + comment: comment.length == 0 ? null : comment + }); + } + }, 'closed'); + }, + showFileMenu(file, ev: MouseEvent) { if (this.menu) return; this.menu = os.modalMenu([{ @@ -100,6 +121,10 @@ export default defineComponent({ icon: file.isSensitive ? 'fas fa-eye-slash' : 'fas fa-eye', action: () => { this.toggleSensitive(file) } }, { + text: this.$ts.describeFile, + icon: 'fas fa-i-cursor', + action: () => { this.describe(file) } + }, { text: this.$ts.attachCancel, icon: 'fas fa-times-circle', action: () => { this.detachMedia(file.id) } diff --git a/src/client/components/timeline.vue b/src/client/components/timeline.vue index 753eba2ba1..c21e1ec2a6 100644 --- a/src/client/components/timeline.vue +++ b/src/client/components/timeline.vue @@ -92,33 +92,33 @@ export default defineComponent({ this.query = { antennaId: this.antenna }; - this.connection = os.stream.connectToChannel('antenna', { + this.connection = os.stream.useChannel('antenna', { antennaId: this.antenna }); this.connection.on('note', prepend); } else if (this.src == 'home') { endpoint = 'notes/timeline'; - this.connection = os.stream.useSharedConnection('homeTimeline'); + this.connection = os.stream.useChannel('homeTimeline'); this.connection.on('note', prepend); - this.connection2 = os.stream.useSharedConnection('main'); + this.connection2 = os.stream.useChannel('main'); this.connection2.on('follow', onChangeFollowing); this.connection2.on('unfollow', onChangeFollowing); } else if (this.src == 'local') { endpoint = 'notes/local-timeline'; - this.connection = os.stream.useSharedConnection('localTimeline'); + this.connection = os.stream.useChannel('localTimeline'); this.connection.on('note', prepend); } else if (this.src == 'social') { endpoint = 'notes/hybrid-timeline'; - this.connection = os.stream.useSharedConnection('hybridTimeline'); + this.connection = os.stream.useChannel('hybridTimeline'); this.connection.on('note', prepend); } else if (this.src == 'global') { endpoint = 'notes/global-timeline'; - this.connection = os.stream.useSharedConnection('globalTimeline'); + this.connection = os.stream.useChannel('globalTimeline'); this.connection.on('note', prepend); } else if (this.src == 'mentions') { endpoint = 'notes/mentions'; - this.connection = os.stream.useSharedConnection('main'); + this.connection = os.stream.useChannel('main'); this.connection.on('mention', prepend); } else if (this.src == 'directs') { endpoint = 'notes/mentions'; @@ -130,14 +130,14 @@ export default defineComponent({ prepend(note); } }; - this.connection = os.stream.useSharedConnection('main'); + this.connection = os.stream.useChannel('main'); this.connection.on('mention', onNote); } else if (this.src == 'list') { endpoint = 'notes/user-list-timeline'; this.query = { listId: this.list }; - this.connection = os.stream.connectToChannel('userList', { + this.connection = os.stream.useChannel('userList', { listId: this.list }); this.connection.on('note', prepend); @@ -148,7 +148,7 @@ export default defineComponent({ this.query = { channelId: this.channel }; - this.connection = os.stream.connectToChannel('channel', { + this.connection = os.stream.useChannel('channel', { channelId: this.channel }); this.connection.on('note', prepend); |