From a8b3b117dc5e8336263449beba17dc557cceaf41 Mon Sep 17 00:00:00 2001 From: Erik Michelson Date: Sat, 7 Oct 2023 13:45:24 +0200 Subject: [PATCH] feature: add identicon generation to users without photo Signed-off-by: Erik Michelson --- ...ebear-converter-npm-7.0.1-cb9d17808e.patch | 17 ++++ ...nverter-npm-7.0.1-cb9d17808e.patch.license | 2 +- frontend/package.json | 2 + frontend/src/api/users/types.ts | 4 +- .../__snapshots__/user-avatar.spec.tsx.snap | 44 ++++++++++ .../common/user-avatar/default-avatar.png | Bin 14031 -> 0 bytes .../user-avatar/hooks/use-avatar-url.ts | 28 ++++++ .../user-avatar/user-avatar-for-user.tsx | 4 +- .../common/user-avatar/user-avatar.spec.tsx | 20 ++++- .../common/user-avatar/user-avatar.tsx | 8 +- .../login-page/utils/fetch-and-set-user.ts | 4 +- frontend/src/pages/api/private/me/index.ts | 4 +- frontend/src/pages/api/private/users/erik.ts | 4 +- frontend/src/pages/api/private/users/molly.ts | 4 +- .../src/pages/api/private/users/tilman.ts | 4 +- package.json | 3 +- yarn.lock | 81 +++++++++++++++++- 17 files changed, 210 insertions(+), 23 deletions(-) create mode 100644 .yarn/patches/@dicebear-converter-npm-7.0.1-cb9d17808e.patch rename frontend/src/components/common/user-avatar/default-avatar.png.license => .yarn/patches/@dicebear-converter-npm-7.0.1-cb9d17808e.patch.license (65%) delete mode 100644 frontend/src/components/common/user-avatar/default-avatar.png create mode 100644 frontend/src/components/common/user-avatar/hooks/use-avatar-url.ts diff --git a/.yarn/patches/@dicebear-converter-npm-7.0.1-cb9d17808e.patch b/.yarn/patches/@dicebear-converter-npm-7.0.1-cb9d17808e.patch new file mode 100644 index 000000000..1bfd0c31a --- /dev/null +++ b/.yarn/patches/@dicebear-converter-npm-7.0.1-cb9d17808e.patch @@ -0,0 +1,17 @@ +diff --git a/package.json b/package.json +index 4619da270df88b972b4f9ea95aeffc32aa52e341..944cadb5e2ab4e1be596e76255ee4f9ae7572b18 100644 +--- a/package.json ++++ b/package.json +@@ -16,10 +16,10 @@ + "license": "MIT", + "author": "Florian Körner ", + "type": "module", +- "main": "./lib/node/index.js", ++ "main": "./lib/index.js", + "browser": "./lib/index.js", + "exports": { +- "node": "./lib/node/index.js", ++ "node": "./lib/index.js", + "default": "./lib/index.js" + }, + "types": "./lib/index.d.ts", diff --git a/frontend/src/components/common/user-avatar/default-avatar.png.license b/.yarn/patches/@dicebear-converter-npm-7.0.1-cb9d17808e.patch.license similarity index 65% rename from frontend/src/components/common/user-avatar/default-avatar.png.license rename to .yarn/patches/@dicebear-converter-npm-7.0.1-cb9d17808e.patch.license index c223474fb..2053aa609 100644 --- a/frontend/src/components/common/user-avatar/default-avatar.png.license +++ b/.yarn/patches/@dicebear-converter-npm-7.0.1-cb9d17808e.patch.license @@ -1,3 +1,3 @@ SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) -SPDX-License-Identifier: CC0-1.0 +SPDX-License-Identifier: AGPL-3.0-only diff --git a/frontend/package.json b/frontend/package.json index 433976ed7..16cf4eee8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -46,6 +46,8 @@ "@codemirror/state": "6.2.1", "@codemirror/theme-one-dark": "6.1.2", "@codemirror/view": "6.20.2", + "@dicebear/core": "7.0.1", + "@dicebear/identicon": "7.0.1", "@fontsource/source-sans-pro": "5.0.8", "@hedgedoc/commons": "workspace:commons", "@hedgedoc/html-to-react": "workspace:html-to-react", diff --git a/frontend/src/api/users/types.ts b/frontend/src/api/users/types.ts index 96e6f0d92..f4ad524e6 100644 --- a/frontend/src/api/users/types.ts +++ b/frontend/src/api/users/types.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ @@ -7,5 +7,5 @@ export interface UserInfo { username: string displayName: string - photo: string + photoUrl: string } diff --git a/frontend/src/components/common/user-avatar/__snapshots__/user-avatar.spec.tsx.snap b/frontend/src/components/common/user-avatar/__snapshots__/user-avatar.spec.tsx.snap index 7be911f06..ecddb7e72 100644 --- a/frontend/src/components/common/user-avatar/__snapshots__/user-avatar.spec.tsx.snap +++ b/frontend/src/components/common/user-avatar/__snapshots__/user-avatar.spec.tsx.snap @@ -104,3 +104,47 @@ exports[`UserAvatar renders the user avatar in size sm 1`] = ` `; + +exports[`UserAvatar uses identicon when empty photoUrl is given 1`] = ` +
+ + common.avatarOf + + test + + +
+`; + +exports[`UserAvatar uses identicon when no photoUrl is given 1`] = ` +
+ + common.avatarOf + + test + + +
+`; diff --git a/frontend/src/components/common/user-avatar/default-avatar.png b/frontend/src/components/common/user-avatar/default-avatar.png deleted file mode 100644 index 1f5de57409c7facb1c620797384a0ea71596da61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14031 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 { + return useMemo(() => { + if (photoUrl && photoUrl.trim() !== '') { + return photoUrl + } + const avatar = createAvatar(identicon, { + seed: displayName + }) + return avatar.toDataUriSync() + }, [photoUrl, displayName]) +} diff --git a/frontend/src/components/common/user-avatar/user-avatar-for-user.tsx b/frontend/src/components/common/user-avatar/user-avatar-for-user.tsx index 9af787f71..c576d76b9 100644 --- a/frontend/src/components/common/user-avatar/user-avatar-for-user.tsx +++ b/frontend/src/components/common/user-avatar/user-avatar-for-user.tsx @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ @@ -19,5 +19,5 @@ export interface UserAvatarForUserProps extends Omit = ({ user, ...props }) => { - return + return } diff --git a/frontend/src/components/common/user-avatar/user-avatar.spec.tsx b/frontend/src/components/common/user-avatar/user-avatar.spec.tsx index 3f59e1910..91cc659af 100644 --- a/frontend/src/components/common/user-avatar/user-avatar.spec.tsx +++ b/frontend/src/components/common/user-avatar/user-avatar.spec.tsx @@ -7,12 +7,20 @@ import type { UserInfo } from '../../../api/users/types' import { mockI18n } from '../../../test-utils/mock-i18n' import { UserAvatarForUser } from './user-avatar-for-user' import { render } from '@testing-library/react' +import { UserAvatar } from './user-avatar' + +jest.mock('@dicebear/identicon', () => null) +jest.mock('@dicebear/core', () => ({ + createAvatar: jest.fn(() => ({ + toDataUriSync: jest.fn(() => 'data:image/x-other,identicon-mock') + })) +})) describe('UserAvatar', () => { const user: UserInfo = { username: 'boatface', displayName: 'Boaty McBoatFace', - photo: 'https://example.com/test.png' + photoUrl: 'https://example.com/test.png' } beforeEach(async () => { @@ -41,4 +49,14 @@ describe('UserAvatar', () => { const view = render() expect(view.container).toMatchSnapshot() }) + + it('uses identicon when no photoUrl is given', () => { + const view = render() + expect(view.container).toMatchSnapshot() + }) + + it('uses identicon when empty photoUrl is given', () => { + const view = render() + expect(view.container).toMatchSnapshot() + }) }) diff --git a/frontend/src/components/common/user-avatar/user-avatar.tsx b/frontend/src/components/common/user-avatar/user-avatar.tsx index 106e11a2e..51ea44a12 100644 --- a/frontend/src/components/common/user-avatar/user-avatar.tsx +++ b/frontend/src/components/common/user-avatar/user-avatar.tsx @@ -1,15 +1,15 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ import { useTranslatedText } from '../../../hooks/common/use-translated-text' import { ShowIf } from '../show-if/show-if' -import defaultAvatar from './default-avatar.png' import styles from './user-avatar.module.scss' import React, { useCallback, useMemo } from 'react' import { OverlayTrigger, Tooltip } from 'react-bootstrap' import type { OverlayInjectedProps } from 'react-bootstrap/Overlay' +import { useAvatarUrl } from './hooks/use-avatar-url' export interface UserAvatarProps { size?: 'sm' | 'lg' @@ -45,9 +45,7 @@ export const UserAvatar: React.FC = ({ } }, [size]) - const avatarUrl = useMemo(() => { - return photoUrl || defaultAvatar.src - }, [photoUrl]) + const avatarUrl = useAvatarUrl(photoUrl, displayName) const imageTranslateOptions = useMemo( () => ({ diff --git a/frontend/src/components/login-page/utils/fetch-and-set-user.ts b/frontend/src/components/login-page/utils/fetch-and-set-user.ts index 6734bb3ee..6008b366e 100644 --- a/frontend/src/components/login-page/utils/fetch-and-set-user.ts +++ b/frontend/src/components/login-page/utils/fetch-and-set-user.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ @@ -15,7 +15,7 @@ export const fetchAndSetUser: () => Promise = async () => { setUser({ username: me.username, displayName: me.displayName, - photo: me.photo, + photoUrl: me.photoUrl, authProvider: me.authProvider, email: me.email }) diff --git a/frontend/src/pages/api/private/me/index.ts b/frontend/src/pages/api/private/me/index.ts index 130ae8641..4432f3014 100644 --- a/frontend/src/pages/api/private/me/index.ts +++ b/frontend/src/pages/api/private/me/index.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ @@ -15,7 +15,7 @@ const handler = (req: NextApiRequest, res: NextApiResponse): void => { } respondToMatchingRequest(HttpMethod.GET, req, res, { username: 'mock', - photo: '/public/img/avatar.png', + photoUrl: '/public/img/avatar.png', displayName: 'Mock User', authProvider: 'local', email: 'mock@hedgedoc.test' diff --git a/frontend/src/pages/api/private/users/erik.ts b/frontend/src/pages/api/private/users/erik.ts index f42614d44..bd3855b88 100644 --- a/frontend/src/pages/api/private/users/erik.ts +++ b/frontend/src/pages/api/private/users/erik.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ @@ -11,7 +11,7 @@ const handler = (req: NextApiRequest, res: NextApiResponse): void => { respondToMatchingRequest(HttpMethod.GET, req, res, { username: 'erik', displayName: 'Erik', - photo: '/public/img/avatar.png' + photoUrl: '/public/img/avatar.png' }) } diff --git a/frontend/src/pages/api/private/users/molly.ts b/frontend/src/pages/api/private/users/molly.ts index 36741d757..ee8d58087 100644 --- a/frontend/src/pages/api/private/users/molly.ts +++ b/frontend/src/pages/api/private/users/molly.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ @@ -11,7 +11,7 @@ const handler = (req: NextApiRequest, res: NextApiResponse): void => { respondToMatchingRequest(HttpMethod.GET, req, res, { username: 'molly', displayName: 'Molly', - photo: '/public/img/avatar.png' + photoUrl: '/public/img/avatar.png' }) } diff --git a/frontend/src/pages/api/private/users/tilman.ts b/frontend/src/pages/api/private/users/tilman.ts index 528617ad0..039860086 100644 --- a/frontend/src/pages/api/private/users/tilman.ts +++ b/frontend/src/pages/api/private/users/tilman.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ @@ -11,7 +11,7 @@ const handler = (req: NextApiRequest, res: NextApiResponse): void => { respondToMatchingRequest(HttpMethod.GET, req, res, { username: 'tilman', displayName: 'Tilman', - photo: '/public/img/avatar.png' + photoUrl: '/public/img/avatar.png' }) } diff --git a/package.json b/package.json index d3b7c0cc7..d2758fd4e 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,8 @@ "eventemitter2@6.4.9": "patch:eventemitter2@npm%3A6.4.9#./.yarn/patches/eventemitter2-npm-6.4.9-ba37798a18.patch", "yjs@13.6.8": "patch:yjs@npm%3A13.6.8#./.yarn/patches/yjs-remove-import-warning-in-test.patch", "vega-canvas@^1.2.6": "patch:vega-canvas@npm%3A1.2.7#./.yarn/patches/remove-vega-canvas-node.patch", - "vega-canvas@^1.2.7": "patch:vega-canvas@npm%3A1.2.7#./.yarn/patches/remove-vega-canvas-node.patch" + "vega-canvas@^1.2.7": "patch:vega-canvas@npm%3A1.2.7#./.yarn/patches/remove-vega-canvas-node.patch", + "@dicebear/converter@7.0.1": "patch:@dicebear/converter@npm%3A7.0.1#./.yarn/patches/@dicebear-converter-npm-7.0.1-cb9d17808e.patch" }, "devDependencies": { "dotenv-cli": "7.3.0", diff --git a/yarn.lock b/yarn.lock index 77b8df62e..68900e063 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2112,6 +2112,67 @@ __metadata: languageName: node linkType: hard +"@dicebear/converter@npm:7.0.1": + version: 7.0.1 + resolution: "@dicebear/converter@npm:7.0.1" + dependencies: + "@types/json-schema": ^7.0.11 + tmp-promise: ^3.0.3 + peerDependencies: + "@resvg/resvg-js": ^2.4.1 + exiftool-vendored: ^22.0.0 + sharp: ^0.32.1 + peerDependenciesMeta: + "@resvg/resvg-js": + optional: true + exiftool-vendored: + optional: true + sharp: + optional: true + checksum: ba7b631c5ce4bd14740035465e622c4a9daf6f67ddcbff635ca8f7486a9063fe9cca47f2a4db2df53913a063a1b52df2d8015c72ac8d8a57b4e69818411845ef + languageName: node + linkType: hard + +"@dicebear/converter@patch:@dicebear/converter@npm%3A7.0.1#./.yarn/patches/@dicebear-converter-npm-7.0.1-cb9d17808e.patch::locator=hedgedoc%40workspace%3A.": + version: 7.0.1 + resolution: "@dicebear/converter@patch:@dicebear/converter@npm%3A7.0.1#./.yarn/patches/@dicebear-converter-npm-7.0.1-cb9d17808e.patch::version=7.0.1&hash=659bc7&locator=hedgedoc%40workspace%3A." + dependencies: + "@types/json-schema": ^7.0.11 + tmp-promise: ^3.0.3 + peerDependencies: + "@resvg/resvg-js": ^2.4.1 + exiftool-vendored: ^22.0.0 + sharp: ^0.32.1 + peerDependenciesMeta: + "@resvg/resvg-js": + optional: true + exiftool-vendored: + optional: true + sharp: + optional: true + checksum: f20da5a44bed334c788568dc12fd49887de93171f71a23ba37397cdc00e693ad2bead5bed158fb06bea78ffe67c3e5c7cb611982c42da37457f319090dfbcf12 + languageName: node + linkType: hard + +"@dicebear/core@npm:7.0.1": + version: 7.0.1 + resolution: "@dicebear/core@npm:7.0.1" + dependencies: + "@dicebear/converter": 7.0.1 + "@types/json-schema": ^7.0.11 + checksum: 9ba71a4946ae0d4fdda9074e7f4db8c545cfb4cb13c0106517943c3de5c76618bc60eb61e01d909961c8f66f5c46b9dc03491a9f7e2075b7e9f3581980ffbac9 + languageName: node + linkType: hard + +"@dicebear/identicon@npm:7.0.1": + version: 7.0.1 + resolution: "@dicebear/identicon@npm:7.0.1" + peerDependencies: + "@dicebear/core": ^7.0.0 + checksum: 93eb3f19b2112bcf32d6f7768fa569c080100628f90b8ecb8e633a82cdf1e943fa6ab93dc627d3631c83cb81adb643c8637d1c0f924cc7629e7d070fac6ca16d + languageName: node + linkType: hard + "@emotion/cache@npm:^10.0.27": version: 10.0.29 resolution: "@emotion/cache@npm:10.0.29" @@ -2412,6 +2473,8 @@ __metadata: "@codemirror/state": 6.2.1 "@codemirror/theme-one-dark": 6.1.2 "@codemirror/view": 6.20.2 + "@dicebear/core": 7.0.1 + "@dicebear/identicon": 7.0.1 "@fontsource/source-sans-pro": 5.0.8 "@hedgedoc/commons": "workspace:commons" "@hedgedoc/html-to-react": "workspace:html-to-react" @@ -4648,6 +4711,13 @@ __metadata: languageName: node linkType: hard +"@types/json-schema@npm:^7.0.11": + version: 7.0.13 + resolution: "@types/json-schema@npm:7.0.13" + checksum: 345df21a678fa72fb389f35f33de77833d09d4a142bb2bcb27c18690efa4cf70fc2876e43843cefb3fbdb9fcb12cd3e970a90936df30f53bbee899865ff605ab + languageName: node + linkType: hard + "@types/json5@npm:^0.0.29": version: 0.0.29 resolution: "@types/json5@npm:0.0.29" @@ -17183,6 +17253,15 @@ __metadata: languageName: node linkType: hard +"tmp-promise@npm:^3.0.3": + version: 3.0.3 + resolution: "tmp-promise@npm:3.0.3" + dependencies: + tmp: ^0.2.0 + checksum: f854f5307dcee6455927ec3da9398f139897faf715c5c6dcee6d9471ae85136983ea06662eba2edf2533bdcb0fca66d16648e79e14381e30c7fb20be9c1aa62c + languageName: node + linkType: hard + "tmp@npm:^0.0.33": version: 0.0.33 resolution: "tmp@npm:0.0.33" @@ -17192,7 +17271,7 @@ __metadata: languageName: node linkType: hard -"tmp@npm:~0.2.1": +"tmp@npm:^0.2.0, tmp@npm:~0.2.1": version: 0.2.1 resolution: "tmp@npm:0.2.1" dependencies: