Skip to content

Commit 8ead1f1

Browse files
authored
browser-chat: make it work on mobile (#108)
* add responsiveness to the UI so that it works on mobile * various minor fixes and improvements to the UI
1 parent 318bccd commit 8ead1f1

File tree

16 files changed

+683
-284
lines changed

16 files changed

+683
-284
lines changed

browser-chat/frontend/package-lock.json

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

browser-chat/frontend/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"@radix-ui/react-popover": "^1.1.6",
1919
"@radix-ui/react-scroll-area": "^1.2.3",
2020
"@radix-ui/react-slot": "^1.1.2",
21+
"@radix-ui/react-toggle": "^1.1.2",
2122
"@types/react-timeago": "^4.1.7",
2223
"autoprefixer": "^10.4.20",
2324
"chat-browser": "file:../browser-wasm/pkg",
@@ -30,6 +31,7 @@
3031
"react-timeago": "^7.2.0",
3132
"tailwind-merge": "^2.5.5",
3233
"tailwindcss-animate": "^1.0.7",
34+
"vaul": "^1.1.2",
3335
"yet-another-name-generator": "^1.2.0"
3436
},
3537
"devDependencies": {

browser-chat/frontend/src/app.tsx

Lines changed: 14 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@ import { useState, useEffect } from "react"
44
import HomeScreen from "./components/homescreen"
55
import ChatView from "./components/chatview"
66
import Header from "./components/header"
7-
import LogView from "./components/logview"
87
import Sidebar from "./components/sidebar"
98
import { ThemeProvider } from "next-themes"
10-
import { InvitePopup } from "./components/invitepopup"
119
import { API, initApi, type ChannelInfo } from "./lib/api"
12-
import { generate as generateName } from 'yet-another-name-generator'
1310
import { log } from "./lib/log"
11+
import { useIsDesktop } from "./hooks/use-media-query"
1412

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

4745
function SplashScreen({ children }: React.PropsWithChildren) {
48-
const [showLogView, setShowLogView] = useState(false)
4946
return (
5047
<div className="flex flex-col flex-grow">
51-
<Header
52-
onLogsClick={() => setShowLogView(!showLogView)}
53-
/>
54-
{showLogView && <LogView onClose={() => setShowLogView(false)} />}
48+
<Header />
5549
<div className="flex items-center justify-center">
5650
{children}
5751
</div>
@@ -68,28 +62,27 @@ function App({ api }: AppProps) {
6862
const [currentView, setCurrentView] = useState<"home" | "chat">("home")
6963
const [channels, setChannels] = useState<ChannelInfo[]>([])
7064
const [activeChannel, setActiveChannel] = useState<string | null>(null)
71-
const [showLogView, setShowLogView] = useState(false)
72-
const [nickname, setNickname] = useState(generateName())
73-
const [showInvitePopup, setShowInvitePopup] = useState(false)
7465
const [showSidebar, setShowSidebar] = useState(false)
7566

76-
const joinChannel = async (ticket: string) => {
67+
const joinChannel = (ticket: string, nickname: string) => {
7768
try {
78-
const channel = await api.joinChannel(ticket, nickname)
69+
const channel = api.joinChannel(ticket, nickname)
7970
setChannels((prevChannels) => [...prevChannels, channel])
80-
setActiveChannel(channel.id)
8171
setCurrentView("chat")
72+
setActiveChannel(channel.id)
73+
setShowSidebar(true)
8274
} catch (error) {
8375
log.error("Failed to join channel", error)
8476
}
8577
}
8678

87-
const createChannel = async () => {
79+
const createChannel = (nickname: string) => {
8880
try {
89-
const channel = await api.createChannel(nickname)
81+
const channel = api.createChannel(nickname)
9082
setChannels((prevChannels) => [...prevChannels, channel])
9183
setActiveChannel(channel.id)
9284
setCurrentView("chat")
85+
setShowSidebar(true)
9386
} catch (error) {
9487
log.error("Failed to create channel", error)
9588
}
@@ -115,14 +108,16 @@ function App({ api }: AppProps) {
115108
setShowSidebar(true)
116109
}
117110

111+
const isDesktop = useIsDesktop()
112+
118113
let title
119114
if (activeChannel) {
120115
title = '#' + channels.find((c) => c.id === activeChannel)?.name
121116
}
122117

123118
return (
124119
<>
125-
{(currentView === "chat" || showSidebar) && (
120+
{isDesktop && (showSidebar) && (
126121
<Sidebar
127122
channels={channels}
128123
activeChannel={activeChannel}
@@ -135,39 +130,17 @@ function App({ api }: AppProps) {
135130
)}
136131
<div className="flex flex-col flex-grow">
137132
<Header
138-
onLogsClick={() => setShowLogView(!showLogView)}
139133
title={title}
140-
onInviteClick={activeChannel ? (() => setShowInvitePopup(true)) : undefined}
141134
/>
142135
{currentView === "home" && (
143136
<HomeScreen
144-
name={nickname}
145-
onSetName={setNickname}
146-
onJoin={(ticket) => {
147-
joinChannel(ticket)
148-
setShowSidebar(false)
149-
}}
150-
onCreate={() => {
151-
createChannel()
152-
setShowSidebar(false)
153-
}}
137+
onJoin={joinChannel}
138+
onCreate={createChannel}
154139
/>
155140
)}
156141
{currentView === "chat" && activeChannel && (
157142
<ChatView api={api} channel={activeChannel} onClose={() => closeChannel(activeChannel)} />
158143
)}
159-
{showLogView && <LogView onClose={() => setShowLogView(false)} />}
160-
{showInvitePopup && activeChannel && (
161-
<InvitePopup
162-
open={showInvitePopup}
163-
onOpenChange={(x) => {
164-
console.log("openchange", x)
165-
setShowInvitePopup(x)
166-
}}
167-
channel={channels.find((c) => c.id === activeChannel)?.name || ""}
168-
getTicket={(opts) => api.getTicket(activeChannel!, opts)}
169-
/>
170-
)}
171144
</div>
172145
</>
173146
)

browser-chat/frontend/src/components/change-nickname-button.tsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ import { FormEvent, useEffect, useState } from "react"
33
import { Button } from "@/components/ui/button"
44
import { Input } from "@/components/ui/input"
55
import {
6-
Dialog,
7-
DialogContent,
8-
DialogHeader,
9-
DialogTitle,
10-
DialogTrigger,
11-
} from "@/components/ui/dialog"
6+
AdaptiveDialog,
7+
AdaptiveDialogContent,
8+
AdaptiveDialogHeader,
9+
AdaptiveDialogTitle,
10+
AdaptiveDialogTrigger,
11+
} from "@/components/ui/adaptive-dialog"
1212
import { API } from "@/lib/api"
1313

1414
interface ChangeNicknameProps {
@@ -33,19 +33,19 @@ export function ChangeNicknameButton({ api, channel }: ChangeNicknameProps) {
3333
}
3434
}
3535
return (
36-
<Dialog open={open} onOpenChange={setOpen}>
37-
<DialogTrigger asChild>
36+
<AdaptiveDialog open={open} onOpenChange={setOpen}>
37+
<AdaptiveDialogTrigger>
3838
<Button variant="secondary" size="sm">Change nickname</Button>
39-
</DialogTrigger>
40-
<DialogContent className="sm:max-w-[425px]">
41-
<DialogHeader>
42-
<DialogTitle>Change nickname</DialogTitle>
43-
</DialogHeader>
39+
</AdaptiveDialogTrigger>
40+
<AdaptiveDialogContent className="sm:max-w-[425px]">
41+
<AdaptiveDialogHeader>
42+
<AdaptiveDialogTitle>Change nickname</AdaptiveDialogTitle>
43+
</AdaptiveDialogHeader>
4444
<form onSubmit={handleSubmit} className="flex space-x-2">
4545
<Input value={name} onChange={(e) => setName(e.target.value)} placeholder="Enter your nickname" />
4646
<Button size="sm" type="submit">Save</Button>
4747
</form>
48-
</DialogContent>
49-
</Dialog>
48+
</AdaptiveDialogContent>
49+
</AdaptiveDialog>
5050
)
5151
}

0 commit comments

Comments
 (0)