Skip to content

Commit dbcf707

Browse files
committed
finish all of slack integration!
1 parent e3d5f62 commit dbcf707

8 files changed

Lines changed: 794 additions & 44 deletions

File tree

src/App.jsx

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,36 @@ import {
99
clearTokens,
1010
hasValidSpreadsheet,
1111
hasValidSession,
12-
getSavedSession
12+
getSavedSession,
13+
setTokenRefreshCallback
1314
} from './utils/googleAuth';
15+
import { setupGlobalErrorHandlers } from './utils/errorReporter';
16+
import { slackUserCache } from './utils/slackUserCache';
17+
import { Alert, Button } from './components/ui';
1418

1519
export default function App() {
1620
const [user, setUser] = useState(null);
1721
const [loading, setLoading] = useState(true);
1822
const [needsSpreadsheetSelection, setNeedsSpreadsheetSelection] = useState(false);
23+
const [tokenExpired, setTokenExpired] = useState(false);
24+
const [ignoreTokenExpiry, setIgnoreTokenExpiry] = useState(false);
1925

2026
useEffect(() => {
27+
// Setup global error handlers
28+
setupGlobalErrorHandlers();
29+
2130
const initializeApp = async () => {
2231
// Initialize Google Auth
2332
await new Promise(resolve => {
2433
initializeGoogleAuth(() => resolve());
2534
});
2635

36+
// Set token refresh callback
37+
setTokenRefreshCallback((error) => {
38+
console.error('Token refresh failed:', error);
39+
setTokenExpired(true);
40+
});
41+
2742
// Check if we have a valid saved session
2843
if (hasValidSession()) {
2944
try {
@@ -35,6 +50,11 @@ export default function App() {
3550
if (!hasValidSpreadsheet()) {
3651
setNeedsSpreadsheetSelection(true);
3752
}
53+
54+
// Load Slack users in background
55+
slackUserCache.loadUsers().catch(err => {
56+
console.error('Failed to load Slack users:', err);
57+
});
3858
}
3959
} catch (err) {
4060
console.error('Failed to restore session:', err);
@@ -51,11 +71,18 @@ export default function App() {
5171

5272
const handleSignIn = (userData) => {
5373
setUser(userData);
74+
setTokenExpired(false);
75+
setIgnoreTokenExpiry(false);
5476

5577
// Check if spreadsheet is already selected
5678
if (!hasValidSpreadsheet()) {
5779
setNeedsSpreadsheetSelection(true);
5880
}
81+
82+
// Load Slack users in background
83+
slackUserCache.loadUsers().catch(err => {
84+
console.error('Failed to load Slack users:', err);
85+
});
5986
};
6087

6188
const handleSpreadsheetSelected = () => {
@@ -69,8 +96,20 @@ export default function App() {
6996

7097
const handleSignOut = () => {
7198
clearTokens();
99+
slackUserCache.clearCache();
72100
setUser(null);
73101
setNeedsSpreadsheetSelection(false);
102+
setTokenExpired(false);
103+
setIgnoreTokenExpiry(false);
104+
};
105+
106+
const handleRelogin = () => {
107+
handleSignOut();
108+
};
109+
110+
const handleIgnoreExpiry = () => {
111+
setIgnoreTokenExpiry(true);
112+
setTokenExpired(false);
74113
};
75114

76115
if (loading) {
@@ -79,6 +118,41 @@ export default function App() {
79118

80119
return (
81120
<AlertProvider>
121+
{/* Token Expiry Warning */}
122+
{tokenExpired && !ignoreTokenExpiry && user && (
123+
<div className="fixed top-0 left-0 right-0 z-[100] p-4 bg-red-600">
124+
<div className="max-w-4xl mx-auto">
125+
<Alert type="error" className="mb-0">
126+
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3">
127+
<div className="flex-1">
128+
<p className="font-semibold text-white mb-1">Authentication Expired</p>
129+
<p className="text-sm text-red-100">
130+
Your session has expired. Please sign in again to continue making changes.
131+
You can still view data, but operations may fail.
132+
</p>
133+
</div>
134+
<div className="flex gap-2 flex-shrink-0">
135+
<Button
136+
variant="secondary"
137+
size="sm"
138+
onClick={handleIgnoreExpiry}
139+
>
140+
Ignore (risky)
141+
</Button>
142+
<Button
143+
variant="primary"
144+
size="sm"
145+
onClick={handleRelogin}
146+
>
147+
Sign In Again
148+
</Button>
149+
</div>
150+
</div>
151+
</Alert>
152+
</div>
153+
</div>
154+
)}
155+
82156
{!user ? (
83157
<LoginPage onSignIn={handleSignIn} />
84158
) : needsSpreadsheetSelection ? (

src/components/modals/SlackThreadSection.jsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useState } from 'react';
22
import { MessageSquare, ChevronDown, ChevronUp, ExternalLink } from 'lucide-react';
33
import { Button, Spinner, Alert } from '../ui';
44
import { useSlack } from '../../hooks/useSlack';
5+
import { renderSlackText } from '../../utils/slackApi';
56
import { animations } from '../../styles/design-tokens';
67

78
export default function SlackThreadSection({ purchase, onCreateThread, creatingThread }) {
@@ -183,9 +184,9 @@ export default function SlackThreadSection({ purchase, onCreateThread, creatingT
183184
{formatTimestamp(reply.ts)}
184185
</p>
185186
</div>
186-
<p className="text-sm text-gray-700 whitespace-pre-wrap break-words">
187-
{reply.text}
188-
</p>
187+
<div className="text-sm text-gray-700 whitespace-pre-wrap break-words">
188+
{renderSlackText(reply.text)}
189+
</div>
189190
</div>
190191
</div>
191192
</div>

0 commit comments

Comments
 (0)