Merge remote-tracking branch 'upstream/develop' into feature/theming2
* upstream/develop: (60 commits) whoops whoops DM timeline: stream new statuses update-japanese-translation Add actual user search. incorporate most translation changes from MR 368 update french translation Always show dm panel. Add direct message tab. api service url remove deploy stage remove deploy stage updated and completed German translation On logout switch to public timeline. minor modification of Chinese translation update Chinese translation Add Chinese language Fix posting. Put oauth text into description. Display OAuth login on login form button. ...
This commit is contained in:
commit
a806d43f05
56 changed files with 2963 additions and 383 deletions
14
src/components/dm_timeline/dm_timeline.js
Normal file
14
src/components/dm_timeline/dm_timeline.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import Timeline from '../timeline/timeline.vue'
|
||||
|
||||
const DMs = {
|
||||
computed: {
|
||||
timeline () {
|
||||
return this.$store.state.statuses.timelines.dms
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Timeline
|
||||
}
|
||||
}
|
||||
|
||||
export default DMs
|
5
src/components/dm_timeline/dm_timeline.vue
Normal file
5
src/components/dm_timeline/dm_timeline.vue
Normal file
|
@ -0,0 +1,5 @@
|
|||
<template>
|
||||
<Timeline :title="$t('nav.dms')" v-bind:timeline="timeline" v-bind:timeline-name="'dms'"/>
|
||||
</template>
|
||||
|
||||
<script src="./dm_timeline.js"></script>
|
|
@ -2,6 +2,9 @@ const FavoriteButton = {
|
|||
props: ['status', 'loggedIn'],
|
||||
data () {
|
||||
return {
|
||||
hidePostStatsLocal: typeof this.$store.state.config.hidePostStats === 'undefined'
|
||||
? this.$store.state.instance.hidePostStats
|
||||
: this.$store.state.config.hidePostStats,
|
||||
animated: false
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<div v-if="loggedIn">
|
||||
<i :class='classes' class='favorite-button fav-active' @click.prevent='favorite()'/>
|
||||
<span v-if='status.fave_num > 0'>{{status.fave_num}}</span>
|
||||
<span v-if='!hidePostStatsLocal && status.fave_num > 0'>{{status.fave_num}}</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<i :class='classes' class='favorite-button'/>
|
||||
<span v-if='status.fave_num > 0'>{{status.fave_num}}</span>
|
||||
<span v-if='!hidePostStatsLocal && status.fave_num > 0'>{{status.fave_num}}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,22 +1,40 @@
|
|||
import oauthApi from '../../services/new_api/oauth.js'
|
||||
const LoginForm = {
|
||||
data: () => ({
|
||||
user: {},
|
||||
authError: false
|
||||
}),
|
||||
computed: {
|
||||
loginMethod () { return this.$store.state.instance.loginMethod },
|
||||
loggingIn () { return this.$store.state.users.loggingIn },
|
||||
registrationOpen () { return this.$store.state.instance.registrationOpen }
|
||||
},
|
||||
methods: {
|
||||
oAuthLogin () {
|
||||
oauthApi.login({
|
||||
oauth: this.$store.state.oauth,
|
||||
instance: this.$store.state.instance.server,
|
||||
commit: this.$store.commit
|
||||
})
|
||||
},
|
||||
submit () {
|
||||
this.$store.dispatch('loginUser', this.user).then(
|
||||
() => {},
|
||||
(error) => {
|
||||
this.authError = error
|
||||
this.user.username = ''
|
||||
this.user.password = ''
|
||||
}
|
||||
)
|
||||
const data = {
|
||||
oauth: this.$store.state.oauth,
|
||||
instance: this.$store.state.instance.server
|
||||
}
|
||||
oauthApi.getOrCreateApp(data).then((app) => {
|
||||
oauthApi.getTokenWithCredentials(
|
||||
{
|
||||
app,
|
||||
instance: data.instance,
|
||||
username: this.user.username,
|
||||
password: this.user.password})
|
||||
.then((result) => {
|
||||
this.$store.commit('setToken', result.access_token)
|
||||
this.$store.dispatch('loginUser', result.access_token)
|
||||
this.$router.push('/main/friends')
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{{$t('login.login')}}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form v-on:submit.prevent='submit(user)' class='login-form'>
|
||||
<form v-if="loginMethod == 'password'" v-on:submit.prevent='submit(user)' class='login-form'>
|
||||
<div class='form-group'>
|
||||
<label for='username'>{{$t('login.username')}}</label>
|
||||
<input :disabled="loggingIn" v-model='user.username' class='form-control' id='username' v-bind:placeholder="$t('login.placeholder')">
|
||||
|
@ -20,8 +20,17 @@
|
|||
<button :disabled="loggingIn" type='submit' class='btn btn-default'>{{$t('login.login')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="authError" class='form-group'>
|
||||
<div class='alert error'>{{authError}}</div>
|
||||
</form>
|
||||
|
||||
<form v-if="loginMethod == 'token'" v-on:submit.prevent='oAuthLogin' class="login-form">
|
||||
<div class="form-group">
|
||||
<p>{{$t('login.description')}}</p>
|
||||
</div>
|
||||
<div class='form-group'>
|
||||
<div class='login-bottom'>
|
||||
<div><router-link :to="{name: 'registration'}" v-if='registrationOpen' class='register'>{{$t('login.register')}}</router-link></div>
|
||||
<button :disabled="loggingIn" type='submit' class='btn btn-default'>{{$t('login.login')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
{{ $t("nav.mentions") }}
|
||||
</router-link>
|
||||
</li>
|
||||
<li v-if='currentUser'>
|
||||
<router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
|
||||
{{ $t("nav.dms") }}
|
||||
</router-link>
|
||||
</li>
|
||||
<li v-if='currentUser && currentUser.locked'>
|
||||
<router-link to='/friend-requests'>
|
||||
{{ $t("nav.friend_requests") }}
|
||||
|
|
20
src/components/oauth_callback/oauth_callback.js
Normal file
20
src/components/oauth_callback/oauth_callback.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
import oauth from '../../services/new_api/oauth.js'
|
||||
|
||||
const oac = {
|
||||
props: ['code'],
|
||||
mounted () {
|
||||
if (this.code) {
|
||||
oauth.getToken({
|
||||
app: this.$store.state.oauth,
|
||||
instance: this.$store.state.instance.server,
|
||||
code: this.code
|
||||
}).then((result) => {
|
||||
this.$store.commit('setToken', result.access_token)
|
||||
this.$store.dispatch('loginUser', result.access_token)
|
||||
this.$router.push('/main/friends')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default oac
|
5
src/components/oauth_callback/oauth_callback.vue
Normal file
5
src/components/oauth_callback/oauth_callback.vue
Normal file
|
@ -0,0 +1,5 @@
|
|||
<template>
|
||||
<h1>...</h1>
|
||||
</template>
|
||||
|
||||
<script src="./oauth_callback.js"></script>
|
|
@ -24,7 +24,7 @@ const PostStatusForm = {
|
|||
'replyTo',
|
||||
'repliedUser',
|
||||
'attentions',
|
||||
'messageScope',
|
||||
'copyMessageScope',
|
||||
'subject'
|
||||
],
|
||||
components: {
|
||||
|
@ -46,6 +46,10 @@ const PostStatusForm = {
|
|||
statusText = buildMentionsString({ user: this.repliedUser, attentions: this.attentions }, currentUser)
|
||||
}
|
||||
|
||||
const scope = (this.copyMessageScope && this.$store.state.config.copyScope || this.copyMessageScope === 'direct')
|
||||
? this.copyMessageScope
|
||||
: this.$store.state.users.currentUser.default_scope
|
||||
|
||||
return {
|
||||
dropFiles: [],
|
||||
submitDisabled: false,
|
||||
|
@ -53,12 +57,12 @@ const PostStatusForm = {
|
|||
posting: false,
|
||||
highlighted: 0,
|
||||
newStatus: {
|
||||
spoilerText: this.subject,
|
||||
spoilerText: this.subject || '',
|
||||
status: statusText,
|
||||
contentType: 'text/plain',
|
||||
nsfw: false,
|
||||
files: [],
|
||||
visibility: this.messageScope || this.$store.state.users.currentUser.default_scope
|
||||
visibility: scope
|
||||
},
|
||||
caret: 0
|
||||
}
|
||||
|
@ -128,6 +132,9 @@ const PostStatusForm = {
|
|||
statusLength () {
|
||||
return this.newStatus.status.length
|
||||
},
|
||||
spoilerTextLength () {
|
||||
return this.newStatus.spoilerText.length
|
||||
},
|
||||
statusLengthLimit () {
|
||||
return this.$store.state.instance.textlimit
|
||||
},
|
||||
|
@ -135,10 +142,10 @@ const PostStatusForm = {
|
|||
return this.statusLengthLimit > 0
|
||||
},
|
||||
charactersLeft () {
|
||||
return this.statusLengthLimit - this.statusLength
|
||||
return this.statusLengthLimit - (this.statusLength + this.spoilerTextLength)
|
||||
},
|
||||
isOverLengthLimit () {
|
||||
return this.hasStatusLengthLimit && (this.statusLength > this.statusLengthLimit)
|
||||
return this.hasStatusLengthLimit && (this.charactersLeft < 0)
|
||||
},
|
||||
scopeOptionsEnabled () {
|
||||
return this.$store.state.instance.scopeOptionsEnabled
|
||||
|
@ -223,6 +230,7 @@ const PostStatusForm = {
|
|||
if (!data.error) {
|
||||
this.newStatus = {
|
||||
status: '',
|
||||
spoilerText: '',
|
||||
files: [],
|
||||
visibility: newStatus.visibility,
|
||||
contentType: newStatus.contentType
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import oauthApi from '../../services/new_api/oauth.js'
|
||||
|
||||
const registration = {
|
||||
data: () => ({
|
||||
user: {},
|
||||
|
@ -25,9 +27,23 @@ const registration = {
|
|||
this.$store.state.api.backendInteractor.register(this.user).then(
|
||||
(response) => {
|
||||
if (response.ok) {
|
||||
this.$store.dispatch('loginUser', this.user)
|
||||
this.$router.push('/main/all')
|
||||
this.registering = false
|
||||
const data = {
|
||||
oauth: this.$store.state.oauth,
|
||||
instance: this.$store.state.instance.server
|
||||
}
|
||||
oauthApi.getOrCreateApp(data).then((app) => {
|
||||
oauthApi.getTokenWithCredentials(
|
||||
{
|
||||
app,
|
||||
instance: data.instance,
|
||||
username: this.user.username,
|
||||
password: this.user.password})
|
||||
.then((result) => {
|
||||
this.$store.commit('setToken', result.access_token)
|
||||
this.$store.dispatch('loginUser', result.access_token)
|
||||
this.$router.push('/main/friends')
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.registering = false
|
||||
response.json().then((data) => {
|
||||
|
|
|
@ -2,6 +2,9 @@ const RetweetButton = {
|
|||
props: ['status', 'loggedIn', 'visibility'],
|
||||
data () {
|
||||
return {
|
||||
hidePostStatsLocal: typeof this.$store.state.config.hidePostStats === 'undefined'
|
||||
? this.$store.state.instance.hidePostStats
|
||||
: this.$store.state.config.hidePostStats,
|
||||
animated: false
|
||||
}
|
||||
},
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div v-if="loggedIn">
|
||||
<template v-if="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>
|
||||
<span v-if='!hidePostStatsLocal && status.repeat_num > 0'>{{status.repeat_num}}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<i :class='classes' class='icon-lock' :title="$t('timeline.no_retweet_hint')"></i>
|
||||
|
@ -10,7 +10,7 @@
|
|||
</div>
|
||||
<div v-else-if="!loggedIn">
|
||||
<i :class='classes' class='icon-retweet'></i>
|
||||
<span v-if='status.repeat_num > 0'>{{status.repeat_num}}</span>
|
||||
<span v-if='!hidePostStatsLocal && status.repeat_num > 0'>{{status.repeat_num}}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -13,6 +13,14 @@ const settings = {
|
|||
hideAttachmentsLocal: user.hideAttachments,
|
||||
hideAttachmentsInConvLocal: user.hideAttachmentsInConv,
|
||||
hideNsfwLocal: user.hideNsfw,
|
||||
hidePostStatsLocal: typeof user.hidePostStats === 'undefined'
|
||||
? instance.hidePostStats
|
||||
: user.hidePostStats,
|
||||
hidePostStatsDefault: this.$t('settings.values.' + instance.hidePostStats),
|
||||
hideUserStatsLocal: typeof user.hideUserStats === 'undefined'
|
||||
? instance.hideUserStats
|
||||
: user.hideUserStats,
|
||||
hideUserStatsDefault: this.$t('settings.values.' + instance.hideUserStats),
|
||||
notificationVisibilityLocal: user.notificationVisibility,
|
||||
replyVisibilityLocal: user.replyVisibility,
|
||||
loopVideoLocal: user.loopVideo,
|
||||
|
@ -26,6 +34,12 @@ const settings = {
|
|||
? instance.collapseMessageWithSubject
|
||||
: user.collapseMessageWithSubject,
|
||||
collapseMessageWithSubjectDefault: this.$t('settings.values.' + instance.collapseMessageWithSubject),
|
||||
subjectLineBehaviorLocal: typeof user.subjectLineBehavior === 'undefined'
|
||||
? instance.subjectLineBehavior
|
||||
: user.subjectLineBehavior,
|
||||
subjectLineBehaviorDefault: instance.subjectLineBehavior,
|
||||
scopeCopyLocal: user.scopeCopy,
|
||||
scopeCopyDefault: this.$t('settings.values.' + instance.scopeCopy),
|
||||
stopGifs: user.stopGifs,
|
||||
loopSilentAvailable:
|
||||
// Firefox
|
||||
|
@ -56,6 +70,12 @@ const settings = {
|
|||
hideAttachmentsInConvLocal (value) {
|
||||
this.$store.dispatch('setOption', { name: 'hideAttachmentsInConv', value })
|
||||
},
|
||||
hidePostStatsLocal (value) {
|
||||
this.$store.dispatch('setOption', { name: 'hidePostStats', value })
|
||||
},
|
||||
hideUserStatsLocal (value) {
|
||||
this.$store.dispatch('setOption', { name: 'hideUserStats', value })
|
||||
},
|
||||
hideNsfwLocal (value) {
|
||||
this.$store.dispatch('setOption', { name: 'hideNsfw', value })
|
||||
},
|
||||
|
@ -99,6 +119,12 @@ const settings = {
|
|||
collapseMessageWithSubjectLocal (value) {
|
||||
this.$store.dispatch('setOption', { name: 'collapseMessageWithSubject', value })
|
||||
},
|
||||
scopeCopyLocal (value) {
|
||||
this.$store.dispatch('setOption', { name: 'scopeCopy', value })
|
||||
},
|
||||
subjectLineBehaviorLocal (value) {
|
||||
this.$store.dispatch('setOption', { name: 'subjectLineBehavior', value })
|
||||
},
|
||||
stopGifs (value) {
|
||||
this.$store.dispatch('setOption', { name: 'stopGifs', value })
|
||||
}
|
||||
|
|
|
@ -54,6 +54,41 @@
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.composing')}}</h2>
|
||||
<ul class="setting-list">
|
||||
<li>
|
||||
<input type="checkbox" id="scopeCopy" v-model="scopeCopyLocal">
|
||||
<label for="scopeCopy">
|
||||
{{$t('settings.scope_copy')}} {{$t('settings.instance_default', { value: scopeCopyDefault })}}
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
{{$t('settings.subject_line_behavior')}}
|
||||
<label for="subjectLineBehavior" class="select">
|
||||
<select id="subjectLineBehavior" v-model="subjectLineBehaviorLocal">
|
||||
<option value="email">
|
||||
{{$t('settings.subject_line_email')}}
|
||||
{{subjectLineBehaviorDefault == 'email' ? $t('settings.instance_default_simple') : ''}}
|
||||
</option>
|
||||
<option value="masto">
|
||||
{{$t('settings.subject_line_mastodon')}}
|
||||
{{subjectLineBehaviorDefault == 'mastodon' ? $t('settings.instance_default_simple') : ''}}
|
||||
</option>
|
||||
<option value="noop">
|
||||
{{$t('settings.subject_line_noop')}}
|
||||
{{subjectLineBehaviorDefault == 'noop' ? $t('settings.instance_default_simple') : ''}}
|
||||
</option>
|
||||
</select>
|
||||
<i class="icon-down-open"/>
|
||||
</label>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.attachments')}}</h2>
|
||||
<ul class="setting-list">
|
||||
|
@ -139,6 +174,18 @@
|
|||
<i class="icon-down-open"/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" id="hidePostStats" v-model="hidePostStatsLocal">
|
||||
<label for="hidePostStats">
|
||||
{{$t('settings.hide_post_stats')}} {{$t('settings.instance_default', { value: hidePostStatsDefault })}}
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" id="hideUserStats" v-model="hideUserStatsLocal">
|
||||
<label for="hideUserStats">
|
||||
{{$t('settings.hide_user_stats')}} {{$t('settings.instance_default', { value: hideUserStatsDefault })}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<p>{{$t('settings.filtering_explanation')}}</p>
|
||||
|
|
|
@ -31,10 +31,17 @@ const Status = {
|
|||
preview: null,
|
||||
showPreview: false,
|
||||
showingTall: false,
|
||||
expandingSubject: !this.$store.state.config.collapseMessageWithSubject
|
||||
expandingSubject: typeof this.$store.state.config.collapseMessageWithSubject === 'undefined'
|
||||
? !this.$store.state.instance.collapseMessageWithSubject
|
||||
: !this.$store.state.config.collapseMessageWithSubject
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
localCollapseSubjectDefault () {
|
||||
return typeof this.$store.state.config.collapseMessageWithSubject === 'undefined'
|
||||
? this.$store.state.instance.collapseMessageWithSubject
|
||||
: this.$store.state.config.collapseMessageWithSubject
|
||||
},
|
||||
muteWords () {
|
||||
return this.$store.state.config.muteWords
|
||||
},
|
||||
|
@ -147,13 +154,13 @@ const Status = {
|
|||
return this.status.attentions.length > 0
|
||||
},
|
||||
hideSubjectStatus () {
|
||||
if (this.tallStatus && !this.$store.state.config.collapseMessageWithSubject) {
|
||||
if (this.tallStatus && !this.localCollapseSubjectDefault) {
|
||||
return false
|
||||
}
|
||||
return !this.expandingSubject && this.status.summary
|
||||
},
|
||||
hideTallStatus () {
|
||||
if (this.status.summary && this.$store.state.config.collapseMessageWithSubject) {
|
||||
if (this.status.summary && this.localCollapseSubjectDefault) {
|
||||
return false
|
||||
}
|
||||
if (this.showingTall) {
|
||||
|
@ -168,16 +175,22 @@ const Status = {
|
|||
if (!this.status.nsfw) {
|
||||
return false
|
||||
}
|
||||
if (this.status.summary && this.$store.state.config.collapseMessageWithSubject) {
|
||||
if (this.status.summary && this.localCollapseSubjectDefault) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
replySubject () {
|
||||
if (this.status.summary && !this.status.summary.match(/^re[: ]/i)) {
|
||||
if (!this.status.summary) return ''
|
||||
const behavior = this.$store.state.config.subjectLineBehavior
|
||||
const startsWithRe = this.status.summary.match(/^re[: ]/i)
|
||||
if (behavior !== 'noop' && startsWithRe || behavior === 'masto') {
|
||||
return this.status.summary
|
||||
} else if (behavior === 'email') {
|
||||
return 're: '.concat(this.status.summary)
|
||||
} else if (behavior === 'noop') {
|
||||
return ''
|
||||
}
|
||||
return this.status.summary
|
||||
},
|
||||
attachmentSize () {
|
||||
if ((this.$store.state.config.hideAttachments && !this.inConversation) ||
|
||||
|
|
|
@ -106,7 +106,7 @@
|
|||
</div>
|
||||
<div class="container" v-if="replying">
|
||||
<div class="reply-left"/>
|
||||
<post-status-form class="reply-body" :reply-to="status.id" :attentions="status.attentions" :repliedUser="status.user" :message-scope="status.visibility" :subject="replySubject" v-on:posted="toggleReplying"/>
|
||||
<post-status-form class="reply-body" :reply-to="status.id" :attentions="status.attentions" :repliedUser="status.user" :copy-message-scope="status.visibility" :subject="replySubject" v-on:posted="toggleReplying"/>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
|
|
@ -3,6 +3,13 @@ import { hex2rgb } from '../../services/color_convert/color_convert.js'
|
|||
|
||||
export default {
|
||||
props: [ 'user', 'switcher', 'selected', 'hideBio' ],
|
||||
data () {
|
||||
return {
|
||||
hideUserStatsLocal: typeof this.$store.state.config.hideUserStats === 'undefined'
|
||||
? this.$store.state.instance.hideUserStats
|
||||
: this.$store.state.config.hideUserStats
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
headingStyle () {
|
||||
const color = this.$store.state.config.customTheme.colors.bg
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<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>
|
||||
<span v-if="!hideUserStatsLocal" class="dailyAvg">{{dailyAvg}} {{ $t('user_card.per_day') }}</span>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -91,23 +91,24 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="panel-body profile-panel-body">
|
||||
<div class="user-counts" :class="{clickable: switcher}">
|
||||
<div v-if="!hideUserStatsLocal || switcher" class="user-counts" :class="{clickable: switcher}">
|
||||
<div class="user-count" v-on:click.prevent="setProfileView('statuses')" :class="{selected: selected === 'statuses'}">
|
||||
<h5>{{ $t('user_card.statuses') }}</h5>
|
||||
<span>{{user.statuses_count}} <br></span>
|
||||
<span v-if="!hideUserStatsLocal">{{user.statuses_count}} <br></span>
|
||||
</div>
|
||||
<div class="user-count" v-on:click.prevent="setProfileView('friends')" :class="{selected: selected === 'friends'}">
|
||||
<h5>{{ $t('user_card.followees') }}</h5>
|
||||
<span>{{user.friends_count}}</span>
|
||||
<span v-if="!hideUserStatsLocal">{{user.friends_count}}</span>
|
||||
</div>
|
||||
<div class="user-count" v-on:click.prevent="setProfileView('followers')" :class="{selected: selected === 'followers'}">
|
||||
<h5>{{ $t('user_card.followers') }}</h5>
|
||||
<span>{{user.followers_count}}</span>
|
||||
<span v-if="!hideUserStatsLocal">{{user.followers_count}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="!hideBio && user.description_html" class="profile-bio" v-html="user.description_html"></p>
|
||||
<p v-else-if="!hideBio" class="profile-bio">{{ user.description }}</p>
|
||||
</div>
|
||||
<p v-if="!hideBio && user.description_html" class="profile-bio" v-html="user.description_html"></p>
|
||||
<p v-else-if="!hideBio" class="profile-bio">{{ user.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -7,25 +7,10 @@ const UserFinder = {
|
|||
}),
|
||||
methods: {
|
||||
findUser (username) {
|
||||
username = username[0] === '@' ? username.slice(1) : username
|
||||
this.loading = true
|
||||
this.$store.state.api.backendInteractor.externalProfile(username)
|
||||
.then((user) => {
|
||||
this.loading = false
|
||||
this.hidden = true
|
||||
if (!user.error) {
|
||||
this.$store.commit('addNewUsers', [user])
|
||||
this.$router.push({name: 'user-profile', params: {id: user.id}})
|
||||
} else {
|
||||
this.error = true
|
||||
}
|
||||
})
|
||||
this.$router.push({ name: 'user-search', query: { query: username } })
|
||||
},
|
||||
toggleHidden () {
|
||||
this.hidden = !this.hidden
|
||||
},
|
||||
dismissError () {
|
||||
this.error = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
<template>
|
||||
<span class="user-finder-container">
|
||||
<span class="alert error" v-if="error">
|
||||
<i class="icon-cancel user-finder-icon" @click="dismissError"/>
|
||||
{{$t('finder.error_fetching_user')}}
|
||||
</span>
|
||||
<i class="icon-spin4 user-finder-icon animate-spin-slow" v-if="loading" />
|
||||
<a href="#" v-if="hidden"><i class="icon-user-plus user-finder-icon" @click.prevent.stop="toggleHidden"/></a>
|
||||
<span v-else>
|
||||
|
|
33
src/components/user_search/user_search.js
Normal file
33
src/components/user_search/user_search.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
import UserCard from '../user_card/user_card.vue'
|
||||
import userSearchApi from '../../services/new_api/user_search.js'
|
||||
const userSearch = {
|
||||
components: {
|
||||
UserCard
|
||||
},
|
||||
props: [
|
||||
'query'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
users: []
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.search(this.query)
|
||||
},
|
||||
watch: {
|
||||
query (newV) {
|
||||
this.search(newV)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
search (query) {
|
||||
userSearchApi.search({query, store: this.$store})
|
||||
.then((res) => {
|
||||
this.users = res
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default userSearch
|
12
src/components/user_search/user_search.vue
Normal file
12
src/components/user_search/user_search.vue
Normal file
|
@ -0,0 +1,12 @@
|
|||
<template>
|
||||
<div class="user-seach panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{{$t('nav.user_search')}}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<user-card v-for="user in users" :key="user.id" :user="user" :showFollows="true"></user-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./user_search.js"></script>
|
Loading…
Add table
Add a link
Reference in a new issue