mirror of
https://github.com/SrIzan10/hctv.git
synced 2026-06-06 00:56:56 +00:00
feat: add dropdown and default personal channel to settings
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
'use client'
|
||||
|
||||
import { UniversalForm } from "@/components/app/UniversalForm/UniversalForm";
|
||||
import { createChannel } from "@/lib/form/actions";
|
||||
import { Hash } from "lucide-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
function CreateChannelPage() {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<div className="flex h-full w-full flex-col items-center justify-center px-4 py-12">
|
||||
@@ -26,6 +31,13 @@ function CreateChannelPage() {
|
||||
]}
|
||||
schemaName="createChannel"
|
||||
action={createChannel}
|
||||
onActionComplete={(r) => {
|
||||
// @ts-expect-error
|
||||
const channelName = r?.channel;
|
||||
if (channelName) {
|
||||
router.push(`/${channelName}`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
@@ -44,6 +44,9 @@ import { parseAsString, useQueryState } from 'nuqs';
|
||||
import { Write } from '@/components/ui/channel-desc-fancy-area/write';
|
||||
import { Preview } from '@/components/ui/channel-desc-fancy-area/preview';
|
||||
import { UploadButton } from '@/lib/uploadthing';
|
||||
import { useOwnedChannels } from '@/lib/hooks/useUserList';
|
||||
import { ChannelSelect } from '@/components/app/ChannelSelect/ChannelSelect';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
interface ChannelSettingsClientProps {
|
||||
channel: Channel & {
|
||||
@@ -73,6 +76,8 @@ export default function ChannelSettingsClient({
|
||||
const [selTab, setSelTab] = useQueryState('tabs', parseAsString.withDefault('general'));
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
const [uploadError, setUploadError] = useState<string | null>(null);
|
||||
const channelList = useOwnedChannels();
|
||||
const router = useRouter();
|
||||
|
||||
const copyStreamKey = async () => {
|
||||
if (streamKey) {
|
||||
@@ -105,7 +110,7 @@ export default function ChannelSettingsClient({
|
||||
|
||||
return (
|
||||
<div className="container max-w-4xl mx-auto py-6 px-4">
|
||||
<div className="mb-6">
|
||||
<div className="mb-6 flex">
|
||||
<div className="flex items-center gap-4 mb-4">
|
||||
<Avatar className="h-16 w-16">
|
||||
<AvatarImage src={channel.pfpUrl} alt={channel.name} />
|
||||
@@ -122,6 +127,20 @@ export default function ChannelSettingsClient({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex-1' />
|
||||
<div>
|
||||
<ChannelSelect
|
||||
channelList={channelList.channels.map(c => c.channel)}
|
||||
value={channel.name}
|
||||
onSelect={(value) => {
|
||||
if (value === 'create') {
|
||||
router.push('/create');
|
||||
} else {
|
||||
router.push(`/settings/channel/${value}`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Tabs className="w-full" value={selTab} onValueChange={setSelTab}>
|
||||
|
||||
12
apps/web/src/app/(protected)/settings/channel/page.tsx
Normal file
12
apps/web/src/app/(protected)/settings/channel/page.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { resolvePersonalChannel } from "@/lib/auth/resolve";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default async function ChannelSettingsRedirector() {
|
||||
const personalChannel = await resolvePersonalChannel();
|
||||
if (personalChannel) {
|
||||
return redirect(`/settings/channel/${personalChannel.name}`);
|
||||
}
|
||||
|
||||
// lil easter egg which i doubt anyone will see
|
||||
return <p>erm</p>;
|
||||
}
|
||||
46
apps/web/src/components/app/ChannelSelect/ChannelSelect.tsx
Normal file
46
apps/web/src/components/app/ChannelSelect/ChannelSelect.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
'use client'
|
||||
|
||||
import type { Channel } from "@hctv/db";
|
||||
import * as React from 'react';
|
||||
import { Plus } from 'lucide-react';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
|
||||
|
||||
export function ChannelSelect(props: Props) {
|
||||
const { channelList } = props;
|
||||
return (
|
||||
<Select onValueChange={props.onSelect} value={props.value}>
|
||||
<SelectTrigger className="w-[180px]">
|
||||
<SelectValue placeholder="Channel" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{channelList.map((channel) => (
|
||||
<SelectItem key={channel.id} value={channel.name}>
|
||||
<div className="flex items-center gap-3">
|
||||
<Avatar className="h-8 w-8">
|
||||
<AvatarImage src={channel.pfpUrl} alt={channel.name} />
|
||||
<AvatarFallback>{channel.name[0]}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="font-medium">{channel.name}</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectItem key="create" value="create" icon={<Plus className="h-4 w-4" />} className='h-11'>
|
||||
Create Channel
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
|
||||
interface Props {
|
||||
channelList: Channel[];
|
||||
value?: string;
|
||||
onSelect: (value: string) => void;
|
||||
}
|
||||
@@ -63,7 +63,7 @@ export default function EditLivestreamDialog(props: Props) {
|
||||
setSelectedChannel('');
|
||||
// using window location href as a really janky way to just close the dialog
|
||||
// TODO: use a proper dialog close method
|
||||
window.location.href = '/settings/channel/create';
|
||||
window.location.href = '/create';
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedChannel]);
|
||||
|
||||
@@ -155,7 +155,7 @@ export async function createChannel(prev: any, formData: FormData) {
|
||||
|
||||
await initializeStreamInfo(createdChannel.id);
|
||||
|
||||
return { success: true };
|
||||
return { success: true, channel: createdChannel.name };
|
||||
}
|
||||
|
||||
export async function updateChannelSettings(prev: any, formData: FormData) {
|
||||
|
||||
Reference in New Issue
Block a user