Skip to content
37 linesCodeBlameRaw
1import { redirect } from "react-router";
2
3import type { Route } from "./+types/index";
4import { ChatUnavailable, NoChannels } from "../../../components/chat/empty";
5import { channelPath } from "../../../lib/chat";
6import { LAST_CHAT_COOKIE, sidebarOrNull } from "../../../lib/chat.server";
7import { readCookie } from "../../../lib/mission";
8import { page } from "../../../lib/meta";
9import { requireUser } from "../../../lib/session.server";
10
11export function meta({ params, ...args }: Route.MetaArgs) {
12 return page(args, { title: `Chat · ${params.owner} · g1t` });
13}
14
15/**
16 * Chat opens where it was left: the last conversation open in this
17 * workspace, else #general, else the first there is.
18 */
19export async function loader({ params, context, request }: Route.LoaderArgs) {
20 const viewer = requireUser(context, request);
21 const slug = params.owner.toLowerCase();
22 const last = readCookie(request.headers.get("cookie"), LAST_CHAT_COOKIE);
23 if (last && last.startsWith(`/${slug}/-/chat/`) && !last.includes("..")) throw redirect(last);
24 const sidebar = await sidebarOrNull(slug, viewer);
25 if (!sidebar) return { unavailable: true };
26 const entries = sidebar.entries;
27 const first =
28 entries.find((entry) => entry.channel.kind === "channel" && entry.channel.name === "general") ??
29 entries.find((entry) => entry.channel.kind === "channel") ??
30 entries[0];
31 if (first) throw redirect(channelPath(slug, first.channel));
32 return { unavailable: false };
33}
34
35export default function ChatIndex({ loaderData }: Route.ComponentProps) {
36 return loaderData.unavailable ? <ChatUnavailable /> : <NoChannels />;
37}