From 40e1e212d41ac88e05e9f65ecac020d780d6c1cc Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Mon, 1 Apr 2024 16:11:28 -0700 Subject: [PATCH 01/29] feat: default profile image with user initials --- .../components/chat/Settings/Account.svelte | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/lib/components/chat/Settings/Account.svelte b/src/lib/components/chat/Settings/Account.svelte index 3a2259a79..ba33056ec 100644 --- a/src/lib/components/chat/Settings/Account.svelte +++ b/src/lib/components/chat/Settings/Account.svelte @@ -19,6 +19,25 @@ let JWTTokenCopied = false; let profileImageInputElement: HTMLInputElement; + const generateInitialsImage = (name) => { + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + canvas.width = 100; + canvas.height = 100; + + ctx.fillStyle = '#F39C12'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + ctx.fillStyle = '#FFFFFF'; + ctx.font = '40px Helvetica'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + const initials = name.split(' ').map(word => word[0]).join(''); + ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); + + return canvas.toDataURL(); + }; + const submitHandler = async () => { const updatedUser = await updateUserProfile(localStorage.token, name, profileImageUrl).catch( (error) => { @@ -116,7 +135,7 @@ }} > profile @@ -142,9 +161,7 @@ From a0a064f4c8a3bd8414c953379331668be4f5f2ab Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Mon, 1 Apr 2024 16:23:54 -0700 Subject: [PATCH 02/29] update initals avatar if user changes name --- src/lib/components/chat/Settings/Account.svelte | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib/components/chat/Settings/Account.svelte b/src/lib/components/chat/Settings/Account.svelte index ba33056ec..36d2d6320 100644 --- a/src/lib/components/chat/Settings/Account.svelte +++ b/src/lib/components/chat/Settings/Account.svelte @@ -39,6 +39,11 @@ }; const submitHandler = async () => { + const isInitialsImage: boolean = profileImageUrl === generateInitialsImage($user.name) || profileImageUrl === ''; + if (isInitialsImage && name !== $user.name) { + profileImageUrl = generateInitialsImage(name); + } + const updatedUser = await updateUserProfile(localStorage.token, name, profileImageUrl).catch( (error) => { toast.error(error); From 6bb299ae25434b9b3aea642dd77d75778dc70ce5 Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Mon, 1 Apr 2024 16:26:05 -0700 Subject: [PATCH 03/29] run npm run format --- .../components/chat/Settings/Account.svelte | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/lib/components/chat/Settings/Account.svelte b/src/lib/components/chat/Settings/Account.svelte index 36d2d6320..85a14cd48 100644 --- a/src/lib/components/chat/Settings/Account.svelte +++ b/src/lib/components/chat/Settings/Account.svelte @@ -20,29 +20,33 @@ let profileImageInputElement: HTMLInputElement; const generateInitialsImage = (name) => { - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - canvas.width = 100; - canvas.height = 100; + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + canvas.width = 100; + canvas.height = 100; - ctx.fillStyle = '#F39C12'; - ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.fillStyle = '#F39C12'; + ctx.fillRect(0, 0, canvas.width, canvas.height); - ctx.fillStyle = '#FFFFFF'; - ctx.font = '40px Helvetica'; - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; - const initials = name.split(' ').map(word => word[0]).join(''); - ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); + ctx.fillStyle = '#FFFFFF'; + ctx.font = '40px Helvetica'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + const initials = name + .split(' ') + .map((word) => word[0]) + .join(''); + ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); - return canvas.toDataURL(); - }; + return canvas.toDataURL(); + }; const submitHandler = async () => { - const isInitialsImage: boolean = profileImageUrl === generateInitialsImage($user.name) || profileImageUrl === ''; - if (isInitialsImage && name !== $user.name) { - profileImageUrl = generateInitialsImage(name); - } + const isInitialsImage: boolean = + profileImageUrl === generateInitialsImage($user.name) || profileImageUrl === ''; + if (isInitialsImage && name !== $user.name) { + profileImageUrl = generateInitialsImage(name); + } const updatedUser = await updateUserProfile(localStorage.token, name, profileImageUrl).catch( (error) => { From 8d1db9a1c081e6b76c286484654b19b1019689ec Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Wed, 3 Apr 2024 22:36:27 -0700 Subject: [PATCH 04/29] feat: api endpoint to receive profile_image_uirl on signup --- backend/apps/web/models/auths.py | 5 +++-- backend/apps/web/models/users.py | 6 +++--- backend/apps/web/routers/auths.py | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/backend/apps/web/models/auths.py b/backend/apps/web/models/auths.py index 75637700d..5b262d631 100644 --- a/backend/apps/web/models/auths.py +++ b/backend/apps/web/models/auths.py @@ -82,6 +82,7 @@ class SignupForm(BaseModel): name: str email: str password: str + profile_image_url: str class AuthsTable: @@ -90,7 +91,7 @@ class AuthsTable: self.db.create_tables([Auth]) def insert_new_auth( - self, email: str, password: str, name: str, role: str = "pending" + self, email: str, password: str, name: str, profile_image_url: str, role: str = "pending" ) -> Optional[UserModel]: log.info("insert_new_auth") @@ -101,7 +102,7 @@ class AuthsTable: ) result = Auth.create(**auth.model_dump()) - user = Users.insert_new_user(id, name, email, role) + user = Users.insert_new_user(id, name, email, profile_image_url, role) if result and user: return user diff --git a/backend/apps/web/models/users.py b/backend/apps/web/models/users.py index 255c701df..62613581d 100644 --- a/backend/apps/web/models/users.py +++ b/backend/apps/web/models/users.py @@ -30,7 +30,7 @@ class UserModel(BaseModel): name: str email: str role: str = "pending" - profile_image_url: str = "/user.png" + profile_image_url: str timestamp: int # timestamp in epoch @@ -57,7 +57,7 @@ class UsersTable: self.db.create_tables([User]) def insert_new_user( - self, id: str, name: str, email: str, role: str = "pending" + self, id: str, name: str, email: str, profile_image_url: str, role: str = "pending", ) -> Optional[UserModel]: user = UserModel( **{ @@ -65,7 +65,7 @@ class UsersTable: "name": name, "email": email, "role": role, - "profile_image_url": "/user.png", + "profile_image_url": profile_image_url, "timestamp": int(time.time()), } ) diff --git a/backend/apps/web/routers/auths.py b/backend/apps/web/routers/auths.py index d881ec746..a1931b009 100644 --- a/backend/apps/web/routers/auths.py +++ b/backend/apps/web/routers/auths.py @@ -146,7 +146,7 @@ async def signup(request: Request, form_data: SignupForm): ) hashed = get_password_hash(form_data.password) user = Auths.insert_new_auth( - form_data.email.lower(), hashed, form_data.name, role + form_data.email.lower(), hashed, form_data.name, form_data.profile_image_url, role ) if user: From 3b06096c522ffa91ab956cc866708823966479dd Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Thu, 4 Apr 2024 01:10:51 -0700 Subject: [PATCH 05/29] run npm run lint:backend --- backend/apps/web/models/auths.py | 7 ++++++- backend/apps/web/models/users.py | 7 ++++++- backend/apps/web/routers/auths.py | 6 +++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/backend/apps/web/models/auths.py b/backend/apps/web/models/auths.py index 5b262d631..790856c7b 100644 --- a/backend/apps/web/models/auths.py +++ b/backend/apps/web/models/auths.py @@ -91,7 +91,12 @@ class AuthsTable: self.db.create_tables([Auth]) def insert_new_auth( - self, email: str, password: str, name: str, profile_image_url: str, role: str = "pending" + self, + email: str, + password: str, + name: str, + profile_image_url: str, + role: str = "pending", ) -> Optional[UserModel]: log.info("insert_new_auth") diff --git a/backend/apps/web/models/users.py b/backend/apps/web/models/users.py index 62613581d..fd5d35c2e 100644 --- a/backend/apps/web/models/users.py +++ b/backend/apps/web/models/users.py @@ -57,7 +57,12 @@ class UsersTable: self.db.create_tables([User]) def insert_new_user( - self, id: str, name: str, email: str, profile_image_url: str, role: str = "pending", + self, + id: str, + name: str, + email: str, + profile_image_url: str, + role: str = "pending", ) -> Optional[UserModel]: user = UserModel( **{ diff --git a/backend/apps/web/routers/auths.py b/backend/apps/web/routers/auths.py index a1931b009..1554cb49b 100644 --- a/backend/apps/web/routers/auths.py +++ b/backend/apps/web/routers/auths.py @@ -146,7 +146,11 @@ async def signup(request: Request, form_data: SignupForm): ) hashed = get_password_hash(form_data.password) user = Auths.insert_new_auth( - form_data.email.lower(), hashed, form_data.name, form_data.profile_image_url, role + form_data.email.lower(), + hashed, + form_data.name, + form_data.profile_image_url, + role, ) if user: From 4195af4942828c476084dfccf498a287713805b5 Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Thu, 4 Apr 2024 12:08:20 -0700 Subject: [PATCH 06/29] pass generated profile image in signup api call --- src/lib/apis/auths/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib/apis/auths/index.ts b/src/lib/apis/auths/index.ts index 169998726..c3e2dc2ff 100644 --- a/src/lib/apis/auths/index.ts +++ b/src/lib/apis/auths/index.ts @@ -58,7 +58,7 @@ export const userSignIn = async (email: string, password: string) => { return res; }; -export const userSignUp = async (name: string, email: string, password: string) => { +export const userSignUp = async (name: string, email: string, password: string, profile_image_url: string) => { let error = null; const res = await fetch(`${WEBUI_API_BASE_URL}/auths/signup`, { @@ -69,7 +69,8 @@ export const userSignUp = async (name: string, email: string, password: string) body: JSON.stringify({ name: name, email: email, - password: password + password: password, + profile_image_url: profile_image_url }) }) .then(async (res) => { From 0c43897f3d428e23d3c6318b081518d7de452b84 Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Thu, 4 Apr 2024 12:09:07 -0700 Subject: [PATCH 07/29] refac: move generateInitialsImage function to utils --- .../components/chat/Settings/Account.svelte | 24 +------------------ src/lib/utils/index.ts | 22 +++++++++++++++++ src/routes/auth/+page.svelte | 3 ++- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/lib/components/chat/Settings/Account.svelte b/src/lib/components/chat/Settings/Account.svelte index 85a14cd48..5d8d873d0 100644 --- a/src/lib/components/chat/Settings/Account.svelte +++ b/src/lib/components/chat/Settings/Account.svelte @@ -6,7 +6,7 @@ import { updateUserProfile } from '$lib/apis/auths'; import UpdatePassword from './Account/UpdatePassword.svelte'; - import { getGravatarUrl } from '$lib/apis/utils'; + import { generateInitialsImage } from '$lib/utils'; import { copyToClipboard } from '$lib/utils'; const i18n = getContext('i18n'); @@ -19,28 +19,6 @@ let JWTTokenCopied = false; let profileImageInputElement: HTMLInputElement; - const generateInitialsImage = (name) => { - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - canvas.width = 100; - canvas.height = 100; - - ctx.fillStyle = '#F39C12'; - ctx.fillRect(0, 0, canvas.width, canvas.height); - - ctx.fillStyle = '#FFFFFF'; - ctx.font = '40px Helvetica'; - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; - const initials = name - .split(' ') - .map((word) => word[0]) - .join(''); - ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); - - return canvas.toDataURL(); - }; - const submitHandler = async () => { const isInitialsImage: boolean = profileImageUrl === generateInitialsImage($user.name) || profileImageUrl === ''; diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 90d5d3c38..32830fed7 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -96,6 +96,28 @@ export const getGravatarURL = (email) => { return `https://www.gravatar.com/avatar/${hash}`; }; +export const generateInitialsImage = (name) => { + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + canvas.width = 100; + canvas.height = 100; + + ctx.fillStyle = '#F39C12'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + ctx.fillStyle = '#FFFFFF'; + ctx.font = '40px Helvetica'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + const initials = name + .split(' ') + .map((word) => word[0]) + .join(''); + ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); + + return canvas.toDataURL(); +}; + export const copyToClipboard = (text) => { if (!navigator.clipboard) { const textArea = document.createElement('textarea'); diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte index d392e9f77..8788cbca6 100644 --- a/src/routes/auth/+page.svelte +++ b/src/routes/auth/+page.svelte @@ -5,6 +5,7 @@ import { WEBUI_NAME, config, user } from '$lib/stores'; import { onMount, getContext } from 'svelte'; import { toast } from 'svelte-sonner'; + import { generateInitialsImage } from '$lib/utils'; const i18n = getContext('i18n'); @@ -35,7 +36,7 @@ }; const signUpHandler = async () => { - const sessionUser = await userSignUp(name, email, password).catch((error) => { + const sessionUser = await userSignUp(name, email, password, generateInitialsImage(name)).catch((error) => { toast.error(error); return null; }); From a2bd9b8639fba89d7c460095e47b38c529338302 Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Thu, 4 Apr 2024 12:10:45 -0700 Subject: [PATCH 08/29] style: npm run format --- src/lib/apis/auths/index.ts | 7 ++++++- src/routes/auth/+page.svelte | 10 ++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/lib/apis/auths/index.ts b/src/lib/apis/auths/index.ts index c3e2dc2ff..aa4371272 100644 --- a/src/lib/apis/auths/index.ts +++ b/src/lib/apis/auths/index.ts @@ -58,7 +58,12 @@ export const userSignIn = async (email: string, password: string) => { return res; }; -export const userSignUp = async (name: string, email: string, password: string, profile_image_url: string) => { +export const userSignUp = async ( + name: string, + email: string, + password: string, + profile_image_url: string +) => { let error = null; const res = await fetch(`${WEBUI_API_BASE_URL}/auths/signup`, { diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte index 8788cbca6..b40882ff2 100644 --- a/src/routes/auth/+page.svelte +++ b/src/routes/auth/+page.svelte @@ -36,10 +36,12 @@ }; const signUpHandler = async () => { - const sessionUser = await userSignUp(name, email, password, generateInitialsImage(name)).catch((error) => { - toast.error(error); - return null; - }); + const sessionUser = await userSignUp(name, email, password, generateInitialsImage(name)).catch( + (error) => { + toast.error(error); + return null; + } + ); await setSessionUser(sessionUser); }; From c52cc46d2c8d4d6ca57f52ab1402a7943edb5d9b Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Thu, 4 Apr 2024 13:23:59 -0700 Subject: [PATCH 09/29] feat: initial avatar set to first letter of firstname, first letter of lastname --- src/lib/utils/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 32830fed7..be08cae94 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -109,10 +109,10 @@ export const generateInitialsImage = (name) => { ctx.font = '40px Helvetica'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; - const initials = name - .split(' ') - .map((word) => word[0]) - .join(''); + const firstNameInitial = name[0]; + const lastNameInitial = name.lastIndexOf(' ') > -1 ? name[name.lastIndexOf(' ') + 1] : ''; + const initials = `${firstNameInitial}${lastNameInitial}`.toUpperCase() + ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); return canvas.toDataURL(); From ac470e64e0987f7b8c3300c2401d05eb259f6859 Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Thu, 4 Apr 2024 13:26:00 -0700 Subject: [PATCH 10/29] npm run format --- src/lib/utils/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index be08cae94..f5bd778b8 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -111,8 +111,8 @@ export const generateInitialsImage = (name) => { ctx.textBaseline = 'middle'; const firstNameInitial = name[0]; const lastNameInitial = name.lastIndexOf(' ') > -1 ? name[name.lastIndexOf(' ') + 1] : ''; - const initials = `${firstNameInitial}${lastNameInitial}`.toUpperCase() - + const initials = `${firstNameInitial}${lastNameInitial}`.toUpperCase(); + ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); return canvas.toDataURL(); From 4200ad111c6a14af22466b3d30c0cd26120f540e Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Thu, 4 Apr 2024 19:56:23 -0700 Subject: [PATCH 11/29] handle names with trailing whitespace --- src/lib/utils/index.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index f5bd778b8..636f68eee 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -109,9 +109,8 @@ export const generateInitialsImage = (name) => { ctx.font = '40px Helvetica'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; - const firstNameInitial = name[0]; - const lastNameInitial = name.lastIndexOf(' ') > -1 ? name[name.lastIndexOf(' ') + 1] : ''; - const initials = `${firstNameInitial}${lastNameInitial}`.toUpperCase(); + + const initials = name.trim().length > 0 ? name[0] + (name.trim().split(' ').length > 1 ? name[name.lastIndexOf(' ') + 1] : '') : ''; ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); From b8790200e98c21719730c706380d2f66551bb568 Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Thu, 4 Apr 2024 20:05:39 -0700 Subject: [PATCH 12/29] refac: code style --- src/lib/utils/index.ts | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 636f68eee..0f7a5ae13 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -97,24 +97,25 @@ export const getGravatarURL = (email) => { }; export const generateInitialsImage = (name) => { - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - canvas.width = 100; - canvas.height = 100; + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + canvas.width = 100; + canvas.height = 100; - ctx.fillStyle = '#F39C12'; - ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.fillStyle = '#F39C12'; + ctx.fillRect(0, 0, canvas.width, canvas.height); - ctx.fillStyle = '#FFFFFF'; - ctx.font = '40px Helvetica'; - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; + ctx.fillStyle = '#FFFFFF'; + ctx.font = '40px Helvetica'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; - const initials = name.trim().length > 0 ? name[0] + (name.trim().split(' ').length > 1 ? name[name.lastIndexOf(' ') + 1] : '') : ''; + const sanitizedName = name.trim(); + const initials = sanitizedName.length > 0 ? sanitizedName[0] + (sanitizedName.split(' ').length > 1 ? sanitizedName[sanitizedName.lastIndexOf(' ') + 1] : '') : ''; - ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); + ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); - return canvas.toDataURL(); + return canvas.toDataURL(); }; export const copyToClipboard = (text) => { From c8f7bb990c072c77d8cfc8a6c883ba0c352a5671 Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Thu, 4 Apr 2024 20:07:52 -0700 Subject: [PATCH 13/29] code style: npm run format --- src/lib/utils/index.ts | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 0f7a5ae13..c09b844c8 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -97,25 +97,31 @@ export const getGravatarURL = (email) => { }; export const generateInitialsImage = (name) => { - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - canvas.width = 100; - canvas.height = 100; + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + canvas.width = 100; + canvas.height = 100; - ctx.fillStyle = '#F39C12'; - ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.fillStyle = '#F39C12'; + ctx.fillRect(0, 0, canvas.width, canvas.height); - ctx.fillStyle = '#FFFFFF'; - ctx.font = '40px Helvetica'; - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; + ctx.fillStyle = '#FFFFFF'; + ctx.font = '40px Helvetica'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; const sanitizedName = name.trim(); - const initials = sanitizedName.length > 0 ? sanitizedName[0] + (sanitizedName.split(' ').length > 1 ? sanitizedName[sanitizedName.lastIndexOf(' ') + 1] : '') : ''; + const initials = + sanitizedName.length > 0 + ? sanitizedName[0] + + (sanitizedName.split(' ').length > 1 + ? sanitizedName[sanitizedName.lastIndexOf(' ') + 1] + : '') + : ''; - ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); + ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); - return canvas.toDataURL(); + return canvas.toDataURL(); }; export const copyToClipboard = (text) => { From ac9308dbed92ebc1a83b5c29ade63ece5a0cf80c Mon Sep 17 00:00:00 2001 From: Self Denial Date: Fri, 5 Apr 2024 16:04:00 -0600 Subject: [PATCH 14/29] Introduce canvasPixelTest() intended to validate canvas functionality Browsers and plugins that spoof canvas data produce corrupt images. In attempt to mitigate: * Add canvasPixelTest() to test a single pixel and test the RGB values * Test canvasPixelTest() inside generateInitialsImage() and use default `/user.png` if failure detected * Call canvasPixelTest() directly within settings to avoid setting an invalid image * Use toast.error() with 10 second autoClose --- .../components/chat/Settings/Account.svelte | 10 ++++- src/lib/utils/index.ts | 40 +++++++++++++++++++ src/routes/auth/+page.svelte | 8 +++- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/lib/components/chat/Settings/Account.svelte b/src/lib/components/chat/Settings/Account.svelte index 5d8d873d0..136d42230 100644 --- a/src/lib/components/chat/Settings/Account.svelte +++ b/src/lib/components/chat/Settings/Account.svelte @@ -6,7 +6,7 @@ import { updateUserProfile } from '$lib/apis/auths'; import UpdatePassword from './Account/UpdatePassword.svelte'; - import { generateInitialsImage } from '$lib/utils'; + import { generateInitialsImage, canvasPixelTest } from '$lib/utils'; import { copyToClipboard } from '$lib/utils'; const i18n = getContext('i18n'); @@ -148,7 +148,13 @@ diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index c09b844c8..ee3b4a77e 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -96,12 +96,52 @@ export const getGravatarURL = (email) => { return `https://www.gravatar.com/avatar/${hash}`; }; +export const canvasPixelTest = () => { + // Test a 1x1 pixel to potentially identify browser/plugin fingerprint blocking or spoofing + // Inspiration: https://github.com/kkapsner/CanvasBlocker/blob/master/test/detectionTest.js + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext('2d'); + canvas.height = 1; + canvas.width = 1; + const imageData = new ImageData(canvas.width, canvas.height); + const pixelValues = imageData.data; + + // Generate RGB test data + for (let i = 0; i < imageData.data.length; i += 1){ + if (i % 4 !== 3){ + pixelValues[i] = Math.floor(256 * Math.random()); + } + else { + pixelValues[i] = 255; + } + } + + ctx.putImageData(imageData, 0, 0); + const p = ctx.getImageData(0, 0, canvas.width, canvas.height).data; + + // Read RGB data and fail if unmatched + for (let i = 0; i < p.length; i += 1){ + if (p[i] !== pixelValues[i]){ + console.log("canvasPixelTest: Wrong canvas pixel RGB value detected:", p[i], "at:", i, "expected:", pixelValues[i]); + console.log("canvasPixelTest: Canvas blocking or spoofing is likely"); + return false; + } + } + + return true; +} + export const generateInitialsImage = (name) => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.width = 100; canvas.height = 100; + if (!canvasPixelTest()) { + console.log("generateInitialsImage: failed pixel test, fingerprint evasion is likely. Using default image."); + return '/user.png'; + } + ctx.fillStyle = '#F39C12'; ctx.fillRect(0, 0, canvas.width, canvas.height); diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte index b40882ff2..c7492cb26 100644 --- a/src/routes/auth/+page.svelte +++ b/src/routes/auth/+page.svelte @@ -5,7 +5,7 @@ import { WEBUI_NAME, config, user } from '$lib/stores'; import { onMount, getContext } from 'svelte'; import { toast } from 'svelte-sonner'; - import { generateInitialsImage } from '$lib/utils'; + import { generateInitialsImage, canvasPixelTest } from '$lib/utils'; const i18n = getContext('i18n'); @@ -43,6 +43,12 @@ } ); + if (!canvasPixelTest()) { + toast.error("Canvas pixel test failed, fingerprint evasion likely. Default image used.", { + autoClose: 1000 * 10, + }); + } + await setSessionUser(sessionUser); }; From 5694f166247052ed79a12145d67d6a7b436a604b Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Fri, 5 Apr 2024 21:02:02 -0700 Subject: [PATCH 15/29] style: run npm run format --- .../components/chat/Settings/Account.svelte | 9 ++++-- src/lib/utils/index.ts | 30 ++++++++++++------- src/routes/auth/+page.svelte | 4 +-- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/lib/components/chat/Settings/Account.svelte b/src/lib/components/chat/Settings/Account.svelte index 136d42230..651a4ee03 100644 --- a/src/lib/components/chat/Settings/Account.svelte +++ b/src/lib/components/chat/Settings/Account.svelte @@ -151,9 +151,12 @@ if (canvasPixelTest()) { profileImageUrl = generateInitialsImage(name); } else { - toast.error("Canvas pixel test failed, fingerprint evasion likely. Disable fingerprint evasion and try again!", { - autoClose: 1000 * 10, - }); + toast.error( + 'Canvas pixel test failed, fingerprint evasion likely. Disable fingerprint evasion and try again!', + { + autoClose: 1000 * 10 + } + ); } }}>{$i18n.t('Use Gravatar')} diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index ee3b4a77e..77454114f 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -99,7 +99,7 @@ export const getGravatarURL = (email) => { export const canvasPixelTest = () => { // Test a 1x1 pixel to potentially identify browser/plugin fingerprint blocking or spoofing // Inspiration: https://github.com/kkapsner/CanvasBlocker/blob/master/test/detectionTest.js - const canvas = document.createElement("canvas"); + const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.height = 1; canvas.width = 1; @@ -107,11 +107,10 @@ export const canvasPixelTest = () => { const pixelValues = imageData.data; // Generate RGB test data - for (let i = 0; i < imageData.data.length; i += 1){ - if (i % 4 !== 3){ + for (let i = 0; i < imageData.data.length; i += 1) { + if (i % 4 !== 3) { pixelValues[i] = Math.floor(256 * Math.random()); - } - else { + } else { pixelValues[i] = 255; } } @@ -120,16 +119,23 @@ export const canvasPixelTest = () => { const p = ctx.getImageData(0, 0, canvas.width, canvas.height).data; // Read RGB data and fail if unmatched - for (let i = 0; i < p.length; i += 1){ - if (p[i] !== pixelValues[i]){ - console.log("canvasPixelTest: Wrong canvas pixel RGB value detected:", p[i], "at:", i, "expected:", pixelValues[i]); - console.log("canvasPixelTest: Canvas blocking or spoofing is likely"); + for (let i = 0; i < p.length; i += 1) { + if (p[i] !== pixelValues[i]) { + console.log( + 'canvasPixelTest: Wrong canvas pixel RGB value detected:', + p[i], + 'at:', + i, + 'expected:', + pixelValues[i] + ); + console.log('canvasPixelTest: Canvas blocking or spoofing is likely'); return false; } } return true; -} +}; export const generateInitialsImage = (name) => { const canvas = document.createElement('canvas'); @@ -138,7 +144,9 @@ export const generateInitialsImage = (name) => { canvas.height = 100; if (!canvasPixelTest()) { - console.log("generateInitialsImage: failed pixel test, fingerprint evasion is likely. Using default image."); + console.log( + 'generateInitialsImage: failed pixel test, fingerprint evasion is likely. Using default image.' + ); return '/user.png'; } diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte index c7492cb26..0f2f428c8 100644 --- a/src/routes/auth/+page.svelte +++ b/src/routes/auth/+page.svelte @@ -44,8 +44,8 @@ ); if (!canvasPixelTest()) { - toast.error("Canvas pixel test failed, fingerprint evasion likely. Default image used.", { - autoClose: 1000 * 10, + toast.error('Canvas pixel test failed, fingerprint evasion likely. Default image used.', { + autoClose: 1000 * 10 }); } From 1af62a70f0083ee0040b05dffec7a737998decb6 Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Fri, 5 Apr 2024 21:16:48 -0700 Subject: [PATCH 16/29] omit canvas spoofing toast.error for signups --- src/routes/auth/+page.svelte | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte index 0f2f428c8..cf70456c8 100644 --- a/src/routes/auth/+page.svelte +++ b/src/routes/auth/+page.svelte @@ -43,12 +43,6 @@ } ); - if (!canvasPixelTest()) { - toast.error('Canvas pixel test failed, fingerprint evasion likely. Default image used.', { - autoClose: 1000 * 10 - }); - } - await setSessionUser(sessionUser); }; From 69716a5cec581f77d99760aad8f6d4e42405a00a Mon Sep 17 00:00:00 2001 From: Self Denial Date: Fri, 5 Apr 2024 22:31:40 -0600 Subject: [PATCH 17/29] Revert "omit canvas spoofing toast.error for signups" This reverts commit 1af62a70f0083ee0040b05dffec7a737998decb6. --- src/routes/auth/+page.svelte | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte index cf70456c8..0f2f428c8 100644 --- a/src/routes/auth/+page.svelte +++ b/src/routes/auth/+page.svelte @@ -43,6 +43,12 @@ } ); + if (!canvasPixelTest()) { + toast.error('Canvas pixel test failed, fingerprint evasion likely. Default image used.', { + autoClose: 1000 * 10 + }); + } + await setSessionUser(sessionUser); }; From bad7dca51ede5ca30749d387200bd086f276fb2b Mon Sep 17 00:00:00 2001 From: Self Denial Date: Fri, 5 Apr 2024 22:43:42 -0600 Subject: [PATCH 18/29] Move login page toast error to the bottom of page and enable i18n for translation --- src/lib/components/chat/Settings/Account.svelte | 2 +- src/routes/auth/+page.svelte | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lib/components/chat/Settings/Account.svelte b/src/lib/components/chat/Settings/Account.svelte index 651a4ee03..1dda14685 100644 --- a/src/lib/components/chat/Settings/Account.svelte +++ b/src/lib/components/chat/Settings/Account.svelte @@ -152,7 +152,7 @@ profileImageUrl = generateInitialsImage(name); } else { toast.error( - 'Canvas pixel test failed, fingerprint evasion likely. Disable fingerprint evasion and try again!', + $i18n.t('Canvas pixel test failed, fingerprint evasion likely. Disable fingerprint evasion and try again!'), { autoClose: 1000 * 10 } diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte index 0f2f428c8..28f4d6f6b 100644 --- a/src/routes/auth/+page.svelte +++ b/src/routes/auth/+page.svelte @@ -44,9 +44,13 @@ ); if (!canvasPixelTest()) { - toast.error('Canvas pixel test failed, fingerprint evasion likely. Default image used.', { - autoClose: 1000 * 10 - }); + toast.error( + $i18n.t('Canvas pixel test failed, fingerprint evasion likely. Default image used.'), + { + position: "bottom-center", + autoClose: 1000 * 10, + } + ); } await setSessionUser(sessionUser); From ae9922a2cd5f0c4970e1eefd7a000f43c3d2f5d3 Mon Sep 17 00:00:00 2001 From: Self Denial Date: Fri, 5 Apr 2024 22:58:40 -0600 Subject: [PATCH 19/29] Re-word account creation error to be more descriptive --- src/routes/auth/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte index 28f4d6f6b..099d4a5b3 100644 --- a/src/routes/auth/+page.svelte +++ b/src/routes/auth/+page.svelte @@ -45,7 +45,7 @@ if (!canvasPixelTest()) { toast.error( - $i18n.t('Canvas pixel test failed, fingerprint evasion likely. Default image used.'), + $i18n.t('Canvas pixel test failed: fingerprint evasion likely. Using default avatar image.'), { position: "bottom-center", autoClose: 1000 * 10, From cf54adf5c43d8dd7b9cb16290ecc91ed2c392a4f Mon Sep 17 00:00:00 2001 From: Self Denial Date: Fri, 5 Apr 2024 23:01:48 -0600 Subject: [PATCH 20/29] Toast error consistency --- src/lib/components/chat/Settings/Account.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/chat/Settings/Account.svelte b/src/lib/components/chat/Settings/Account.svelte index 1dda14685..6c484b54b 100644 --- a/src/lib/components/chat/Settings/Account.svelte +++ b/src/lib/components/chat/Settings/Account.svelte @@ -152,7 +152,7 @@ profileImageUrl = generateInitialsImage(name); } else { toast.error( - $i18n.t('Canvas pixel test failed, fingerprint evasion likely. Disable fingerprint evasion and try again!'), + $i18n.t('Canvas pixel test failed: fingerprint evasion likely. Disable fingerprint evasion and try again!'), { autoClose: 1000 * 10 } From 78565e554b5d69d9ab027a7ccb2c1761d3a1bd01 Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Sat, 6 Apr 2024 01:01:23 -0700 Subject: [PATCH 21/29] notify user with toast.info() + update toast message --- src/lib/components/chat/Settings/Account.svelte | 4 ++-- src/routes/auth/+page.svelte | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/components/chat/Settings/Account.svelte b/src/lib/components/chat/Settings/Account.svelte index 6c484b54b..35d9aa882 100644 --- a/src/lib/components/chat/Settings/Account.svelte +++ b/src/lib/components/chat/Settings/Account.svelte @@ -151,8 +151,8 @@ if (canvasPixelTest()) { profileImageUrl = generateInitialsImage(name); } else { - toast.error( - $i18n.t('Canvas pixel test failed: fingerprint evasion likely. Disable fingerprint evasion and try again!'), + toast.info( + $i18n.t('Fingerprint spoofing detected: default profile picture set. Disable to access initial gravatar!'), { autoClose: 1000 * 10 } diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte index 099d4a5b3..bab13c868 100644 --- a/src/routes/auth/+page.svelte +++ b/src/routes/auth/+page.svelte @@ -44,8 +44,8 @@ ); if (!canvasPixelTest()) { - toast.error( - $i18n.t('Canvas pixel test failed: fingerprint evasion likely. Using default avatar image.'), + toast.info( + $i18n.t('Fingerprint spoofing detected: default profile picture set. Disable to access initial gravatar!'), { position: "bottom-center", autoClose: 1000 * 10, From 8a7075c3bf199585acdd85802cc502fa958f3ed5 Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Sat, 6 Apr 2024 01:13:22 -0700 Subject: [PATCH 22/29] style: npm run format --- src/lib/components/chat/Settings/Account.svelte | 4 +++- src/routes/auth/+page.svelte | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lib/components/chat/Settings/Account.svelte b/src/lib/components/chat/Settings/Account.svelte index 35d9aa882..5a152bc40 100644 --- a/src/lib/components/chat/Settings/Account.svelte +++ b/src/lib/components/chat/Settings/Account.svelte @@ -152,7 +152,9 @@ profileImageUrl = generateInitialsImage(name); } else { toast.info( - $i18n.t('Fingerprint spoofing detected: default profile picture set. Disable to access initial gravatar!'), + $i18n.t( + 'Fingerprint spoofing detected: default profile picture set. Disable to access initial gravatar!' + ), { autoClose: 1000 * 10 } diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte index bab13c868..babdc68a1 100644 --- a/src/routes/auth/+page.svelte +++ b/src/routes/auth/+page.svelte @@ -45,10 +45,12 @@ if (!canvasPixelTest()) { toast.info( - $i18n.t('Fingerprint spoofing detected: default profile picture set. Disable to access initial gravatar!'), + $i18n.t( + 'Fingerprint spoofing detected: default profile picture set. Disable to access initial gravatar!' + ), { - position: "bottom-center", - autoClose: 1000 * 10, + position: 'bottom-center', + autoClose: 1000 * 10 } ); } From bee0338763f848f0dd3afeb2c5dbe2d4b8e8120b Mon Sep 17 00:00:00 2001 From: Danny Liu Date: Sat, 6 Apr 2024 02:23:32 -0700 Subject: [PATCH 23/29] captalize Initial for improved clarity --- src/lib/components/chat/Settings/Account.svelte | 2 +- src/routes/auth/+page.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/components/chat/Settings/Account.svelte b/src/lib/components/chat/Settings/Account.svelte index 5a152bc40..df7c2056c 100644 --- a/src/lib/components/chat/Settings/Account.svelte +++ b/src/lib/components/chat/Settings/Account.svelte @@ -153,7 +153,7 @@ } else { toast.info( $i18n.t( - 'Fingerprint spoofing detected: default profile picture set. Disable to access initial gravatar!' + 'Fingerprint spoofing detected: default profile picture set. Disable to access Initial gravatar!' ), { autoClose: 1000 * 10 diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte index babdc68a1..041640f73 100644 --- a/src/routes/auth/+page.svelte +++ b/src/routes/auth/+page.svelte @@ -46,7 +46,7 @@ if (!canvasPixelTest()) { toast.info( $i18n.t( - 'Fingerprint spoofing detected: default profile picture set. Disable to access initial gravatar!' + 'Fingerprint spoofing detected: default profile picture set. Disable to access Initial gravatar!' ), { position: 'bottom-center', From 924ebf035bfa5a5be5f95c188a63b709423f1e58 Mon Sep 17 00:00:00 2001 From: Self Denial Date: Sat, 6 Apr 2024 16:04:05 -0600 Subject: [PATCH 24/29] Fix: Restore Gravatar functionality, add button initials, toast duration - Restore Gravatar functionality - Add new button for "Use Initials" - Set both buttons to use text-left class - Update toast property autoClose to duration (wrong library, my bad!) - Update toast messages to clarify that this isn't "Gravatar" but "avatar" - Add i18n text to en-US/translation.json --- src/lib/components/chat/Settings/Account.svelte | 15 ++++++++++++--- src/lib/i18n/locales/en-US/translation.json | 2 ++ src/routes/auth/+page.svelte | 4 ++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/lib/components/chat/Settings/Account.svelte b/src/lib/components/chat/Settings/Account.svelte index df7c2056c..ce2c0b30f 100644 --- a/src/lib/components/chat/Settings/Account.svelte +++ b/src/lib/components/chat/Settings/Account.svelte @@ -6,6 +6,7 @@ import { updateUserProfile } from '$lib/apis/auths'; import UpdatePassword from './Account/UpdatePassword.svelte'; + import { getGravatarUrl } from '$lib/apis/utils'; import { generateInitialsImage, canvasPixelTest } from '$lib/utils'; import { copyToClipboard } from '$lib/utils'; @@ -146,20 +147,28 @@ + diff --git a/src/lib/i18n/locales/en-US/translation.json b/src/lib/i18n/locales/en-US/translation.json index 251834e00..e97df0c8c 100644 --- a/src/lib/i18n/locales/en-US/translation.json +++ b/src/lib/i18n/locales/en-US/translation.json @@ -150,6 +150,7 @@ "Failed to read clipboard contents": "", "File Mode": "", "File not found.": "", + "Fingerprint spoofing detected: default profile picture set. Disable to access Initial avatar!": "", "Focus chat input": "", "Format your variables using square brackets like this:": "", "From (Base Model)": "", @@ -340,6 +341,7 @@ "URL Mode": "", "Use '#' in the prompt input to load and select your documents.": "", "Use Gravatar": "", + "Use Initials": "", "user": "", "User Permissions": "", "Users": "", diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte index 041640f73..f02bbdb4a 100644 --- a/src/routes/auth/+page.svelte +++ b/src/routes/auth/+page.svelte @@ -46,11 +46,11 @@ if (!canvasPixelTest()) { toast.info( $i18n.t( - 'Fingerprint spoofing detected: default profile picture set. Disable to access Initial gravatar!' + 'Fingerprint spoofing detected: default profile picture set. Disable to access Initial avatar!' ), { position: 'bottom-center', - autoClose: 1000 * 10 + duration: 1000 * 10 } ); } From f267f3f7b084cb56fd93a8b187bbbb284c512f73 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 6 Apr 2024 23:16:29 -0700 Subject: [PATCH 25/29] refac --- backend/apps/web/models/auths.py | 4 ++-- backend/apps/web/models/users.py | 2 +- src/routes/auth/+page.svelte | 12 ------------ 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/backend/apps/web/models/auths.py b/backend/apps/web/models/auths.py index 790856c7b..8759be505 100644 --- a/backend/apps/web/models/auths.py +++ b/backend/apps/web/models/auths.py @@ -82,7 +82,7 @@ class SignupForm(BaseModel): name: str email: str password: str - profile_image_url: str + profile_image_url: Optional[str] = "/user.png" class AuthsTable: @@ -95,7 +95,7 @@ class AuthsTable: email: str, password: str, name: str, - profile_image_url: str, + profile_image_url: str = "/user.png", role: str = "pending", ) -> Optional[UserModel]: log.info("insert_new_auth") diff --git a/backend/apps/web/models/users.py b/backend/apps/web/models/users.py index fd5d35c2e..1c377de73 100644 --- a/backend/apps/web/models/users.py +++ b/backend/apps/web/models/users.py @@ -61,7 +61,7 @@ class UsersTable: id: str, name: str, email: str, - profile_image_url: str, + profile_image_url: str = "/user.png", role: str = "pending", ) -> Optional[UserModel]: user = UserModel( diff --git a/src/routes/auth/+page.svelte b/src/routes/auth/+page.svelte index f02bbdb4a..cf70456c8 100644 --- a/src/routes/auth/+page.svelte +++ b/src/routes/auth/+page.svelte @@ -43,18 +43,6 @@ } ); - if (!canvasPixelTest()) { - toast.info( - $i18n.t( - 'Fingerprint spoofing detected: default profile picture set. Disable to access Initial avatar!' - ), - { - position: 'bottom-center', - duration: 1000 * 10 - } - ); - } - await setSessionUser(sessionUser); }; From df2cb1608652fb8d4c4fb41d405e39eaa2f51d35 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 6 Apr 2024 23:49:25 -0700 Subject: [PATCH 26/29] refac: styling --- .../components/chat/Settings/Account.svelte | 165 ++++++++++++++---- src/lib/i18n/locales/en-US/translation.json | 4 +- 2 files changed, 132 insertions(+), 37 deletions(-) diff --git a/src/lib/components/chat/Settings/Account.svelte b/src/lib/components/chat/Settings/Account.svelte index ce2c0b30f..406056e38 100644 --- a/src/lib/components/chat/Settings/Account.svelte +++ b/src/lib/components/chat/Settings/Account.svelte @@ -21,10 +21,10 @@ let profileImageInputElement: HTMLInputElement; const submitHandler = async () => { - const isInitialsImage: boolean = - profileImageUrl === generateInitialsImage($user.name) || profileImageUrl === ''; - if (isInitialsImage && name !== $user.name) { - profileImageUrl = generateInitialsImage(name); + if (name !== $user.name) { + if (profileImageUrl === generateInitialsImage($user.name) || profileImageUrl === '') { + profileImageUrl = generateInitialsImage(name); + } } const updatedUser = await updateUserProfile(localStorage.token, name, profileImageUrl).catch( @@ -110,11 +110,11 @@ }} /> -
{$i18n.t('Profile')}
- -
+ + +
+
+
+ +
+
+ +
+
{$i18n.t('Profile Image')}
+ +
+ + + + +
+
+
+
{$i18n.t('Name')}
+ +
+ +
+
+

diff --git a/src/lib/i18n/locales/en-US/translation.json b/src/lib/i18n/locales/en-US/translation.json index e97df0c8c..f1e301b87 100644 --- a/src/lib/i18n/locales/en-US/translation.json +++ b/src/lib/i18n/locales/en-US/translation.json @@ -150,7 +150,7 @@ "Failed to read clipboard contents": "", "File Mode": "", "File not found.": "", - "Fingerprint spoofing detected: default profile picture set. Disable to access Initial avatar!": "", + "Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "", "Focus chat input": "", "Format your variables using square brackets like this:": "", "From (Base Model)": "", @@ -362,4 +362,4 @@ "You": "", "You're a helpful assistant.": "", "You're now logged in.": "" -} +} \ No newline at end of file From c73e8916ed9f33170d24ecd35f9b46c921a93bbb Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 6 Apr 2024 23:52:02 -0700 Subject: [PATCH 27/29] chore: formatting --- src/lib/i18n/locales/en-US/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/i18n/locales/en-US/translation.json b/src/lib/i18n/locales/en-US/translation.json index f1e301b87..2a5b3a30c 100644 --- a/src/lib/i18n/locales/en-US/translation.json +++ b/src/lib/i18n/locales/en-US/translation.json @@ -362,4 +362,4 @@ "You": "", "You're a helpful assistant.": "", "You're now logged in.": "" -} \ No newline at end of file +} From efa6aa4b4caeff3be3a0989945e7d74c8b5fcf32 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 6 Apr 2024 23:53:01 -0700 Subject: [PATCH 28/29] Update languages.json --- src/lib/i18n/locales/languages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/i18n/locales/languages.json b/src/lib/i18n/locales/languages.json index 691b68d28..567900722 100644 --- a/src/lib/i18n/locales/languages.json +++ b/src/lib/i18n/locales/languages.json @@ -71,4 +71,4 @@ "code": "zh-TW", "title": "Chinese (Traditional)" } -] +] \ No newline at end of file From 117e07b0d4a5fe7fe3b685f8b0184153bf0e65bd Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 6 Apr 2024 23:57:55 -0700 Subject: [PATCH 29/29] Update languages.json --- src/lib/i18n/locales/languages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/i18n/locales/languages.json b/src/lib/i18n/locales/languages.json index 567900722..691b68d28 100644 --- a/src/lib/i18n/locales/languages.json +++ b/src/lib/i18n/locales/languages.json @@ -71,4 +71,4 @@ "code": "zh-TW", "title": "Chinese (Traditional)" } -] \ No newline at end of file +]