From 89c7a3854b2856b9364d0c1da8471b86cdba5c18 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Tue, 8 Oct 2019 19:32:48 +0200 Subject: [PATCH] Fix sending empty picture when updating identity without updated picture Closes #188 Signed-off-by: Thomas Citharel --- js/src/graphql/actor.ts | 12 +++++++++ js/src/utils/image.ts | 14 ++++++++++ .../views/Account/children/EditIdentity.vue | 26 ++++++++++++++----- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/js/src/graphql/actor.ts b/js/src/graphql/actor.ts index 105bd5b48..b3fd867ba 100644 --- a/js/src/graphql/actor.ts +++ b/js/src/graphql/actor.ts @@ -11,16 +11,19 @@ query($username: String!) { preferredUsername, suspended, avatar { + id, name, url }, banner { + id, url }, feedTokens { token }, organizedEvents { + id, uuid, title, beginsOn @@ -40,6 +43,7 @@ export const GET_PERSON = gql` preferredUsername, suspended, avatar { + id, name, url }, @@ -50,6 +54,7 @@ export const GET_PERSON = gql` token }, organizedEvents { + id, uuid, title, beginsOn @@ -63,6 +68,7 @@ query { loggedPerson { id, avatar { + id, url }, preferredUsername, @@ -109,6 +115,7 @@ query LoggedUserParticipations($afterDateTime: DateTime, $beforeDateTime: DateTi name, domain, avatar { + id, url } }, @@ -129,6 +136,7 @@ query LoggedUserParticipations($afterDateTime: DateTime, $beforeDateTime: DateTi name, domain, avatar { + id, url } } @@ -156,6 +164,7 @@ export const LOGGED_USER_DRAFTS = gql` name, domain, avatar { + id, url } }, @@ -176,6 +185,7 @@ query { identities { id, avatar { + id, url }, preferredUsername, @@ -196,6 +206,7 @@ mutation CreatePerson($preferredUsername: String!, $name: String!, $summary: Str name, summary, avatar { + id, url } } @@ -215,6 +226,7 @@ export const UPDATE_PERSON = gql` name, summary, avatar { + id, url }, } diff --git a/js/src/utils/image.ts b/js/src/utils/image.ts index 8eeba866b..372eab73e 100644 --- a/js/src/utils/image.ts +++ b/js/src/utils/image.ts @@ -22,3 +22,17 @@ export function buildFileVariable(file: File | null, name: string, alt?: stri }, }; } + +export function readFileAsync(file: File): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onload = () => { + resolve(reader.result); + }; + + reader.onerror = reject; + + reader.readAsBinaryString(file); + }); +} diff --git a/js/src/views/Account/children/EditIdentity.vue b/js/src/views/Account/children/EditIdentity.vue index 93bd14621..aa46a3928 100644 --- a/js/src/views/Account/children/EditIdentity.vue +++ b/js/src/views/Account/children/EditIdentity.vue @@ -94,7 +94,7 @@ import PictureUpload from '@/components/PictureUpload.vue'; import { MOBILIZON_INSTANCE_HOST } from '@/api/_entrypoint'; import { Dialog } from 'buefy/dist/components/dialog'; import { RouteName } from '@/router'; -import { buildFileFromIPicture, buildFileVariable } from '@/utils/image'; +import { buildFileFromIPicture, buildFileVariable, readFileAsync } from '@/utils/image'; import { changeIdentity } from '@/utils/auth'; @Component({ @@ -198,9 +198,11 @@ export default class EditIdentity extends Vue { async updateIdentity() { try { + const variables = await this.buildVariables(); + await this.$apollo.mutate({ mutation: UPDATE_PERSON, - variables: this.buildVariables(), + variables, update: (store, { data: { updatePerson } }) => { const data = store.readQuery<{ identities: IPerson[] }>({ query: IDENTITIES }); @@ -225,9 +227,11 @@ export default class EditIdentity extends Vue { async createIdentity() { try { + const variables = await this.buildVariables(); + await this.$apollo.mutate({ mutation: CREATE_PERSON, - variables: this.buildVariables(), + variables, update: (store, { data: { createPerson } }) => { const data = store.readQuery<{ identities: IPerson[] }>({ query: IDENTITIES }); @@ -305,10 +309,20 @@ export default class EditIdentity extends Vue { .replace(/[^a-z0-9._]/g, ''); } - private buildVariables() { - const avatarObj = buildFileVariable(this.avatarFile, 'avatar', `${this.identity.preferredUsername}'s avatar`); + private async buildVariables() { + const oldAvatarFile = await buildFileFromIPicture(this.identity.avatar); + const oldAvatarFileContent = await readFileAsync(oldAvatarFile); + const newAvatarFileContent = await readFileAsync(this.avatarFile); - return Object.assign({}, this.identity, avatarObj); + const avatarObj = buildFileVariable(this.avatarFile, 'avatar', `${this.identity.preferredUsername}'s avatar`); + const res = Object.assign({}, this.identity, avatarObj); + /** + * If the avatar didn't change, no need to try reuploading it + */ + if (oldAvatarFileContent === newAvatarFileContent) { + res.avatar = {}; + } + return res; } private async redirectIfNoIdentitySelected (identityParam?: string) {