Skip to content

Commit

Permalink
Bluesky for user & team pages (#1891)
Browse files Browse the repository at this point in the history
* Migrations

* Bluesky for team page

* Unify interfaces

* For user page

* To org social links
  • Loading branch information
Sendouc authored Sep 28, 2024
1 parent 803b93e commit 59d7764
Show file tree
Hide file tree
Showing 20 changed files with 198 additions and 60 deletions.
16 changes: 16 additions & 0 deletions app/components/icons/Bsky.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export function BskyIcon({ className }: { className?: string }) {
return (
<svg
className={className}
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 568 501"
>
<title>Bluesky butterfly logo</title>
<path
fill="currentColor"
d="M123.121 33.664C188.241 82.553 258.281 181.68 284 234.873c25.719-53.192 95.759-152.32 160.879-201.21C491.866-1.611 568-28.906 568 57.947c0 17.346-9.945 145.713-15.778 166.555-20.275 72.453-94.155 90.933-159.875 79.748C507.222 323.8 536.444 388.56 473.333 453.32c-119.86 122.992-172.272-30.859-185.702-70.281-2.462-7.227-3.614-10.608-3.631-7.733-.017-2.875-1.169.506-3.631 7.733-13.43 39.422-65.842 193.273-185.702 70.281-63.111-64.76-33.89-129.52 80.986-149.071-65.72 11.185-139.6-7.295-159.875-79.748C9.945 203.659 0 75.291 0 57.946 0-28.906 76.135-1.612 123.121 33.664Z"
/>
</svg>
);
}
1 change: 1 addition & 0 deletions app/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const USER = {
CUSTOM_URL_MAX_LENGTH: 32,
CUSTOM_NAME_MAX_LENGTH: 32,
BATTLEFY_MAX_LENGTH: 32,
BSKY_MAX_LENGTH: 50,
IN_GAME_NAME_TEXT_MAX_LENGTH: 20,
IN_GAME_NAME_DISCRIMINATOR_MAX_LENGTH: 5,
WEAPON_POOL_MAX_SIZE: 5,
Expand Down
32 changes: 10 additions & 22 deletions app/db/tables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ export type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
? ColumnType<S, I | undefined, U>
: ColumnType<T, T | undefined, T>;

export interface AllTeam {
export type MemberRole = (typeof TEAM_MEMBER_ROLES)[number];

export interface Team {
avatarImgId: number | null;
bannerImgId: number | null;
bio: string | null;
Expand All @@ -32,11 +34,10 @@ export interface AllTeam {
inviteCode: string;
name: string;
twitter: string | null;
bsky: string | null;
}

export type MemberRole = (typeof TEAM_MEMBER_ROLES)[number];

export interface AllTeamMember {
export interface TeamMember {
createdAt: Generated<number>;
isOwner: Generated<number>;
leftAt: number | null;
Expand All @@ -46,20 +47,6 @@ export interface AllTeamMember {
isMainTeam: number;
}

export interface Team {
avatarImgId: number | null;
bannerImgId: number | null;
bio: string | null;
createdAt: number | null;
css: ColumnType<Record<string, string> | null, string | null, string | null>;
customUrl: string;
deletedAt: number | null;
id: GeneratedAlways<number>;
inviteCode: string;
name: string;
twitter: string | null;
}

export interface Art {
authorId: number;
createdAt: Generated<number>;
Expand Down Expand Up @@ -759,6 +746,7 @@ export interface User {
stickSens: number | null;
twitch: string | null;
twitter: string | null;
bsky: string | null;
battlefy: string | null;
vc: Generated<"YES" | "NO" | "LISTEN_ONLY">;
youtubeId: string | null;
Expand Down Expand Up @@ -848,8 +836,8 @@ export type Tables = { [P in keyof DB]: Selectable<DB[P]> };
export type TablesInsertable = { [P in keyof DB]: Insertable<DB[P]> };

export interface DB {
AllTeam: AllTeam;
AllTeamMember: AllTeamMember;
AllTeam: Team;
AllTeamMember: TeamMember;
Art: Art;
ArtTag: ArtTag;
ArtUserMetadata: ArtUserMetadata;
Expand Down Expand Up @@ -887,8 +875,8 @@ export interface DB {
SplatoonPlayer: SplatoonPlayer;
TaggedArt: TaggedArt;
Team: Team;
TeamMember: AllTeamMember;
TeamMemberWithSecondary: AllTeamMember;
TeamMember: TeamMember;
TeamMemberWithSecondary: TeamMember;
Tournament: Tournament;
TournamentStaff: TournamentStaff;
TournamentBadgeOwner: TournamentBadgeOwner;
Expand Down
28 changes: 28 additions & 0 deletions app/features/team/TeamRepository.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export function findByCustomUrl(customUrl: string) {
"Team.id",
"Team.name",
"Team.twitter",
"Team.bsky",
"Team.bio",
"Team.customUrl",
"Team.css",
Expand Down Expand Up @@ -140,6 +141,33 @@ export async function create(
});
}

export async function update({
id,
name,
customUrl,
bio,
twitter,
bsky,
css,
}: Pick<
Insertable<Tables["Team"]>,
"id" | "name" | "customUrl" | "bio" | "twitter" | "bsky"
> & { css: string | null }) {
return db
.updateTable("AllTeam")
.set({
name,
customUrl,
bio,
twitter,
bsky,
css,
})
.where("id", "=", id)
.returningAll()
.executeTakeFirstOrThrow();
}

export function switchMainTeam({
userId,
teamId,
Expand Down
32 changes: 0 additions & 32 deletions app/features/team/queries/edit.server.ts

This file was deleted.

24 changes: 22 additions & 2 deletions app/features/team/routes/t.$customUrl.edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import {
} from "~/utils/urls";
import * as TeamRepository from "../TeamRepository.server";
import { deleteTeam } from "../queries/deleteTeam.server";
import { edit } from "../queries/edit.server";
import { TEAM } from "../team-constants";
import { editTeamSchema, teamParamsSchema } from "../team-schemas.server";
import { canAddCustomizedColors, isTeamOwner } from "../team-utils";
Expand Down Expand Up @@ -106,7 +105,7 @@ export const action: ActionFunction = async ({ request, params }) => {
};
}

const editedTeam = edit({
const editedTeam = await TeamRepository.update({
id: team.id,
customUrl: newCustomUrl,
...data,
Expand Down Expand Up @@ -158,6 +157,7 @@ export default function EditTeamPage() {
) : null}
<NameInput />
<TwitterInput />
<BlueskyInput />
<BioTextarea />
<SubmitButton
className="mt-4"
Expand Down Expand Up @@ -249,6 +249,26 @@ function TwitterInput() {
);
}

function BlueskyInput() {
const { t } = useTranslation(["team"]);
const { team } = useLoaderData<typeof loader>();
const [value, setValue] = React.useState(team.bsky ?? "");

return (
<div>
<Label htmlFor="bsky">{t("team:forms.fields.teamBsky")}</Label>
<Input
leftAddon="https://bsky.app/profile/"
id="bsky"
name="bsky"
maxLength={TEAM.BSKY_MAX_LENGTH}
value={value}
onChange={(e) => setValue(e.target.value)}
/>
</div>
);
}

function BioTextarea() {
const { t } = useTranslation(["team"]);
const { team } = useLoaderData<typeof loader>();
Expand Down
22 changes: 21 additions & 1 deletion app/features/team/routes/t.$customUrl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { FormWithConfirm } from "~/components/FormWithConfirm";
import { WeaponImage } from "~/components/Image";
import { Main } from "~/components/Main";
import { SubmitButton } from "~/components/SubmitButton";
import { BskyIcon } from "~/components/icons/Bsky";
import { EditIcon } from "~/components/icons/Edit";
import { StarIcon } from "~/components/icons/Star";
import { TwitterIcon } from "~/components/icons/Twitter";
Expand All @@ -21,6 +22,7 @@ import type { SendouRouteHandle } from "~/utils/remix";
import { makeTitle } from "~/utils/strings";
import {
TEAM_SEARCH_PAGE,
bskyUrl,
editTeamPage,
manageTeamRosterPage,
navIconUrl,
Expand Down Expand Up @@ -126,7 +128,7 @@ function TeamBanner() {
})}
</div>
<div className="team__banner__name">
{team.name} <TwitterLink testId="twitter-link" />
{team.name} <TwitterLink testId="twitter-link" /> <BskyLink />
</div>
</div>
{team.avatarSrc ? <div className="team__banner__avatar__spacer" /> : null}
Expand All @@ -151,6 +153,7 @@ function MobileTeamNameCountry() {
<div className="team__mobile-team-name">
{team.name}
<TwitterLink />
<BskyLink />
</div>
</div>
);
Expand All @@ -174,6 +177,23 @@ function TwitterLink({ testId }: { testId?: string }) {
);
}

function BskyLink() {
const { team } = useLoaderData<typeof loader>();

if (!team.bsky) return null;

return (
<a
className="team__bsky-link"
href={bskyUrl(team.bsky)}
target="_blank"
rel="noreferrer"
>
<BskyIcon />
</a>
);
}

function ActionButtons() {
const { t } = useTranslation(["team"]);
const user = useUser();
Expand Down
1 change: 1 addition & 0 deletions app/features/team/team-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export const TEAM = {
NAME_MIN_LENGTH: 2,
BIO_MAX_LENGTH: 2000,
TWITTER_MAX_LENGTH: 50,
BSKY_MAX_LENGTH: 50,
MAX_MEMBER_COUNT: 10,
MAX_TEAM_COUNT_NON_PATRON: 2,
MAX_TEAM_COUNT_PATRON: 5,
Expand Down
4 changes: 4 additions & 0 deletions app/features/team/team-schemas.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ export const editTeamSchema = z.union([
falsyToNull,
z.string().max(TEAM.TWITTER_MAX_LENGTH).nullable(),
),
bsky: z.preprocess(
falsyToNull,
z.string().max(TEAM.BSKY_MAX_LENGTH).nullable(),
),
css: z.preprocess(falsyToNull, z.string().refine(jsonParseable).nullable()),
}),
]);
Expand Down
20 changes: 20 additions & 0 deletions app/features/team/team.css
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,26 @@
fill: #1da1f2;
}

.team__bsky-link {
padding: var(--s-1);
border: 1px solid;
border-radius: 50%;
border-color: #1285fe;
background-color: #1285fe2f;
height: 24.4px;
width: 24.4px;
display: grid;
place-items: center;
}

.team__bsky-link > svg {
width: 0.9rem;
}

.team__bsky-link path {
fill: #1285fe;
}

.team__banner__avatar {
grid-area: avatar;
align-self: flex-end;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import clsx from "clsx";
import { BskyIcon } from "~/components/icons/Bsky";
import { LinkIcon } from "~/components/icons/Link";
import { TwitchIcon } from "~/components/icons/Twitch";
import { TwitterIcon } from "~/components/icons/Twitter";
Expand All @@ -24,6 +25,7 @@ function SocialLink({ url }: { url: string }) {
youtube: type === "youtube",
twitter: type === "twitter",
twitch: type === "twitch",
bsky: type === "bsky",
})}
>
<SocialLinkIcon url={url} />
Expand All @@ -48,6 +50,10 @@ function SocialLinkIcon({ url }: { url: string }) {
return <YouTubeIcon />;
}

if (type === "bsky") {
return <BskyIcon />;
}

return <LinkIcon />;
}

Expand All @@ -64,5 +70,9 @@ const urlToLinkType = (url: string) => {
return "youtube";
}

if (url.includes("bsky.app")) {
return "bsky";
}

return null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,7 @@
.org__social-link__icon-container.twitter svg {
fill: #1da1f2;
}

.org__social-link__icon-container.bsky path {
fill: #1285fe;
}
3 changes: 3 additions & 0 deletions app/features/user-page/UserRepository.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export async function findProfileByIdentifier(
"User.twitter",
"User.youtubeId",
"User.battlefy",
"User.bsky",
"User.country",
"User.bio",
"User.motionSens",
Expand Down Expand Up @@ -586,6 +587,7 @@ type UpdateProfileArgs = Pick<
| "stickSens"
| "inGameName"
| "battlefy"
| "bsky"
| "css"
| "favoriteBadgeId"
| "showDiscordUniqueName"
Expand Down Expand Up @@ -628,6 +630,7 @@ export function updateProfile(args: UpdateProfileArgs) {
inGameName: args.inGameName,
css: args.css,
battlefy: args.battlefy,
bsky: args.bsky,
favoriteBadgeId: args.favoriteBadgeId,
showDiscordUniqueName: args.showDiscordUniqueName,
commissionText: args.commissionText,
Expand Down
Loading

0 comments on commit 59d7764

Please sign in to comment.