diff --git a/studio/src/app/models/data/user.tsx b/studio/src/app/models/data/user.tsx index 086015831..94e9d48e6 100644 --- a/studio/src/app/models/data/user.tsx +++ b/studio/src/app/models/data/user.tsx @@ -4,7 +4,9 @@ export interface UserSocial { dev?: string; medium?: string; github?: string; + custom?: string; + custom_logo_url?: string; } export interface UserData { diff --git a/studio/src/app/pages/core/app-settings/app-settings.scss b/studio/src/app/pages/core/app-settings/app-settings.scss index 8f9aae5a9..827541dd4 100644 --- a/studio/src/app/pages/core/app-settings/app-settings.scss +++ b/studio/src/app/pages/core/app-settings/app-settings.scss @@ -24,6 +24,11 @@ app-settings { div.avatar { --deckgo-avatar-size: 3rem; + deckgo-lazy-img { + width: 3rem; + height: 3rem; + } + input { padding-left: 8px; padding-right: 8px; diff --git a/studio/src/app/pages/core/app-settings/app-settings.tsx b/studio/src/app/pages/core/app-settings/app-settings.tsx index 50c321eb5..08b991f1f 100644 --- a/studio/src/app/pages/core/app-settings/app-settings.tsx +++ b/studio/src/app/pages/core/app-settings/app-settings.tsx @@ -23,6 +23,9 @@ import {StorageService} from '../../../services/storage/storage.service'; import {ApiUserFactoryService} from '../../../services/api/user/api.user.factory.service'; import {ThemeService} from '../../../services/theme/theme.service'; +import {EnvironmentDeckDeckGoConfig} from '../../../services/core/environment/environment-config'; +import {EnvironmentConfigService} from '../../../services/core/environment/environment-config.service'; + @Component({ tag: 'app-settings', styleUrl: 'app-settings.scss', @@ -56,6 +59,8 @@ export class AppHome { private profilePicture: File; + private customLogo: File; + private storageService: StorageService; private themeService: ThemeService; @@ -81,6 +86,8 @@ export class AppHome { private destroyUserListener; private destroyApiUserListener; + private config: EnvironmentDeckDeckGoConfig = EnvironmentConfigService.getInstance().get('deckdeckgo'); + constructor() { this.apiUserService = ApiUserFactoryService.getInstance(); this.imageHistoryService = ImageHistoryService.getInstance(); @@ -243,6 +250,8 @@ export class AppHome { this.saving = true; await this.uploadProfilePicture(); + await this.uploadCustomLogo(); + await this.saveUser(); await this.saveApiUser(); @@ -323,6 +332,37 @@ export class AppHome { }); } + private uploadCustomLogo(): Promise { + return new Promise(async (resolve, reject) => { + if (!this.valid || !this.user || !this.user.data) { + resolve(); + return; + } + + if (!this.user.data.social || !this.user.data.social.custom) { + resolve(); + return; + } + + if (!this.customLogo) { + resolve(); + return; + } + + try { + const storageFile: StorageFile = await this.storageService.uploadFile(this.customLogo, 'images', 524288); + + if (storageFile) { + this.user.data.social.custom_logo_url = storageFile.downloadUrl; + } + + resolve(); + } catch (err) { + reject('Could not upload your profile picture!'); + } + }); + } + private async presentConfirmDelete() { const modal: HTMLIonModalElement = await modalController.create({ component: 'app-user-delete', @@ -377,21 +417,28 @@ export class AppHome { }); } - private selectProfilePicture(): Promise { - return new Promise(async (resolve) => { - const filePicker: HTMLInputElement = this.el.querySelector('input#inputProfilePicture'); + private async selectProfilePicture() { + const filePicker: HTMLInputElement = this.el.querySelector('input#inputProfilePicture'); - if (!filePicker) { - resolve(); - return; - } + if (!filePicker) { + return; + } - if (filePicker.files && filePicker.files.length > 0) { - this.profilePicture = filePicker.files[0]; - } + if (filePicker.files && filePicker.files.length > 0) { + this.profilePicture = filePicker.files[0]; + } + } - resolve(); - }); + private async selectCustomLogo() { + const filePicker: HTMLInputElement = this.el.querySelector('input#inputCustomLogo'); + + if (!filePicker) { + return; + } + + if (filePicker.files && filePicker.files.length > 0) { + this.customLogo = filePicker.files[0]; + } } render() { @@ -732,7 +779,7 @@ export class AppHome { ,

- Your website or any custom url (for example: {this.custom ? this.custom : 'https://yourwebsite.com'}) + Your website or any url (for example: {this.custom ? this.custom : 'https://yourwebsite.com'})

, @@ -744,6 +791,33 @@ export class AppHome { disabled={this.saving} onIonInput={($event: CustomEvent) => this.handleSocialInput($event, 'custom')}> , + + this.renderCustomLogo(), + ]; + } + + private renderCustomLogo() { + return [ +

+ A logo for this custom address +

, +
+ {this.user && this.user.data && this.user.data.social && this.user.data.social.custom_logo_url ? ( + + ) : ( + + )} + this.selectCustomLogo()} + disabled={this.saving || !this.user || !this.user.data || !this.user.data.social || !this.user.data.social.custom} + /> +
, ]; } } diff --git a/studio/src/app/utils/editor/header-footer.utils.tsx b/studio/src/app/utils/editor/header-footer.utils.tsx index c582fa5a0..769cb369e 100644 --- a/studio/src/app/utils/editor/header-footer.utils.tsx +++ b/studio/src/app/utils/editor/header-footer.utils.tsx @@ -26,7 +26,7 @@ export class HeaderFooterUtils { deck.removeChild(currentSlotElement); } - const promises: Promise[] = [this.createContainer(slotName), this.createSocial(user, type), this.createImg(type)]; + const promises: Promise[] = [this.createContainer(slotName), this.createSocial(user, type), this.createImg(user, type)]; const [div, social, deckgoImg] = await Promise.all(promises); social.appendChild(deckgoImg); @@ -60,7 +60,7 @@ export class HeaderFooterUtils { return socialElement; } - private static async createImg(type: 'twitter' | 'linkedin' | 'dev' | 'medium' | 'github' | 'custom'): Promise { + private static async createImg(user: User, type: 'twitter' | 'linkedin' | 'dev' | 'medium' | 'github' | 'custom'): Promise { const deckgoImg: HTMLElement = document.createElement(SlotType.IMG); deckgoImg.setAttribute('slot', 'icon'); deckgoImg.setAttribute('aria-label', type); @@ -71,6 +71,8 @@ export class HeaderFooterUtils { deckgoImg.setAttribute('svg-src', `${config.globalAssetsUrl}/icons/ionicons/${type}.svg`); } else if (type === 'medium' || type === 'dev') { deckgoImg.setAttribute('svg-src', `${config.globalAssetsUrl}/icons/${type}.svg`); + } else if (user.data.social.custom_logo_url !== undefined && user.data.social.custom_logo_url !== '') { + deckgoImg.setAttribute('img-src', user.data.social.custom_logo_url); } else { deckgoImg.setAttribute('svg-src', `${config.globalAssetsUrl}/icons/ionicons/globe.svg`); } diff --git a/studio/src/app/utils/editor/social.utils.tsx b/studio/src/app/utils/editor/social.utils.tsx index 71f41818a..8a4eef8b4 100644 --- a/studio/src/app/utils/editor/social.utils.tsx +++ b/studio/src/app/utils/editor/social.utils.tsx @@ -41,15 +41,23 @@ export class SocialUtils { } static createCustom(user: User): JSX.IntrinsicElements { - const config: EnvironmentDeckDeckGoConfig = EnvironmentConfigService.getInstance().get('deckdeckgo'); - return ( - + {this.createCustomLogo(user)} ); } + private static createCustomLogo(user: User): JSX.IntrinsicElements { + if (user.data.social.custom_logo_url) { + return ; + } + + const config: EnvironmentDeckDeckGoConfig = EnvironmentConfigService.getInstance().get('deckdeckgo'); + + return ; + } + static createGitHub(user: User): JSX.IntrinsicElements { const config: EnvironmentDeckDeckGoConfig = EnvironmentConfigService.getInstance().get('deckdeckgo');