diff options
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/conversation/conversation.js | 19 | ||||
| -rw-r--r-- | src/components/follow_list/follow_list.js | 3 | ||||
| -rw-r--r-- | src/components/follow_list/follow_list.vue | 2 | ||||
| -rw-r--r-- | src/components/settings/settings.js | 3 | ||||
| -rw-r--r-- | src/components/settings/settings.vue | 2 | ||||
| -rw-r--r-- | src/components/status/status.js | 25 | ||||
| -rw-r--r-- | src/components/status/status.vue | 6 | ||||
| -rw-r--r-- | src/components/user_card/user_card.js | 29 | ||||
| -rw-r--r-- | src/components/user_card/user_card.vue | 117 | ||||
| -rw-r--r-- | src/components/user_card_content/user_card_content.js | 67 | ||||
| -rw-r--r-- | src/components/user_card_content/user_card_content.vue | 2 | ||||
| -rw-r--r-- | src/components/user_profile/user_profile.js | 2 | ||||
| -rw-r--r-- | src/components/user_settings/user_settings.vue | 6 |
13 files changed, 167 insertions, 116 deletions
diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index c18781de..48b8aaaa 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -9,9 +9,9 @@ const sortById = (a, b) => { if (isSeqA && isSeqB) { return seqA < seqB ? -1 : 1 } else if (isSeqA && !isSeqB) { - return 1 - } else if (!isSeqA && isSeqB) { return -1 + } else if (!isSeqA && isSeqB) { + return 1 } else { return a.id < b.id ? -1 : 1 } @@ -36,6 +36,13 @@ const conversation = { status () { return this.statusoid }, + statusId () { + if (this.statusoid.retweeted_status) { + return this.statusoid.retweeted_status.id + } else { + return this.statusoid.id + } + }, conversation () { if (!this.status) { return [] @@ -79,7 +86,7 @@ const conversation = { const conversationId = this.status.statusnet_conversation_id this.$store.state.api.backendInteractor.fetchConversation({id: conversationId}) .then((statuses) => this.$store.dispatch('addNewStatuses', { statuses })) - .then(() => this.setHighlight(this.statusoid.id)) + .then(() => this.setHighlight(this.statusId)) } else { const id = this.$route.params.id this.$store.state.api.backendInteractor.fetchStatus({id}) @@ -91,11 +98,7 @@ const conversation = { return this.replies[id] || [] }, focused (id) { - if (this.statusoid.retweeted_status) { - return (id === this.statusoid.retweeted_status.id) - } else { - return (id === this.statusoid.id) - } + return id === this.statusId }, setHighlight (id) { this.highlight = id diff --git a/src/components/follow_list/follow_list.js b/src/components/follow_list/follow_list.js index 6d00eb94..51327e2f 100644 --- a/src/components/follow_list/follow_list.js +++ b/src/components/follow_list/follow_list.js @@ -25,6 +25,9 @@ const FollowList = { }, entries () { return this.showFollowers ? this.user.followers : this.user.friends + }, + showFollowsYou () { + return !this.showFollowers || (this.showFollowers && this.userId !== this.$store.state.users.currentUser.id) } }, methods: { diff --git a/src/components/follow_list/follow_list.vue b/src/components/follow_list/follow_list.vue index 24ab97d8..27102edf 100644 --- a/src/components/follow_list/follow_list.vue +++ b/src/components/follow_list/follow_list.vue @@ -3,7 +3,7 @@ <user-card v-for="entry in entries" :key="entry.id" :user="entry" - :showFollows="true" + :noFollowsYou="!showFollowsYou" /> <div class="text-center panel-footer"> <a v-if="error" @click="fetchEntries" class="alert error"> diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js index 534a9839..23c1acdb 100644 --- a/src/components/settings/settings.js +++ b/src/components/settings/settings.js @@ -91,7 +91,8 @@ const settings = { }, currentSaveStateNotice () { return this.$store.state.interface.settings.currentSaveStateNotice - } + }, + instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel } }, watch: { hideAttachmentsLocal (value) { diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue index dfb2e49d..e5f8fefb 100644 --- a/src/components/settings/settings.vue +++ b/src/components/settings/settings.vue @@ -27,7 +27,7 @@ <li> <interface-language-switcher /> </li> - <li> + <li v-if="instanceSpecificPanelPresent"> <input type="checkbox" id="hideISP" v-model="hideISPLocal"> <label for="hideISP">{{$t('settings.hide_isp')}}</label> </li> diff --git a/src/components/status/status.js b/src/components/status/status.js index 8181b0db..0273a5be 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -10,8 +10,8 @@ import LinkPreview from '../link-preview/link-preview.vue' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import fileType from 'src/services/file_type/file_type.service' import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js' -import { mentionMatchesUrl } from 'src/services/mention_matcher/mention_matcher.js' -import { filter, find } from 'lodash' +import { mentionMatchesUrl, extractTagFromUrl } from 'src/services/matcher/matcher.service.js' +import { filter, find, unescape } from 'lodash' const Status = { name: 'Status', @@ -209,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 '' } @@ -281,7 +282,7 @@ const Status = { } if (target.tagName === 'A') { if (target.className.match(/mention/)) { - const href = target.getAttribute('href') + const href = target.href const attn = this.status.attentions.find(attn => mentionMatchesUrl(attn, href)) if (attn) { event.stopPropagation() @@ -291,6 +292,15 @@ const Status = { return } } + if (target.className.match(/hashtag/)) { + // Extract tag name from link url + const tag = extractTagFromUrl(target.href) + if (tag) { + const link = this.generateTagLink(tag) + this.$router.push(link) + return + } + } window.open(target.href, '_blank') } }, @@ -347,6 +357,9 @@ const Status = { generateUserProfileLink (id, name) { return generateProfileLink(id, name, this.$store.state.instance.restrictedNicknames) }, + generateTagLink (tag) { + return `/tag/${tag}` + }, setMedia () { const attachments = this.attachmentSize === 'hide' ? this.status.attachments : this.galleryAttachments return () => this.$store.dispatch('setMedia', attachments) diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 5bc7c664..3fc5b486 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -56,7 +56,7 @@ </div> <h4 class="replies" v-if="inConversation && !noReplyLinks"> <small v-if="replies.length">Replies:</small> - <small class="reply-link" v-for="reply in replies"> + <small class="reply-link" v-bind:key="reply.id" v-for="reply in replies"> <a href="#" @click.prevent="gotoOriginal(reply.id)" @mouseenter="replyEnter(reply.id, $event)" @mouseout="replyLeave()">{{reply.name}} </a> </small> </h4> @@ -438,6 +438,8 @@ .user-name { font-weight: bold; + overflow: hidden; + text-overflow: ellipsis; img { width: 14px; @@ -552,7 +554,7 @@ a.unmute { .timeline > { .status-el:last-child { - border-bottom-radius: 0 0 $fallback--panelRadius $fallback--panelRadius;; + border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius; border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius); border-bottom: none; } diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js index ecc36a4d..28e22f09 100644 --- a/src/components/user_card/user_card.js +++ b/src/components/user_card/user_card.js @@ -1,16 +1,20 @@ import UserCardContent from '../user_card_content/user_card_content.vue' import UserAvatar from '../user_avatar/user_avatar.vue' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' +import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate' const UserCard = { props: [ 'user', - 'showFollows', + 'noFollowsYou', 'showApproval' ], data () { return { - userExpanded: false + userExpanded: false, + followRequestInProgress: false, + followRequestSent: false, + updated: false } }, components: { @@ -18,7 +22,11 @@ const UserCard = { UserAvatar }, computed: { - currentUser () { return this.$store.state.users.currentUser } + currentUser () { return this.$store.state.users.currentUser }, + following () { return this.updated ? this.updated.following : this.user.following }, + showFollow () { + return !this.showApproval && (!this.following || this.updated && !this.updated.following) + } }, methods: { toggleUserExpanded () { @@ -34,6 +42,21 @@ const UserCard = { }, userProfileLink (user) { return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames) + }, + followUser () { + this.followRequestInProgress = true + requestFollow(this.user, this.$store).then(({ sent, updated }) => { + this.followRequestInProgress = false + this.followRequestSent = sent + this.updated = updated + }) + }, + unfollowUser () { + this.followRequestInProgress = true + requestUnfollow(this.user, this.$store).then(({ updated }) => { + this.followRequestInProgress = false + this.updated = updated + }) } } } diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index 7129430b..ce4edb3c 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -1,32 +1,57 @@ <template> <div class="card"> <router-link :to="userProfileLink(user)"> - <UserAvatar class="avatar" :compact="true" @click.prevent.native="toggleUserExpanded" :src="user.profile_image_url"/> + <UserAvatar class="avatar" @click.prevent.native="toggleUserExpanded" :src="user.profile_image_url"/> </router-link> - <div class="usercard" v-if="userExpanded"> - <user-card-content :user="user" :switcher="false"></user-card-content> - </div> - <div class="name-and-screen-name" v-else> - <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"> - {{ currentUser.id == user.id ? $t('user_card.its_you') : $t('user_card.follows_you') }} - </span> + <div class="user-card-main-content"> + <div class="usercard" v-if="userExpanded"> + <user-card-content :user="user" :switcher="false"></user-card-content> </div> - <div :title="user.name" v-else class="user-name"> - {{ user.name }} - <span class="follows-you" v-if="!userExpanded && showFollows && user.follows_you"> + <div class="name-and-screen-name" v-if="!userExpanded"> + <div :title="user.name" class="user-name"> + <span v-if="user.name_html" v-html="user.name_html"></span> + <span v-else>{{ user.name }}</span> + </div> + <div class="user-link-action"> + <router-link class='user-screen-name' :to="userProfileLink(user)"> + @{{user.screen_name}} + </router-link> + </div> + </div> + <div class="follow-box" v-if="!userExpanded"> + <span class="faint" v-if="!noFollowsYou && user.follows_you"> {{ currentUser.id == user.id ? $t('user_card.its_you') : $t('user_card.follows_you') }} </span> + <button + v-if="showFollow" + class="btn btn-default" + @click="followUser" + :disabled="followRequestInProgress" + :title="followRequestSent ? $t('user_card.follow_again') : ''" + > + <template v-if="followRequestInProgress"> + {{ $t('user_card.follow_progress') }} + </template> + <template v-else-if="followRequestSent"> + {{ $t('user_card.follow_sent') }} + </template> + <template v-else> + {{ $t('user_card.follow') }} + </template> + </button> + <button v-if="following" class="btn btn-default pressed" @click="unfollowUser" :disabled="followRequestInProgress"> + <template v-if="followRequestInProgress"> + {{ $t('user_card.follow_progress') }} + </template> + <template v-else> + {{ $t('user_card.follow_unfollow') }} + </template> + </button> + </div> + <div class="approval" v-if="showApproval"> + <button class="btn btn-default" @click="approveUser">{{ $t('user_card.approve') }}</button> + <button class="btn btn-default" @click="denyUser">{{ $t('user_card.deny') }}</button> </div> - - <router-link class='user-screen-name' :to="userProfileLink(user)"> - @{{user.screen_name}} - </router-link> - </div> - <div class="approval" v-if="showApproval"> - <button class="btn btn-default" @click="approveUser">{{ $t('user_card.approve') }}</button> - <button class="btn btn-default" @click="denyUser">{{ $t('user_card.deny') }}</button> </div> </div> </template> @@ -36,11 +61,18 @@ <style lang="scss"> @import '../../_variables.scss'; -.name-and-screen-name { +.user-card-main-content { + display: flex; + flex-direction: column; + flex: 1 1 100%; margin-left: 0.7em; - margin-top:0.0em; + min-width: 0; +} + +.name-and-screen-name { text-align: left; width: 100%; + .user-name { img { object-fit: contain; @@ -49,13 +81,15 @@ vertical-align: middle; } } -} -.follows-you { - margin-left: 2em; - float: right; + .user-link-action { + display: flex; + align-items: flex-start; + justify-content: space-between; + } } + .card { display: flex; flex: 1 0; @@ -66,16 +100,31 @@ border-bottom: 1px solid; margin: 0; border-bottom-color: $fallback--border; - border-bottom-color: var(--border, $fallback--border); + border-bottom-color: var(--border, $fallback--border); .avatar { padding: 0; } + + .follow-box { + text-align: center; + flex-shrink: 0; + display: flex; + flex-direction: row; + justify-content: space-between; + flex-wrap: wrap; + line-height: 1.5em; + + .btn { + margin-top: 0.5em; + margin-left: auto; + width: 10em; + } + } } .usercard { width: fill-available; - margin: 0.2em 0 0 0.7em; border-radius: $fallback--panelRadius; border-radius: var(--panelRadius, $fallback--panelRadius); border-style: solid; @@ -96,9 +145,15 @@ } .approval { + display: flex; + flex-direction: row; + flex-wrap: wrap; button { - width: 100%; - margin-bottom: 0.5em; + margin-top: 0.5em; + margin-right: 0.5em; + flex: 1 1; + max-width: 12em; + min-width: 8em; } } </style> diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js index 1888f8c6..7a7b89d4 100644 --- a/src/components/user_card_content/user_card_content.js +++ b/src/components/user_card_content/user_card_content.js @@ -1,5 +1,6 @@ import UserAvatar from '../user_avatar/user_avatar.vue' import { hex2rgb } from '../../services/color_convert/color_convert.js' +import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' export default { @@ -92,69 +93,17 @@ export default { }, methods: { followUser () { - const store = this.$store this.followRequestInProgress = true - store.state.api.backendInteractor.followUser(this.user.id) - .then((followedUser) => store.commit('addNewUsers', [followedUser])) - .then(() => { - // For locked users we just mark it that we sent the follow request - if (this.user.locked) { - this.followRequestInProgress = false - this.followRequestSent = true - return - } - - if (this.user.following) { - // If we get result immediately, just stop. - this.followRequestInProgress = false - return - } - - // But usually we don't get result immediately, so we ask server - // for updated user profile to confirm if we are following them - // Sometimes it takes several tries. Sometimes we end up not following - // user anyway, probably because they locked themselves and we - // don't know that yet. - // Recursive Promise, it will call itself up to 3 times. - const fetchUser = (attempt) => new Promise((resolve, reject) => { - setTimeout(() => { - store.state.api.backendInteractor.fetchUser({ id: this.user.id }) - .then((user) => store.commit('addNewUsers', [user])) - .then(() => resolve([this.user.following, attempt])) - .catch((e) => reject(e)) - }, 500) - }).then(([following, attempt]) => { - if (!following && attempt <= 3) { - // If we BE reports that we still not following that user - retry, - // increment attempts by one - return fetchUser(++attempt) - } else { - // If we run out of attempts, just return whatever status is. - return following - } - }) - - return fetchUser(1) - .then((following) => { - if (following) { - // We confirmed and everything its good. - this.followRequestInProgress = false - } else { - // If after all the tries, just treat it as if user is locked - this.followRequestInProgress = false - this.followRequestSent = true - } - }) - }) + requestFollow(this.user, this.$store).then(({sent}) => { + this.followRequestInProgress = false + this.followRequestSent = sent + }) }, unfollowUser () { - const store = this.$store this.followRequestInProgress = true - store.state.api.backendInteractor.unfollowUser(this.user.id) - .then((unfollowedUser) => store.commit('addNewUsers', [unfollowedUser])) - .then(() => { - this.followRequestInProgress = false - }) + requestUnfollow(this.user, this.$store).then(() => { + this.followRequestInProgress = false + }) }, blockUser () { const store = this.$store diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue index 7f9909c4..4d1950c5 100644 --- a/src/components/user_card_content/user_card_content.vue +++ b/src/components/user_card_content/user_card_content.vue @@ -386,6 +386,4 @@ } } -.floater { -} </style> diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index a22b8722..37179ce1 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -16,7 +16,7 @@ const UserProfile = { } }, destroyed () { - this.cleanUp(this.userId) + this.cleanUp() }, computed: { timeline () { diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue index ea5b3de5..d2381da2 100644 --- a/src/components/user_settings/user_settings.vue +++ b/src/components/user_settings/user_settings.vue @@ -178,7 +178,7 @@ } .banner { - max-width: 400px; + max-width: 100%; } .uploading { @@ -189,5 +189,9 @@ .name-changer { width: 100%; } + + .bg { + max-width: 100%; + } } </style> |
