diff options
Diffstat (limited to 'src/components')
19 files changed, 143 insertions, 35 deletions
diff --git a/src/components/about/about.js b/src/components/about/about.js index b4433b4e..ae1cb182 100644 --- a/src/components/about/about.js +++ b/src/components/about/about.js @@ -7,6 +7,9 @@ const About = { InstanceSpecificPanel, FeaturesPanel, TermsOfServicePanel + }, + computed: { + showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel } } } diff --git a/src/components/about/about.vue b/src/components/about/about.vue index bf87e0b8..13dec87c 100644 --- a/src/components/about/about.vue +++ b/src/components/about/about.vue @@ -1,7 +1,7 @@ <template> <div class="sidebar"> <instance-specific-panel></instance-specific-panel> - <features-panel></features-panel> + <features-panel v-if="showFeaturesPanel"></features-panel> <terms-of-service-panel></terms-of-service-panel> </div> </template> diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 5e8c2252..ab379c23 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -65,7 +65,6 @@ const PostStatusForm = { newStatus: { spoilerText: this.subject || '', status: statusText, - contentType: 'text/plain', nsfw: false, files: [], visibility: scope @@ -167,6 +166,11 @@ const PostStatusForm = { }, formattingOptionsEnabled () { return this.$store.state.instance.formattingOptionsEnabled + }, + defaultPostContentType () { + return typeof this.$store.state.config.postContentType === 'undefined' + ? this.$store.state.instance.postContentType + : this.$store.state.config.postContentType } }, methods: { diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index e09ad37f..6ed5d92e 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -35,7 +35,7 @@ <div class="visibility-tray"> <span class="text-format" v-if="formattingOptionsEnabled"> <label for="post-content-type" class="select"> - <select id="post-content-type" v-model="newStatus.contentType" class="form-control"> + <select id="post-content-type" v-model="defaultPostContentType" class="form-control"> <option value="text/plain">{{$t('post_status.content_type.plain_text')}}</option> <option value="text/html">HTML</option> <option value="text/markdown">Markdown</option> diff --git a/src/components/public_and_external_timeline/public_and_external_timeline.js b/src/components/public_and_external_timeline/public_and_external_timeline.js index 0db6efae..d45677e0 100644 --- a/src/components/public_and_external_timeline/public_and_external_timeline.js +++ b/src/components/public_and_external_timeline/public_and_external_timeline.js @@ -7,7 +7,7 @@ const PublicAndExternalTimeline = { timeline () { return this.$store.state.statuses.timelines.publicAndExternal } }, created () { - this.$store.dispatch('startFetching', 'publicAndExternal') + this.$store.dispatch('startFetching', { timeline: 'publicAndExternal' }) }, destroyed () { this.$store.dispatch('stopFetching', 'publicAndExternal') diff --git a/src/components/public_and_external_timeline/public_and_external_timeline.vue b/src/components/public_and_external_timeline/public_and_external_timeline.vue index aded2ead..6be9f955 100644 --- a/src/components/public_and_external_timeline/public_and_external_timeline.vue +++ b/src/components/public_and_external_timeline/public_and_external_timeline.vue @@ -1,5 +1,5 @@ <template> - <Timeline :title="$t('nav.twkn')"v-bind:timeline="timeline" v-bind:timeline-name="'publicAndExternal'"/> + <Timeline :title="$t('nav.twkn')" v-bind:timeline="timeline" v-bind:timeline-name="'publicAndExternal'"/> </template> <script src="./public_and_external_timeline.js"></script> diff --git a/src/components/public_timeline/public_timeline.js b/src/components/public_timeline/public_timeline.js index 9b866be8..64c951ac 100644 --- a/src/components/public_timeline/public_timeline.js +++ b/src/components/public_timeline/public_timeline.js @@ -7,7 +7,7 @@ const PublicTimeline = { timeline () { return this.$store.state.statuses.timelines.public } }, created () { - this.$store.dispatch('startFetching', 'public') + this.$store.dispatch('startFetching', { timeline: 'public' }) }, destroyed () { this.$store.dispatch('stopFetching', 'public') diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js index 8d138485..534a9839 100644 --- a/src/components/settings/settings.js +++ b/src/components/settings/settings.js @@ -27,6 +27,11 @@ const settings = { : user.hideUserStats, hideUserStatsDefault: this.$t('settings.values.' + instance.hideUserStats), + hideFilteredStatusesLocal: typeof user.hideFilteredStatuses === 'undefined' + ? instance.hideFilteredStatuses + : user.hideFilteredStatuses, + hideFilteredStatusesDefault: this.$t('settings.values.' + instance.hideFilteredStatuses), + notificationVisibilityLocal: user.notificationVisibility, replyVisibilityLocal: user.replyVisibility, loopVideoLocal: user.loopVideo, @@ -46,6 +51,11 @@ const settings = { : user.subjectLineBehavior, subjectLineBehaviorDefault: instance.subjectLineBehavior, + postContentTypeLocal: typeof user.postContentType === 'undefined' + ? instance.postContentType + : user.postContentType, + postContentTypeDefault: instance.postContentType, + alwaysShowSubjectInputLocal: typeof user.alwaysShowSubjectInput === 'undefined' ? instance.alwaysShowSubjectInput : user.alwaysShowSubjectInput, @@ -96,6 +106,9 @@ const settings = { hideUserStatsLocal (value) { this.$store.dispatch('setOption', { name: 'hideUserStats', value }) }, + hideFilteredStatusesLocal (value) { + this.$store.dispatch('setOption', { name: 'hideFilteredStatuses', value }) + }, hideNsfwLocal (value) { this.$store.dispatch('setOption', { name: 'hideNsfw', value }) }, @@ -157,6 +170,9 @@ const settings = { subjectLineBehaviorLocal (value) { this.$store.dispatch('setOption', { name: 'subjectLineBehavior', value }) }, + postContentTypeLocal (value) { + this.$store.dispatch('setOption', { name: 'postContentType', value }) + }, stopGifs (value) { this.$store.dispatch('setOption', { name: 'stopGifs', value }) }, diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue index 9953780f..dfb2e49d 100644 --- a/src/components/settings/settings.vue +++ b/src/components/settings/settings.vue @@ -100,6 +100,28 @@ </label> </div> </li> + <li> + <div> + {{$t('settings.post_status_content_type')}} + <label for="postContentType" class="select"> + <select id="postContentType" v-model="postContentTypeLocal"> + <option value="text/plain"> + {{$t('settings.status_content_type_plain')}} + {{postContentTypeDefault == 'text/plain' ? $t('settings.instance_default_simple') : ''}} + </option> + <option value="text/html"> + HTML + {{postContentTypeDefault == 'text/html' ? $t('settings.instance_default_simple') : ''}} + </option> + <option value="text/markdown"> + Markdown + {{postContentTypeDefault == 'text/markdown' ? $t('settings.instance_default_simple') : ''}} + </option> + </select> + <i class="icon-down-open"/> + </label> + </div> + </li> </ul> </div> @@ -205,7 +227,6 @@ </label> </li> </ul> - </label> </div> <div> {{$t('settings.replies_in_timeline')}} @@ -232,11 +253,18 @@ </div> </div> <div class="setting-item"> - <p>{{$t('settings.filtering_explanation')}}</p> - <textarea id="muteWords" v-model="muteWordsString"></textarea> + <div> + <p>{{$t('settings.filtering_explanation')}}</p> + <textarea id="muteWords" v-model="muteWordsString"></textarea> + </div> + <div> + <input type="checkbox" id="hideFilteredStatuses" v-model="hideFilteredStatusesLocal"> + <label for="hideFilteredStatuses"> + {{$t('settings.hide_filtered_statuses')}} {{$t('settings.instance_default', { value: hideFilteredStatusesDefault })}} + </label> + </div> </div> </div> - </tab-switcher> </keep-alive> </div> diff --git a/src/components/status/status.js b/src/components/status/status.js index a3b662b6..06e4fe93 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -11,7 +11,7 @@ import generateProfileLink from 'src/services/user_profile_link_generator/user_p import fileType from 'src/services/file_type/file_type.service' import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js' import { mentionMatchesUrl, extractTagFromUrl } from 'src/services/matcher/matcher.service.js' -import { filter, find } from 'lodash' +import { filter, find, unescape } from 'lodash' const Status = { name: 'Status', @@ -110,6 +110,14 @@ const Status = { return hits }, muted () { return !this.unmuted && (this.status.user.muted || this.muteWordHits.length > 0) }, + hideFilteredStatuses () { + return typeof this.$store.state.config.hideFilteredStatuses === 'undefined' + ? this.$store.state.instance.hideFilteredStatuses + : this.$store.state.config.hideFilteredStatuses + }, + hideStatus () { + return (this.hideReply || this.deleted) || (this.muted && this.hideFilteredStatuses) + }, isFocused () { // retweet or root of an expanded conversation if (this.focused) { @@ -201,14 +209,15 @@ const Status = { }, replySubject () { if (!this.status.summary) return '' + const decodedSummary = unescape(this.status.summary) const behavior = typeof this.$store.state.config.subjectLineBehavior === 'undefined' ? this.$store.state.instance.subjectLineBehavior : this.$store.state.config.subjectLineBehavior - const startsWithRe = this.status.summary.match(/^re[: ]/i) + const startsWithRe = decodedSummary.match(/^re[: ]/i) if (behavior !== 'noop' && startsWithRe || behavior === 'masto') { - return this.status.summary + return decodedSummary } else if (behavior === 'email') { - return 're: '.concat(this.status.summary) + return 're: '.concat(decodedSummary) } else if (behavior === 'noop') { return '' } diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 779696ea..76daf73a 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -1,5 +1,5 @@ <template> - <div class="status-el" v-if="!hideReply && !deleted" :class="[{ 'status-el_focused': isFocused }, { 'status-conversation': inlineExpanded }]"> + <div class="status-el" v-if="!hideStatus" :class="[{ 'status-el_focused': isFocused }, { 'status-conversation': inlineExpanded }]"> <template v-if="muted && !noReplyLinks"> <div class="media status container muted"> <small> @@ -16,9 +16,8 @@ <UserAvatar v-if="retweet" :betterShadow="betterShadow" :src="statusoid.user.profile_image_url_original"/> <div class="media-body faint"> <span class="user-name"> - <router-link :to="retweeterProfileLink"> - {{retweeterHtml || retweeter}} - </router-link> + <router-link v-if="retweeterHtml" :to="retweeterProfileLink" v-html="retweeterHtml"/> + <router-link v-else :to="retweeterProfileLink">{{retweeter}}</router-link> </span> <i class='fa icon-retweet retweeted' :title="$t('tool_tip.repeat')"></i> {{$t('timeline.repeated')}} diff --git a/src/components/tab_switcher/tab_switcher.js b/src/components/tab_switcher/tab_switcher.js index f9c3f927..423df258 100644 --- a/src/components/tab_switcher/tab_switcher.js +++ b/src/components/tab_switcher/tab_switcher.js @@ -37,7 +37,7 @@ export default Vue.component('tab-switcher', { return ( <div class={ classesWrapper.join(' ')}> - <button onClick={this.activateTab(index)} class={ classesTab.join(' ') }>{slot.data.attrs.label}</button> + <button disabled={slot.data.attrs.disabled} onClick={this.activateTab(index)} class={ classesTab.join(' ') }>{slot.data.attrs.label}</button> </div> ) }) diff --git a/src/components/tag_timeline/tag_timeline.js b/src/components/tag_timeline/tag_timeline.js index 43de4f49..41b09706 100644 --- a/src/components/tag_timeline/tag_timeline.js +++ b/src/components/tag_timeline/tag_timeline.js @@ -3,7 +3,7 @@ import Timeline from '../timeline/timeline.vue' const TagTimeline = { created () { this.$store.commit('clearTimeline', { timeline: 'tag' }) - this.$store.dispatch('startFetching', { 'tag': this.tag }) + this.$store.dispatch('startFetching', { timeline: 'tag', tag: this.tag }) }, components: { Timeline @@ -15,7 +15,7 @@ const TagTimeline = { watch: { tag () { this.$store.commit('clearTimeline', { timeline: 'tag' }) - this.$store.dispatch('startFetching', { 'tag': this.tag }) + this.$store.dispatch('startFetching', { timeline: 'tag', tag: this.tag }) } }, destroyed () { diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js index 6f6d04a7..1888f8c6 100644 --- a/src/components/user_card_content/user_card_content.js +++ b/src/components/user_card_content/user_card_content.js @@ -79,6 +79,12 @@ export default { set (color) { this.$store.dispatch('setHighlight', { user: this.user.screen_name, color }) } + }, + visibleRole () { + const validRole = (this.user.role === 'admin' || this.user.role === 'moderator') + const showRole = this.isOtherUser || this.user.show_role + + return validRole && showRole && this.user.role } }, components: { diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue index ce65ec2f..7f9909c4 100644 --- a/src/components/user_card_content/user_card_content.vue +++ b/src/components/user_card_content/user_card_content.vue @@ -19,7 +19,9 @@ </div> <router-link class='user-screen-name' :to="userProfileLink(user)"> - <span class="handle">@{{user.screen_name}}</span><span v-if="user.locked"><i class="icon icon-lock"></i></span> + <span class="handle">@{{user.screen_name}} + <span class="alert staff" v-if="!hideBio && !!visibleRole">{{visibleRole}}</span> + </span><span v-if="user.locked"><i class="icon icon-lock"></i></span> <span v-if="!hideUserStatsLocal && !hideBio" class="dailyAvg">{{dailyAvg}} {{ $t('user_card.per_day') }}</span> </router-link> </div> @@ -247,6 +249,15 @@ text-overflow: ellipsis; overflow: hidden; } + + // TODO use proper colors + .staff { + text-transform: capitalize; + color: $fallback--text; + color: var(--btnText, $fallback--text); + background-color: $fallback--fg; + background-color: var(--btn, $fallback--fg); + } } .user-meta { diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index 7b0ab705..a22b8722 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -8,8 +8,8 @@ const UserProfile = { this.$store.commit('clearTimeline', { timeline: 'user' }) this.$store.commit('clearTimeline', { timeline: 'favorites' }) this.$store.commit('clearTimeline', { timeline: 'media' }) - this.$store.dispatch('startFetching', ['user', this.fetchBy]) - this.$store.dispatch('startFetching', ['media', this.fetchBy]) + this.$store.dispatch('startFetching', { timeline: 'user', userId: this.fetchBy }) + this.$store.dispatch('startFetching', { timeline: 'media', userId: this.fetchBy }) this.startFetchFavorites() if (!this.user.id) { this.$store.dispatch('fetchUser', this.fetchBy) @@ -58,17 +58,23 @@ const UserProfile = { }, isExternal () { return this.$route.name === 'external-user-profile' + }, + followsTabVisible () { + return this.isUs || !this.user.hide_follows + }, + followersTabVisible () { + return this.isUs || !this.user.hide_followers } }, methods: { startFetchFavorites () { if (this.isUs) { - this.$store.dispatch('startFetching', ['favorites', this.fetchBy]) + this.$store.dispatch('startFetching', { timeline: 'favorites', userId: this.fetchBy }) } }, startUp () { - this.$store.dispatch('startFetching', ['user', this.fetchBy]) - this.$store.dispatch('startFetching', ['media', this.fetchBy]) + this.$store.dispatch('startFetching', { timeline: 'user', userId: this.fetchBy }) + this.$store.dispatch('startFetching', { timeline: 'media', userId: this.fetchBy }) this.startFetchFavorites() }, diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue index 6d5b00d1..79461291 100644 --- a/src/components/user_profile/user_profile.vue +++ b/src/components/user_profile/user_profile.vue @@ -9,19 +9,20 @@ <tab-switcher :renderOnlyFocused="true"> <Timeline :label="$t('user_card.statuses')" + :disabled="!user.statuses_count" :embedded="true" :title="$t('user_profile.timeline_title')" :timeline="timeline" :timeline-name="'user'" :user-id="fetchBy" /> - <div :label="$t('user_card.followees')"> + <div :label="$t('user_card.followees')" v-if="followsTabVisible" :disabled="!user.friends_count"> <FollowList v-if="user.friends_count > 0" :userId="userId" :showFollowers="false" /> <div class="userlist-placeholder" v-else> <i class="icon-spin3 animate-spin"></i> </div> </div> - <div :label="$t('user_card.followers')"> + <div :label="$t('user_card.followers')" v-if="followersTabVisible" :disabled="!user.followers_count"> <FollowList v-if="user.followers_count > 0" :userId="userId" :showFollowers="true" /> <div class="userlist-placeholder" v-else> <i class="icon-spin3 animate-spin"></i> @@ -29,6 +30,7 @@ </div> <Timeline :label="$t('user_card.media')" + :disabled="!media.visibleStatuses.length" :embedded="true" :title="$t('user_card.media')" timeline-name="media" :timeline="media" @@ -37,6 +39,7 @@ <Timeline v-if="isUs" :label="$t('user_card.favorites')" + :disabled="!favorites.visibleStatuses.length" :embedded="true" :title="$t('user_card.favorites')" timeline-name="favorites" diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js index df757dfb..d20bf308 100644 --- a/src/components/user_settings/user_settings.js +++ b/src/components/user_settings/user_settings.js @@ -12,7 +12,10 @@ const UserSettings = { newLocked: this.$store.state.users.currentUser.locked, newNoRichText: this.$store.state.users.currentUser.no_rich_text, newDefaultScope: this.$store.state.users.currentUser.default_scope, - newHideNetwork: this.$store.state.users.currentUser.hide_network, + hideFollows: this.$store.state.users.currentUser.hide_follows, + hideFollowers: this.$store.state.users.currentUser.hide_followers, + showRole: this.$store.state.users.currentUser.show_role, + role: this.$store.state.users.currentUser.role, followList: null, followImportError: false, followsImported: false, @@ -68,7 +71,10 @@ const UserSettings = { /* eslint-disable camelcase */ const default_scope = this.newDefaultScope const no_rich_text = this.newNoRichText - const hide_network = this.newHideNetwork + const hide_follows = this.hideFollows + const hide_followers = this.hideFollowers + const show_role = this.showRole + /* eslint-enable camelcase */ this.$store.state.api.backendInteractor .updateProfile({ @@ -80,7 +86,9 @@ const UserSettings = { /* eslint-disable camelcase */ default_scope, no_rich_text, - hide_network + hide_follows, + hide_followers, + show_role /* eslint-enable camelcase */ }}).then((user) => { if (!user.error) { @@ -235,7 +243,9 @@ const UserSettings = { exportFollows () { this.enableFollowsExport = false this.$store.state.api.backendInteractor - .fetchFriends({id: this.$store.state.users.currentUser.id}) + .exportFriends({ + id: this.$store.state.users.currentUser.id + }) .then((friendList) => { this.exportPeople(friendList, 'friends.csv') setTimeout(() => { this.enableFollowsExport = true }, 2000) diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue index d0743ef0..134f70ef 100644 --- a/src/components/user_settings/user_settings.vue +++ b/src/components/user_settings/user_settings.vue @@ -30,8 +30,17 @@ <label for="account-no-rich-text">{{$t('settings.no_rich_text_description')}}</label> </p> <p> - <input type="checkbox" v-model="newHideNetwork" id="account-hide-network"> - <label for="account-hide-network">{{$t('settings.hide_network_description')}}</label> + <input type="checkbox" v-model="hideFollows" id="account-hide-follows"> + <label for="account-hide-follows">{{$t('settings.hide_follows_description')}}</label> + </p> + <p> + <input type="checkbox" v-model="hideFollowers" id="account-hide-followers"> + <label for="account-hide-followers">{{$t('settings.hide_followers_description')}}</label> + </p> + <p> + <input type="checkbox" v-model="showRole" id="account-show-role"> + <label for="account-show-role" v-if="role === 'admin'">{{$t('settings.show_admin_badge')}}</label> + <label for="account-show-role" v-if="role === 'moderator'">{{$t('settings.show_moderator_badge')}}</label> </p> <button :disabled='newName && newName.length === 0' class="btn btn-default" @click="updateProfile">{{$t('general.submit')}}</button> </div> @@ -180,5 +189,9 @@ .name-changer { width: 100%; } + + .bg { + max-width: 100%; + } } </style> |
