summaryrefslogtreecommitdiff
path: root/packages/tweetdeck/src/components/ChatColumn.tsx
blob: 0c336e5ca7c0e93fc6eef5618cb002fc42c593a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import { useCallback, useEffect, useState } from "react";
import type { DeckAccount, DeckColumn, ChatState } from "../types/app";
import { twitterClient } from "../lib/client/twitterClient";
import { ChatCard } from "./ChatCard";

interface ChatColumnProps {
  column: DeckColumn & { kind: "chat" };
  account: DeckAccount;
  onRemove: () => void;
}

export function ChatColumn({ column, account, onRemove }: ChatColumnProps) {
  const [state, setState] = useState<ChatState>({ entries: [], isLoading: false });
  const [error, setError] = useState<string | undefined>();

  const refresh = useCallback(async () => {
    setState(prev => ({ ...prev, isLoading: true }));
    setError(undefined);
    try {
      const notifications = await twitterClient.notifications({ cookie: account.cookie });
      setState({ entries: notifications, isLoading: false });
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to refresh chat");
      setState(prev => ({ ...prev, isLoading: false }));
    }
  }, [account.cookie]);

  useEffect(() => {
    refresh();
  }, [refresh, account.id]);

  return (
    <article className="column">
      <header>
        <div>
          <p className="eyebrow">Signal</p>
          <h3>{column.title || "Chat"}</h3>
          <p className="muted tiny">Mentions, follows and notifications for {account.label}</p>
        </div>
        <div className="column-actions">
          <button className="ghost" onClick={refresh} aria-label="Refresh chat">
            ↻
          </button>
          <button className="ghost" onClick={onRemove} aria-label="Remove column">
            ×
          </button>
        </div>
      </header>
      {error && <p className="error">{error}</p>}
      {state.isLoading && !state.entries.length ? (
        <div className="column-loading">Loading…</div>
      ) : (
        <div className="chat-stack">
          {state.entries.map(entry => (
            <ChatCard key={entry.id} notification={entry} accent={account.accent} />
          ))}
          {!state.entries.length && <p className="muted">No recent notifications.</p>}
        </div>
      )}
    </article>
  );
}