Improve avatar/banner setting

This commit is contained in:
syuilo 2020-01-30 07:13:36 +09:00
parent b70542cedc
commit 261f71474b
2 changed files with 119 additions and 63 deletions

View file

@ -1,7 +1,11 @@
<template> <template>
<section class="mk-settings-page-profile _section"> <section class="llvierxe _section">
<div class="_title"><fa :icon="faUser"/> {{ $t('profile') }}<small style="display: block; font-weight: normal; opacity: 0.6;">@{{ $store.state.i.username }}@{{ host }}</small></div> <div class="_title"><fa :icon="faUser"/> {{ $t('profile') }}<small style="display: block; font-weight: normal; opacity: 0.6;">@{{ $store.state.i.username }}@{{ host }}</small></div>
<div class="_content"> <div class="_content">
<div class="header" :style="{ backgroundImage: $store.state.i.bannerUrl ? `url(${ $store.state.i.bannerUrl })` : null }" @click="changeBanner">
<mk-avatar class="avatar" :user="$store.state.i" :disable-preview="true" :disable-link="true" @click.stop="changeAvatar"/>
</div>
<mk-input v-model="name" :max="30"> <mk-input v-model="name" :max="30">
<span>{{ $t('_profile.name') }}</span> <span>{{ $t('_profile.name') }}</span>
</mk-input> </mk-input>
@ -21,18 +25,6 @@
<template #prefix><fa :icon="faBirthdayCake"/></template> <template #prefix><fa :icon="faBirthdayCake"/></template>
</mk-input> </mk-input>
<mk-input type="file" @change="onAvatarChange">
<span>{{ $t('avatar') }}</span>
<template #icon><fa :icon="faImage"/></template>
<template #desc v-if="avatarUploading">{{ $t('uploading') }}<mk-ellipsis/></template>
</mk-input>
<mk-input type="file" @change="onBannerChange">
<span>{{ $t('banner') }}</span>
<template #icon><fa :icon="faImage"/></template>
<template #desc v-if="bannerUploading">{{ $t('uploading') }}<mk-ellipsis/></template>
</mk-input>
<details class="fields"> <details class="fields">
<summary>{{ $t('_profile.metadata') }}</summary> <summary>{{ $t('_profile.metadata') }}</summary>
<div class="row"> <div class="row">
@ -64,14 +56,15 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import { faUnlockAlt, faCogs, faImage, faUser, faMapMarkerAlt, faBirthdayCake } from '@fortawesome/free-solid-svg-icons'; import { faUnlockAlt, faCogs, faUser, faMapMarkerAlt, faBirthdayCake } from '@fortawesome/free-solid-svg-icons';
import { faSave } from '@fortawesome/free-regular-svg-icons'; import { faSave } from '@fortawesome/free-regular-svg-icons';
import MkButton from '../../components/ui/button.vue'; import MkButton from '../../components/ui/button.vue';
import MkInput from '../../components/ui/input.vue'; import MkInput from '../../components/ui/input.vue';
import MkTextarea from '../../components/ui/textarea.vue'; import MkTextarea from '../../components/ui/textarea.vue';
import MkSwitch from '../../components/ui/switch.vue'; import MkSwitch from '../../components/ui/switch.vue';
import i18n from '../../i18n'; import i18n from '../../i18n';
import { apiUrl, host } from '../../config'; import { host } from '../../config';
import { selectFile } from '../../scripts/select-file';
export default Vue.extend({ export default Vue.extend({
i18n, i18n,
@ -103,9 +96,7 @@ export default Vue.extend({
isBot: false, isBot: false,
isCat: false, isCat: false,
saving: false, saving: false,
avatarUploading: false, faSave, faUnlockAlt, faCogs, faUser, faMapMarkerAlt, faBirthdayCake
bannerUploading: false,
faSave, faUnlockAlt, faCogs, faImage, faUser, faMapMarkerAlt, faBirthdayCake
} }
}, },
@ -130,52 +121,18 @@ export default Vue.extend({
}, },
methods: { methods: {
onAvatarChange([file]) { changeAvatar(e) {
this.avatarUploading = true; selectFile(this, e.currentTarget || e.target, this.$t('avatar')).then(file => {
this.$root.api('i/update', {
const data = new FormData(); avatarId: file.id,
data.append('file', file);
data.append('i', this.$store.state.i.token);
fetch(apiUrl + '/drive/files/create', {
method: 'POST',
body: data
})
.then(response => response.json())
.then(f => {
this.avatarId = f.id;
this.avatarUploading = false;
})
.catch(e => {
this.avatarUploading = false;
this.$root.dialog({
type: 'error',
text: e
}); });
}); });
}, },
onBannerChange([file]) { changeBanner(e) {
this.bannerUploading = true; selectFile(this, e.currentTarget || e.target, this.$t('banner')).then(file => {
this.$root.api('i/update', {
const data = new FormData(); bannerId: file.id,
data.append('file', file);
data.append('i', this.$store.state.i.token);
fetch(apiUrl + '/drive/files/create', {
method: 'POST',
body: data
})
.then(response => response.json())
.then(f => {
this.bannerId = f.id;
this.bannerUploading = false;
})
.catch(e => {
this.bannerUploading = false;
this.$root.dialog({
type: 'error',
text: e
}); });
}); });
}, },
@ -226,10 +183,31 @@ export default Vue.extend({
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.mk-settings-page-profile { .llvierxe {
> ._content { > ._content {
> *:first-child { > .header {
margin-top: 0; position: relative;
height: 150px;
overflow: hidden;
background-size: cover;
background-position: center;
border-radius: 5px;
border: solid 1px var(--divider);
box-sizing: border-box;
cursor: pointer;
> .avatar {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: block;
width: 72px;
height: 72px;
margin: auto;
cursor: pointer;
}
} }
> .fields { > .fields {

View file

@ -0,0 +1,78 @@
import { faUpload, faCloud, faLink } from '@fortawesome/free-solid-svg-icons';
import { selectDriveFile } from './select-drive-file';
import { apiUrl } from '../config';
export function selectFile(component: any, src: any, label: string, multiple = false) {
return new Promise((res, rej) => {
const chooseFileFromPc = () => {
const input = document.createElement('input');
input.type = 'file';
input.multiple = multiple;
input.onchange = () => {
const dialog = component.$root.dialog({
type: 'waiting',
text: component.$t('uploading') + '...',
showOkButton: false,
showCancelButton: false,
cancelableByBgClick: false
});
const promises = Array.from(input.files).map(file => new Promise((ok, err) => {
const data = new FormData();
data.append('file', file);
data.append('i', component.$store.state.i.token);
fetch(apiUrl + '/drive/files/create', {
method: 'POST',
body: data
})
.then(response => response.json())
.then(ok)
.catch(err);
}));
Promise.all(promises).then(driveFiles => {
res(multiple ? driveFiles : driveFiles[0]);
}).catch(e => {
component.$root.dialog({
type: 'error',
text: e
});
}).finally(() => {
dialog.close();
});
};
input.click();
};
const chooseFileFromDrive = () => {
selectDriveFile(component.$root, multiple).then(files => {
res(files);
});
};
const chooseFileFromUrl = () => {
};
component.$root.menu({
items: [{
text: label,
type: 'label'
}, {
text: component.$t('upload'),
icon: faUpload,
action: chooseFileFromPc
}, {
text: component.$t('fromDrive'),
icon: faCloud,
action: chooseFileFromDrive
}, /*{
text: component.$t('fromUrl'),
icon: faLink,
action: chooseFileFromUrl
}*/],
source: src
});
});
}