summaryrefslogtreecommitdiffstats
path: root/src/components/ContactDetails/ContactDetailsAvatar.vue
diff options
context:
space:
mode:
authormatthias <matthias@butler>2020-03-30 23:32:37 +0200
committerJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2020-07-25 09:40:05 +0200
commite84571f0037b1222549e5fe9b4ac65ee4a1285aa (patch)
tree691f701b6021e6b0db7fcf339afe0edb69e5a617 /src/components/ContactDetails/ContactDetailsAvatar.vue
parente2633171d6a0581c76fcbf9abb162b581b1d219e (diff)
Allow for avatar downloads from social networks
Signed-off-by: call-me-matt <nextcloud@matthiasheinisch.de>
Diffstat (limited to 'src/components/ContactDetails/ContactDetailsAvatar.vue')
-rw-r--r--src/components/ContactDetails/ContactDetailsAvatar.vue86
1 files changed, 78 insertions, 8 deletions
diff --git a/src/components/ContactDetails/ContactDetailsAvatar.vue b/src/components/ContactDetails/ContactDetailsAvatar.vue
index 7b211c8c..3fc6f1ec 100644
--- a/src/components/ContactDetails/ContactDetailsAvatar.vue
+++ b/src/components/ContactDetails/ContactDetailsAvatar.vue
@@ -3,6 +3,7 @@
-
- @author Team Popcorn <teampopcornberlin@gmail.com>
- @author John Molakvoæ <skjnldsv@protonmail.com>
+ - @author Matthias Heinisch <nextcloud@matthiasheinisch.de>
-
- @license GNU AGPL version 3 or any later version
-
@@ -25,6 +26,7 @@
<div class="contact-header-avatar">
<div class="contact-header-avatar__wrapper">
<div class="contact-header-avatar__background" @click="toggleModal" />
+
<div v-if="contact.photo"
:style="{ 'backgroundImage': `url(${contact.photoUrl})` }"
class="contact-header-avatar__photo"
@@ -73,13 +75,20 @@
</Modal>
<!-- out of the avatar__options because of the overflow hidden -->
- <Actions :open="opened" class="contact-avatar-options__popovermenu">
- <ActionButton v-if="!isReadOnly" icon="icon-upload" @click="selectFileInput">
+ <Actions v-if="!isReadOnly" :open="opened" class="contact-avatar-options__popovermenu">
+ <ActionButton icon="icon-upload" @click="selectFileInput">
{{ t('contacts', 'Upload a new picture') }}
</ActionButton>
- <ActionButton v-if="!isReadOnly" icon="icon-picture" @click="selectFilePicker">
+ <ActionButton icon="icon-picture" @click="selectFilePicker">
{{ t('contacts', 'Choose from files') }}
</ActionButton>
+ <ActionButton
+ v-for="network in supportedSocial"
+ :key="network"
+ :icon="'icon-' + network.toLowerCase()"
+ @click="getSocialAvatar(network)">
+ {{ t('contacts', 'Get from ' + network) }}
+ </ActionButton>
</Actions>
</div>
</div>
@@ -93,11 +102,14 @@ import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
import Modal from '@nextcloud/vue/dist/Components/Modal'
import { getFilePickerBuilder } from '@nextcloud/dialogs'
-import { generateRemoteUrl } from '@nextcloud/router'
+import { generateUrl, generateRemoteUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
+import { loadState } from '@nextcloud/initial-state'
import sanitizeSVG from '@mattkrick/sanitize-svg'
-const axios = () => import('axios')
+import axios from '@nextcloud/axios'
+
+const supportedNetworks = loadState('contacts', 'supportedNetworks')
export default {
name: 'ContactDetailsAvatar',
@@ -133,6 +145,16 @@ export default {
}
return false
},
+ supportedSocial() {
+ // get social networks set for the current contact
+ const available = this.contact.vCard.getAllProperties('x-socialprofile')
+ .map(a => a.jCal[1].type.toString().toLowerCase())
+ // get list of social networks that allow for avatar download
+ const supported = supportedNetworks.map(v => v.toLowerCase())
+ // return supported social networks which are set
+ return supported.filter(i => available.includes(i))
+ .map(j => this.capitalize(j))
+ },
},
mounted() {
// update image size on window resize
@@ -215,7 +237,15 @@ export default {
this.$refs.uploadInput.value = ''
this.loading = false
},
-
+ /**
+ * Return the word with (only) the first letter capitalized
+ *
+ * @param {string} word the word to handle
+ * @returns {string} the word with the first letter capitalized
+ */
+ capitalize(word) {
+ return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
+ },
/**
* Return the mimetype based on the first magix byte
*
@@ -314,8 +344,7 @@ export default {
if (file) {
this.loading = true
try {
- const { get } = await axios()
- const response = await get(`${this.root}${file}`, {
+ const response = await axios.get(`${this.root}${file}`, {
responseType: 'arraybuffer',
})
const type = response.headers['content-type']
@@ -331,6 +360,47 @@ export default {
},
/**
+ * Downloads the Avatar from social media
+ *
+ * @param {String} network the social network to use (or 'any' for first match)
+ */
+ async getSocialAvatar(network) {
+
+ if (!this.loading) {
+
+ this.loading = true
+ try {
+ const response = await axios.put(generateUrl('/apps/contacts/api/v1/social/avatar/{network}/{id}/{uid}', {
+ network: network.toLowerCase(),
+ id: this.contact.addressbook.id,
+ uid: this.contact.uid,
+ }))
+ if (response.status !== 200) {
+ throw new URIError('Download of social profile avatar failed')
+ }
+
+ // Fetch newly updated contact
+ await this.$store.dispatch('fetchFullContact', { contact: this.contact, forceReFetch: true })
+
+ // Update local clone
+ const contact = this.$store.getters.getContact(this.contact.key)
+ await this.$emit('updateLocalContact', contact)
+
+ // Notify user
+ OC.Notification.showTemporary(t('contacts', 'Avatar downloaded from social network'))
+ } catch (error) {
+ if (error.response.status === 304) {
+ OC.Notification.showTemporary(t('contacts', 'Avatar already up to date'))
+ } else {
+ OC.Notification.showTemporary(t('contacts', 'Avatar download failed'))
+ console.debug(error)
+ }
+ }
+ }
+ this.loading = false
+ },
+
+ /**
* Menu handling
*/
toggleMenu() {