Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions browser-chat/frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions browser-chat/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-scroll-area": "^1.2.3",
"@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-toggle": "^1.1.2",
"@types/react-timeago": "^4.1.7",
"autoprefixer": "^10.4.20",
"chat-browser": "file:../browser-wasm/pkg",
Expand All @@ -30,6 +31,7 @@
"react-timeago": "^7.2.0",
"tailwind-merge": "^2.5.5",
"tailwindcss-animate": "^1.0.7",
"vaul": "^1.1.2",
"yet-another-name-generator": "^1.2.0"
},
"devDependencies": {
Expand Down
55 changes: 14 additions & 41 deletions browser-chat/frontend/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ import { useState, useEffect } from "react"
import HomeScreen from "./components/homescreen"
import ChatView from "./components/chatview"
import Header from "./components/header"
import LogView from "./components/logview"
import Sidebar from "./components/sidebar"
import { ThemeProvider } from "next-themes"
import { InvitePopup } from "./components/invitepopup"
import { API, initApi, type ChannelInfo } from "./lib/api"
import { generate as generateName } from 'yet-another-name-generator'
import { log } from "./lib/log"
import { useIsDesktop } from "./hooks/use-media-query"

export default function AppWrapper() {
const [api, setApi] = useState<API | null>(null)
Expand Down Expand Up @@ -45,13 +43,9 @@ function Spinner() {
}

function SplashScreen({ children }: React.PropsWithChildren) {
const [showLogView, setShowLogView] = useState(false)
return (
<div className="flex flex-col flex-grow">
<Header
onLogsClick={() => setShowLogView(!showLogView)}
/>
{showLogView && <LogView onClose={() => setShowLogView(false)} />}
<Header />
<div className="flex items-center justify-center">
{children}
</div>
Expand All @@ -68,28 +62,27 @@ function App({ api }: AppProps) {
const [currentView, setCurrentView] = useState<"home" | "chat">("home")
const [channels, setChannels] = useState<ChannelInfo[]>([])
const [activeChannel, setActiveChannel] = useState<string | null>(null)
const [showLogView, setShowLogView] = useState(false)
const [nickname, setNickname] = useState(generateName())
const [showInvitePopup, setShowInvitePopup] = useState(false)
const [showSidebar, setShowSidebar] = useState(false)

const joinChannel = async (ticket: string) => {
const joinChannel = (ticket: string, nickname: string) => {
try {
const channel = await api.joinChannel(ticket, nickname)
const channel = api.joinChannel(ticket, nickname)
setChannels((prevChannels) => [...prevChannels, channel])
setActiveChannel(channel.id)
setCurrentView("chat")
setActiveChannel(channel.id)
setShowSidebar(true)
} catch (error) {
log.error("Failed to join channel", error)
}
}

const createChannel = async () => {
const createChannel = (nickname: string) => {
try {
const channel = await api.createChannel(nickname)
const channel = api.createChannel(nickname)
setChannels((prevChannels) => [...prevChannels, channel])
setActiveChannel(channel.id)
setCurrentView("chat")
setShowSidebar(true)
} catch (error) {
log.error("Failed to create channel", error)
}
Expand All @@ -115,14 +108,16 @@ function App({ api }: AppProps) {
setShowSidebar(true)
}

const isDesktop = useIsDesktop()

let title
if (activeChannel) {
title = '#' + channels.find((c) => c.id === activeChannel)?.name
}

return (
<>
{(currentView === "chat" || showSidebar) && (
{isDesktop && (showSidebar) && (
<Sidebar
channels={channels}
activeChannel={activeChannel}
Expand All @@ -135,39 +130,17 @@ function App({ api }: AppProps) {
)}
<div className="flex flex-col flex-grow">
<Header
onLogsClick={() => setShowLogView(!showLogView)}
title={title}
onInviteClick={activeChannel ? (() => setShowInvitePopup(true)) : undefined}
/>
{currentView === "home" && (
<HomeScreen
name={nickname}
onSetName={setNickname}
onJoin={(ticket) => {
joinChannel(ticket)
setShowSidebar(false)
}}
onCreate={() => {
createChannel()
setShowSidebar(false)
}}
onJoin={joinChannel}
onCreate={createChannel}
/>
)}
{currentView === "chat" && activeChannel && (
<ChatView api={api} channel={activeChannel} onClose={() => closeChannel(activeChannel)} />
)}
{showLogView && <LogView onClose={() => setShowLogView(false)} />}
{showInvitePopup && activeChannel && (
<InvitePopup
open={showInvitePopup}
onOpenChange={(x) => {
console.log("openchange", x)
setShowInvitePopup(x)
}}
channel={channels.find((c) => c.id === activeChannel)?.name || ""}
getTicket={(opts) => api.getTicket(activeChannel!, opts)}
/>
)}
</div>
</>
)
Expand Down
30 changes: 15 additions & 15 deletions browser-chat/frontend/src/components/change-nickname-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { FormEvent, useEffect, useState } from "react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
AdaptiveDialog,
AdaptiveDialogContent,
AdaptiveDialogHeader,
AdaptiveDialogTitle,
AdaptiveDialogTrigger,
} from "@/components/ui/adaptive-dialog"
import { API } from "@/lib/api"

interface ChangeNicknameProps {
Expand All @@ -33,19 +33,19 @@ export function ChangeNicknameButton({ api, channel }: ChangeNicknameProps) {
}
}
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<AdaptiveDialog open={open} onOpenChange={setOpen}>
<AdaptiveDialogTrigger>
<Button variant="secondary" size="sm">Change nickname</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Change nickname</DialogTitle>
</DialogHeader>
</AdaptiveDialogTrigger>
<AdaptiveDialogContent className="sm:max-w-[425px]">
<AdaptiveDialogHeader>
<AdaptiveDialogTitle>Change nickname</AdaptiveDialogTitle>
</AdaptiveDialogHeader>
<form onSubmit={handleSubmit} className="flex space-x-2">
<Input value={name} onChange={(e) => setName(e.target.value)} placeholder="Enter your nickname" />
<Button size="sm" type="submit">Save</Button>
</form>
</DialogContent>
</Dialog>
</AdaptiveDialogContent>
</AdaptiveDialog>
)
}
Loading