Merge remote-tracking branch 'upstream/develop' into async_follow
* upstream/develop: (45 commits) fix chrome Prevent html-minifier to remove placeholder comment in index.html template Add placeholder to insert server generated metatags. Related to #430 added condition to check for logined user fix gradients and minor artifacts keep track of new instance options fix old MR oof get rid of slots fix timeago font added hide_network option, fixed properties naming Fix fetching new users, add storing local users in usersObjects with their screen_name as well as id, so that they could be fetched zero-state with screen-name link. improve notification subscription Refactor arrays to individual options Reset enableFollowsExport to true after 2 sec when an export file is available to download Write a unit test for fileSizeFormatService add checkbox to disable web push I am dumb Handle errors from server Moved upload errors in user_settings to an array. Moved upload error strings to its separate section in i18n ...
This commit is contained in:
commit
d7973b0b80
40 changed files with 569 additions and 119 deletions
|
@ -11,7 +11,7 @@ const Attachment = {
|
|||
],
|
||||
data () {
|
||||
return {
|
||||
nsfwImage,
|
||||
nsfwImage: this.$store.state.config.nsfwCensorImage || nsfwImage,
|
||||
hideNsfwLocal: this.$store.state.config.hideNsfw,
|
||||
preloadImage: this.$store.state.config.preloadImage,
|
||||
loopVideo: this.$store.state.config.loopVideo,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* eslint-env browser */
|
||||
import statusPosterService from '../../services/status_poster/status_poster.service.js'
|
||||
import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
|
||||
|
||||
const mediaUpload = {
|
||||
mounted () {
|
||||
|
@ -21,6 +22,12 @@ const mediaUpload = {
|
|||
uploadFile (file) {
|
||||
const self = this
|
||||
const store = this.$store
|
||||
if (file.size > store.state.instance.uploadlimit) {
|
||||
const filesize = fileSizeFormatService.fileSizeFormat(file.size)
|
||||
const allowedsize = fileSizeFormatService.fileSizeFormat(store.state.instance.uploadlimit)
|
||||
self.$emit('upload-failed', 'file_too_big', {filesize: filesize.num, filesizeunit: filesize.unit, allowedsize: allowedsize.num, allowedsizeunit: allowedsize.unit})
|
||||
return
|
||||
}
|
||||
const formData = new FormData()
|
||||
formData.append('media', file)
|
||||
|
||||
|
@ -32,7 +39,7 @@ const mediaUpload = {
|
|||
self.$emit('uploaded', fileData)
|
||||
self.uploading = false
|
||||
}, (error) => { // eslint-disable-line handle-callback-err
|
||||
self.$emit('upload-failed')
|
||||
self.$emit('upload-failed', 'default')
|
||||
self.uploading = false
|
||||
})
|
||||
},
|
||||
|
|
|
@ -262,6 +262,11 @@ const PostStatusForm = {
|
|||
let index = this.newStatus.files.indexOf(fileInfo)
|
||||
this.newStatus.files.splice(index, 1)
|
||||
},
|
||||
uploadFailed (errString, templateArgs) {
|
||||
templateArgs = templateArgs || {}
|
||||
this.error = this.$t('upload.error.base') + ' ' + this.$t('upload.error.' + errString, templateArgs)
|
||||
this.enableSubmit()
|
||||
},
|
||||
disableSubmit () {
|
||||
this.submitDisabled = true
|
||||
},
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class='form-bottom'>
|
||||
<media-upload @uploading="disableSubmit" @uploaded="addMediaFile" @upload-failed="enableSubmit" :drop-files="dropFiles"></media-upload>
|
||||
<media-upload @uploading="disableSubmit" @uploaded="addMediaFile" @upload-failed="uploadFailed" :drop-files="dropFiles"></media-upload>
|
||||
|
||||
<p v-if="isOverLengthLimit" class="error">{{ charactersLeft }}</p>
|
||||
<p class="faint" v-else-if="hasStatusLengthLimit">{{ charactersLeft }}</p>
|
||||
|
|
|
@ -47,6 +47,7 @@ const settings = {
|
|||
scopeCopyLocal: user.scopeCopy,
|
||||
scopeCopyDefault: this.$t('settings.values.' + instance.scopeCopy),
|
||||
stopGifs: user.stopGifs,
|
||||
webPushNotificationsLocal: user.webPushNotifications,
|
||||
loopSilentAvailable:
|
||||
// Firefox
|
||||
Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
|
||||
|
@ -142,6 +143,10 @@ const settings = {
|
|||
},
|
||||
stopGifs (value) {
|
||||
this.$store.dispatch('setOption', { name: 'stopGifs', value })
|
||||
},
|
||||
webPushNotificationsLocal (value) {
|
||||
this.$store.dispatch('setOption', { name: 'webPushNotifications', value })
|
||||
if (value) this.$store.dispatch('registerPushNotifications')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,6 +143,18 @@
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.notifications')}}</h2>
|
||||
<ul class="setting-list">
|
||||
<li>
|
||||
<input type="checkbox" id="webPushNotifications" v-model="webPushNotificationsLocal">
|
||||
<label for="webPushNotifications">
|
||||
{{$t('settings.enable_web_push_notifications')}}
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div :label="$t('settings.theme')" >
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
</h4>
|
||||
</div>
|
||||
<div class="media-heading-right">
|
||||
<router-link @click.native="activatePanel('timeline')" :to="{ name: 'conversation', params: { id: status.id } }">
|
||||
<router-link class="timeago" @click.native="activatePanel('timeline')" :to="{ name: 'conversation', params: { id: status.id } }">
|
||||
<timeago :since="status.created_at" :auto-update="60"></timeago>
|
||||
</router-link>
|
||||
<div class="visibility-icon" v-if="status.visibility">
|
||||
|
|
|
@ -2,6 +2,7 @@ import Status from '../status/status.vue'
|
|||
import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js'
|
||||
import StatusOrConversation from '../status_or_conversation/status_or_conversation.vue'
|
||||
import UserCard from '../user_card/user_card.vue'
|
||||
import { throttle } from 'lodash'
|
||||
|
||||
const Timeline = {
|
||||
props: [
|
||||
|
@ -88,7 +89,7 @@ const Timeline = {
|
|||
this.paused = false
|
||||
}
|
||||
},
|
||||
fetchOlderStatuses () {
|
||||
fetchOlderStatuses: throttle(function () {
|
||||
const store = this.$store
|
||||
const credentials = store.state.users.currentUser.credentials
|
||||
store.commit('setLoading', { timeline: this.timelineName, value: true })
|
||||
|
@ -101,7 +102,7 @@ const Timeline = {
|
|||
userId: this.userId,
|
||||
tag: this.tag
|
||||
}).then(() => store.commit('setLoading', { timeline: this.timelineName, value: false }))
|
||||
},
|
||||
}, 1000, this),
|
||||
fetchFollowers () {
|
||||
const id = this.userId
|
||||
this.$store.state.api.backendInteractor.fetchFollowers({ id })
|
||||
|
|
|
@ -14,6 +14,9 @@ const UserCard = {
|
|||
components: {
|
||||
UserCardContent
|
||||
},
|
||||
computed: {
|
||||
currentUser () { return this.$store.state.users.currentUser }
|
||||
},
|
||||
methods: {
|
||||
toggleUserExpanded () {
|
||||
this.userExpanded = !this.userExpanded
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
<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') }}
|
||||
{{ currentUser.id == user.id ? $t('user_card.its_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') }}
|
||||
{{ currentUser.id == user.id ? $t('user_card.its_you') : $t('user_card.follows_you') }}
|
||||
</span>
|
||||
</div>
|
||||
<router-link class='user-screen-name' :to="{ name: 'user-profile', params: { id: user.id } }">
|
||||
|
|
|
@ -22,10 +22,20 @@ export default {
|
|||
if (color) {
|
||||
const rgb = (typeof color === 'string') ? hex2rgb(color) : color
|
||||
const tintColor = `rgba(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)}, .5)`
|
||||
|
||||
const gradient = [
|
||||
[tintColor, this.hideBio ? '60%' : ''],
|
||||
this.hideBio ? [
|
||||
color, '100%'
|
||||
] : [
|
||||
tintColor, ''
|
||||
]
|
||||
].map(_ => _.join(' ')).join(', ')
|
||||
|
||||
return {
|
||||
backgroundColor: `rgb(${Math.floor(rgb.r * 0.53)}, ${Math.floor(rgb.g * 0.56)}, ${Math.floor(rgb.b * 0.59)})`,
|
||||
backgroundImage: [
|
||||
`linear-gradient(to bottom, ${tintColor}, ${tintColor})`,
|
||||
`linear-gradient(to bottom, ${gradient})`,
|
||||
`url(${this.user.cover_photo})`
|
||||
].join(', ')
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body profile-panel-body" v-if="switcher">
|
||||
<div class="panel-body profile-panel-body" v-if="!hideBio">
|
||||
<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>
|
||||
|
@ -135,6 +135,9 @@
|
|||
border-radius: var(--panelRadius, $fallback--panelRadius);
|
||||
overflow: hidden;
|
||||
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
|
||||
.panel-heading {
|
||||
padding: 0.6em 0em;
|
||||
text-align: center;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<template>
|
||||
<span class="user-finder-container">
|
||||
<div class="user-finder-container">
|
||||
<i class="icon-spin4 user-finder-icon animate-spin-slow" v-if="loading" />
|
||||
<a href="#" v-if="hidden" :title="$t('finder.find_user')" ><i class="icon-user-plus user-finder-icon" @click.prevent.stop="toggleHidden" /></a>
|
||||
<span v-else>
|
||||
<input class="user-finder-input" @keyup.enter="findUser(username)" v-model="username" :placeholder="$t('finder.find_user')" id="user-finder-input" type="text"/>
|
||||
<i class="icon-cancel user-finder-icon" @click.prevent.stop="toggleHidden"/>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./user_finder.js"></script>
|
||||
|
@ -15,7 +15,6 @@
|
|||
@import '../../_variables.scss';
|
||||
|
||||
.user-finder-container {
|
||||
height: 29px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,16 @@
|
|||
<div v-if="user" class="user-profile panel panel-default">
|
||||
<user-card-content :user="user" :switcher="true" :selected="timeline.viewing"></user-card-content>
|
||||
</div>
|
||||
<div v-else class="panel user-profile-placeholder">
|
||||
<div class="panel-heading">
|
||||
<div class="title">
|
||||
{{ $t('settings.profile_tab') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<i class="icon-spin3 animate-spin"></i>
|
||||
</div>
|
||||
</div>
|
||||
<Timeline :title="$t('user_profile.timeline_title')" :timeline="timeline" :timeline-name="'user'" :user-id="userId"/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -21,4 +31,12 @@
|
|||
align-items: stretch;
|
||||
}
|
||||
}
|
||||
.user-profile-placeholder {
|
||||
.panel-body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: middle;
|
||||
padding: 7em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,20 +1,30 @@
|
|||
import TabSwitcher from '../tab_switcher/tab_switcher.jsx'
|
||||
import StyleSwitcher from '../style_switcher/style_switcher.vue'
|
||||
import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
|
||||
|
||||
const UserSettings = {
|
||||
data () {
|
||||
return {
|
||||
newname: this.$store.state.users.currentUser.name,
|
||||
newbio: this.$store.state.users.currentUser.description,
|
||||
newlocked: this.$store.state.users.currentUser.locked,
|
||||
newnorichtext: this.$store.state.users.currentUser.no_rich_text,
|
||||
newdefaultScope: this.$store.state.users.currentUser.default_scope,
|
||||
newName: this.$store.state.users.currentUser.name,
|
||||
newBio: this.$store.state.users.currentUser.description,
|
||||
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,
|
||||
followList: null,
|
||||
followImportError: false,
|
||||
followsImported: false,
|
||||
enableFollowsExport: true,
|
||||
uploading: [ false, false, false, false ],
|
||||
previews: [ null, null, null ],
|
||||
avatarUploading: false,
|
||||
bannerUploading: false,
|
||||
backgroundUploading: false,
|
||||
followListUploading: false,
|
||||
avatarPreview: null,
|
||||
bannerPreview: null,
|
||||
backgroundPreview: null,
|
||||
avatarUploadError: null,
|
||||
bannerUploadError: null,
|
||||
backgroundUploadError: null,
|
||||
deletingAccount: false,
|
||||
deleteAccountConfirmPasswordInput: '',
|
||||
deleteAccountError: false,
|
||||
|
@ -40,48 +50,67 @@ const UserSettings = {
|
|||
},
|
||||
vis () {
|
||||
return {
|
||||
public: { selected: this.newdefaultScope === 'public' },
|
||||
unlisted: { selected: this.newdefaultScope === 'unlisted' },
|
||||
private: { selected: this.newdefaultScope === 'private' },
|
||||
direct: { selected: this.newdefaultScope === 'direct' }
|
||||
public: { selected: this.newDefaultScope === 'public' },
|
||||
unlisted: { selected: this.newDefaultScope === 'unlisted' },
|
||||
private: { selected: this.newDefaultScope === 'private' },
|
||||
direct: { selected: this.newDefaultScope === 'direct' }
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateProfile () {
|
||||
const name = this.newname
|
||||
const description = this.newbio
|
||||
const locked = this.newlocked
|
||||
const description = this.newBio
|
||||
const locked = this.newLocked
|
||||
// Backend notation.
|
||||
/* eslint-disable camelcase */
|
||||
const default_scope = this.newdefaultScope
|
||||
const no_rich_text = this.newnorichtext
|
||||
this.$store.state.api.backendInteractor.updateProfile({params: {name, description, locked, default_scope, no_rich_text}}).then((user) => {
|
||||
if (!user.error) {
|
||||
this.$store.commit('addNewUsers', [user])
|
||||
this.$store.commit('setCurrentUser', user)
|
||||
}
|
||||
})
|
||||
const default_scope = this.newDefaultScope
|
||||
const no_rich_text = this.newNoRichText
|
||||
const hide_network = this.newHideNetwork
|
||||
/* eslint-enable camelcase */
|
||||
this.$store.state.api.backendInteractor
|
||||
.updateProfile({
|
||||
params: {
|
||||
name,
|
||||
description,
|
||||
locked,
|
||||
// Backend notation.
|
||||
/* eslint-disable camelcase */
|
||||
default_scope,
|
||||
no_rich_text,
|
||||
hide_network
|
||||
/* eslint-enable camelcase */
|
||||
}}).then((user) => {
|
||||
if (!user.error) {
|
||||
this.$store.commit('addNewUsers', [user])
|
||||
this.$store.commit('setCurrentUser', user)
|
||||
}
|
||||
})
|
||||
},
|
||||
changeVis (visibility) {
|
||||
this.newdefaultScope = visibility
|
||||
this.newDefaultScope = visibility
|
||||
},
|
||||
uploadFile (slot, e) {
|
||||
const file = e.target.files[0]
|
||||
if (!file) { return }
|
||||
if (file.size > this.$store.state.instance[slot + 'limit']) {
|
||||
const filesize = fileSizeFormatService.fileSizeFormat(file.size)
|
||||
const allowedsize = fileSizeFormatService.fileSizeFormat(this.$store.state.instance[slot + 'limit'])
|
||||
this[slot + 'UploadError'] = this.$t('upload.error.base') + ' ' + this.$t('upload.error.file_too_big', {filesize: filesize.num, filesizeunit: filesize.unit, allowedsize: allowedsize.num, allowedsizeunit: allowedsize.unit})
|
||||
return
|
||||
}
|
||||
// eslint-disable-next-line no-undef
|
||||
const reader = new FileReader()
|
||||
reader.onload = ({target}) => {
|
||||
const img = target.result
|
||||
this.previews[slot] = img
|
||||
this.$forceUpdate() // just changing the array with the index doesn't update the view
|
||||
this[slot + 'Preview'] = img
|
||||
}
|
||||
reader.readAsDataURL(file)
|
||||
},
|
||||
submitAvatar () {
|
||||
if (!this.previews[0]) { return }
|
||||
if (!this.avatarPreview) { return }
|
||||
|
||||
let img = this.previews[0]
|
||||
let img = this.avatarPreview
|
||||
// eslint-disable-next-line no-undef
|
||||
let imginfo = new Image()
|
||||
let cropX, cropY, cropW, cropH
|
||||
|
@ -97,20 +126,25 @@ const UserSettings = {
|
|||
cropX = Math.floor((imginfo.width - imginfo.height) / 2)
|
||||
cropW = imginfo.height
|
||||
}
|
||||
this.uploading[0] = true
|
||||
this.avatarUploading = true
|
||||
this.$store.state.api.backendInteractor.updateAvatar({params: {img, cropX, cropY, cropW, cropH}}).then((user) => {
|
||||
if (!user.error) {
|
||||
this.$store.commit('addNewUsers', [user])
|
||||
this.$store.commit('setCurrentUser', user)
|
||||
this.previews[0] = null
|
||||
this.avatarPreview = null
|
||||
} else {
|
||||
this.avatarUploadError = this.$t('upload.error.base') + user.error
|
||||
}
|
||||
this.uploading[0] = false
|
||||
this.avatarUploading = false
|
||||
})
|
||||
},
|
||||
clearUploadError (slot) {
|
||||
this[slot + 'UploadError'] = null
|
||||
},
|
||||
submitBanner () {
|
||||
if (!this.previews[1]) { return }
|
||||
if (!this.bannerPreview) { return }
|
||||
|
||||
let banner = this.previews[1]
|
||||
let banner = this.bannerPreview
|
||||
// eslint-disable-next-line no-undef
|
||||
let imginfo = new Image()
|
||||
/* eslint-disable camelcase */
|
||||
|
@ -120,22 +154,24 @@ const UserSettings = {
|
|||
height = imginfo.height
|
||||
offset_top = 0
|
||||
offset_left = 0
|
||||
this.uploading[1] = true
|
||||
this.bannerUploading = true
|
||||
this.$store.state.api.backendInteractor.updateBanner({params: {banner, offset_top, offset_left, width, height}}).then((data) => {
|
||||
if (!data.error) {
|
||||
let clone = JSON.parse(JSON.stringify(this.$store.state.users.currentUser))
|
||||
clone.cover_photo = data.url
|
||||
this.$store.commit('addNewUsers', [clone])
|
||||
this.$store.commit('setCurrentUser', clone)
|
||||
this.previews[1] = null
|
||||
this.bannerPreview = null
|
||||
} else {
|
||||
this.bannerUploadError = this.$t('upload.error.base') + data.error
|
||||
}
|
||||
this.uploading[1] = false
|
||||
this.bannerUploading = false
|
||||
})
|
||||
/* eslint-enable camelcase */
|
||||
},
|
||||
submitBg () {
|
||||
if (!this.previews[2]) { return }
|
||||
let img = this.previews[2]
|
||||
if (!this.backgroundPreview) { return }
|
||||
let img = this.backgroundPreview
|
||||
// eslint-disable-next-line no-undef
|
||||
let imginfo = new Image()
|
||||
let cropX, cropY, cropW, cropH
|
||||
|
@ -144,20 +180,22 @@ const UserSettings = {
|
|||
cropY = 0
|
||||
cropW = imginfo.width
|
||||
cropH = imginfo.width
|
||||
this.uploading[2] = true
|
||||
this.backgroundUploading = true
|
||||
this.$store.state.api.backendInteractor.updateBg({params: {img, cropX, cropY, cropW, cropH}}).then((data) => {
|
||||
if (!data.error) {
|
||||
let clone = JSON.parse(JSON.stringify(this.$store.state.users.currentUser))
|
||||
clone.background_image = data.url
|
||||
this.$store.commit('addNewUsers', [clone])
|
||||
this.$store.commit('setCurrentUser', clone)
|
||||
this.previews[2] = null
|
||||
this.backgroundPreview = null
|
||||
} else {
|
||||
this.backgroundUploadError = this.$t('upload.error.base') + data.error
|
||||
}
|
||||
this.uploading[2] = false
|
||||
this.backgroundUploading = false
|
||||
})
|
||||
},
|
||||
importFollows () {
|
||||
this.uploading[3] = true
|
||||
this.followListUploading = true
|
||||
const followList = this.followList
|
||||
this.$store.state.api.backendInteractor.followImport({params: followList})
|
||||
.then((status) => {
|
||||
|
@ -166,7 +204,7 @@ const UserSettings = {
|
|||
} else {
|
||||
this.followImportError = true
|
||||
}
|
||||
this.uploading[3] = false
|
||||
this.followListUploading = false
|
||||
})
|
||||
},
|
||||
/* This function takes an Array of Users
|
||||
|
@ -198,6 +236,7 @@ const UserSettings = {
|
|||
.fetchFriends({id: this.$store.state.users.currentUser.id})
|
||||
.then((friendList) => {
|
||||
this.exportPeople(friendList, 'friends.csv')
|
||||
setTimeout(() => { this.enableFollowsExport = true }, 2000)
|
||||
})
|
||||
},
|
||||
followListChange () {
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
<div class="setting-item" >
|
||||
<h2>{{$t('settings.name_bio')}}</h2>
|
||||
<p>{{$t('settings.name')}}</p>
|
||||
<input class='name-changer' id='username' v-model="newname"></input>
|
||||
<input class='name-changer' id='username' v-model="newName"></input>
|
||||
<p>{{$t('settings.bio')}}</p>
|
||||
<textarea class="bio" v-model="newbio"></textarea>
|
||||
<textarea class="bio" v-model="newBio"></textarea>
|
||||
<p>
|
||||
<input type="checkbox" v-model="newlocked" id="account-locked">
|
||||
<input type="checkbox" v-model="newLocked" id="account-locked">
|
||||
<label for="account-locked">{{$t('settings.lock_account_description')}}</label>
|
||||
</p>
|
||||
<div v-if="scopeOptionsEnabled">
|
||||
|
@ -26,47 +26,63 @@
|
|||
</div>
|
||||
</div>
|
||||
<p>
|
||||
<input type="checkbox" v-model="newnorichtext" id="account-no-rich-text">
|
||||
<input type="checkbox" v-model="newNoRichText" id="account-no-rich-text">
|
||||
<label for="account-no-rich-text">{{$t('settings.no_rich_text_description')}}</label>
|
||||
</p>
|
||||
<button :disabled='newname.length <= 0' class="btn btn-default" @click="updateProfile">{{$t('general.submit')}}</button>
|
||||
<p>
|
||||
<input type="checkbox" v-model="newHideNetwork" id="account-hide-network">
|
||||
<label for="account-no-rich-text">{{$t('settings.hide_network_description')}}</label>
|
||||
</p>
|
||||
<button :disabled='newName.length <= 0' class="btn btn-default" @click="updateProfile">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.avatar')}}</h2>
|
||||
<p>{{$t('settings.current_avatar')}}</p>
|
||||
<img :src="user.profile_image_url_original" class="old-avatar"></img>
|
||||
<p>{{$t('settings.set_new_avatar')}}</p>
|
||||
<img class="new-avatar" v-bind:src="previews[0]" v-if="previews[0]">
|
||||
<img class="new-avatar" v-bind:src="avatarPreview" v-if="avatarPreview">
|
||||
</img>
|
||||
<div>
|
||||
<input type="file" @change="uploadFile(0, $event)" ></input>
|
||||
<input type="file" @change="uploadFile('avatar', $event)" ></input>
|
||||
</div>
|
||||
<i class="icon-spin4 animate-spin" v-if="avatarUploading"></i>
|
||||
<button class="btn btn-default" v-else-if="avatarPreview" @click="submitAvatar">{{$t('general.submit')}}</button>
|
||||
<div class='alert error' v-if="avatarUploadError">
|
||||
Error: {{ avatarUploadError }}
|
||||
<i class="icon-cancel" @click="clearUploadError('avatar')"></i>
|
||||
</div>
|
||||
<i class="icon-spin4 animate-spin" v-if="uploading[0]"></i>
|
||||
<button class="btn btn-default" v-else-if="previews[0]" @click="submitAvatar">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.profile_banner')}}</h2>
|
||||
<p>{{$t('settings.current_profile_banner')}}</p>
|
||||
<img :src="user.cover_photo" class="banner"></img>
|
||||
<p>{{$t('settings.set_new_profile_banner')}}</p>
|
||||
<img class="banner" v-bind:src="previews[1]" v-if="previews[1]">
|
||||
<img class="banner" v-bind:src="bannerPreview" v-if="bannerPreview">
|
||||
</img>
|
||||
<div>
|
||||
<input type="file" @change="uploadFile(1, $event)" ></input>
|
||||
<input type="file" @change="uploadFile('banner', $event)" ></input>
|
||||
</div>
|
||||
<i class=" icon-spin4 animate-spin uploading" v-if="bannerUploading"></i>
|
||||
<button class="btn btn-default" v-else-if="bannerPreview" @click="submitBanner">{{$t('general.submit')}}</button>
|
||||
<div class='alert error' v-if="bannerUploadError">
|
||||
Error: {{ bannerUploadError }}
|
||||
<i class="icon-cancel" @click="clearUploadError('banner')"></i>
|
||||
</div>
|
||||
<i class=" icon-spin4 animate-spin uploading" v-if="uploading[1]"></i>
|
||||
<button class="btn btn-default" v-else-if="previews[1]" @click="submitBanner">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<h2>{{$t('settings.profile_background')}}</h2>
|
||||
<p>{{$t('settings.set_new_profile_background')}}</p>
|
||||
<img class="bg" v-bind:src="previews[2]" v-if="previews[2]">
|
||||
<img class="bg" v-bind:src="backgroundPreview" v-if="backgroundPreview">
|
||||
</img>
|
||||
<div>
|
||||
<input type="file" @change="uploadFile(2, $event)" ></input>
|
||||
<input type="file" @change="uploadFile('background', $event)" ></input>
|
||||
</div>
|
||||
<i class=" icon-spin4 animate-spin uploading" v-if="backgroundUploading"></i>
|
||||
<button class="btn btn-default" v-else-if="backgroundPreview" @click="submitBg">{{$t('general.submit')}}</button>
|
||||
<div class='alert error' v-if="backgroundUploadError">
|
||||
Error: {{ backgroundUploadError }}
|
||||
<i class="icon-cancel" @click="clearUploadError('background')"></i>
|
||||
</div>
|
||||
<i class=" icon-spin4 animate-spin uploading" v-if="uploading[2]"></i>
|
||||
<button class="btn btn-default" v-else-if="previews[2]" @click="submitBg">{{$t('general.submit')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -113,7 +129,7 @@
|
|||
<form v-model="followImportForm">
|
||||
<input type="file" ref="followlist" v-on:change="followListChange"></input>
|
||||
</form>
|
||||
<i class=" icon-spin4 animate-spin uploading" v-if="uploading[3]"></i>
|
||||
<i class=" icon-spin4 animate-spin uploading" v-if="followListUploading"></i>
|
||||
<button class="btn btn-default" v-else @click="importFollows">{{$t('general.submit')}}</button>
|
||||
<div v-if="followsImported">
|
||||
<i class="icon-cross" @click="dismissImported"></i>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue