diff options
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/attachment/attachment.js | 2 | ||||
| -rw-r--r-- | src/components/media_upload/media_upload.js | 9 | ||||
| -rw-r--r-- | src/components/post_status_form/post_status_form.js | 5 | ||||
| -rw-r--r-- | src/components/post_status_form/post_status_form.vue | 2 | ||||
| -rw-r--r-- | src/components/settings/settings.js | 5 | ||||
| -rw-r--r-- | src/components/settings/settings.vue | 12 | ||||
| -rw-r--r-- | src/components/status/status.vue | 2 | ||||
| -rw-r--r-- | src/components/timeline/timeline.js | 5 | ||||
| -rw-r--r-- | src/components/user_card/user_card.js | 3 | ||||
| -rw-r--r-- | src/components/user_card/user_card.vue | 4 | ||||
| -rw-r--r-- | src/components/user_card_content/user_card_content.js | 12 | ||||
| -rw-r--r-- | src/components/user_card_content/user_card_content.vue | 5 | ||||
| -rw-r--r-- | src/components/user_finder/user_finder.vue | 5 | ||||
| -rw-r--r-- | src/components/user_profile/user_profile.vue | 18 | ||||
| -rw-r--r-- | src/components/user_settings/user_settings.js | 121 | ||||
| -rw-r--r-- | src/components/user_settings/user_settings.vue | 52 |
16 files changed, 190 insertions, 72 deletions
diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js index 16114c30..97c4f283 100644 --- a/src/components/attachment/attachment.js +++ b/src/components/attachment/attachment.js @@ -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, diff --git a/src/components/media_upload/media_upload.js b/src/components/media_upload/media_upload.js index 66337c3f..42d900d3 100644 --- a/src/components/media_upload/media_upload.js +++ b/src/components/media_upload/media_upload.js @@ -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 }) }, diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index f9252f73..0ce2aff0 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -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 }, diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index fcf5c873..4776c819 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -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> diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js index c9e12708..681ccda8 100644 --- a/src/components/settings/settings.js +++ b/src/components/settings/settings.js @@ -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') } } } diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue index 6cdc82da..3f920de5 100644 --- a/src/components/settings/settings.vue +++ b/src/components/settings/settings.vue @@ -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')" > diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 96709084..067980ac 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -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"> diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index a651f619..f28b85bd 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -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 }) diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js index a019627a..b8eb28e3 100644 --- a/src/components/user_card/user_card.js +++ b/src/components/user_card/user_card.js @@ -14,6 +14,9 @@ const UserCard = { components: { UserCardContent }, + computed: { + currentUser () { return this.$store.state.users.currentUser } + }, methods: { toggleUserExpanded () { this.userExpanded = !this.userExpanded diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index 5a8e5531..eb0d7576 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -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 } }"> diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js index 7e0bd725..8c6de8ec 100644 --- a/src/components/user_card_content/user_card_content.js +++ b/src/components/user_card_content/user_card_content.js @@ -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(', ') } diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue index 2dc53c17..a40aff35 100644 --- a/src/components/user_card_content/user_card_content.vue +++ b/src/components/user_card_content/user_card_content.vue @@ -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; diff --git a/src/components/user_finder/user_finder.vue b/src/components/user_finder/user_finder.vue index 8786f6c7..4d9f6842 100644 --- a/src/components/user_finder/user_finder.vue +++ b/src/components/user_finder/user_finder.vue @@ -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%; } diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue index 91d4acd2..4d2853a6 100644 --- a/src/components/user_profile/user_profile.vue +++ b/src/components/user_profile/user_profile.vue @@ -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> diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js index 761e674a..ca7bf319 100644 --- a/src/components/user_settings/user_settings.js +++ b/src/components/user_settings/user_settings.js @@ -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 () { diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue index 234a7d86..67b65b57 100644 --- a/src/components/user_settings/user_settings.vue +++ b/src/components/user_settings/user_settings.vue @@ -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> |
