Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Bluesky to Profile Social Links #4052

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
9 changes: 9 additions & 0 deletions packages/shared/src/components/icons/Bluesky/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { ReactElement } from 'react';
import React from 'react';
import type { IconProps } from '../../Icon';
import Icon from '../../Icon';
import MonoIcon from './mono.svg';

export const BlueskyIcon = (props: IconProps): ReactElement => (
<Icon {...props} IconPrimary={MonoIcon} IconSecondary={MonoIcon} />
);
12 changes: 12 additions & 0 deletions packages/shared/src/components/icons/Bluesky/mono.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/shared/src/components/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from './Arrow';
export * from './At';
export * from './Bell';
export * from './Block';
export * from './Bluesky';
export * from './Bookmark';
export * from './BringForward';
export * from './Calendar';
Expand Down
12 changes: 12 additions & 0 deletions packages/shared/src/components/profile/ProfileWidgets.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const defaultLoggedUser: LoggedUser = {
youtube: 'idoshamun',
linkedin: 'idoshamun',
mastodon: 'https://mastodon.social/@idoshamun',
bluesky: 'https://bsky.app/profile/dailydotdev.bsky.social',
};

const defaultProfile: PublicProfile = {
Expand All @@ -69,6 +70,7 @@ const defaultProfile: PublicProfile = {
youtube: 'dailydotdev',
linkedin: 'dailydotdev',
mastodon: 'https://mastodon.social/@dailydotdev',
bluesky: 'https://bsky.app/profile/dailydotdev.bsky.social',
};

const defaultMemberships: Connection<SourceMember> = {
Expand Down Expand Up @@ -289,6 +291,16 @@ it('should show mastodon link', () => {
expect(el).toHaveTextContent('mastodon.social/@dailydotdev');
});

it('should show bluesky link', () => {
renderComponent();
const el = screen.getByTestId('bluesky');
expect(el).toHaveAttribute(
'href',
'https://bsky.app/profile/dailydotdev.bsky.social',
);
expect(el).toHaveTextContent('bsky.app/profile/dailydotdev.bsky.social');
});

it('should show portfolio link', async () => {
renderComponent();
const el = screen.getByTestId('portfolio');
Expand Down
8 changes: 8 additions & 0 deletions packages/shared/src/components/profile/SocialChips.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
RedditIcon,
RoadmapIcon,
MastodonIcon,
BlueskyIcon,
ThreadsIcon,
CodePenIcon,
} from '../icons';
Expand All @@ -32,6 +33,7 @@ export interface SocialChipsProps {
youtube?: string;
linkedin?: string;
mastodon?: string;
bluesky?: string;
};
}

Expand Down Expand Up @@ -89,6 +91,11 @@ const handlers: Record<
href: (x) => x,
label: (x) => withoutProtocol(x),
},
bluesky: {
icon: <BlueskyIcon />,
href: (x) => x,
Copy link
Contributor

@AmarTrebinjac AmarTrebinjac Jan 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to prepend the bluesky profile path https://bsky.app/profile/

label: (x) => withoutProtocol(x),
},
threads: {
icon: <ThreadsIcon />,
href: (x) => `https://threads.net/@${x}`,
Expand All @@ -111,6 +118,7 @@ const order: (keyof SocialChipsProps['links'])[] = [
'roadmap',
'codepen',
'mastodon',
'bluesky',
'threads',
];

Expand Down
2 changes: 2 additions & 0 deletions packages/shared/src/graphql/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const USER_BY_ID_STATIC_FIELDS_QUERY = `
youtube
linkedin
mastodon
bluesky
timezone
portfolio
reputation
Expand Down Expand Up @@ -304,6 +305,7 @@ export const UPDATE_USER_PROFILE_MUTATION = gql`
youtube
linkedin
mastodon
bluesky
createdAt
infoConfirmed
timezone
Expand Down
3 changes: 3 additions & 0 deletions packages/shared/src/hooks/useProfileForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface ProfileFormHint {
youtube?: string;
linkedin?: string;
mastodon?: string;
bluesky?: string;
}

export interface UpdateProfileParameters extends Partial<UserProfile> {
Expand Down Expand Up @@ -64,6 +65,7 @@ type Handles = Pick<
| 'youtube'
| 'linkedin'
| 'mastodon'
| 'bluesky'
>;
const socials: Array<keyof Handles> = [
'github',
Expand All @@ -77,6 +79,7 @@ const socials: Array<keyof Handles> = [
'youtube',
'linkedin',
'mastodon',
'bluesky',
];

export const onValidateHandles = (
Expand Down
2 changes: 2 additions & 0 deletions packages/shared/src/lib/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export interface PublicProfile {
youtube?: string;
linkedin?: string;
mastodon?: string;
bluesky?: string;
bio?: string;
createdAt: string;
premium: boolean;
Expand Down Expand Up @@ -81,6 +82,7 @@ export interface UserProfile {
youtube?: string;
linkedin?: string;
mastodon?: string;
bluesky?: string;
portfolio?: string;
bio?: string;
acceptedMarketing?: boolean;
Expand Down
4 changes: 4 additions & 0 deletions packages/webapp/__tests__/AccountProfilePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const defaultLoggedUser: LoggedUser = {
youtube: 'dailydotdev',
linkedin: 'dailydotdev',
mastodon: 'https://mastodon.social/@dailydotdev',
bluesky: 'https://bsky.app/profile/dailydotdev.bsky.social',
};
const updateUser = jest.fn();

Expand Down Expand Up @@ -122,4 +123,7 @@ it('should show profile social links', () => {
const mastodon = screen.getByPlaceholderText('Mastodon');
expect(mastodon).toBeInTheDocument();
expect(mastodon).toHaveValue(defaultLoggedUser.mastodon);
const bluesky = screen.getByPlaceholderText('Bluesky');
expect(bluesky).toBeInTheDocument();
expect(bluesky).toHaveValue(defaultLoggedUser.bluesky);
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
LinkedInIcon,
LinkIcon,
MastodonIcon,
BlueskyIcon,
RedditIcon,
RoadmapIcon,
StackOverflowIcon,
Expand Down Expand Up @@ -88,6 +89,7 @@ const ProfileIndex = ({
youtube: values.youtube,
linkedin: values.linkedin,
mastodon: values.mastodon ? withHttps(values.mastodon) : null,
bluesky: values.bluesky ? withHttps(values.bluesky) : null,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably not call withHttps here, as it will always add a protocol due to bluesky usernames having domain structures.

experienceLevel: values.experienceLevel,
onUpdateSuccess: () =>
router.push(`/${values.username}`).then(() => {
Expand Down Expand Up @@ -285,7 +287,6 @@ const ProfileIndex = ({
hint={hint.portfolio}
valid={!hint.portfolio}
name="portfolio"
type="url"
value={user?.portfolio}
placeholder="example.com"
/>
Expand Down Expand Up @@ -356,10 +357,19 @@ const ProfileIndex = ({
hint={hint.mastodon}
valid={!hint.mastodon}
name="mastodon"
type="url"
value={user?.mastodon}
placeholder="mastodon.social/@username"
/>
<AccountTextField
leftIcon={<BlueskyIcon />}
label="Bluesky"
inputId="bluesky"
hint={hint.bluesky}
valid={!hint.bluesky}
name="bluesky"
value={user?.bluesky}
placeholder="bsky.app/profile/username"
/>
<AccountTextField
leftIcon={<ThreadsIcon />}
label="Threads"
Expand Down