Skip to content

Commit 55f4312

Browse files
authored
feat: support manual confirmation before downloading (#86)
1 parent 90b8743 commit 55f4312

7 files changed

Lines changed: 481 additions & 11 deletions

File tree

background/index.ts

Lines changed: 146 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1-
import path from "path"
21
import Client from "@gopeed/rest"
32
import { type Request } from "@gopeed/types"
43
import contentDisposition from "content-disposition"
4+
import path from "path"
55

66
import { getPort } from "@plasmohq/messaging/background"
77
import { Storage } from "@plasmohq/storage"
88

9+
import {
10+
requestServerSelection
11+
} from "~background/messages/api/select-server"
912
import { skip as pressToSkip } from "~background/messages/api/skip"
1013
import { STORAGE_SETTINGS } from "~constants"
1114
import { getFullUrl } from "~options/components/RemoteSettings"
1215
import { defaultSettings, type Settings } from "~options/types"
1316

14-
export {}
17+
export { }
1518

1619
/* function initContextMenus() {
1720
chrome.contextMenus.create({
@@ -288,21 +291,153 @@ function handleRemoteDownload(
288291
info: DownloadInfo,
289292
settings: Settings
290293
): Function | undefined {
291-
const server = settings.remote.servers.find(
292-
(server) => getFullUrl(server) === settings.remote.selectedServer
293-
)
294-
if (!server) {
295-
return
294+
// If only one server, no servers, or manual selection is disabled, use existing logic
295+
if (settings.remote.servers.length <= 1 || !settings.remote.requireManualSelection) {
296+
const server = settings.remote.servers.find(
297+
(server) => getFullUrl(server) === settings.remote.selectedServer
298+
)
299+
if (!server) {
300+
return
301+
}
302+
return createDownloadTask(info, server, settings)
303+
}
304+
305+
// Multiple servers available and manual selection is enabled - show server selector
306+
return async () => {
307+
try {
308+
// Show server selector overlay
309+
const tabs = await chrome.tabs.query({ active: true, currentWindow: true })
310+
if (tabs.length === 0) {
311+
// Fallback to default server if no active tab
312+
const defaultServer = settings.remote.servers.find(
313+
(server) => getFullUrl(server) === settings.remote.selectedServer
314+
)
315+
if (defaultServer) {
316+
await createDownloadTask(info, defaultServer, settings)()
317+
}
318+
return
319+
}
320+
321+
const tabId = tabs[0].id!
322+
const requestId = tabId.toString()
323+
324+
// Send message to content script to show server selector
325+
await chrome.tabs.sendMessage(tabId, {
326+
name: "show-server-selector",
327+
body: {
328+
servers: settings.remote.servers,
329+
downloadInfo: {
330+
url: info.url,
331+
filename: info.filename
332+
},
333+
defaultServer: settings.remote.selectedServer,
334+
requestId: requestId
335+
}
336+
})
337+
338+
// Wait for server selection
339+
const response = await requestServerSelection(requestId, {
340+
servers: settings.remote.servers,
341+
downloadInfo: {
342+
url: info.url,
343+
filename: info.filename
344+
}
345+
})
346+
347+
if (response.cancelled || !response.selectedServer) {
348+
return
349+
}
350+
351+
// Find selected server and create download task
352+
const selectedServer = settings.remote.servers.find(
353+
(server) => getFullUrl(server) === response.selectedServer
354+
)
355+
356+
if (selectedServer) {
357+
// Execute download task and get result
358+
const downloadSuccess = await executeDownloadTask(info, selectedServer, settings)
359+
360+
// Send result back to content script to handle popup closure
361+
await chrome.tabs.sendMessage(tabId, {
362+
name: "download-result",
363+
body: {
364+
success: downloadSuccess,
365+
requestId: requestId
366+
}
367+
})
368+
}
369+
} catch (error) {
370+
console.error("Server selection failed:", error)
371+
// Fallback to default server
372+
const defaultServer = settings.remote.servers.find(
373+
(server) => getFullUrl(server) === settings.remote.selectedServer
374+
)
375+
if (defaultServer) {
376+
await createDownloadTask(info, defaultServer, settings)()
377+
}
378+
}
296379
}
380+
}
297381

382+
async function executeDownloadTask(
383+
info: DownloadInfo,
384+
server: Server,
385+
settings: Settings
386+
): Promise<boolean> {
387+
const client = new Client({
388+
host: getFullUrl(server),
389+
token: server.token
390+
})
391+
let notificationType: string = "success"
392+
let notificationTitle: string
393+
let notificationMessage: string
394+
let success = false
395+
396+
try {
397+
await client.createTask({
398+
req: await toCreateRequest(info)
399+
})
400+
notificationTitle = chrome.i18n.getMessage("notification_create_success")
401+
notificationMessage = chrome.i18n.getMessage(
402+
"notification_create_success_message"
403+
)
404+
success = true
405+
} catch (e) {
406+
console.error(e)
407+
notificationType = "error"
408+
notificationTitle = chrome.i18n.getMessage("notification_create_error")
409+
notificationMessage = chrome.i18n.getMessage(
410+
"notification_create_error_message"
411+
)
412+
success = false
413+
}
414+
415+
if (settings.remote.notification) {
416+
const port = getPort("notify")
417+
port.postMessage({
418+
type: notificationType,
419+
title: notificationTitle,
420+
message: notificationMessage
421+
})
422+
}
423+
424+
return success
425+
}
426+
427+
function createDownloadTask(
428+
info: DownloadInfo,
429+
server: Server,
430+
settings: Settings
431+
): Function {
298432
return async () => {
299433
const client = new Client({
300434
host: getFullUrl(server),
301435
token: server.token
302436
})
303-
let notificationType: string
437+
let notificationType: string = "success"
304438
let notificationTitle: string
305439
let notificationMessage: string
440+
let success = false
306441
try {
307442
await client.createTask({
308443
req: await toCreateRequest(info)
@@ -311,13 +446,15 @@ function handleRemoteDownload(
311446
notificationMessage = chrome.i18n.getMessage(
312447
"notification_create_success_message"
313448
)
449+
success = true
314450
} catch (e) {
315451
console.error(e)
316452
notificationType = "error"
317453
notificationTitle = chrome.i18n.getMessage("notification_create_error")
318454
notificationMessage = chrome.i18n.getMessage(
319455
"notification_create_error_message"
320456
)
457+
success = false
321458
}
322459
if (settings.remote.notification) {
323460
const port = getPort("notify")
@@ -327,6 +464,7 @@ function handleRemoteDownload(
327464
message: notificationMessage
328465
})
329466
}
467+
return success
330468
}
331469
}
332470

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import type { PlasmoMessaging } from "@plasmohq/messaging"
2+
3+
export interface ServerSelectionRequest {
4+
servers: Server[]
5+
downloadInfo: {
6+
url: string
7+
filename: string
8+
}
9+
}
10+
11+
export interface ServerSelectionResponse {
12+
selectedServer: string | null
13+
cancelled: boolean
14+
}
15+
16+
// Store pending server selections
17+
const pendingSelections = new Map<string, {
18+
resolve: (response: ServerSelectionResponse) => void
19+
reject: (error: Error) => void
20+
}>()
21+
22+
export function requestServerSelection(
23+
requestId: string,
24+
data: ServerSelectionRequest
25+
): Promise<ServerSelectionResponse> {
26+
return new Promise((resolve, reject) => {
27+
pendingSelections.set(requestId, { resolve, reject })
28+
29+
// Timeout after 30 seconds
30+
setTimeout(() => {
31+
if (pendingSelections.has(requestId)) {
32+
pendingSelections.delete(requestId)
33+
resolve({ selectedServer: null, cancelled: true })
34+
}
35+
}, 30000)
36+
})
37+
}
38+
39+
const handler: PlasmoMessaging.MessageHandler<ServerSelectionResponse, void> = (
40+
req,
41+
res
42+
) => {
43+
const requestId = req.sender?.tab?.id?.toString() || "unknown"
44+
const pending = pendingSelections.get(requestId)
45+
46+
if (pending) {
47+
pendingSelections.delete(requestId)
48+
pending.resolve(req.body)
49+
}
50+
51+
res.send()
52+
}
53+
54+
export default handler

0 commit comments

Comments
 (0)