commit: fc341aa40da786ea0b168bbee2f52add0514a046
parent: 9982296866f0592747064d3cb6ddfac0fce516b1
Author: lambadalambda <gitgud@rogerbraun.net>
Date: Wed, 7 Jun 2017 12:18:55 -0400
Merge branch 'feature/reply-previews' into 'develop'
Reply previews in conversations
See merge request !89
Diffstat:
8 files changed, 80 insertions(+), 11 deletions(-)
diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js
@@ -1,4 +1,4 @@
-import { filter, sortBy } from 'lodash'
+import { find, filter, sortBy } from 'lodash'
import { statusType } from '../../modules/statuses.js'
import Status from '../status/status.vue'
@@ -10,7 +10,12 @@ const sortAndFilterConversation = (conversation) => {
const conversation = {
data () {
return {
- highlight: null
+ highlight: null,
+ preview: {
+ x: 0,
+ y: 0,
+ status: null
+ }
}
},
props: [
@@ -76,6 +81,15 @@ const conversation = {
},
setHighlight (id) {
this.highlight = Number(id)
+ },
+ setPreview (id, x, y) {
+ if (id) {
+ this.preview.x = x
+ this.preview.y = y
+ this.preview.status = find(this.conversation, { id: id })
+ } else {
+ this.preview.status = null
+ }
}
}
}
diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
@@ -8,7 +8,17 @@
</div>
<div class="panel-body">
<div class="timeline">
- <status v-for="status in conversation" @goto="setHighlight" :key="status.id" :statusoid="status" :expandable='false' :focused="focused(status.id)" :inConversation='true' :highlight="highlight" :replies="getReplies(status.id)"></status>
+ <status v-for="status in conversation" @goto="setHighlight" :key="status.id" @preview="setPreview" :statusoid="status" :expandable='false' :focused="focused(status.id)" :inConversation='true' :highlight="highlight" :replies="getReplies(status.id)"></status>
+ </div>
+ </div>
+ <div class="status-preview base00-background base03-border" :style="{ left: preview.x + 'px', top: preview.y + 'px'}" v-if="preview.status">
+ <img class="avatar" :src="preview.status.user.profile_image_url_original">
+ <div class="text">
+ <h4>
+ {{ preview.status.user.name }}
+ <small><a>{{ preview.status.user.screen_name}}</a></small>
+ </h4>
+ <div @click.prevent="linkClicked" class="status-content" v-html="preview.status.statusnet_html"></div>
</div>
</div>
</div>
@@ -21,4 +31,30 @@
border-bottom-style: solid;
border-bottom-width: 1px;
}
+
+ .status-preview {
+ position: absolute;
+ max-width: 35em;
+ padding: 0.5em;
+ display: flex;
+ border-color: inherit;
+ border-style: solid;
+ border-width: 1px;
+ border-radius: 4px;
+ box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5);
+ .avatar {
+ width: 32px;
+ height: 32px;
+ border-radius: 50%;
+ }
+ .text {
+ h4 {
+ margin-bottom: 0.4em;
+ small {
+ font-weight: lighter;
+ }
+ }
+ padding: 0 0.5em 0.5em 0.5em;
+ }
+ }
</style>
diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js
@@ -8,6 +8,7 @@ const settings = {
hideAttachmentsInConvLocal: this.$store.state.config.hideAttachmentsInConv,
hideNsfwLocal: this.$store.state.config.hideNsfw,
autoLoadLocal: this.$store.state.config.autoLoad,
+ hoverPreviewLocal: this.$store.state.config.hoverPreview,
muteWordsString: this.$store.state.config.muteWords.join('\n')
}
},
@@ -27,6 +28,9 @@ const settings = {
autoLoadLocal (value) {
this.$store.dispatch('setOption', { name: 'autoLoad', value })
},
+ hoverPreviewLocal (value) {
+ this.$store.dispatch('setOption', { name: 'hoverPreview', value })
+ },
muteWordsString (value) {
value = filter(value.split('\n'), (word) => trim(word).length > 0)
this.$store.dispatch('setOption', { name: 'muteWords', value })
diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
@@ -32,6 +32,10 @@
<input type="checkbox" id="autoLoad" v-model="autoLoadLocal">
<label for="autoLoad">Enable automatic loading when scrolled to the bottom</label>
</li>
+ <li>
+ <input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal">
+ <label for="hoverPreview">Enable reply-link preview on mouse hover</label>
+ </li>
</ul>
</div>
</div>
diff --git a/src/components/status/status.js b/src/components/status/status.js
@@ -100,6 +100,15 @@ const Status = {
},
toggleUserExpanded () {
this.userExpanded = !this.userExpanded
+ },
+ replyEnter (id, event) {
+ if (this.$store.state.config.hoverPreview) {
+ let rect = event.target.getBoundingClientRect()
+ this.$emit('preview', Number(id), rect.left + 20, rect.top + 20 + window.pageYOffset)
+ }
+ },
+ replyLeave () {
+ this.$emit('preview', 0, 0, 0)
}
},
watch: {
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
@@ -19,7 +19,7 @@
<div class="media status container muted">
<small><router-link :to="{ name: 'user-profile', params: { id: status.user.id } }">{{status.user.screen_name}}</router-link></small>
<small class="muteWords">{{muteWordHits.join(', ')}}</small>
- <a href="#" class="unmute" @click.prevent="toggleMute"><i class="icon-eye-off"></i></a>
+ <a href="#" class="unmute" @click.prevent="toggleMute"><i class="fa icon-eye-off"></i></a>
</div>
</template>
<template v-if="!muted">
@@ -56,7 +56,7 @@
</small>
<template v-if="isReply && !expandable">
<small>
- <a href="#" @click.prevent="gotoOriginal(status.in_reply_to_status_id)" ><i class="icon-reply"></i></a>
+ <a href="#" @click.prevent="gotoOriginal(status.in_reply_to_status_id)"><i class="icon-reply" @mouseenter="replyEnter(status.in_reply_to_status_id, $event)" @mouseout="replyLeave()"></i></a>
</small>
</template>
-
@@ -70,7 +70,7 @@
<h4 class="replies" v-if="inConversation">
<small v-if="replies.length">Replies:</small>
<small v-for="reply in replies">
- <a href="#" @click.prevent="gotoOriginal(reply.id)">{{reply.name}} </a>
+ <a href="#" @click.prevent="gotoOriginal(reply.id)" @mouseenter="replyEnter(reply.id, $event)" @mouseout="replyLeave()">{{reply.name}} </a>
</small>
</h4>
</div>
@@ -178,10 +178,6 @@
margin-right: -0.3em;
}
- .greentext {
- color: green;
- }
-
a {
display: inline-block;
word-break: break-all;
@@ -222,6 +218,10 @@
}
}
+ .greentext {
+ color: green;
+ }
+
.status-conversation {
border-left-style: solid;
}
@@ -278,7 +278,7 @@
}
.muted {
- padding: 0.1em 0.7em 0.1em 0.8em;
+ padding: 0.1em 0.4em 0.1em 0.8em;
button {
margin-left: auto;
}
diff --git a/src/main.js b/src/main.js
@@ -34,6 +34,7 @@ const persistedStateOptions = {
'config.hideAttachmentsInConv',
'config.hideNsfw',
'config.autoLoad',
+ 'config.hoverPreview',
'config.muteWords',
'statuses.notifications',
'users.users'
diff --git a/src/modules/config.js b/src/modules/config.js
@@ -8,6 +8,7 @@ const defaultState = {
hideAttachmentsInConv: false,
hideNsfw: true,
autoLoad: true,
+ hoverPreview: true,
muteWords: []
}