Skip to content

Commit 5f851b2

Browse files
committed
feat: add continue processing and start from current position functionality
1 parent be52ff0 commit 5f851b2

File tree

4 files changed

+166
-17
lines changed

4 files changed

+166
-17
lines changed

src/app/contexts/ProcessingContext.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ export interface ProcessingContextValue {
1212
refreshTwitterStatus: () => Promise<boolean>
1313
startProcessing: () => Promise<void>
1414
stopProcessing: () => Promise<void>
15+
continueProcessing: () => Promise<void>
16+
startFromCurrentPosition: () => Promise<void>
1517
resetProcessing: () => void
1618
updateProcessingState: (updates: Partial<ProcessingState>, options?: { persist?: boolean }) => void
1719
}

src/app/providers/ProcessingProvider.tsx

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,74 @@ export function ProcessingProvider({ children }: { children: React.ReactNode })
161161
}, { persist: true })
162162
}, [updateProcessingState])
163163

164+
const continueProcessing = useCallback(async () => {
165+
const onTwitter = await refreshStatus()
166+
if (!onTwitter) {
167+
alert('Please navigate to Twitter/X first')
168+
return
169+
}
170+
171+
const tab = await getActiveTab()
172+
if (!tab?.id) {
173+
alert('Extension could not locate the active tab. Please try again.')
174+
return
175+
}
176+
177+
updateProcessingState({
178+
isProcessing: true,
179+
isCompleted: false
180+
}, { persist: true })
181+
182+
try {
183+
await sendMessageToTab(tab.id, {
184+
action: 'CONTINUE_PROCESSING',
185+
settings
186+
})
187+
} catch (error) {
188+
console.error('Error sending CONTINUE_PROCESSING message:', error)
189+
alert('Extension failed to continue. Please refresh the Twitter/X page and try again.')
190+
updateProcessingState({ isProcessing: false }, { persist: true })
191+
}
192+
}, [refreshStatus, settings, updateProcessingState])
193+
194+
const startFromCurrentPosition = useCallback(async () => {
195+
const onTwitter = await refreshStatus()
196+
if (!onTwitter) {
197+
alert('Please navigate to Twitter/X first')
198+
return
199+
}
200+
201+
try {
202+
await saveSettings()
203+
} catch (error) {
204+
console.error('Failed to persist settings before restarting:', error)
205+
}
206+
207+
const tab = await getActiveTab()
208+
if (!tab?.id) {
209+
alert('Extension could not locate the active tab. Please try again.')
210+
return
211+
}
212+
213+
updateProcessingState({
214+
isProcessing: true,
215+
isCompleted: false,
216+
processedCount: 0,
217+
bookmarkedCount: 0
218+
}, { persist: true })
219+
220+
try {
221+
await sendMessageToTab(tab.id, {
222+
action: 'RESTART_PROCESSING_FROM_CURRENT',
223+
settings
224+
})
225+
} catch (error) {
226+
console.error('Error sending RESTART_PROCESSING_FROM_CURRENT message:', error)
227+
alert('Extension failed to restart. Please refresh the Twitter/X page and try again.')
228+
updateProcessingState({ isProcessing: false }, { persist: true })
229+
}
230+
}, [refreshStatus, saveSettings, settings, updateProcessingState])
231+
164232
const resetProcessing = useCallback(() => {
165233
updateProcessingState({
166234
...INITIAL_PROCESSING_STATE
@@ -178,9 +246,11 @@ export function ProcessingProvider({ children }: { children: React.ReactNode })
178246
refreshTwitterStatus: refreshStatus,
179247
startProcessing,
180248
stopProcessing,
249+
continueProcessing,
250+
startFromCurrentPosition,
181251
resetProcessing,
182252
updateProcessingState
183-
}), [isProcessingLoaded, isTwitterPage, refreshStatus, resetProcessing, startProcessing, state, stopProcessing, updateProcessingState])
253+
}), [continueProcessing, isProcessingLoaded, isTwitterPage, refreshStatus, resetProcessing, startFromCurrentPosition, startProcessing, state, stopProcessing, updateProcessingState])
184254

185255
return (
186256
<ProcessingContext.Provider value={value}>

src/content.ts

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,65 @@ let isProcessing = false
44
let processedCount = 0
55
let bookmarkedCount = 0
66
let settings: Settings
7+
let processedTweets = new Set<string>()
8+
9+
interface StartProcessingOptions {
10+
resetCounters?: boolean
11+
scrollToTop?: boolean
12+
resetProcessedTweets?: boolean
13+
}
714

815
// Listen for messages from popup
916
chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
1017
if (message.action === 'START_PROCESSING') {
1118
settings = message.settings
12-
startProcessing()
19+
void startProcessing({ resetCounters: true, scrollToTop: true, resetProcessedTweets: true })
20+
} else if (message.action === 'CONTINUE_PROCESSING') {
21+
settings = message.settings ?? settings
22+
void startProcessing({ resetCounters: false, scrollToTop: false, resetProcessedTweets: false })
23+
} else if (message.action === 'RESTART_PROCESSING_FROM_CURRENT') {
24+
settings = message.settings ?? settings
25+
void startProcessing({ resetCounters: true, scrollToTop: false, resetProcessedTweets: false })
1326
} else if (message.action === 'STOP_PROCESSING') {
1427
isProcessing = false
1528
}
1629

1730
sendResponse({ success: true })
1831
})
1932

20-
async function startProcessing() {
33+
async function startProcessing(options: StartProcessingOptions = {}) {
34+
if (isProcessing) {
35+
return
36+
}
37+
38+
const {
39+
resetCounters = true,
40+
scrollToTop = true,
41+
resetProcessedTweets = resetCounters
42+
} = options
43+
44+
if (!settings) {
45+
console.warn('No settings supplied for processing run')
46+
return
47+
}
48+
49+
if (resetCounters) {
50+
processedCount = 0
51+
bookmarkedCount = 0
52+
}
53+
54+
if (resetProcessedTweets) {
55+
processedTweets = new Set<string>()
56+
}
57+
2158
isProcessing = true
22-
processedCount = 0
23-
bookmarkedCount = 0
24-
25-
// Scroll to top first
26-
window.scrollTo(0, 0)
27-
await sleep(1000)
28-
29-
const processedTweets = new Set<string>()
59+
60+
if (scrollToTop) {
61+
window.scrollTo(0, 0)
62+
await sleep(1000)
63+
} else {
64+
await sleep(300)
65+
}
3066

3167
while (isProcessing && bookmarkedCount < settings.bookmarksLimit) {
3268
// Find all tweet articles on the page

src/features/popup/Popup.tsx

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ export function Popup() {
2020
bookmarkedCount,
2121
startProcessing,
2222
stopProcessing,
23+
continueProcessing,
24+
startFromCurrentPosition,
2325
resetProcessing,
2426
isTwitterPage
2527
} = useProcessingContext()
@@ -40,6 +42,14 @@ export function Popup() {
4042
resetProcessing()
4143
}, [resetProcessing])
4244

45+
const handleContinue = useCallback(() => {
46+
void continueProcessing()
47+
}, [continueProcessing])
48+
49+
const handleStartFromHere = useCallback(() => {
50+
void startFromCurrentPosition()
51+
}, [startFromCurrentPosition])
52+
4353
const { progressPercentage, bookmarkRate } = useMemo(() => {
4454
const progress = settings.bookmarksLimit > 0
4555
? (bookmarkedCount / settings.bookmarksLimit) * 100
@@ -56,6 +66,10 @@ export function Popup() {
5666
}, [bookmarkedCount, processedCount, settings.bookmarksLimit])
5767

5868
const showProcessingState = isProcessing || isCompleted
69+
const hasBookmarksGoal = settings.bookmarksLimit > 0
70+
const hasReachedBookmarksGoal = hasBookmarksGoal && bookmarkedCount >= settings.bookmarksLimit
71+
const showContinueButton = isCompleted && !hasReachedBookmarksGoal
72+
const showStartFromHereButton = isCompleted && hasReachedBookmarksGoal
5973

6074
return (
6175
<div className="x-posts-finder-container">
@@ -71,13 +85,40 @@ export function Popup() {
7185
bookmarkRate={bookmarkRate}
7286
isCompleted={isCompleted}
7387
/>
88+
{isProcessing ? (
89+
<ActionButton
90+
onClick={handleStop}
91+
variant="stop"
92+
>
93+
Stop analysis
94+
</ActionButton>
95+
) : (
96+
<>
97+
{showContinueButton && (
98+
<ActionButton
99+
onClick={handleContinue}
100+
variant="start"
101+
>
102+
Continue
103+
</ActionButton>
104+
)}
74105

75-
<ActionButton
76-
onClick={isCompleted ? handleReset : handleStop}
77-
variant={isCompleted ? 'start' : 'stop'}
78-
>
79-
{isCompleted ? 'Back to setup' : 'Stop analysis'}
80-
</ActionButton>
106+
{showStartFromHereButton && (
107+
<ActionButton
108+
onClick={handleStartFromHere}
109+
variant="start"
110+
>
111+
Start from here
112+
</ActionButton>
113+
)}
114+
115+
<ActionButton
116+
onClick={handleReset}
117+
>
118+
Back to setup
119+
</ActionButton>
120+
</>
121+
)}
81122
</>
82123
) : (
83124
<>

0 commit comments

Comments
 (0)