Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85829292
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
11 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js
index 3a274374b4..d2dd91ded1 100644
--- a/src/components/notification/notification.js
+++ b/src/components/notification/notification.js
@@ -1,24 +1,33 @@
import Status from '../status/status.vue'
import StillImage from '../still-image/still-image.vue'
import UserCardContent from '../user_card_content/user_card_content.vue'
+import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
const Notification = {
data () {
return {
userExpanded: false
}
},
props: [
'notification'
],
components: {
Status, StillImage, UserCardContent
},
methods: {
toggleUserExpanded () {
this.userExpanded = !this.userExpanded
}
+ },
+ computed: {
+ userClass () {
+ return highlightClass(this.notification.action.user, this.$store)
+ },
+ userStyle () {
+ return highlightStyle(this.notification.action.user, this.$store)
+ },
}
}
export default Notification
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index eed598a863..97673752ac 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -1,37 +1,37 @@
<template>
<status v-if="notification.type === 'mention'" :compact="true" :statusoid="notification.status"></status>
- <div class="non-mention" v-else>
+ <div class="non-mention" :class="[userClass, { highlighted: userStyle }]" :style="[ userStyle ]"v-else>
<a class='avatar-container' :href="notification.action.user.statusnet_profile_url" @click.stop.prevent.capture="toggleUserExpanded">
<StillImage class='avatar-compact' :src="notification.action.user.profile_image_url_original"/>
</a>
<div class='notification-right'>
<div class="usercard notification-usercard" v-if="userExpanded">
<user-card-content :user="notification.action.user" :switcher="false"></user-card-content>
</div>
<span class="notification-details">
<div class="name-and-action">
<span class="username" :title="'@'+notification.action.user.screen_name">{{ notification.action.user.name }}</span>
<span v-if="notification.type === 'favorite'">
<i class="fa icon-star lit"></i>
<small>{{$t('notifications.favorited_you')}}</small>
</span>
<span v-if="notification.type === 'repeat'">
<i class="fa icon-retweet lit"></i>
<small>{{$t('notifications.repeated_you')}}</small>
</span>
<span v-if="notification.type === 'follow'">
<i class="fa icon-user-plus lit"></i>
<small>{{$t('notifications.followed_you')}}</small>
</span>
</div>
<small class="timeago"><router-link :to="{ name: 'conversation', params: { id: notification.status.id } }"><timeago :since="notification.action.created_at" :auto-update="240"></timeago></router-link></small>
</span>
<div class="follow-text" v-if="notification.type === 'follow'">
<router-link :to="{ name: 'user-profile', params: { id: notification.action.user.id } }">@{{notification.action.user.screen_name}}</router-link>
</div>
<status v-else class="faint" :compact="true" :statusoid="notification.status" :noHeading="true"></status>
</div>
</div>
</template>
<script src="./notification.js"></script>
diff --git a/src/components/status/status.js b/src/components/status/status.js
index f4d0aecb47..fcdc6f6128 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -1,224 +1,203 @@
import Attachment from '../attachment/attachment.vue'
import FavoriteButton from '../favorite_button/favorite_button.vue'
import RetweetButton from '../retweet_button/retweet_button.vue'
import DeleteButton from '../delete_button/delete_button.vue'
import PostStatusForm from '../post_status_form/post_status_form.vue'
import UserCardContent from '../user_card_content/user_card_content.vue'
import StillImage from '../still-image/still-image.vue'
import { filter, find } from 'lodash'
import { hex2rgb } from '../../services/color_convert/color_convert.js'
+import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
const Status = {
name: 'Status',
props: [
'statusoid',
'expandable',
'inConversation',
'focused',
'highlight',
'compact',
'replies',
'noReplyLinks',
'noHeading',
'inlineExpanded'
],
data: () => ({
replying: false,
expanded: false,
unmuted: false,
userExpanded: false,
preview: null,
showPreview: false,
showingTall: false
}),
computed: {
muteWords () {
return this.$store.state.config.muteWords
},
repeaterClass () {
const user = this.statusoid.user
- return this.highlightClass(user)
+ return highlightClass(user, this.$store)
},
userClass () {
const user = this.retweet ? (this.statusoid.retweeted_status.user) : this.statusoid.user
- return this.highlightClass(user)
+ return highlightClass(user, this.$store)
},
repeaterStyle () {
const user = this.statusoid.user
- return this.highlightStyle(user)
+ return highlightStyle(user, this.$store)
},
userStyle () {
const user = this.retweet ? (this.statusoid.retweeted_status.user) : this.statusoid.user
- return this.highlightStyle(user)
+ return highlightStyle(user, this.$store)
},
hideAttachments () {
return (this.$store.state.config.hideAttachments && !this.inConversation) ||
(this.$store.state.config.hideAttachmentsInConv && this.inConversation)
},
retweet () { return !!this.statusoid.retweeted_status },
retweeter () { return this.statusoid.user.name },
status () {
if (this.retweet) {
return this.statusoid.retweeted_status
} else {
return this.statusoid
}
},
loggedIn () {
return !!this.$store.state.users.currentUser
},
muteWordHits () {
const statusText = this.status.text.toLowerCase()
const hits = filter(this.muteWords, (muteWord) => {
return statusText.includes(muteWord.toLowerCase())
})
return hits
},
muted () { return !this.unmuted && (this.status.user.muted || this.muteWordHits.length > 0) },
isReply () { return !!this.status.in_reply_to_status_id },
isFocused () {
// retweet or root of an expanded conversation
if (this.focused) {
return true
} else if (!this.inConversation) {
return false
}
// use conversation highlight only when in conversation
return this.status.id === this.highlight
},
// This is a bit hacky, but we want to approximate post height before rendering
// so we count newlines (masto uses <p> for paragraphs, GS uses <br> between them)
// as well as approximate line count by counting characters and approximating ~80
// per line.
//
// Using max-height + overflow: auto for status components resulted in false positives
// very often with japanese characters, and it was very annoying.
hideTallStatus () {
if (this.showingTall) {
return false
}
const lengthScore = this.status.statusnet_html.split(/<p|<br/).length + this.status.text.length / 80
return lengthScore > 20
},
attachmentSize () {
if ((this.$store.state.config.hideAttachments && !this.inConversation) ||
(this.$store.state.config.hideAttachmentsInConv && this.inConversation)) {
return 'hide'
} else if (this.compact) {
return 'small'
}
return 'normal'
}
},
components: {
Attachment,
FavoriteButton,
RetweetButton,
DeleteButton,
PostStatusForm,
UserCardContent,
StillImage
},
methods: {
visibilityIcon (visibility) {
switch (visibility) {
case 'private':
return 'icon-lock'
case 'unlisted':
return 'icon-lock-open-alt'
case 'direct':
return 'icon-mail-alt'
default:
return 'icon-globe'
}
},
linkClicked ({target}) {
if (target.tagName === 'SPAN') {
target = target.parentNode
}
if (target.tagName === 'A') {
window.open(target.href, '_blank')
}
},
toggleReplying () {
this.replying = !this.replying
},
gotoOriginal (id) {
// only handled by conversation, not status_or_conversation
if (this.inConversation) {
this.$emit('goto', id)
}
},
toggleExpanded () {
this.$emit('toggleExpanded')
},
toggleMute () {
this.unmuted = !this.unmuted
},
toggleUserExpanded () {
this.userExpanded = !this.userExpanded
},
toggleShowTall () {
this.showingTall = !this.showingTall
},
replyEnter (id, event) {
this.showPreview = true
const targetId = Number(id)
const statuses = this.$store.state.statuses.allStatuses
if (!this.preview) {
// if we have the status somewhere already
this.preview = find(statuses, { 'id': targetId })
// or if we have to fetch it
if (!this.preview) {
this.$store.state.api.backendInteractor.fetchStatus({id}).then((status) => {
this.preview = status
})
}
} else if (this.preview.id !== targetId) {
this.preview = find(statuses, { 'id': targetId })
}
},
replyLeave () {
this.showPreview = false
},
- highlightStyle (user) {
- const color = this.$store.state.config.highlight[user.screen_name]
- if (!color) return
- const rgb = hex2rgb(color)
- const tintColor = `rgba(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)}, .1)`
- const tintColor2 = `rgba(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)}, .2)`
- return {
- backgroundImage: [
- 'repeating-linear-gradient(-45deg,',
- tintColor, ',',
- tintColor, '20px,',
- tintColor2, '20px,',
- tintColor2, '40px',
- ].join(' '),
- backgroundPosition: '0 0'
- }
- },
- highlightClass (user) {
- return 'USER____' + user.screen_name
- .replace(/\./g,'_')
- .replace(/\@/g,'_AT_')
- }
},
watch: {
'highlight': function (id) {
id = Number(id)
if (this.status.id === id) {
let rect = this.$el.getBoundingClientRect()
if (rect.top < 100) {
window.scrollBy(0, rect.top - 200)
} else if (rect.bottom > window.innerHeight - 50) {
window.scrollBy(0, rect.bottom - window.innerHeight + 50)
}
}
}
}
}
export default Status
diff --git a/src/services/user_highlighter/user_highlighter.js b/src/services/user_highlighter/user_highlighter.js
new file mode 100644
index 0000000000..94bf2c4064
--- /dev/null
+++ b/src/services/user_highlighter/user_highlighter.js
@@ -0,0 +1,29 @@
+import { hex2rgb } from '../color_convert/color_convert.js'
+const highlightStyle = (user, store) => {
+ const color = store.state.config.highlight[user.screen_name]
+ if (!color) return
+ const rgb = hex2rgb(color)
+ const tintColor = `rgba(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)}, .1)`
+ const tintColor2 = `rgba(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)}, .2)`
+ return {
+ backgroundImage: [
+ 'repeating-linear-gradient(-45deg,',
+ `${tintColor} ,`,
+ `${tintColor} 20px,`,
+ `${tintColor2} 20px,`,
+ `${tintColor2} 40px`
+ ].join(' '),
+ backgroundPosition: '0 0'
+ }
+}
+
+const highlightClass = (user) => {
+ return 'USER____' + user.screen_name
+ .replace(/\./g, '_')
+ .replace(/@/g, '_AT_')
+}
+
+export {
+ highlightClass,
+ highlightStyle
+}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Oct 31, 6:09 PM (19 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1801647
Default Alt Text
(11 KB)
Attached To
Mode
rPUFE pleroma-fe-upstream
Attached
Detach File
Event Timeline