Skip to content

Commit e4af090

Browse files
committed
1:在偏好设置窗口基础设置分类【浏览器扩展】卡片,新增【不接管以下网站】设置项。2:在浏览器扩展悬浮窗,新增【不接管此网站】按钮,点击后直接将当前网站添加进【不接管以下网站】输入框里。3:在浏览器扩展悬浮窗,新增【跳过文件类型】输入框,输入后点击添加直接添加进【跳过文件类型】输入框。4:任务详情【追踪器】分类新增【协议】字段。5:任务详情【追踪器】分类新增【状态】字段。6:任务详情【追踪器】分类新增【节点数】字段。7:任务详情【追踪器】分类新增【种子数】字段。8:任务详情【追踪器】分类新增【下载数】字段。9:任务详情【追踪器】分类新增【下次连接】字段。10:任务详情【追踪器】分类新增【连接次数】字段。11:任务进度窗口底部新增固定按钮,默认关闭开启后将该任务进度窗口始终置于最前。12:删除浏览器扩展悬浮窗里的下载任务区域。13:优化偏好设置的窗口基础设置分类【浏览器扩展】卡片,【跳过文件类型】输入框的UI。14:优化部分本地化翻译使其更简洁易懂。15:优化任务详情追踪器分类的表格UI。16:优化任务进度窗口底部按钮UI。17:将任务进度窗口的进度条固定至底部控制按钮的上方。18:优化应用内部分图标。19:修复通过浏览器扩展传入下载器的任务,新添加任务的名称是上个任务的名称的问题。20:修复进行磁力元数据下载时任务卡片左下角没有显示进度信息的问题。
1 parent 24537d4 commit e4af090

25 files changed

Lines changed: 1840 additions & 254 deletions

File tree

extensions/linkcore-webextension/background.js

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const extConfigDefaults = {
88
interceptAllDownloads: false,
99
silentDownload: false,
1010
skipFileExtensions: [],
11+
minFileSize: 0,
1112
shiftToggleEnabled: false,
1213
videoSnifferEnabled: true,
1314
videoSnifferFormats: ['m4s', 'mp4', 'flv', 'm3u8', 'ts'],
@@ -316,8 +317,11 @@ const syncExtConfigFromClient = async () => {
316317
const interceptAllDownloads = !!data.interceptAllDownloads
317318
const silentDownload = !!data.silentDownload
318319
const shiftToggleEnabled = !!data.shiftToggleEnabled
320+
const minFileSize = Number(data.minFileSize) || 0
319321
const rawList = Array.isArray(data.skipFileExtensions) ? data.skipFileExtensions : []
320322
const skipFileExtensions = rawList.map(x => `${x}`.trim().toLowerCase()).filter(Boolean)
323+
const rawDomainList = Array.isArray(data.excludeDomains) ? data.excludeDomains : []
324+
const excludeDomains = rawDomainList.map(x => `${x}`.trim()).filter(Boolean)
321325

322326
// 视频嗅探器配置
323327
const videoSnifferEnabled = data.videoSnifferEnabled !== undefined ? !!data.videoSnifferEnabled : true
@@ -340,6 +344,8 @@ const syncExtConfigFromClient = async () => {
340344
interceptAllDownloads,
341345
silentDownload,
342346
skipFileExtensions,
347+
excludeDomains,
348+
minFileSize,
343349
shiftToggleEnabled,
344350
videoSnifferEnabled,
345351
videoSnifferFormats,
@@ -837,6 +843,164 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
837843
handleAddFromContent()
838844
return true
839845
}
846+
847+
if (msg && msg.type === 'addExcludeDomain' && msg.domain) {
848+
const handleAddExcludeDomain = async () => {
849+
try {
850+
// 先获取当前配置
851+
const currentConfig = await tryChannel('/linkcore/ext-config', {
852+
method: 'GET'
853+
}, 3000)
854+
855+
let excludeDomains = []
856+
if (currentConfig && currentConfig.resp) {
857+
const data = await currentConfig.resp.json()
858+
if (Array.isArray(data.excludeDomains)) {
859+
excludeDomains = data.excludeDomains
860+
}
861+
}
862+
863+
const domain = msg.domain.toLowerCase().trim()
864+
const existingIndex = excludeDomains.findIndex(d => d.toLowerCase().trim() === domain)
865+
866+
if (existingIndex !== -1) {
867+
// 域名已存在,移除它
868+
excludeDomains.splice(existingIndex, 1)
869+
const result = await tryChannel('/linkcore/ext-config', {
870+
method: 'POST',
871+
headers: { 'Content-Type': 'application/json' },
872+
body: JSON.stringify({ excludeDomains })
873+
}, 3000)
874+
875+
if (result && result.resp && result.resp.ok) {
876+
sendResponse({ ok: true, removed: true })
877+
} else {
878+
sendResponse({ ok: false })
879+
}
880+
} else {
881+
// 域名不存在,添加它
882+
excludeDomains.push(domain)
883+
const result = await tryChannel('/linkcore/ext-config', {
884+
method: 'POST',
885+
headers: { 'Content-Type': 'application/json' },
886+
body: JSON.stringify({ excludeDomains })
887+
}, 3000)
888+
889+
if (result && result.resp && result.resp.ok) {
890+
sendResponse({ ok: true, added: true })
891+
} else {
892+
sendResponse({ ok: false })
893+
}
894+
}
895+
} catch (e) {
896+
console.error('[Background] Failed to add/remove exclude domain:', e)
897+
sendResponse({ ok: false })
898+
}
899+
}
900+
handleAddExcludeDomain()
901+
return true
902+
}
903+
904+
if (msg && msg.type === 'getExcludeDomains') {
905+
const handleGetExcludeDomains = async () => {
906+
try {
907+
const result = await tryChannel('/linkcore/ext-config', {
908+
method: 'GET'
909+
}, 3000)
910+
911+
if (result && result.resp) {
912+
const data = await result.resp.json()
913+
sendResponse({ excludeDomains: data.excludeDomains || [] })
914+
} else {
915+
sendResponse({ excludeDomains: [] })
916+
}
917+
} catch (e) {
918+
console.error('[Background] Failed to get exclude domains:', e)
919+
sendResponse({ excludeDomains: [] })
920+
}
921+
}
922+
handleGetExcludeDomains()
923+
return true
924+
}
925+
926+
if (msg && msg.type === 'addSkipFileType' && msg.fileType) {
927+
const handleAddSkipFileType = async () => {
928+
try {
929+
const result = await tryChannel('/linkcore/ext-config', {
930+
method: 'POST',
931+
headers: { 'Content-Type': 'application/json' },
932+
body: JSON.stringify({ skipFileExtensions: [msg.fileType] })
933+
}, 3000)
934+
935+
if (result && result.resp && result.resp.ok) {
936+
sendResponse({ ok: true })
937+
} else {
938+
sendResponse({ ok: false })
939+
}
940+
} catch (e) {
941+
console.error('[Background] Failed to add skip file type:', e)
942+
sendResponse({ ok: false })
943+
}
944+
}
945+
handleAddSkipFileType()
946+
return true
947+
}
948+
949+
if (msg && msg.type === 'addSkipFileTypes' && Array.isArray(msg.fileTypes)) {
950+
const handleAddSkipFileTypes = async () => {
951+
let response = { ok: false, error: 'unknown' }
952+
try {
953+
console.log('[Background] Adding skip file types:', msg.fileTypes)
954+
955+
// 先获取当前配置
956+
const currentConfig = await tryChannel('/linkcore/ext-config', {
957+
method: 'GET'
958+
}, 5000)
959+
960+
let skipFileExtensions = []
961+
if (currentConfig && currentConfig.resp) {
962+
const data = await currentConfig.resp.json()
963+
console.log('[Background] Current config data:', data)
964+
if (Array.isArray(data.skipFileExtensions)) {
965+
skipFileExtensions = data.skipFileExtensions
966+
}
967+
}
968+
969+
// 合并并去重(与程序逻辑一致)
970+
const allExtensions = [...skipFileExtensions, ...msg.fileTypes]
971+
const uniqueExtensions = Array.from(new Set(allExtensions))
972+
973+
console.log('[Background] Sending skipFileExtensions:', uniqueExtensions)
974+
975+
const result = await tryChannel('/linkcore/ext-config', {
976+
method: 'POST',
977+
headers: { 'Content-Type': 'application/json' },
978+
body: JSON.stringify({ skipFileExtensions: uniqueExtensions })
979+
}, 5000)
980+
981+
console.log('[Background] POST result:', result)
982+
983+
if (result && result.resp && result.resp.ok) {
984+
response = { ok: true, added: msg.fileTypes.length }
985+
} else {
986+
console.error('[Background] POST failed, result:', result)
987+
response = { ok: false, error: 'POST failed' }
988+
}
989+
} catch (e) {
990+
console.error('[Background] Failed to add skip file types:', e)
991+
response = { ok: false, error: e.message }
992+
}
993+
994+
// 确保总是发送响应
995+
try {
996+
sendResponse(response)
997+
} catch (e) {
998+
console.error('[Background] Failed to send response:', e)
999+
}
1000+
}
1001+
handleAddSkipFileTypes()
1002+
return true
1003+
}
8401004
})
8411005
chrome.contextMenus.onClicked.addListener(async (info, tab) => {
8421006
let url = info.linkUrl || info.srcUrl || info.pageUrl
@@ -870,6 +1034,39 @@ chrome.downloads.onCreated.addListener((item) => {
8701034
if (!effectiveAutoHijack) return
8711035
const url = item && item.url ? item.url : ''
8721036
if (!url || !/^https?:/i.test(url)) return
1037+
1038+
// 检查是否在排除域名列表中
1039+
try {
1040+
const downloadUrl = new URL(url)
1041+
const downloadDomain = downloadUrl.hostname
1042+
1043+
// 检查 referer 域名
1044+
let refererDomain = ''
1045+
if (item.referrer) {
1046+
try {
1047+
const refererUrl = new URL(item.referrer)
1048+
refererDomain = refererUrl.hostname
1049+
} catch (e) {}
1050+
}
1051+
1052+
// 获取排除域名列表
1053+
const excludeDomains = Array.isArray(extConfig.excludeDomains) ? extConfig.excludeDomains : []
1054+
1055+
// 检查下载域名或 referer 域名是否在排除列表中
1056+
const isDomainExcluded = excludeDomains.some(domain => {
1057+
const normalizedDomain = domain.toLowerCase().trim()
1058+
return downloadDomain.toLowerCase().includes(normalizedDomain) ||
1059+
(refererDomain && refererDomain.toLowerCase().includes(normalizedDomain))
1060+
})
1061+
1062+
if (isDomainExcluded) {
1063+
console.log('[LinkCore] Domain excluded, skipping download:', downloadDomain)
1064+
return
1065+
}
1066+
} catch (e) {
1067+
console.error('[LinkCore] Error checking excluded domain:', e)
1068+
}
1069+
8731070
try {
8741071
let name = ''
8751072
if (item && item.filename) {
@@ -886,6 +1083,26 @@ chrome.downloads.onCreated.addListener((item) => {
8861083
if (ext && Array.isArray(extConfig.skipFileExtensions) && extConfig.skipFileExtensions.includes(ext)) {
8871084
return
8881085
}
1086+
1087+
// 检查文件大小限制(minFileSize 单位为 MB)
1088+
const minFileSizeMB = Number(extConfig.minFileSize) || 0
1089+
if (minFileSizeMB > 0) {
1090+
// 获取文件大小(字节)
1091+
// totalBytes 是文件总大小,如果未知则为 -1
1092+
const totalBytes = item.totalBytes || 0
1093+
const fileSizeMB = totalBytes / (1024 * 1024)
1094+
1095+
// 如果已知文件大小且小于最小限制,跳过拦截
1096+
if (totalBytes > 0 && fileSizeMB < minFileSizeMB) {
1097+
console.log('[LinkCore] File size (' + fileSizeMB.toFixed(2) + 'MB) below minimum (' + minFileSizeMB + 'MB), skipping:', url)
1098+
return
1099+
}
1100+
1101+
// 如果文件大小未知(totalBytes 为 0 或 -1),继续拦截
1102+
if (totalBytes <= 0) {
1103+
console.log('[LinkCore] File size unknown, will intercept anyway:', url)
1104+
}
1105+
}
8891106
} catch (e) {
8901107
}
8911108
try {

extensions/linkcore-webextension/i18n.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,16 @@ const translations = {
1414
autoHijack: "Auto-hijack browser downloads",
1515
connected: "Connected",
1616
disconnected: "Disconnected",
17-
contextMenuDownload: "Download with LinkCore"
17+
contextMenuDownload: "Download with LinkCore",
18+
labelExcludeCurrentSite: "Exclude this site",
19+
labelRemoveFromExclude: "Restore download",
20+
labelAdded: "Added",
21+
labelRemoved: "Removed",
22+
labelSuccess: "Success",
23+
labelFailed: "Failed",
24+
labelAdd: "Add",
25+
placeholderInputExt: "Enter file extension",
26+
placeholderExample: "Example: exe, zip, rar"
1827
},
1928
zh_CN: {
2029
extensionName: "LinkCore Download Manager",
@@ -30,7 +39,16 @@ const translations = {
3039
autoHijack: "自动接管浏览器下载",
3140
connected: "已连接",
3241
disconnected: "未连接",
33-
contextMenuDownload: "使用 LinkCore 下载"
42+
contextMenuDownload: "使用 LinkCore 下载",
43+
labelExcludeCurrentSite: "不接管此网站",
44+
labelRemoveFromExclude: "恢复接管",
45+
labelAdded: "已添加",
46+
labelRemoved: "已移除",
47+
labelSuccess: "成功",
48+
labelFailed: "操作失败",
49+
labelAdd: "添加",
50+
placeholderInputExt: "输入文件扩展名",
51+
placeholderExample: "示例: exe, zip, rar"
3452
},
3553
zh_TW: {
3654
extensionName: "LinkCore Download Manager",

0 commit comments

Comments
 (0)