From 111eb43fd93d0a496da054c36ec84c6066c1c434 Mon Sep 17 00:00:00 2001 From: tamaina Date: Wed, 3 Jun 2020 13:30:17 +0900 Subject: feat(client): 投稿フォームのボタンの説明を表示するように (#6408) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add title attr with buttons on the post form * fix * tooltip * missing ; * remove title attr * fix bug * Update reactions-viewer.details.vue * help wip * ok! * i18n Co-authored-by: syuilo --- src/client/components/cw-button.vue | 2 +- src/client/components/link.vue | 4 +- src/client/components/post-form.vue | 18 ++-- src/client/components/reactions-viewer.details.vue | 104 ++++----------------- .../components/reactions-viewer.reaction.vue | 5 +- src/client/components/ui/tooltip.vue | 96 +++++++++++++++++++ src/client/components/url.vue | 4 +- src/client/directives/index.ts | 2 + src/client/directives/tooltip.ts | 62 ++++++++++++ src/client/scripts/compose-notification.ts | 2 +- src/client/scripts/is-device-touch.ts | 4 +- 11 files changed, 200 insertions(+), 103 deletions(-) create mode 100644 src/client/components/ui/tooltip.vue create mode 100644 src/client/directives/tooltip.ts (limited to 'src/client') diff --git a/src/client/components/cw-button.vue b/src/client/components/cw-button.vue index 07a44d970f..16a9b84f62 100644 --- a/src/client/components/cw-button.vue +++ b/src/client/components/cw-button.vue @@ -27,7 +27,7 @@ export default Vue.extend({ return concat([ this.note.text ? [this.$t('_cw.chars', { count: length(this.note.text) })] : [], this.note.files && this.note.files.length !== 0 ? [this.$t('_cw.files', { count: this.note.files.length }) ] : [], - this.note.poll != null ? [this.$t('_cw.poll')] : [] + this.note.poll != null ? [this.$t('poll')] : [] ] as string[][]).join(' / '); } }, diff --git a/src/client/components/link.vue b/src/client/components/link.vue index 4c709375d3..7a364d0986 100644 --- a/src/client/components/link.vue +++ b/src/client/components/link.vue @@ -62,13 +62,13 @@ export default Vue.extend({ } }, onMouseover() { - if (isDeviceTouch()) return; + if (isDeviceTouch) return; clearTimeout(this.showTimer); clearTimeout(this.hideTimer); this.showTimer = setTimeout(this.showPreview, 500); }, onMouseleave() { - if (isDeviceTouch()) return; + if (isDeviceTouch) return; clearTimeout(this.showTimer); clearTimeout(this.hideTimer); this.hideTimer = setTimeout(this.closePreview, 500); diff --git a/src/client/components/post-form.vue b/src/client/components/post-form.vue index cdb61f51d5..ee6148a355 100644 --- a/src/client/components/post-form.vue +++ b/src/client/components/post-form.vue @@ -9,13 +9,13 @@
{{ max - trimmedLength(text) }} - - +
@@ -26,7 +26,7 @@
{{ $t('recipient') }}
- + @@ -39,11 +39,11 @@
- - - - - + + + + +
@@ -576,7 +576,7 @@ export default Vue.extend({ insertTextAtCursor(this.$refs.text, emoji); vm.close(); }); - } + }, } }); diff --git a/src/client/components/reactions-viewer.details.vue b/src/client/components/reactions-viewer.details.vue index 67c8b261be..96d1408fc1 100644 --- a/src/client/components/reactions-viewer.details.vue +++ b/src/client/components/reactions-viewer.details.vue @@ -1,27 +1,29 @@ - - diff --git a/src/client/components/reactions-viewer.reaction.vue b/src/client/components/reactions-viewer.reaction.vue index 33911dedb8..6b72f2e105 100644 --- a/src/client/components/reactions-viewer.reaction.vue +++ b/src/client/components/reactions-viewer.reaction.vue @@ -4,8 +4,10 @@ :class="{ reacted: note.myReaction == reaction, canToggle }" @click="toggleReaction(reaction)" v-if="count > 0" + @touchstart="onMouseover" @mouseover="onMouseover" @mouseleave="onMouseleave" + @touchend="onMouseleave" ref="reaction" v-particle > @@ -90,16 +92,17 @@ export default Vue.extend({ } }, onMouseover() { + if (this.isHovering) return; this.isHovering = true; this.detailsTimeoutId = setTimeout(this.openDetails, 300); }, onMouseleave() { + if (!this.isHovering) return; this.isHovering = false; clearTimeout(this.detailsTimeoutId); this.closeDetails(); }, openDetails() { - if (this.$root.isMobile) return; this.$root.api('notes/reactions', { noteId: this.note.id, type: this.reaction, diff --git a/src/client/components/ui/tooltip.vue b/src/client/components/ui/tooltip.vue new file mode 100644 index 0000000000..b7a56708b7 --- /dev/null +++ b/src/client/components/ui/tooltip.vue @@ -0,0 +1,96 @@ + + + + + diff --git a/src/client/components/url.vue b/src/client/components/url.vue index 4dd23a50ed..0a5a5bc508 100644 --- a/src/client/components/url.vue +++ b/src/client/components/url.vue @@ -93,13 +93,13 @@ export default Vue.extend({ } }, onMouseover() { - if (isDeviceTouch()) return; + if (isDeviceTouch) return; clearTimeout(this.showTimer); clearTimeout(this.hideTimer); this.showTimer = setTimeout(this.showPreview, 500); }, onMouseleave() { - if (isDeviceTouch()) return; + if (isDeviceTouch) return; clearTimeout(this.showTimer); clearTimeout(this.hideTimer); this.hideTimer = setTimeout(this.closePreview, 500); diff --git a/src/client/directives/index.ts b/src/client/directives/index.ts index 64d33c0ff3..8cd5ed464d 100644 --- a/src/client/directives/index.ts +++ b/src/client/directives/index.ts @@ -4,9 +4,11 @@ import userPreview from './user-preview'; import autocomplete from './autocomplete'; import size from './size'; import particle from './particle'; +import tooltip from './tooltip'; Vue.directive('autocomplete', autocomplete); Vue.directive('userPreview', userPreview); Vue.directive('user-preview', userPreview); Vue.directive('size', size); Vue.directive('particle', particle); +Vue.directive('tooltip', tooltip); diff --git a/src/client/directives/tooltip.ts b/src/client/directives/tooltip.ts new file mode 100644 index 0000000000..28d22fc024 --- /dev/null +++ b/src/client/directives/tooltip.ts @@ -0,0 +1,62 @@ +import MkTooltip from '../components/ui/tooltip.vue'; +import { isDeviceTouch } from '../scripts/is-device-touch'; + +const start = isDeviceTouch ? 'touchstart' : 'mouseover'; +const end = isDeviceTouch ? 'touchend' : 'mouseleave'; + +export default { + bind(el: HTMLElement, binding, vn) { + const self = (el as any)._tooltipDirective_ = {} as any; + + self.text = binding.value as string; + self.tag = null; + self.showTimer = null; + self.hideTimer = null; + self.checkTimer = null; + + self.close = () => { + if (self.tag) { + clearInterval(self.checkTimer); + self.tag.close(); + self.tag = null; + } + }; + + const show = e => { + if (!document.body.contains(el)) return; + if (self.tag) return; + + self.tag = new MkTooltip({ + parent: vn.context, + propsData: { + text: self.text, + source: el + } + }).$mount(); + + document.body.appendChild(self.tag.$el); + }; + + el.addEventListener(start, () => { + clearTimeout(self.showTimer); + clearTimeout(self.hideTimer); + self.showTimer = setTimeout(show, 300); + }); + + el.addEventListener(end, () => { + clearTimeout(self.showTimer); + clearTimeout(self.hideTimer); + self.hideTimer = setTimeout(self.close, 300); + }); + + el.addEventListener('click', () => { + clearTimeout(self.showTimer); + self.close(); + }); + }, + + unbind(el, binding, vn) { + const self = el._tooltipDirective_; + clearInterval(self.checkTimer); + }, +}; diff --git a/src/client/scripts/compose-notification.ts b/src/client/scripts/compose-notification.ts index c3281955e4..1552d45e4e 100644 --- a/src/client/scripts/compose-notification.ts +++ b/src/client/scripts/compose-notification.ts @@ -5,7 +5,7 @@ import { clientDb, get, bulkGet } from '../db'; const getTranslation = (text: string): Promise => get(text, clientDb.i18n); export default async function(type, data): Promise<[string, NotificationOptions]> { - const contexts = ['deletedNote', 'invisibleNote', 'withNFiles', '_cw.poll']; + const contexts = ['deletedNote', 'invisibleNote', 'withNFiles', 'poll']; const locale = Object.fromEntries(await bulkGet(contexts, clientDb.i18n) as [string, string][]); switch (type) { diff --git a/src/client/scripts/is-device-touch.ts b/src/client/scripts/is-device-touch.ts index 9f439ae4fd..3f0bfefed2 100644 --- a/src/client/scripts/is-device-touch.ts +++ b/src/client/scripts/is-device-touch.ts @@ -1,3 +1 @@ -export function isDeviceTouch(): boolean { - return 'maxTouchPoints' in navigator && navigator.maxTouchPoints > 0; -} +export const isDeviceTouch = 'maxTouchPoints' in navigator && navigator.maxTouchPoints > 0; -- cgit v1.2.3-freya