diff options
| author | Henry Jameson <me@hjkos.com> | 2018-08-16 13:59:01 +0300 |
|---|---|---|
| committer | Henry Jameson <me@hjkos.com> | 2018-08-16 13:59:01 +0300 |
| commit | 6454837ea4d8acc49387562d056490c514dabc91 (patch) | |
| tree | 37e962dbfeab5d8fd2c338faff50333efe979c32 /src/components | |
| parent | decc209fdcd7b62ec46b559b3d5bfc0f1c343b25 (diff) | |
| parent | ce88f351f7b28a36553e67f7e02373be7b51ef8f (diff) | |
Merge remote-tracking branch 'upstream/develop' into notifications
* upstream/develop: (26 commits)
Update status.vue
Update retweet_button.js
Update retweet_button.vue
Use serverside html rendering in usernames and bios if available.
Update status.vue
Revert "Merge branch 'feature/hide-all-status-actions-if-not-logged-in' into 'develop'"
Hide all status actions if not logged in
hopefully, fix linter
Fixes broken custom emoji in autocomplete when proxying to remote BE
Made it so that unfocused tab doesn't autostream posts when scrolled to the top
Remove trailing whitespace
Textarea is now focused when replying
the missing piece for invites system
Fixes selects having unreadable text on some browsers/OSes. Added bonus: theme switcher select now has styled options that show preview of what theme's bg/fg colors are
fixed lint
cleanup, fixed self-highlighting in notifications, fixed incorrect hex code handling
added ability to pick the style of highlighting
post-rebase fix, backported d7d787b84cb8e36ad7f622054808f0e66c496309
notifs fix
maybe i should actually add myself to contributors list?
...
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/notification/notification.js | 11 | ||||
| -rw-r--r-- | src/components/notification/notification.vue | 5 | ||||
| -rw-r--r-- | src/components/notifications/notifications.scss | 4 | ||||
| -rw-r--r-- | src/components/post_status_form/post_status_form.js | 8 | ||||
| -rw-r--r-- | src/components/registration/registration.js | 10 | ||||
| -rw-r--r-- | src/components/registration/registration.vue | 4 | ||||
| -rw-r--r-- | src/components/retweet_button/retweet_button.js | 2 | ||||
| -rw-r--r-- | src/components/retweet_button/retweet_button.vue | 4 | ||||
| -rw-r--r-- | src/components/status/status.js | 21 | ||||
| -rw-r--r-- | src/components/status/status.vue | 17 | ||||
| -rw-r--r-- | src/components/style_switcher/style_switcher.vue | 5 | ||||
| -rw-r--r-- | src/components/timeline/timeline.js | 15 | ||||
| -rw-r--r-- | src/components/user_card/user_card.vue | 10 | ||||
| -rw-r--r-- | src/components/user_card_content/user_card_content.js | 28 | ||||
| -rw-r--r-- | src/components/user_card_content/user_card_content.vue | 122 |
15 files changed, 207 insertions, 59 deletions
diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js index 3a274374..c786f2cc 100644 --- a/src/components/notification/notification.js +++ b/src/components/notification/notification.js @@ -1,6 +1,7 @@ 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 () { @@ -18,6 +19,16 @@ const Notification = { toggleUserExpanded () { this.userExpanded = !this.userExpanded } + }, + computed: { + userClass () { + return highlightClass(this.notification.action.user) + }, + userStyle () { + const highlight = this.$store.state.config.highlight + const user = this.notification.action.user + return highlightStyle(highlight[user.screen_name]) + } } } diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue index 2485b9ff..72c1ca69 100644 --- a/src/components/notification/notification.vue +++ b/src/components/notification/notification.vue @@ -1,6 +1,6 @@ <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> @@ -10,7 +10,8 @@ </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 class="username" v-if="!!notification.action.user.name_html" :title="'@'+notification.action.user.screen_name" v-html="notification.action.user.name_html"></span> + <span class="username" v-else :title="'@'+notification.action.user.screen_name">{{ notification.action.user.name }}</span> <span v-if="notification.type === 'like'"> <i class="fa icon-star lit"></i> <small>{{$t('notifications.favorited_you')}}</small> diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss index 09741060..2bc71bfe 100644 --- a/src/components/notifications/notifications.scss +++ b/src/components/notifications/notifications.scss @@ -45,8 +45,7 @@ } .unseen { - border-left: 4px solid $fallback--cRed; - border-left: 4px solid var(--cRed, $fallback--cRed); + box-shadow: inset 4px 0 0 var(--cRed, $fallback--cRed); padding-left: 0; } } @@ -56,7 +55,6 @@ display: flex; border-bottom: 1px solid; border-bottom-color: inherit; - padding-left: 4px; .broken-favorite { border-radius: $fallback--tooltipRadius; diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 4f4c6aca..61f2ac0a 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -31,6 +31,10 @@ const PostStatusForm = { }, mounted () { this.resize(this.$refs.textarea) + + if (this.replyTo) { + this.$refs.textarea.focus() + } }, data () { const preset = this.$route.query.message @@ -87,11 +91,11 @@ const PostStatusForm = { return false } return map(take(matchedEmoji, 5), ({shortcode, image_url, utf}, index) => ({ - // eslint-disable-next-line camelcase screen_name: `:${shortcode}:`, name: '', utf: utf || '', - img: image_url, + // eslint-disable-next-line camelcase + img: utf ? '' : this.$store.state.config.server + image_url, highlighted: index === this.highlighted })) } else { diff --git a/src/components/registration/registration.js b/src/components/registration/registration.js index 771b3b27..73840608 100644 --- a/src/components/registration/registration.js +++ b/src/components/registration/registration.js @@ -5,17 +5,23 @@ const registration = { registering: false }), created () { - if (!this.$store.state.config.registrationOpen || !!this.$store.state.users.currentUser) { + if ((!this.$store.state.config.registrationOpen && !this.token) || !!this.$store.state.users.currentUser) { this.$router.push('/main/all') } + // Seems like this doesn't work at first page open for some reason + if (this.$store.state.config.registrationOpen && this.token) { + this.$router.push('/registration') + } }, computed: { - termsofservice () { return this.$store.state.config.tos } + termsofservice () { return this.$store.state.config.tos }, + token () { return this.$route.params.token } }, methods: { submit () { this.registering = true this.user.nickname = this.user.username + this.user.token = this.token this.$store.state.api.backendInteractor.register(this.user).then( (response) => { if (response.ok) { diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue index 00f665af..087cab6b 100644 --- a/src/components/registration/registration.vue +++ b/src/components/registration/registration.vue @@ -38,6 +38,10 @@ <input :disabled="registering" v-model='user.captcha' placeholder='Enter captcha' type='test' class='form-control' id='captcha'> </div> --> + <div class='form-group' v-if='token' > + <label for='token'>{{$t('registration.token')}}</label> + <input disabled='true' v-model='token' class='form-control' id='token' type='text'> + </div> <div class='form-group'> <button :disabled="registering" type='submit' class='btn btn-default'>{{$t('general.submit')}}</button> </div> diff --git a/src/components/retweet_button/retweet_button.js b/src/components/retweet_button/retweet_button.js index 9833e8b2..cafa9cbc 100644 --- a/src/components/retweet_button/retweet_button.js +++ b/src/components/retweet_button/retweet_button.js @@ -1,5 +1,5 @@ const RetweetButton = { - props: ['status', 'loggedIn'], + props: ['status', 'loggedIn', 'visibility'], data () { return { animated: false diff --git a/src/components/retweet_button/retweet_button.vue b/src/components/retweet_button/retweet_button.vue index 1bee3d08..f5b00599 100644 --- a/src/components/retweet_button/retweet_button.vue +++ b/src/components/retweet_button/retweet_button.vue @@ -1,9 +1,9 @@ <template> - <div v-if="loggedIn"> + <div v-if="loggedIn && visibility !== 'private' && visibility !== 'direct'"> <i :class='classes' class='icon-retweet rt-active' v-on:click.prevent='retweet()'></i> <span v-if='status.repeat_num > 0'>{{status.repeat_num}}</span> </div> - <div v-else> + <div v-else-if="!loggedIn"> <i :class='classes' class='icon-retweet'></i> <span v-if='status.repeat_num > 0'>{{status.repeat_num}}</span> </div> diff --git a/src/components/status/status.js b/src/components/status/status.js index 87ef90d8..a2d6f41f 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -6,6 +6,7 @@ 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 { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js' const Status = { name: 'Status', @@ -34,12 +35,32 @@ const Status = { muteWords () { return this.$store.state.config.muteWords }, + repeaterClass () { + const user = this.statusoid.user + return highlightClass(user) + }, + userClass () { + const user = this.retweet ? (this.statusoid.retweeted_status.user) : this.statusoid.user + return highlightClass(user) + }, + repeaterStyle () { + const user = this.statusoid.user + const highlight = this.$store.state.config.highlight + return highlightStyle(highlight[user.screen_name]) + }, + userStyle () { + if (this.noHeading) return + const user = this.retweet ? (this.statusoid.retweeted_status.user) : this.statusoid.user + const highlight = this.$store.state.config.highlight + return highlightStyle(highlight[user.screen_name]) + }, 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 }, + retweeterHtml () { return this.statusoid.user.name_html }, status () { if (this.retweet) { return this.statusoid.retweeted_status diff --git a/src/components/status/status.vue b/src/components/status/status.vue index f88c810d..e2fb5d36 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -8,16 +8,17 @@ </div> </template> <template v-else> - <div v-if="retweet && !noHeading" class="media container retweet-info"> + <div v-if="retweet && !noHeading" :class="[repeaterClass, { highlighted: repeaterStyle }]" :style="[repeaterStyle]" class="media container retweet-info"> <StillImage v-if="retweet" class='avatar' :src="statusoid.user.profile_image_url_original"/> <div class="media-body faint"> - <a :href="statusoid.user.statusnet_profile_url" style="font-weight: bold;" :title="'@'+statusoid.user.screen_name">{{retweeter}}</a> + <a v-if="retweeterHtml" :href="statusoid.user.statusnet_profile_url" style="font-weight: bold;" :title="'@'+statusoid.user.screen_name" v-html="retweeterHtml"></a> + <a v-else :href="statusoid.user.statusnet_profile_url" style="font-weight: bold;" :title="'@'+statusoid.user.screen_name">{{retweeter}}</a> <i class='fa icon-retweet retweeted'></i> {{$t('timeline.repeated')}} </div> </div> - <div class="media status"> + <div :class="[userClass, { highlighted: userStyle, 'is-retweet': retweet }]" :style="[ userStyle ]" class="media status"> <div v-if="!noHeading" class="media-left"> <a :href="status.user.statusnet_profile_url" @click.stop.prevent.capture="toggleUserExpanded"> <StillImage class='avatar' :class="{'avatar-compact': compact}" :src="status.user.profile_image_url_original"/> @@ -30,7 +31,8 @@ <div v-if="!noHeading" class="media-body container media-heading"> <div class="media-heading-left"> <div class="name-and-links"> - <h4 class="user-name">{{status.user.name}}</h4> + <h4 class="user-name" v-if="status.user.name_html" v-html="status.user.name_html"></h4> + <h4 class="user-name" v-else>{{status.user.name}}</h4> <span class="links"> <router-link :to="{ name: 'user-profile', params: { id: status.user.id } }">{{status.user.screen_name}}</router-link> <span v-if="status.in_reply_to_screen_name" class="faint reply-info"> @@ -88,7 +90,7 @@ <i class="icon-reply" :class="{'icon-reply-active': replying}"></i> </a> </div> - <retweet-button :loggedIn='loggedIn' :status='status'></retweet-button> + <retweet-button :visibility='status.visibility' :loggedIn='loggedIn' :status='status'></retweet-button> <favorite-button :loggedIn='loggedIn' :status='status'></favorite-button> <delete-button :status='status'></delete-button> </div> @@ -315,7 +317,7 @@ .retweet-info { padding: 0.4em 0.6em 0 0.6em; - margin: 0 0 -0.5em 0; + margin: 0; .avatar { border-radius: $fallback--avatarAltRadius; border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius); @@ -427,6 +429,9 @@ .status { display: flex; padding: 0.6em; + &.is-retweet { + padding-top: 0.1em; + } } .status-conversation:last-child { diff --git a/src/components/style_switcher/style_switcher.vue b/src/components/style_switcher/style_switcher.vue index 7acba1dc..112bbc1e 100644 --- a/src/components/style_switcher/style_switcher.vue +++ b/src/components/style_switcher/style_switcher.vue @@ -3,7 +3,10 @@ <div>{{$t('settings.presets')}} <label for="style-switcher" class='select'> <select id="style-switcher" v-model="selected" class="style-switcher"> - <option v-for="style in availableStyles" :value="style">{{style[0]}}</option> + <option v-for="style in availableStyles" :value="style" :style="{ + backgroundColor: style[1], + color: style[3] + }">{{style[0]}}</option> </select> <i class="icon-down-open"/> </label> diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index f24626f9..5c179567 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -13,7 +13,8 @@ const Timeline = { ], data () { return { - paused: false + paused: false, + unfocused: false } }, computed: { @@ -65,8 +66,15 @@ const Timeline = { this.fetchFollowers() } }, + mounted () { + if (typeof document.hidden !== 'undefined') { + document.addEventListener('visibilitychange', this.handleVisibilityChange, false) + this.unfocused = document.hidden + } + }, destroyed () { window.removeEventListener('scroll', this.scrollLoad) + if (typeof document.hidden !== 'undefined') document.removeEventListener('visibilitychange', this.handleVisibilityChange, false) this.$store.commit('setLoading', { timeline: this.timelineName, value: false }) }, methods: { @@ -113,6 +121,9 @@ const Timeline = { (window.innerHeight + window.pageYOffset) >= (height - 750)) { this.fetchOlderStatuses() } + }, + handleVisibilityChange () { + this.unfocused = document.hidden } }, watch: { @@ -122,7 +133,7 @@ const Timeline = { } if (count > 0) { // only 'stream' them when you're scrolled to the top - if (window.pageYOffset < 15 && !this.paused) { + if (window.pageYOffset < 15 && !this.paused && !this.unfocused) { this.showNewStatuses() } else { this.paused = true diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index 6478a65f..7e3e0afe 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -7,10 +7,16 @@ <user-card-content :user="user" :switcher="false"></user-card-content> </div> <div class="name-and-screen-name" v-else> - <div :title="user.name" class="user-name"> + <div :title="user.name" v-if="user.name_html" class="user-name"> + <span v-html="user.name_html"></span> + <span class="follows-you" v-if="!userExpanded && showFollows && user.follows_you"> + {{ $t('user_card.follows_you') }} + </span> + </div> + <div :title="user.name" v-else class="user-name"> {{ user.name }} <span class="follows-you" v-if="!userExpanded && showFollows && user.follows_you"> - {{ $t('user_card.follows_you') }} + {{ $t('user_card.follows_you') }} </span> </div> <a :href="user.statusnet_profile_url" target="blank"><div class="user-screen-name">@{{ user.screen_name }}</div></a> diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js index 4d4266cb..76a5577e 100644 --- a/src/components/user_card_content/user_card_content.js +++ b/src/components/user_card_content/user_card_content.js @@ -9,11 +9,6 @@ export default { if (color) { const rgb = hex2rgb(color) const tintColor = `rgba(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)}, .5)` - console.log(rgb) - console.log([ - `url(${this.user.cover_photo})`, - `linear-gradient(to bottom, ${tintColor}, ${tintColor})` - ].join(', ')) return { backgroundColor: `rgb(${Math.floor(rgb.r * 0.53)}, ${Math.floor(rgb.g * 0.56)}, ${Math.floor(rgb.b * 0.59)})`, backgroundImage: [ @@ -37,6 +32,29 @@ export default { dailyAvg () { const days = Math.ceil((new Date() - new Date(this.user.created_at)) / (60 * 60 * 24 * 1000)) return Math.round(this.user.statuses_count / days) + }, + userHighlightType: { + get () { + const data = this.$store.state.config.highlight[this.user.screen_name] + return data && data.type || 'disabled' + }, + set (type) { + const data = this.$store.state.config.highlight[this.user.screen_name] + if (type !== 'disabled') { + this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: data && data.color || '#FFFFFF', type }) + } else { + this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: undefined }) + } + } + }, + userHighlightColor: { + get () { + const data = this.$store.state.config.highlight[this.user.screen_name] + return data && data.color + }, + set (color) { + this.$store.dispatch('setHighlight', { user: this.user.screen_name, color }) + } } }, components: { diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue index 09e91271..71222d15 100644 --- a/src/components/user_card_content/user_card_content.vue +++ b/src/components/user_card_content/user_card_content.vue @@ -1,29 +1,46 @@ <template> - <div id="heading" class="profile-panel-background" :style="headingStyle"> - <div class="panel-heading text-center"> - <div class='user-info'> - <router-link to='/user-settings' style="float: right; margin-top:16px;" v-if="!isOtherUser"> - <i class="icon-cog usersettings"></i> +<div id="heading" class="profile-panel-background" :style="headingStyle"> + <div class="panel-heading text-center"> + <div class='user-info'> + <router-link to='/user-settings' style="float: right; margin-top:16px;" v-if="!isOtherUser"> + <i class="icon-cog usersettings"></i> + </router-link> + <a :href="user.statusnet_profile_url" target="_blank" class="floater" v-if="isOtherUser"> + <i class="icon-link-ext usersettings"></i> + </a> + <div class='container'> + <router-link :to="{ name: 'user-profile', params: { id: user.id } }"> + <StillImage class="avatar" :src="user.profile_image_url_original"/> </router-link> - <a :href="user.statusnet_profile_url" target="_blank" style="float: right; margin-top:16px;" v-if="isOtherUser"> - <i class="icon-link-ext usersettings"></i> - </a> - <div class='container'> - <router-link :to="{ name: 'user-profile', params: { id: user.id } }"> - <StillImage class="avatar" :src="user.profile_image_url_original"/> + <div class="name-and-screen-name"> + <div :title="user.name" class='user-name' v-if="user.name_html" v-html="user.name_html"></div> + <div :title="user.name" class='user-name' v-else>{{user.name}}</div> + <router-link class='user-screen-name':to="{ name: 'user-profile', params: { id: user.id } }"> + <span>@{{user.screen_name}}</span><span v-if="user.locked"><i class="icon icon-lock"></i></span> + <span class="dailyAvg">{{dailyAvg}} {{ $t('user_card.per_day') }}</span> </router-link> - <div class="name-and-screen-name"> - <div :title="user.name" class='user-name'>{{user.name}}</div> - <router-link class='user-screen-name':to="{ name: 'user-profile', params: { id: user.id } }"> - <span>@{{user.screen_name}}</span><span v-if="user.locked"><i class="icon icon-lock"></i></span> - <span class="dailyAvg">{{dailyAvg}} {{ $t('user_card.per_day') }}</span> - </router-link> - </div> </div> - <div v-if="isOtherUser" class="user-interactions"> - <div v-if="user.follows_you && loggedIn" class="following"> - {{ $t('user_card.follows_you') }} - </div> + </div> + <div class="user-meta"> + <div v-if="user.follows_you && loggedIn && isOtherUser" class="following"> + {{ $t('user_card.follows_you') }} + </div> + <div class="floater" v-if="switcher || isOtherUser"> + <!-- id's need to be unique, otherwise vue confuses which user-card checkbox belongs to --> + <input class="userHighlightText" type="text" :id="'userHighlightColorTx'+user.id" v-if="userHighlightType !== 'disabled'" v-model="userHighlightColor"/> + <input class="userHighlightCl" type="color" :id="'userHighlightColor'+user.id" v-if="userHighlightType !== 'disabled'" v-model="userHighlightColor"/> + <label for="style-switcher" class='userHighlightSel select'> + <select class="userHighlightSel" :id="'userHighlightSel'+user.id" v-model="userHighlightType"> + <option value="disabled">No highlight</option> + <option value="solid">Solid bg</option> + <option value="striped">Striped bg</option> + <option value="side">Side stripe</option> + </select> + <i class="icon-down-open"/> + </label> + </div> + </div> + <div v-if="isOtherUser" class="user-interactions"> <div class="follow" v-if="loggedIn"> <span v-if="user.following"> <!--Following them!--> @@ -88,7 +105,8 @@ <span>{{user.followers_count}}</span> </div> </div> - <p v-if="!hideBio">{{user.description}}</p> + <p v-if="!hideBio && user.description_html" v-html="user.description_html"></p> + <p v-else-if="!hideBio">{{ user.description }}</p> </div> </div> </template> @@ -179,6 +197,27 @@ padding-right: 0.1em; } + .user-meta { + margin-bottom: .4em; + + .following { + font-size: 14px; + flex: 0 0 100%; + margin: 0; + padding-left: 16px; + text-align: left; + float: left; + } + .floater { + margin: 0; + } + + &::after { + display: block; + content: ''; + clear: both; + } + } .user-interactions { display: flex; flex-flow: row wrap; @@ -188,14 +227,6 @@ flex: 1; } - .following { - font-size: 14px; - flex: 0 0 100%; - margin: 0 0 .4em 0; - padding-left: 16px; - text-align: left; - } - .mute { max-width: 220px; min-height: 28px; @@ -278,4 +309,33 @@ font-size: 0.7em; color: #CCC; } +.floater { + float: right; + margin-top: 16px; + + .userHighlightCl { + padding: 2px 10px; + } + .userHighlightSel, + .userHighlightSel.select { + padding-top: 0; + padding-bottom: 0; + } + .userHighlightSel.select i { + line-height: 22px; + } + + .userHighlightText { + width: 70px; + } + + .userHighlightCl, + .userHighlightText, + .userHighlightSel, + .userHighlightSel.select { + height: 22px; + vertical-align: top; + margin-right: 0 + } +} </style> |
