Private
Public Access
Add a user guide, reachable in-app from Help in the account menu
USER_GUIDE.md at the repo root is the single source of truth -- frontend/public/USER_GUIDE.md symlinks to it so the same file is both readable directly in the repo and served by the app, rendered on a new /help page reusing the existing markdown renderer. Scoped to regular member features (messaging, rooms, attachments, notifications, profile); room admin/site admin features are intentionally left out. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+159
@@ -0,0 +1,159 @@
|
||||
# DS Chat — User Guide
|
||||
|
||||
A quick reference for everyday use: sending messages, organizing rooms,
|
||||
attachments, notifications, and personalizing your account.
|
||||
|
||||
## Contents
|
||||
|
||||
- [Getting started](#getting-started)
|
||||
- [Rooms](#rooms)
|
||||
- [Sending messages](#sending-messages)
|
||||
- [Formatting](#formatting)
|
||||
- [Mentions and room links](#mentions-and-room-links)
|
||||
- [Attachments](#attachments)
|
||||
- [Reactions](#reactions)
|
||||
- [Editing a message](#editing-a-message)
|
||||
- [Presence and notifications](#presence-and-notifications)
|
||||
- [Your profile](#your-profile)
|
||||
- [Room details](#room-details)
|
||||
- [Staying up to date](#staying-up-to-date)
|
||||
|
||||
## Getting started
|
||||
|
||||
DS Chat is invite-only — there's no public sign-up page. You'll either be
|
||||
given an account directly, or you'll receive an email invite with a
|
||||
link. Opening that link lets you pick a username and password; once
|
||||
you submit it, you're signed in automatically.
|
||||
|
||||
If you forget your password, use **Forgot password?** on the login
|
||||
screen. You'll get an email with a reset link that's valid for 15
|
||||
minutes.
|
||||
|
||||
## Rooms
|
||||
|
||||
Rooms are where conversations happen — similar to channels in other chat
|
||||
apps. The sidebar on the left lists every room you belong to, with a
|
||||
search box at the top to filter by name.
|
||||
|
||||
- **Create a room**: click the **+** button above the room list. Give it a
|
||||
name and, optionally, a description. You become that room's owner.
|
||||
- **Browse rooms**: click **Browse rooms** to see every *open* room on the
|
||||
site and join any of them directly.
|
||||
- **Private rooms**: a room marked private (shown with a lock icon) isn't
|
||||
listed in Browse rooms — you can only get in by being added by an
|
||||
owner or admin of that room.
|
||||
- **Unread indicators**: a room with new activity shows a dot next to its
|
||||
name — a plain dot for unread messages, a highlighted dot if you were
|
||||
specifically @mentioned.
|
||||
|
||||
## Sending messages
|
||||
|
||||
Type in the message box at the bottom of a room and press **Enter** to
|
||||
send. Use **Shift+Enter** to add a line break without sending.
|
||||
|
||||
## Formatting
|
||||
|
||||
Messages support Markdown:
|
||||
|
||||
- `**bold**`, `*italic*`, `~~strikethrough~~`
|
||||
- `` `inline code` `` and fenced code blocks (three backticks)
|
||||
- `> blockquotes`
|
||||
- `-` or `1.` for bulleted/numbered lists
|
||||
- `[link text](https://example.com)` — or just paste a bare URL and it
|
||||
becomes clickable automatically
|
||||
- `#`, `##`, `###` for headings
|
||||
|
||||
Pasting a link on its own often also generates a preview card underneath
|
||||
your message, pulled from that page's title/description/image, when the
|
||||
page provides one.
|
||||
|
||||
Emoji: click the 🙂 button in the composer to open the emoji picker, or
|
||||
type a shortcode like `:tada:` and it's converted automatically once you
|
||||
send. The picker remembers your recently-used emoji and has a search box.
|
||||
|
||||
## Mentions and room links
|
||||
|
||||
Type `@` followed by a few letters of someone's username to open an
|
||||
autocomplete of that room's members — pick one (or press Enter/Tab) to
|
||||
insert a mention. Mentioning someone highlights the message for them and
|
||||
marks the room specially in their sidebar, even if they're not currently
|
||||
looking at it.
|
||||
|
||||
Type `#` followed by a few letters of a room name to do the same for
|
||||
rooms you belong to — it inserts a clickable link that takes anyone who
|
||||
can see the message (and is a member of that room) straight to it.
|
||||
|
||||
## Attachments
|
||||
|
||||
Click the paperclip icon to attach a file, or just drag a file onto the
|
||||
message box and drop it. Images show as an inline thumbnail — click one
|
||||
to view it full-size. Other files show as a small card with the
|
||||
filename and size; `.txt`, `.md`, and `.pdf` files open in a preview
|
||||
without leaving the room, everything else downloads when clicked.
|
||||
|
||||
There's a server-configured maximum file size — if a file is too large,
|
||||
you'll see an error before it uploads.
|
||||
|
||||
## Reactions
|
||||
|
||||
Hover over a message and click the 🙂 icon in its action row to react
|
||||
with an emoji. Reactions from everyone appear as small pills under the
|
||||
message with a count; click an existing pill to add or remove your own
|
||||
reaction to it. Hovering a pill shows who reacted.
|
||||
|
||||
## Editing a message
|
||||
|
||||
You can edit any message you sent: hover it and click **Edit**, make your
|
||||
changes, then press **Enter** to save or **Escape** to cancel. Clicking
|
||||
away also saves. Edited messages are marked *(edited)*.
|
||||
|
||||
## Presence and notifications
|
||||
|
||||
Everyone's avatar shows a small status dot — green for online, grey for
|
||||
offline — based on whether they currently have the app open. If you'd
|
||||
rather not broadcast that you're active, open your account menu (click
|
||||
your avatar, top right) and choose **Appear offline**.
|
||||
|
||||
The same menu has a notifications toggle:
|
||||
|
||||
- In a regular browser, turning it on asks your browser for permission
|
||||
and subscribes you to push notifications for messages in rooms you're
|
||||
not actively looking at.
|
||||
- In DS Chat Desktop, the same toggle controls native desktop
|
||||
notifications instead — no browser permission prompt needed. You'll
|
||||
get a notification whenever the app is minimized *or* simply not the
|
||||
focused window, even if it's still open somewhere on screen.
|
||||
|
||||
## Your profile
|
||||
|
||||
Open your account menu and choose **Profile settings** to:
|
||||
|
||||
- Upload or remove a profile photo
|
||||
- Set a display name (shown instead of your username throughout the app)
|
||||
- Pick a theme — Dark, Light, Midnight, Sunset, or build your own custom
|
||||
color scheme (create one, then customize each color; changes preview
|
||||
live)
|
||||
- Change your password
|
||||
|
||||
## Room details
|
||||
|
||||
Click the info icon in a room's header to open its details panel, where
|
||||
you can:
|
||||
|
||||
- See who else is in the room and their role (member/admin/owner)
|
||||
- Browse and re-download every file and image ever shared in the room,
|
||||
without scrolling back through history
|
||||
- Leave the room — unless you're the owner, in which case ownership has
|
||||
to be transferred to someone else first
|
||||
|
||||
Room admins and owners see additional management options here that
|
||||
aren't covered in this guide.
|
||||
|
||||
## Staying up to date
|
||||
|
||||
If your connection drops, a banner lets you know you're offline and
|
||||
working from cached data — sending is disabled until you're back online.
|
||||
|
||||
When a new version of DS Chat has been deployed, a banner offers a
|
||||
**Reload** button to pick it up immediately, instead of waiting for your
|
||||
next natural page refresh.
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../USER_GUIDE.md
|
||||
@@ -11,6 +11,7 @@ import { ForgotPasswordPage } from './pages/ForgotPasswordPage'
|
||||
import { ResetPasswordPage } from './pages/ResetPasswordPage'
|
||||
import { ChatShellPage } from './pages/ChatShellPage'
|
||||
import { AdminPage } from './pages/AdminPage'
|
||||
import { HelpPage } from './pages/HelpPage'
|
||||
|
||||
function AppRoutes() {
|
||||
const routes = (
|
||||
@@ -43,6 +44,14 @@ function AppRoutes() {
|
||||
</AdminRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/help"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<HelpPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route path="*" element={<Navigate to="/rooms" replace />} />
|
||||
</Routes>
|
||||
)
|
||||
|
||||
@@ -122,6 +122,16 @@ export function TopBar() {
|
||||
>
|
||||
Profile settings
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
onClick={() => {
|
||||
setMenuOpen(false)
|
||||
navigate('/help')
|
||||
}}
|
||||
>
|
||||
Help
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
.help-page {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--ds-void);
|
||||
}
|
||||
|
||||
.help-body {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: var(--sp-6) var(--sp-8);
|
||||
max-width: 760px;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.help-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: var(--sp-6);
|
||||
}
|
||||
|
||||
.help-header h1 {
|
||||
font-size: 1.3rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.help-loading {
|
||||
color: var(--ds-muted);
|
||||
}
|
||||
|
||||
.help-content a[href^='#'] {
|
||||
word-break: normal;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import Markdown from 'markdown-to-jsx'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { MARKDOWN_OPTIONS } from '../components/MessageContent'
|
||||
import { TopBar } from '../components/TopBar'
|
||||
import './HelpPage.css'
|
||||
|
||||
// Single source of truth is the repo-root USER_GUIDE.md -- frontend/public/
|
||||
// symlinks to it, so this fetches the same file a developer sees when
|
||||
// browsing the repo, rather than duplicating its content into the bundle.
|
||||
const GUIDE_URL = '/USER_GUIDE.md'
|
||||
|
||||
export function HelpPage() {
|
||||
const [content, setContent] = useState<string | null>(null)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false
|
||||
fetch(GUIDE_URL)
|
||||
.then((res) => {
|
||||
if (!res.ok) throw new Error(`Failed to load guide (${res.status})`)
|
||||
return res.text()
|
||||
})
|
||||
.then((text) => {
|
||||
if (!cancelled) setContent(text)
|
||||
})
|
||||
.catch((err) => {
|
||||
if (!cancelled) setError(err instanceof Error ? err.message : 'Failed to load guide')
|
||||
})
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="help-page">
|
||||
<TopBar />
|
||||
<div className="help-body">
|
||||
<div className="help-header">
|
||||
<h1>Help</h1>
|
||||
<Link to="/rooms" className="btn-secondary">
|
||||
Back to chat
|
||||
</Link>
|
||||
</div>
|
||||
{error && <p className="admin-error">{error}</p>}
|
||||
{!error && content === null && <p className="help-loading">Loading…</p>}
|
||||
{!error && content !== null && (
|
||||
<div className="message-text help-content">
|
||||
<Markdown options={MARKDOWN_OPTIONS}>{content}</Markdown>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user