avatar upload works
This commit is contained in:
parent
7d985bd475
commit
b305748a92
10 changed files with 239 additions and 207 deletions
|
|
@ -15,6 +15,8 @@ import RichContent from 'src/components/rich_content/rich_content.jsx'
|
|||
import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_timed_filter_modal.vue'
|
||||
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||
import EmojiInput from 'src/components/emoji_input/emoji_input.vue'
|
||||
import Modal from 'src/components/modal/modal.vue'
|
||||
import ImageCropper from 'src/components/image_cropper/image_cropper.vue'
|
||||
|
||||
import localeService from 'src/services/locale/locale.service.js'
|
||||
import suggestor from 'src/components/emoji_input/suggestor.js'
|
||||
|
|
@ -34,7 +36,8 @@ import {
|
|||
faTimes,
|
||||
faExpandAlt,
|
||||
faBirthdayCake,
|
||||
faSave
|
||||
faSave,
|
||||
faChevronRight
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
import { useMediaViewerStore } from '../../stores/media_viewer'
|
||||
|
|
@ -49,7 +52,8 @@ library.add(
|
|||
faEdit,
|
||||
faTimes,
|
||||
faExpandAlt,
|
||||
faBirthdayCake
|
||||
faBirthdayCake,
|
||||
faChevronRight
|
||||
)
|
||||
|
||||
export default {
|
||||
|
|
@ -66,6 +70,7 @@ export default {
|
|||
'hasNoteEditor'
|
||||
],
|
||||
components: {
|
||||
Modal,
|
||||
UserAvatar,
|
||||
Checkbox,
|
||||
RemoteFollow,
|
||||
|
|
@ -79,7 +84,8 @@ export default {
|
|||
UserNote,
|
||||
UserTimedFilterModal,
|
||||
ColorInput,
|
||||
EmojiInput
|
||||
EmojiInput,
|
||||
ImageCropper
|
||||
},
|
||||
data () {
|
||||
const user = this.$store.state.users.currentUser
|
||||
|
|
@ -93,6 +99,7 @@ export default {
|
|||
newName: user.name_unescaped,
|
||||
editingName: false,
|
||||
newActorType: user.actor_type,
|
||||
editImage: false,
|
||||
newBio: unescape(user.description),
|
||||
editingBio: false,
|
||||
newBirthday: user.birthday,
|
||||
|
|
@ -223,6 +230,29 @@ export default {
|
|||
},
|
||||
|
||||
// Editable stuff
|
||||
defaultAvatar () {
|
||||
return this.$store.state.instance.server + this.$store.state.instance.defaultAvatar
|
||||
},
|
||||
defaultBanner () {
|
||||
return this.$store.state.instance.server + this.$store.state.instance.defaultBanner
|
||||
},
|
||||
isDefaultAvatar () {
|
||||
const baseAvatar = this.$store.state.instance.defaultAvatar
|
||||
return !(this.$store.state.users.currentUser.profile_image_url) ||
|
||||
this.$store.state.users.currentUser.profile_image_url.includes(baseAvatar)
|
||||
},
|
||||
isDefaultBanner () {
|
||||
const baseBanner = this.$store.state.instance.defaultBanner
|
||||
return !(this.$store.state.users.currentUser.cover_photo) ||
|
||||
this.$store.state.users.currentUser.cover_photo.includes(baseBanner)
|
||||
},
|
||||
isDefaultBackground () {
|
||||
return !(this.$store.state.users.currentUser.background_image)
|
||||
},
|
||||
avatarImgSrc () {
|
||||
const src = this.$store.state.users.currentUser.profile_image_url_original
|
||||
return (!src) ? this.defaultAvatar : src
|
||||
},
|
||||
fieldsLimits () {
|
||||
return this.$store.state.instance.fieldsLimits
|
||||
},
|
||||
|
|
@ -303,6 +333,52 @@ export default {
|
|||
},
|
||||
|
||||
// Editable stuff
|
||||
changeAvatar () {
|
||||
this.editImage = 'avatar'
|
||||
},
|
||||
changeBanner () {
|
||||
this.editImage = 'banner'
|
||||
},
|
||||
resetAvatar () {
|
||||
const confirmed = window.confirm(this.$t('settings.reset_avatar_confirm'))
|
||||
if (confirmed) {
|
||||
this.submitAvatar(undefined, '')
|
||||
}
|
||||
},
|
||||
resetBanner () {
|
||||
const confirmed = window.confirm(this.$t('settings.reset_banner_confirm'))
|
||||
if (confirmed) {
|
||||
this.submitBanner('')
|
||||
}
|
||||
},
|
||||
resetBackground () {
|
||||
const confirmed = window.confirm(this.$t('settings.reset_background_confirm'))
|
||||
if (confirmed) {
|
||||
this.submitBackground('')
|
||||
}
|
||||
},
|
||||
submitImage ({ canvas, file }) {
|
||||
const reqData = {}
|
||||
if (this.editImage === 'avatar') {
|
||||
if (canvas) {
|
||||
return canvas.toBlob((data) => this.submitImage({ canvas: null, file: data }))
|
||||
}
|
||||
reqData.avatar = file
|
||||
reqData.avatarName = file.name
|
||||
} else {
|
||||
reqData.banner = file
|
||||
}
|
||||
|
||||
return this.$store.state.api.backendInteractor.updateProfileImages(reqData)
|
||||
.then((user) => {
|
||||
this.$store.commit('addNewUsers', [user])
|
||||
this.$store.commit('setCurrentUser', user)
|
||||
this.editImage = false
|
||||
})
|
||||
.catch((error) => {
|
||||
this.displayUploadError(error)
|
||||
})
|
||||
},
|
||||
addField () {
|
||||
if (this.newFields.length < this.maxFields) {
|
||||
this.newFields.push({ name: '', value: '' })
|
||||
|
|
@ -316,6 +392,9 @@ export default {
|
|||
propsToNative (props) {
|
||||
return propsToNative(props)
|
||||
},
|
||||
cancelImageText () {
|
||||
return
|
||||
},
|
||||
updateProfile () {
|
||||
const params = {
|
||||
note: this.newBio,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,22 @@
|
|||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
&-bio {
|
||||
text-align: center;
|
||||
color: var(--lightText);
|
||||
display: block;
|
||||
line-height: 1.3;
|
||||
padding: 0.6em;
|
||||
margin: 0 0.6em;
|
||||
|
||||
img {
|
||||
object-fit: contain;
|
||||
vertical-align: middle;
|
||||
max-width: 100%;
|
||||
max-height: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
.user-card-bio {
|
||||
margin: 0.6em;
|
||||
|
||||
|
|
@ -101,22 +117,6 @@
|
|||
z-index: -2;
|
||||
}
|
||||
|
||||
&-bio {
|
||||
text-align: center;
|
||||
color: var(--lightText);
|
||||
display: block;
|
||||
line-height: 1.3;
|
||||
padding: 0.6em;
|
||||
margin: 0 0.6em;
|
||||
|
||||
img {
|
||||
object-fit: contain;
|
||||
vertical-align: middle;
|
||||
max-width: 100%;
|
||||
max-height: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
&.-rounded-t {
|
||||
border-top-left-radius: var(--roundness);
|
||||
border-top-right-radius: var(--roundness);
|
||||
|
|
@ -535,3 +535,44 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.edit-image {
|
||||
.panel-body {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.current-avatar {
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.images-container {
|
||||
display: grid;
|
||||
margin: 1em;
|
||||
grid-template-columns: 1fr 5em 1fr;
|
||||
grid-template-rows: 20em;
|
||||
gap: 0.5em;
|
||||
|
||||
.new-image {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.cropper {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
> * {
|
||||
flex: 1 0 10em;
|
||||
max-height: 100%;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
||||
.separator {
|
||||
min-width: 1.1em;
|
||||
font-size: 500%;
|
||||
align-self: center;
|
||||
flex: 0 1 5em;
|
||||
aspect-ratio: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
v-else-if="editable"
|
||||
class="user-info-avatar button-unstyled -link"
|
||||
:class="{ '-editable': editable }"
|
||||
@click="editAvatar"
|
||||
@click="changeAvatar"
|
||||
>
|
||||
<UserAvatar :user="user" />
|
||||
<div class="user-info-avatar -link -overlay">
|
||||
|
|
@ -63,7 +63,7 @@
|
|||
v-if="editable"
|
||||
:disabled="newName && newName.length === 0"
|
||||
class="btn button-unstyled edit-banner-button"
|
||||
@click="updateProfile"
|
||||
@click="changeBanner"
|
||||
>
|
||||
{{ $t('settings.change_banner') }}
|
||||
<FAIcon
|
||||
|
|
@ -591,6 +591,85 @@
|
|||
:is-mute="true"
|
||||
/>
|
||||
</teleport>
|
||||
<teleport to="#modal">
|
||||
<Modal
|
||||
v-if="editImage"
|
||||
:is-mute="true"
|
||||
class="edit-image"
|
||||
@backdrop-clicked="editImage = false"
|
||||
>
|
||||
<div class="panel">
|
||||
<div class="panel-heading">
|
||||
<h1 class="title">
|
||||
{{ editImage === 'avatar' ? $t('settings.change_avatar') : $t('settings.change_banner') }}
|
||||
</h1>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="images-container">
|
||||
<img
|
||||
:src="editImage === 'avatar' ? user.profile_image_url_original : newBanner"
|
||||
class="current-avatar"
|
||||
/>
|
||||
<FAIcon
|
||||
class="separator"
|
||||
icon="chevron-right"
|
||||
/>
|
||||
<image-cropper
|
||||
ref="cropper"
|
||||
class="cropper"
|
||||
@submit="submitImage"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
id="pick-image"
|
||||
class="button-default btn"
|
||||
type="button"
|
||||
@click="() => this.$refs.cropper.pickImage()"
|
||||
>
|
||||
{{ $t('settings.upload_picture') }}
|
||||
</button>
|
||||
<p class="visibility-notice">
|
||||
{{ $t('settings.avatar_size_instruction') }}
|
||||
</p>
|
||||
<button
|
||||
:title="editImage === 'avatar' ? $t('settings.reset_avatar') : $t('settings.reset_banner')"
|
||||
class="button-unstyled reset-button"
|
||||
@click="resetImage"
|
||||
>
|
||||
</button>
|
||||
<div class="panel-footer">
|
||||
<div/>
|
||||
<button
|
||||
class="button-default btn"
|
||||
type="button"
|
||||
@click="destroy"
|
||||
>
|
||||
{{ this.$t('image_cropper.cancel') }}
|
||||
</button>
|
||||
<button
|
||||
class="button-default btn"
|
||||
type="button"
|
||||
@click="this.$refs.cropper.submit(true)"
|
||||
>
|
||||
{{ $t('image_cropper.save') }}
|
||||
</button>
|
||||
<button
|
||||
class="button-default btn"
|
||||
type="button"
|
||||
@click="this.$refs.cropper.submit(false)"
|
||||
>
|
||||
{{ $t('image_cropper.save_without_cropping') }}
|
||||
</button>
|
||||
<FAIcon
|
||||
v-if="submitting"
|
||||
spin
|
||||
icon="circle-notch"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</teleport>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue