diff --git a/.vs/DownloadManager/CopilotIndices/17.14.1653.19549/CodeChunks.db b/.vs/DownloadManager/CopilotIndices/17.14.1653.19549/CodeChunks.db index f4994bd..004ba74 100644 Binary files a/.vs/DownloadManager/CopilotIndices/17.14.1653.19549/CodeChunks.db and b/.vs/DownloadManager/CopilotIndices/17.14.1653.19549/CodeChunks.db differ diff --git a/.vs/DownloadManager/CopilotIndices/17.14.1653.19549/SemanticSymbols.db b/.vs/DownloadManager/CopilotIndices/17.14.1653.19549/SemanticSymbols.db index deed7d5..c681f21 100644 Binary files a/.vs/DownloadManager/CopilotIndices/17.14.1653.19549/SemanticSymbols.db and b/.vs/DownloadManager/CopilotIndices/17.14.1653.19549/SemanticSymbols.db differ diff --git a/.vs/DownloadManager/DesignTimeBuild/.dtbcache.v2 b/.vs/DownloadManager/DesignTimeBuild/.dtbcache.v2 index 352398e..8320ce8 100644 Binary files a/.vs/DownloadManager/DesignTimeBuild/.dtbcache.v2 and b/.vs/DownloadManager/DesignTimeBuild/.dtbcache.v2 differ diff --git a/.vs/DownloadManager/FileContentIndex/010946e1-f63e-4ce1-b2e2-bf7ddb68bc77.vsidx b/.vs/DownloadManager/FileContentIndex/010946e1-f63e-4ce1-b2e2-bf7ddb68bc77.vsidx deleted file mode 100644 index ad95d02..0000000 Binary files a/.vs/DownloadManager/FileContentIndex/010946e1-f63e-4ce1-b2e2-bf7ddb68bc77.vsidx and /dev/null differ diff --git a/.vs/DownloadManager/FileContentIndex/4e1517d4-f542-4445-8438-0598dd9c54da.vsidx b/.vs/DownloadManager/FileContentIndex/4e1517d4-f542-4445-8438-0598dd9c54da.vsidx deleted file mode 100644 index f8b5569..0000000 Binary files a/.vs/DownloadManager/FileContentIndex/4e1517d4-f542-4445-8438-0598dd9c54da.vsidx and /dev/null differ diff --git a/.vs/DownloadManager/FileContentIndex/5f175271-f65d-49fe-b67e-e4632b5b8775.vsidx b/.vs/DownloadManager/FileContentIndex/5f175271-f65d-49fe-b67e-e4632b5b8775.vsidx deleted file mode 100644 index 7fd41d7..0000000 Binary files a/.vs/DownloadManager/FileContentIndex/5f175271-f65d-49fe-b67e-e4632b5b8775.vsidx and /dev/null differ diff --git a/.vs/DownloadManager/FileContentIndex/6ff86c10-b4e8-4c55-8a7f-74e02e54e792.vsidx b/.vs/DownloadManager/FileContentIndex/6ff86c10-b4e8-4c55-8a7f-74e02e54e792.vsidx new file mode 100644 index 0000000..55c10ae Binary files /dev/null and b/.vs/DownloadManager/FileContentIndex/6ff86c10-b4e8-4c55-8a7f-74e02e54e792.vsidx differ diff --git a/.vs/DownloadManager/FileContentIndex/9229a3ad-0537-4895-9fcf-c5ca360b237a.vsidx b/.vs/DownloadManager/FileContentIndex/9229a3ad-0537-4895-9fcf-c5ca360b237a.vsidx new file mode 100644 index 0000000..a9de2ff Binary files /dev/null and b/.vs/DownloadManager/FileContentIndex/9229a3ad-0537-4895-9fcf-c5ca360b237a.vsidx differ diff --git a/.vs/DownloadManager/FileContentIndex/a0f54a1e-9581-402c-a720-5bff0f01fab3.vsidx b/.vs/DownloadManager/FileContentIndex/a0f54a1e-9581-402c-a720-5bff0f01fab3.vsidx deleted file mode 100644 index c2fd663..0000000 Binary files a/.vs/DownloadManager/FileContentIndex/a0f54a1e-9581-402c-a720-5bff0f01fab3.vsidx and /dev/null differ diff --git a/.vs/DownloadManager/FileContentIndex/b9d57521-62b7-4b5d-8cb8-61d1719e0c73.vsidx b/.vs/DownloadManager/FileContentIndex/b9d57521-62b7-4b5d-8cb8-61d1719e0c73.vsidx new file mode 100644 index 0000000..e553035 Binary files /dev/null and b/.vs/DownloadManager/FileContentIndex/b9d57521-62b7-4b5d-8cb8-61d1719e0c73.vsidx differ diff --git a/.vs/DownloadManager/FileContentIndex/cbfe6b5e-4121-4604-966d-e410886a0814.vsidx b/.vs/DownloadManager/FileContentIndex/cbfe6b5e-4121-4604-966d-e410886a0814.vsidx new file mode 100644 index 0000000..6a2e92b Binary files /dev/null and b/.vs/DownloadManager/FileContentIndex/cbfe6b5e-4121-4604-966d-e410886a0814.vsidx differ diff --git a/.vs/DownloadManager/FileContentIndex/eb2c6167-ac6e-46e4-8071-63e936f4f6ca.vsidx b/.vs/DownloadManager/FileContentIndex/eb2c6167-ac6e-46e4-8071-63e936f4f6ca.vsidx deleted file mode 100644 index 27b587e..0000000 Binary files a/.vs/DownloadManager/FileContentIndex/eb2c6167-ac6e-46e4-8071-63e936f4f6ca.vsidx and /dev/null differ diff --git a/.vs/DownloadManager/FileContentIndex/fce2360e-ed41-41d8-844b-fb83619a7800.vsidx b/.vs/DownloadManager/FileContentIndex/fce2360e-ed41-41d8-844b-fb83619a7800.vsidx new file mode 100644 index 0000000..54d95e4 Binary files /dev/null and b/.vs/DownloadManager/FileContentIndex/fce2360e-ed41-41d8-844b-fb83619a7800.vsidx differ diff --git a/.vs/DownloadManager/v17/.futdcache.v2 b/.vs/DownloadManager/v17/.futdcache.v2 index 8326cf9..48512cd 100644 Binary files a/.vs/DownloadManager/v17/.futdcache.v2 and b/.vs/DownloadManager/v17/.futdcache.v2 differ diff --git a/.vs/DownloadManager/v17/.suo b/.vs/DownloadManager/v17/.suo index 6232a9b..c805419 100644 Binary files a/.vs/DownloadManager/v17/.suo and b/.vs/DownloadManager/v17/.suo differ diff --git a/.vs/DownloadManager/v17/DocumentLayout.backup.json b/.vs/DownloadManager/v17/DocumentLayout.backup.json index 3ec1b00..59c2acf 100644 --- a/.vs/DownloadManager/v17/DocumentLayout.backup.json +++ b/.vs/DownloadManager/v17/DocumentLayout.backup.json @@ -2,6 +2,18 @@ "Version": 1, "WorkspaceRootPath": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\", "Documents": [ + { + "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\views\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}", + "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\views\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}" + }, + { + "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\resources\\icons.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}", + "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\resources\\icons.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}" + }, + { + "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\resources\\appicon.png||{177559E0-D141-11D0-92DF-00A0C9138C45}", + "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\resources\\appicon.png||{177559E0-D141-11D0-92DF-00A0C9138C45}" + }, { "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\viewmodels\\mainviewmodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\viewmodels\\mainviewmodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" @@ -10,10 +22,6 @@ "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\viewmodels\\downloaditemviewmodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\viewmodels\\downloaditemviewmodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, - { - "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\views\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}", - "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\views\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}" - }, { "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\converters\\statustoiconconverter.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\converters\\statustoiconconverter.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" @@ -34,15 +42,39 @@ "DocumentGroups": [ { "DockedWidth": 200, - "SelectedChildIndex": 4, + "SelectedChildIndex": 8, "Children": [ { "$type": "Bookmark", "Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}" }, + { + "$type": "Document", + "DocumentIndex": 2, + "Title": "AppIcon.png - PNG [512x512, 32 bit, PNG]", + "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Resources\\AppIcon.png", + "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\Resources\\AppIcon.png", + "ToolTip": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Resources\\AppIcon.png - PNG [512x512, 32 bit, PNG]", + "RelativeToolTip": "src\\DownloadManager.WPF\\Resources\\AppIcon.png - PNG [512x512, 32 bit, PNG]", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001533|", + "WhenOpened": "2026-05-06T11:23:28.352Z", + "EditorCaption": " - PNG [512x512, 32 bit, PNG]" + }, { "$type": "Document", "DocumentIndex": 1, + "Title": "Icons.xaml", + "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Resources\\Icons.xaml", + "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\Resources\\Icons.xaml", + "ToolTip": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Resources\\Icons.xaml", + "RelativeToolTip": "src\\DownloadManager.WPF\\Resources\\Icons.xaml", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|", + "WhenOpened": "2026-05-06T11:23:19.058Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 4, "Title": "DownloadItemViewModel.cs", "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\ViewModels\\DownloadItemViewModel.cs", "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\ViewModels\\DownloadItemViewModel.cs", @@ -50,12 +82,11 @@ "RelativeToolTip": "src\\DownloadManager.WPF\\ViewModels\\DownloadItemViewModel.cs", "ViewState": "AgIAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-04T23:33:33.635Z", - "EditorCaption": "" + "WhenOpened": "2026-05-04T23:33:33.635Z" }, { "$type": "Document", - "DocumentIndex": 3, + "DocumentIndex": 5, "Title": "StatusToIconConverter.cs", "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Converters\\StatusToIconConverter.cs", "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\Converters\\StatusToIconConverter.cs", @@ -67,7 +98,7 @@ }, { "$type": "Document", - "DocumentIndex": 5, + "DocumentIndex": 7, "Title": "App.xaml", "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\App.xaml", "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\App.xaml", @@ -79,7 +110,7 @@ }, { "$type": "Document", - "DocumentIndex": 0, + "DocumentIndex": 3, "Title": "MainViewModel.cs", "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\ViewModels\\MainViewModel.cs", "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\ViewModels\\MainViewModel.cs", @@ -87,12 +118,11 @@ "RelativeToolTip": "src\\DownloadManager.WPF\\ViewModels\\MainViewModel.cs", "ViewState": "AgIAAI4CAAAAAAAAAAAcwOYAAABVAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-03T21:58:25.845Z", - "EditorCaption": "" + "WhenOpened": "2026-05-03T21:58:25.845Z" }, { "$type": "Document", - "DocumentIndex": 4, + "DocumentIndex": 6, "Title": "App.xaml.cs", "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\App.xaml.cs", "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\App.xaml.cs", @@ -104,7 +134,7 @@ }, { "$type": "Document", - "DocumentIndex": 2, + "DocumentIndex": 0, "Title": "MainWindow.xaml", "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Views\\MainWindow.xaml", "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\Views\\MainWindow.xaml", diff --git a/.vs/DownloadManager/v17/DocumentLayout.json b/.vs/DownloadManager/v17/DocumentLayout.json index 737cfda..59c2acf 100644 --- a/.vs/DownloadManager/v17/DocumentLayout.json +++ b/.vs/DownloadManager/v17/DocumentLayout.json @@ -2,6 +2,10 @@ "Version": 1, "WorkspaceRootPath": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\", "Documents": [ + { + "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\views\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}", + "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\views\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}" + }, { "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\resources\\icons.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}", "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\resources\\icons.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}" @@ -18,10 +22,6 @@ "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\viewmodels\\downloaditemviewmodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\viewmodels\\downloaditemviewmodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, - { - "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\views\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}", - "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\views\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}" - }, { "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\converters\\statustoiconconverter.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\converters\\statustoiconconverter.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" @@ -42,7 +42,7 @@ "DocumentGroups": [ { "DockedWidth": 200, - "SelectedChildIndex": 2, + "SelectedChildIndex": 8, "Children": [ { "$type": "Bookmark", @@ -50,7 +50,7 @@ }, { "$type": "Document", - "DocumentIndex": 1, + "DocumentIndex": 2, "Title": "AppIcon.png - PNG [512x512, 32 bit, PNG]", "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Resources\\AppIcon.png", "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\Resources\\AppIcon.png", @@ -62,7 +62,7 @@ }, { "$type": "Document", - "DocumentIndex": 0, + "DocumentIndex": 1, "Title": "Icons.xaml", "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Resources\\Icons.xaml", "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\Resources\\Icons.xaml", @@ -74,7 +74,7 @@ }, { "$type": "Document", - "DocumentIndex": 3, + "DocumentIndex": 4, "Title": "DownloadItemViewModel.cs", "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\ViewModels\\DownloadItemViewModel.cs", "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\ViewModels\\DownloadItemViewModel.cs", @@ -110,7 +110,7 @@ }, { "$type": "Document", - "DocumentIndex": 2, + "DocumentIndex": 3, "Title": "MainViewModel.cs", "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\ViewModels\\MainViewModel.cs", "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\ViewModels\\MainViewModel.cs", @@ -118,8 +118,7 @@ "RelativeToolTip": "src\\DownloadManager.WPF\\ViewModels\\MainViewModel.cs", "ViewState": "AgIAAI4CAAAAAAAAAAAcwOYAAABVAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-03T21:58:25.845Z", - "EditorCaption": "" + "WhenOpened": "2026-05-03T21:58:25.845Z" }, { "$type": "Document", @@ -135,14 +134,15 @@ }, { "$type": "Document", - "DocumentIndex": 4, + "DocumentIndex": 0, "Title": "MainWindow.xaml", "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Views\\MainWindow.xaml", "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\Views\\MainWindow.xaml", "ToolTip": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Views\\MainWindow.xaml", "RelativeToolTip": "src\\DownloadManager.WPF\\Views\\MainWindow.xaml", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|", - "WhenOpened": "2026-05-01T23:15:00.129Z" + "WhenOpened": "2026-05-01T23:15:00.129Z", + "EditorCaption": "" } ] } diff --git a/.vs/ProjectEvaluation/downloadmanager.metadata.v9.bin b/.vs/ProjectEvaluation/downloadmanager.metadata.v9.bin index b383365..79cc0de 100644 Binary files a/.vs/ProjectEvaluation/downloadmanager.metadata.v9.bin and b/.vs/ProjectEvaluation/downloadmanager.metadata.v9.bin differ diff --git a/.vs/ProjectEvaluation/downloadmanager.projects.v9.bin b/.vs/ProjectEvaluation/downloadmanager.projects.v9.bin index ea2e8ea..d6f0ab8 100644 Binary files a/.vs/ProjectEvaluation/downloadmanager.projects.v9.bin and b/.vs/ProjectEvaluation/downloadmanager.projects.v9.bin differ diff --git a/.vs/ProjectEvaluation/downloadmanager.strings.v9.bin b/.vs/ProjectEvaluation/downloadmanager.strings.v9.bin index e7d0ac7..75bbae7 100644 Binary files a/.vs/ProjectEvaluation/downloadmanager.strings.v9.bin and b/.vs/ProjectEvaluation/downloadmanager.strings.v9.bin differ diff --git a/Down_bridge.png b/Down_bridge.png new file mode 100644 index 0000000..ffade79 Binary files /dev/null and b/Down_bridge.png differ diff --git a/GIZLILIK_POLITIKASI.md b/GIZLILIK_POLITIKASI.md new file mode 100644 index 0000000..4991439 --- /dev/null +++ b/GIZLILIK_POLITIKASI.md @@ -0,0 +1,43 @@ +# hOLOlu Download Manager (hDM) Gizlilik Politikası + +**Son Güncelleme:** 7 Mayıs 2026 + +hOLOlu Download Manager (hDM), gizliliğinizi korumayı taahhüt eder. Bu Gizlilik Politikası, uygulamamızın ve tarayıcı eklentimizin bilgileri nasıl işlediğini açıklar. + +## 1. Bilgi Toplama ve Kullanım + +hDM, yerel olarak kurulan bir yazılımdır. Tam gizlilik prensibine inanıyoruz: +- **Kişisel Veri Toplanmaz:** Herhangi bir kişisel bilgiyi, tarama geçmişini veya kimlik verisini toplamaz, saklamaz veya herhangi bir harici sunucuya iletmeyiz. +- **Yerel İşleme:** Tüm indirme bilgileri, URL'ler ve dosya yolları, makinenizdeki özel bir veri tabanında yerel olarak işlenir ve saklanır. +- **Takip Yapılmaz:** Davranışlarınızı izlemek için herhangi bir takip pikseli, analiz aracı veya çerez kullanmayız. + +## 2. Tarayıcı Eklentisi İzinleri + +hDM Tarayıcı Eklentisi, doğru çalışabilmek için aşağıdaki izinlere ihtiyaç duyar: +- **`downloads`:** Bir indirme başladığında bunu tespit etmek, indirmeyi yakalamak ve hDM tarafından yönetilmesini sağlamak için kullanılır. +- **`nativeMessaging`:** Bilgisayarınızdaki hDM masaüstü uygulamasıyla güvenli bir şekilde iletişim kurmak için kullanılır. +- **`contextMenus`:** Bir bağlantıya sağ tıkladığınızda "hDM ile indir" seçeneğini sunmak için kullanılır. +- **``:** Eklentinin ziyaret ettiğiniz çeşitli web sitelerindeki indirme bağlantılarını yakalamasına olanak tanımak için gereklidir. + +Bu izinler aracılığıyla erişilen verilerin hiçbiri asla hDM'ye veya herhangi bir üçüncü tarafa gönderilmez. Tamamen yerel sisteminizde kalır. + +## 3. Veri Depolama + +- **Yerel Veri Tabanı:** hDM, indirme geçmişinizi ve ayarlarınızı bilgisayarınızdaki yerel bir SQLite veri tabanında saklar. +- **Loglar (Günlükler):** Sorun gidermeye yardımcı olmak için tanılama günlükleri yerel olarak `%AppData%\DownloadManager\logs` klasörünüzde saklanır. Bu günlükler asla otomatik olarak karşıya yüklenmez. + +## 4. Üçüncü Taraf Hizmetleri + +hDM, verilerinizi üçüncü taraflarla paylaşmaz. Bir dosya indirdiğinizde, doğrudan o dosyayı barındıran sunucuya bağlanırsınız. hDM, bir proxy veya aracı görevi görmez. + +## 5. Güvenlik + +Uygulama içinde kaydetmeyi seçebileceğiniz tüm kimlik bilgilerinin korunması dahil olmak üzere, yerel verilerinizi korumak için endüstri standardı güvenlik uygulamalarını kullanıyoruz. + +## 6. Bu Politikadaki Değişiklikler + +Gizlilik Politikamızı zaman zaman güncelleyebiliriz. Herhangi bir değişiklik, güncellenmiş "Son Güncelleme" tarihi ile bu sayfada yayınlanacaktır. + +## 7. Bize Ulaşın + +Bu Gizlilik Politikası hakkında herhangi bir sorunuz varsa, resmi proje deposu üzerinden bizimle iletişime geçebilirsiniz. diff --git a/PRIVACY_POLICY.md b/PRIVACY_POLICY.md new file mode 100644 index 0000000..19436db --- /dev/null +++ b/PRIVACY_POLICY.md @@ -0,0 +1,43 @@ +# Privacy Policy for hOLOlu Download Manager (hDM) + +**Last Updated:** May 7, 2026 + +hOLOlu Download Manager (hDM) is committed to protecting your privacy. This Privacy Policy explains how our application and browser extension handle information. + +## 1. Information Collection and Use + +hDM is a locally installed software. We believe in total privacy: +- **No Personal Data Collection:** We do not collect, store, or transmit any personal information, browsing history, or identity data to any external servers. +- **Local Processing:** All download information, URLs, and file paths are processed and stored locally on your machine in a private database. +- **No Tracking:** We do not use any tracking pixels, analytics, or cookies to monitor your behavior. + +## 2. Browser Extension Permissions + +To function correctly, the hDM Browser Extension requires the following permissions: +- **`downloads`:** Used to detect when a download starts so it can be intercepted and managed by hDM. +- **`nativeMessaging`:** Used to securely communicate with the hDM desktop application on your computer. +- **`contextMenus`:** Used to provide the "Download with hDM" option when you right-click on a link. +- **``:** Necessary to allow the extension to intercept download links from various websites you visit. + +None of the data accessed via these permissions is ever sent to hDM or any third party. It stays entirely on your local system. + +## 3. Data Storage + +- **Local Database:** hDM stores your download history and settings in a local SQLite database on your computer. +- **Logs:** Diagnostic logs are stored locally in your `%AppData%\DownloadManager\logs` folder to help troubleshoot issues. These logs are never automatically uploaded. + +## 4. Third-Party Services + +hDM does not share your data with third parties. When you download a file, you are connecting directly to the server hosting that file. hDM does not act as a proxy or intermediary. + +## 5. Security + +We implement industry-standard security practices to protect your local data, including the use of protected storage for any credentials you may choose to save within the application. + +## 6. Changes to This Policy + +We may update our Privacy Policy from time to time. Any changes will be posted on this page with an updated "Last Updated" date. + +## 7. Contact Us + +If you have any questions about this Privacy Policy, you can contact us through our official project repository. diff --git a/README.md b/README.md index c2cadbb..c8e6074 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,9 @@ Modern, hızlı ve kullanıcı dostu, .NET 8 ve WPF tabanlı açık kaynaklı bi * **Sistem Tepsisi (Systray) Desteği:** Uygulama kapandığında sistem tepsisine küçülür, arka planda çalışmaya devam eder. * **Gelişmiş Sıralama ve Filtreleme:** İndirmeleri tarihe, boyuta, duruma veya isme göre akıllıca sıralar; kategori bazlı filtreleme yapar. * **Kullanıcı Arayüzü Özelleştirme:** Açık/Koyu tema desteği, kategori panelini gizleme/gösterme ve sütun genişliklerini otomatik kaydetme. -* **Türkçe Arayüz ve Loglama:** İndirme durumları ve arka plan motor loglamaları Türkçeye çevrilmiş olup SQL logları minimize edilmiştir. +* **Detaylı Durum Çubuğu:** Toplam, Tamamlanan, Aktif, Duraklatılan ve Hatalı indirme sayılarını anlık olarak gösteren renkli istatistik paneli. +* **Akıllı Kuyruk Yönetimi:** Uygulama açılışında tüm indirmelerin otomatik başlamasını engelleyen, kullanıcı kontrolünde "Bekleyenleri Başlat" ve "Tümünü Duraklat" özellikleri. +* **Tekil Örnek (Single Instance):** Uygulamanın birden fazla kopyasının açılmasını engelleyen Mutex tabanlı koruma. ## 🛠 Teknik Mimari @@ -24,7 +26,7 @@ Uygulama modern yazılım prensipleri (Clean Architecture) ve MVVM deseni üzeri * **DownloadManager.Core:** İndirme motoru, Hız Sınırlayıcı (SpeedThrottler), HTTP protokol yönetimi, SQLite veritabanı katmanı ve temel modelleri içerir. * **DownloadManager.WPF:** CommunityToolkit.Mvvm kullanılarak geliştirilmiş, ModernWpf UI kütüphanesi ile zenginleştirilmiş kullanıcı arayüzü. * **DownloadManager.BrowserBridge:** Tarayıcı eklentisinden gelen verileri Named Pipe üzerinden ana (`hDM`) uygulamaya aktaran hafif köprü uygulaması. -* **Veritabanı:** Ayarlar ve indirme geçmişi SQLite üzerinde Entity Framework Core ile yönetilir. +* **Veritabanı:** Ayarlar ve indirme geçmişi SQLite üzerinde Entity Framework Core ile yönetilir. Arka plan işlemleri için `Scope` tabanlı asenkron erişim ile yüksek stabilite sağlanmıştır. ## 📦 Kurulum ve Çalıştırma @@ -52,25 +54,24 @@ Tarayıcının eklenti üzerinden ana uygulama ile konuşabilmesi için "Native * *Not: Kayıt defterindeki `path` değerinin derlediğiniz `DownloadManager.BrowserBridge.exe` dosyasının gerçek yolu ile eşleştiğinden emin olun.* #### 2. Eklentiyi Tarayıcıya Yükleme -* Chrome veya Edge tarayıcınızda `chrome://extensions` adresine gidin. -* **Geliştirici Modu (Developer Mode)** seçeneğini aktif hale getirin. -* **Paketlenmemiş öğe yükle (Load unpacked)** butonuna tıklayın. -* Proje içindeki `browser-extension` klasörünü seçerek yükleyin. +* Chrome Web Store üzerinden yükleyebilir veya geliştirici modunda `browser-extension` klasörünü seçerek yükleyebilirsiniz. +* **Chrome Web Store ID:** Eklenti yayınlandığında sabitlenen ID'yi `manifest.json` içindeki `allowed_origins` kısmına eklemeyi unutmayın. ### 🖱 Kullanım * **Otomatik Yakalama:** Eklenti yüklendikten sonra tarayıcıda sağ tık menüsünden **"hDM ile indir"** diyerek veya desteklenen uzantılara tıklayarak otomatik yakalama sağlayabilirsiniz. * **Site İncele:** Sayfa içindeyken sağ tıklayıp **"Siteyi hDM ile incele"** diyerek sayfadaki tüm dosyaları topluca analiz edebilirsiniz. +* **Kuyruk Yönetimi:** "Bekleyenleri Başlat" butonu ile duraklatılmış tüm indirmeleri sıraya alabilir, "Tümünü Duraklat" ile ağ trafiğini anında durdurabilirsiniz. * **Pano Desteği:** Herhangi bir linki kopyalayıp hDM içindeki "Ekle" butonuna bastığınızda link otomatik olarak yapıştırılır. ## 📈 Son Durum ve İyileştirmeler Son yapılan güncellemeler ile: -- [x] Derleme adı `hDM.exe` olarak güncellendi. Özel ikonlar (`Down_nb-02`) eklendi. -- [x] İndirme hızı limitleme (`SpeedThrottler`) ve otomatik yeniden deneme (`Auto-Retry`) motoru yazıldı. -- [x] İndirme duraklatma ve devam ettirme mekanizmasındaki ilerleme (progress) sıfırlanma hataları giderildi. -- [x] UI Durum bildirimleri ve arka plan logları Türkçeleştirildi. EF Core SQL logları temizlendi. -- [x] Tarayıcı eklentisinden bağlam menüsü entegrasyonu (Context Menu) ile URL'nin doğrudan Site İncele paneline aktarılması sağlandı. +- [x] **Stabilite:** DbContext eşzamanlılık (concurrency) hataları `Transient` servis ömrü ve `Scope` yönetimi ile tamamen çözüldü. +- [x] **Kuyruk Kontrolü:** "Tümünü Duraklat" komutunun ardından indirmelerin kendiliğinden tekrar başlaması sorunu, veritabanı durum kontrolü ile giderildi. +- [x] **Açılış Hızı:** Uygulama açıldığında bekleyen indirmelerin otomatik başlaması engellenerek sistem kaynakları korundu. +- [x] **Görsel Detaylar:** Alt kısma indirme durumlarını (Tamamlanan, Hata, Aktif vb.) özetleyen detaylı bir durum çubuğu eklendi. +- [x] **Tekil Örnek:** Tarayıcıdan gelen çoklu tetiklemelerin arka planda süreç (process) biriktirmesi `Mutex` ile engellendi. ## 🛡 Güvenlik ve Gizlilik hDM, kullanıcı verilerini sadece yerel SQLite veritabanında saklar. Şifreler ve kimlik bilgileri `ProtectedData` (DPAPI) ile Windows seviyesinde şifrelenerek korunur. diff --git a/browser-extension/128x128.png b/browser-extension/128x128.png new file mode 100644 index 0000000..8d18997 Binary files /dev/null and b/browser-extension/128x128.png differ diff --git a/browser-extension/16x16.png b/browser-extension/16x16.png new file mode 100644 index 0000000..60acf2e Binary files /dev/null and b/browser-extension/16x16.png differ diff --git a/browser-extension/48x48.png b/browser-extension/48x48.png new file mode 100644 index 0000000..e214a24 Binary files /dev/null and b/browser-extension/48x48.png differ diff --git a/browser-extension/background.js b/browser-extension/background.js index 6283cc5..675c518 100644 --- a/browser-extension/background.js +++ b/browser-extension/background.js @@ -1,11 +1,5 @@ const NATIVE_HOST = "com.downloadmanager.bridge"; -const interceptExtensions = [ - "exe","msi","zip","rar","7z","tar","gz","iso", - "mp4","mkv","avi","mp3","flac","wav", - "pdf","docx","xlsx","pptx" -]; - chrome.runtime.onInstalled.addListener(() => { chrome.contextMenus.create({ id: "dm-download-link", @@ -21,9 +15,6 @@ chrome.runtime.onInstalled.addListener(() => { }); chrome.downloads.onCreated.addListener((item) => { - const ext = item.filename?.split(".").pop()?.toLowerCase() ?? ""; - if (!interceptExtensions.includes(ext)) return; - chrome.downloads.cancel(item.id, () => { console.log("İndirme yakalandı, bridge'e gönderiliyor:", item.url); chrome.runtime.sendNativeMessage(NATIVE_HOST, { diff --git a/browser-extension/manifest.json b/browser-extension/manifest.json index 0620ea2..c209dd6 100644 --- a/browser-extension/manifest.json +++ b/browser-extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "hOLOlu Download Manager", - "version": "1.0.0", + "version": "1.0.2", "description": "Bağlantıları hDM ile indir ve sayfaları incele", "permissions": ["downloads", "contextMenus", "storage", "nativeMessaging"], "host_permissions": [""], diff --git a/browser-extension_v1.0.0.zip b/browser-extension_v1.0.0.zip new file mode 100644 index 0000000..2dfd5bf Binary files /dev/null and b/browser-extension_v1.0.0.zip differ diff --git a/browser-extension_v1.0.1.zip b/browser-extension_v1.0.1.zip new file mode 100644 index 0000000..ae43023 Binary files /dev/null and b/browser-extension_v1.0.1.zip differ diff --git a/browser-extension_v1.0.2.zip b/browser-extension_v1.0.2.zip new file mode 100644 index 0000000..571b296 Binary files /dev/null and b/browser-extension_v1.0.2.zip differ diff --git a/hdm_bridge.ico b/hdm_bridge.ico new file mode 100644 index 0000000..4b56e17 Binary files /dev/null and b/hdm_bridge.ico differ diff --git a/src/DownloadManager.BrowserBridge/DownloadManager.BrowserBridge.csproj b/src/DownloadManager.BrowserBridge/DownloadManager.BrowserBridge.csproj index dc358fb..1d2cad5 100644 --- a/src/DownloadManager.BrowserBridge/DownloadManager.BrowserBridge.csproj +++ b/src/DownloadManager.BrowserBridge/DownloadManager.BrowserBridge.csproj @@ -5,6 +5,7 @@ net8.0 enable enable + hdm_bridge.ico diff --git a/src/DownloadManager.BrowserBridge/Program.cs b/src/DownloadManager.BrowserBridge/Program.cs index a649269..3b8fd13 100644 --- a/src/DownloadManager.BrowserBridge/Program.cs +++ b/src/DownloadManager.BrowserBridge/Program.cs @@ -61,32 +61,55 @@ class Program static async Task SendToMainAppAsync(BridgeMessage msg) { + string logDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "DownloadManager", "logs"); + if (!Directory.Exists(logDir)) Directory.CreateDirectory(logDir); + string logPath = Path.Combine(logDir, "bridge.log"); + try { // Ana uygulamanın çalışıp çalışmadığını kontrol et var processes = System.Diagnostics.Process.GetProcessesByName("hDM"); if (processes.Length == 0) { - // Uygulama çalışmıyorsa başlat (Yolu bulmaya çalışalım) - string appPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "hDM.exe"); + // Uygulama çalışmıyorsa başlat + // Önce kök dizine (proje kökü) çıkıp bin/Debug veya bin/Release kontrolü yapalım + string baseDir = AppDomain.CurrentDomain.BaseDirectory; + string appPath = Path.Combine(baseDir, "hDM.exe"); - // Geliştirme ortamı için alternatif yollar + // Geliştirme ortamı için alternatifler if (!File.Exists(appPath)) - appPath = @"D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.WPF\bin\Release\net8.0-windows\hDM.exe"; + { + // Bridge'den WPF bin klasörüne çıkmaya çalış + var di = new DirectoryInfo(baseDir); + // D:\...\DownloadManager\src\DownloadManager.BrowserBridge\bin\Release\net8.0 + // Buradan 4 seviye yukarı çıkarsak src'ye ulaşırız + if (di.Parent?.Parent?.Parent?.Parent != null) + { + string wpfBin = Path.Combine(di.Parent.Parent.Parent.Parent.FullName, "src", "DownloadManager.WPF", "bin", "Debug", "net8.0-windows10.0.19041.0", "hDM.exe"); + if (File.Exists(wpfBin)) appPath = wpfBin; + else + { + wpfBin = Path.Combine(di.Parent.Parent.Parent.Parent.FullName, "src", "DownloadManager.WPF", "bin", "Release", "net8.0-windows10.0.19041.0", "hDM.exe"); + if (File.Exists(wpfBin)) appPath = wpfBin; + } + } + } if (File.Exists(appPath)) { - System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(appPath) { UseShellExecute = true }); - // Uygulamanın açılması ve pipe'ı başlatması için biraz bekleyelim + System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(appPath) { UseShellExecute = true, WorkingDirectory = Path.GetDirectoryName(appPath) }); await Task.Delay(3000); } + else + { + File.AppendAllText(logPath, $"{DateTime.Now}: Uygulama bulunamadı: {appPath}\n"); + } } using var pipe = new NamedPipeClientStream(".", "DownloadManagerPipe", PipeDirection.Out, PipeOptions.Asynchronous); - // Timeout'u 10 saniyeye çıkaralım (Uygulama yeni açılıyorsa gerekebilir) - await pipe.ConnectAsync(10000); + await pipe.ConnectAsync(5000); var json = JsonConvert.SerializeObject(msg); var data = Encoding.UTF8.GetBytes(json); @@ -96,7 +119,7 @@ class Program } catch (Exception ex) { - File.AppendAllText("bridge_error.log", $"{DateTime.Now}: Bağlantı hatası ({msg.Url}): {ex.Message}\n"); + File.AppendAllText(logPath, $"{DateTime.Now}: Bağlantı hatası ({msg.Url}): {ex.Message}\n"); } } } diff --git a/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.deps.json b/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.deps.json new file mode 100644 index 0000000..12f5271 --- /dev/null +++ b/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.deps.json @@ -0,0 +1,41 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v8.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v8.0": { + "DownloadManager.BrowserBridge/1.0.0": { + "dependencies": { + "Newtonsoft.Json": "13.0.4" + }, + "runtime": { + "DownloadManager.BrowserBridge.dll": {} + } + }, + "Newtonsoft.Json/13.0.4": { + "runtime": { + "lib/net6.0/Newtonsoft.Json.dll": { + "assemblyVersion": "13.0.0.0", + "fileVersion": "13.0.4.30916" + } + } + } + } + }, + "libraries": { + "DownloadManager.BrowserBridge/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "Newtonsoft.Json/13.0.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-pdgNNMai3zv51W5aq268sujXUyx7SNdE2bj1wZcWjAQrKMFZV260lbqYop1d2GM67JI1huLRwxo9ZqnfF/lC6A==", + "path": "newtonsoft.json/13.0.4", + "hashPath": "newtonsoft.json.13.0.4.nupkg.sha512" + } + } +} \ No newline at end of file diff --git a/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.dll b/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.dll new file mode 100644 index 0000000..0964ab5 Binary files /dev/null and b/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.dll differ diff --git a/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.exe b/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.exe new file mode 100644 index 0000000..52fc309 Binary files /dev/null and b/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.exe differ diff --git a/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.pdb b/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.pdb new file mode 100644 index 0000000..90b5fb4 Binary files /dev/null and b/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.pdb differ diff --git a/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.runtimeconfig.json b/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.runtimeconfig.json new file mode 100644 index 0000000..becfaea --- /dev/null +++ b/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/DownloadManager.BrowserBridge.runtimeconfig.json @@ -0,0 +1,12 @@ +{ + "runtimeOptions": { + "tfm": "net8.0", + "framework": { + "name": "Microsoft.NETCore.App", + "version": "8.0.0" + }, + "configProperties": { + "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false + } + } +} \ No newline at end of file diff --git a/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/Newtonsoft.Json.dll b/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/Newtonsoft.Json.dll new file mode 100644 index 0000000..5813d8c Binary files /dev/null and b/src/DownloadManager.BrowserBridge/bin/Debug/net8.0/Newtonsoft.Json.dll differ diff --git a/src/DownloadManager.BrowserBridge/bin/Release/net8.0/DownloadManager.BrowserBridge.dll b/src/DownloadManager.BrowserBridge/bin/Release/net8.0/DownloadManager.BrowserBridge.dll index 884e47e..fd152cd 100644 Binary files a/src/DownloadManager.BrowserBridge/bin/Release/net8.0/DownloadManager.BrowserBridge.dll and b/src/DownloadManager.BrowserBridge/bin/Release/net8.0/DownloadManager.BrowserBridge.dll differ diff --git a/src/DownloadManager.BrowserBridge/bin/Release/net8.0/DownloadManager.BrowserBridge.exe b/src/DownloadManager.BrowserBridge/bin/Release/net8.0/DownloadManager.BrowserBridge.exe index a2bf350..52fc309 100644 Binary files a/src/DownloadManager.BrowserBridge/bin/Release/net8.0/DownloadManager.BrowserBridge.exe and b/src/DownloadManager.BrowserBridge/bin/Release/net8.0/DownloadManager.BrowserBridge.exe differ diff --git a/src/DownloadManager.BrowserBridge/bin/Release/net8.0/DownloadManager.BrowserBridge.pdb b/src/DownloadManager.BrowserBridge/bin/Release/net8.0/DownloadManager.BrowserBridge.pdb index d4b151f..b11f4ae 100644 Binary files a/src/DownloadManager.BrowserBridge/bin/Release/net8.0/DownloadManager.BrowserBridge.pdb and b/src/DownloadManager.BrowserBridge/bin/Release/net8.0/DownloadManager.BrowserBridge.pdb differ diff --git a/src/DownloadManager.BrowserBridge/hdm_bridge.ico b/src/DownloadManager.BrowserBridge/hdm_bridge.ico new file mode 100644 index 0000000..4b56e17 Binary files /dev/null and b/src/DownloadManager.BrowserBridge/hdm_bridge.ico differ diff --git a/src/DownloadManager.BrowserBridge/manifest.json b/src/DownloadManager.BrowserBridge/manifest.json index 7e220b9..5f69f04 100644 --- a/src/DownloadManager.BrowserBridge/manifest.json +++ b/src/DownloadManager.BrowserBridge/manifest.json @@ -4,6 +4,7 @@ "path": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.BrowserBridge\\bin\\Release\\net8.0\\DownloadManager.BrowserBridge.exe", "type": "stdio", "allowed_origins": [ - "chrome-extension://gnohncemfbplcagkfdhedbkfaogcoobi/" + "chrome-extension://dnpggiajimpjhghjppekgpejplkcbejg", + "chrome-extension://gnohncemfbplcagkfdhedbkfaogcoobi" ] } diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/Download.A73557B5.Up2Date b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/Download.A73557B5.Up2Date new file mode 100644 index 0000000..e69de29 diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.AssemblyInfo.cs b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.AssemblyInfo.cs new file mode 100644 index 0000000..d172a4c --- /dev/null +++ b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.AssemblyInfo.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("DownloadManager.BrowserBridge")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+561a953b1f10b7ec16bef81fdcd4030ad9d5f1e4")] +[assembly: System.Reflection.AssemblyProductAttribute("DownloadManager.BrowserBridge")] +[assembly: System.Reflection.AssemblyTitleAttribute("DownloadManager.BrowserBridge")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// MSBuild WriteCodeFragment sınıfı tarafından oluşturuldu. + diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.AssemblyInfoInputs.cache b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.AssemblyInfoInputs.cache new file mode 100644 index 0000000..42afb00 --- /dev/null +++ b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +113565b263fcdda4a4665ee4bb805cc1b4b99e5585e061be924810699276bedd diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.GeneratedMSBuildEditorConfig.editorconfig b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..7fa6b73 --- /dev/null +++ b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,15 @@ +is_global = true +build_property.TargetFramework = net8.0 +build_property.TargetPlatformMinVersion = +build_property.UsingMicrosoftNETSdkWeb = +build_property.ProjectTypeGuids = +build_property.InvariantGlobalization = +build_property.PlatformNeutralAssembly = +build_property.EnforceExtendedAnalyzerRules = +build_property._SupportedPlatformList = Linux,macOS,Windows +build_property.RootNamespace = DownloadManager.BrowserBridge +build_property.ProjectDir = D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = +build_property.EffectiveAnalysisLevelStyle = 8.0 +build_property.EnableCodeStyleSeverity = diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.assets.cache b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.assets.cache index 406689f..02eff60 100644 Binary files a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.assets.cache and b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.assets.cache differ diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.csproj.AssemblyReference.cache b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.csproj.AssemblyReference.cache new file mode 100644 index 0000000..63736d8 Binary files /dev/null and b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.csproj.AssemblyReference.cache differ diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.csproj.CoreCompileInputs.cache b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..7698ce7 --- /dev/null +++ b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +5fd99a422a78009cff8ca33e1127d7f18d84d9f6b01faca46a390be79a246ed9 diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.csproj.FileListAbsolute.txt b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.csproj.FileListAbsolute.txt index e69de29..8f910f8 100644 --- a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.csproj.FileListAbsolute.txt +++ b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.csproj.FileListAbsolute.txt @@ -0,0 +1,17 @@ +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\bin\Debug\net8.0\DownloadManager.BrowserBridge.exe +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\bin\Debug\net8.0\DownloadManager.BrowserBridge.deps.json +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\bin\Debug\net8.0\DownloadManager.BrowserBridge.runtimeconfig.json +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\bin\Debug\net8.0\DownloadManager.BrowserBridge.dll +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\bin\Debug\net8.0\DownloadManager.BrowserBridge.pdb +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\bin\Debug\net8.0\Newtonsoft.Json.dll +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\obj\Debug\net8.0\DownloadManager.BrowserBridge.csproj.AssemblyReference.cache +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\obj\Debug\net8.0\DownloadManager.BrowserBridge.GeneratedMSBuildEditorConfig.editorconfig +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\obj\Debug\net8.0\DownloadManager.BrowserBridge.AssemblyInfoInputs.cache +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\obj\Debug\net8.0\DownloadManager.BrowserBridge.AssemblyInfo.cs +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\obj\Debug\net8.0\DownloadManager.BrowserBridge.csproj.CoreCompileInputs.cache +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\obj\Debug\net8.0\Download.A73557B5.Up2Date +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\obj\Debug\net8.0\DownloadManager.BrowserBridge.dll +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\obj\Debug\net8.0\refint\DownloadManager.BrowserBridge.dll +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\obj\Debug\net8.0\DownloadManager.BrowserBridge.pdb +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\obj\Debug\net8.0\DownloadManager.BrowserBridge.genruntimeconfig.cache +D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\obj\Debug\net8.0\ref\DownloadManager.BrowserBridge.dll diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.dll b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.dll new file mode 100644 index 0000000..0964ab5 Binary files /dev/null and b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.dll differ diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.genruntimeconfig.cache b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.genruntimeconfig.cache new file mode 100644 index 0000000..fcdb4c0 --- /dev/null +++ b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.genruntimeconfig.cache @@ -0,0 +1 @@ +55a289d435d94f5304dfb112e526c2c5fd4f8dced6fb87cc465459bf16bab373 diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.pdb b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.pdb new file mode 100644 index 0000000..90b5fb4 Binary files /dev/null and b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.pdb differ diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/apphost.exe b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/apphost.exe index a2bf350..52fc309 100644 Binary files a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/apphost.exe and b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/apphost.exe differ diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/ref/DownloadManager.BrowserBridge.dll b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/ref/DownloadManager.BrowserBridge.dll new file mode 100644 index 0000000..85b2bb5 Binary files /dev/null and b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/ref/DownloadManager.BrowserBridge.dll differ diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/refint/DownloadManager.BrowserBridge.dll b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/refint/DownloadManager.BrowserBridge.dll new file mode 100644 index 0000000..85b2bb5 Binary files /dev/null and b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/refint/DownloadManager.BrowserBridge.dll differ diff --git a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.AssemblyInfo.cs b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.AssemblyInfo.cs index fd003aa..6183b5f 100644 --- a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.AssemblyInfo.cs +++ b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.AssemblyInfo.cs @@ -1,7 +1,6 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -14,10 +13,10 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("DownloadManager.BrowserBridge")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+81faa715a4eb11a2bf648f52891306b46ea7c256")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+561a953b1f10b7ec16bef81fdcd4030ad9d5f1e4")] [assembly: System.Reflection.AssemblyProductAttribute("DownloadManager.BrowserBridge")] [assembly: System.Reflection.AssemblyTitleAttribute("DownloadManager.BrowserBridge")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] -// Generated by the MSBuild WriteCodeFragment class. +// MSBuild WriteCodeFragment sınıfı tarafından oluşturuldu. diff --git a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.AssemblyInfoInputs.cache b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.AssemblyInfoInputs.cache index abd71e8..c56e903 100644 --- a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.AssemblyInfoInputs.cache +++ b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.AssemblyInfoInputs.cache @@ -1 +1 @@ -c41154c222d4c9aaf2ac34116ff46b068de5b4633ca984a833d7394a42fc99da +f0f25ac1863349e31e231b7ddaa3d27d9e23bc3cc9323375791cbf31e36329ff diff --git a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.dll b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.dll index 884e47e..fd152cd 100644 Binary files a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.dll and b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.dll differ diff --git a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.pdb b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.pdb index d4b151f..b11f4ae 100644 Binary files a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.pdb and b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.pdb differ diff --git a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/apphost.exe b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/apphost.exe index a2bf350..52fc309 100644 Binary files a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/apphost.exe and b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/apphost.exe differ diff --git a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/ref/DownloadManager.BrowserBridge.dll b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/ref/DownloadManager.BrowserBridge.dll index d7c30f1..9b7ec07 100644 Binary files a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/ref/DownloadManager.BrowserBridge.dll and b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/ref/DownloadManager.BrowserBridge.dll differ diff --git a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/refint/DownloadManager.BrowserBridge.dll b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/refint/DownloadManager.BrowserBridge.dll index d7c30f1..9b7ec07 100644 Binary files a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/refint/DownloadManager.BrowserBridge.dll and b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/refint/DownloadManager.BrowserBridge.dll differ diff --git a/src/DownloadManager.BrowserBridge/register_bridge.reg b/src/DownloadManager.BrowserBridge/register_bridge.reg index 7ad550c..c2622f4 100644 --- a/src/DownloadManager.BrowserBridge/register_bridge.reg +++ b/src/DownloadManager.BrowserBridge/register_bridge.reg @@ -1,7 +1,9 @@ Windows Registry Editor Version 5.00 +; Google Chrome için Kayıt [HKEY_CURRENT_USER\Software\Google\Chrome\NativeMessagingHosts\com.downloadmanager.bridge] @="D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.BrowserBridge\\manifest.json" +; Microsoft Edge için Kayıt [HKEY_CURRENT_USER\Software\Microsoft\Edge\NativeMessagingHosts\com.downloadmanager.bridge] @="D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.BrowserBridge\\manifest.json" diff --git a/src/DownloadManager.Core/Data/Repositories/CategoryRepository.cs b/src/DownloadManager.Core/Data/Repositories/CategoryRepository.cs index d258af0..ce88d57 100644 --- a/src/DownloadManager.Core/Data/Repositories/CategoryRepository.cs +++ b/src/DownloadManager.Core/Data/Repositories/CategoryRepository.cs @@ -15,4 +15,30 @@ public class CategoryRepository : ICategoryRepository public async Task GetByIdAsync(int id) => await _db.Categories.FindAsync(id); + + public async Task AddAsync(DownloadCategory category) + { + _db.Categories.Add(category); + await _db.SaveChangesAsync(); + } + + public async Task UpdateAsync(DownloadCategory category) + { + var existing = await _db.Categories.FindAsync(category.Id); + if (existing != null) + { + _db.Entry(existing).CurrentValues.SetValues(category); + await _db.SaveChangesAsync(); + } + } + + public async Task DeleteAsync(int id) + { + var category = await _db.Categories.FindAsync(id); + if (category != null) + { + _db.Categories.Remove(category); + await _db.SaveChangesAsync(); + } + } } diff --git a/src/DownloadManager.Core/Data/Repositories/IRepositories.cs b/src/DownloadManager.Core/Data/Repositories/IRepositories.cs index ffc5724..c934eeb 100644 --- a/src/DownloadManager.Core/Data/Repositories/IRepositories.cs +++ b/src/DownloadManager.Core/Data/Repositories/IRepositories.cs @@ -18,6 +18,9 @@ public interface ICategoryRepository { Task> GetAllAsync(); Task GetByIdAsync(int id); + Task AddAsync(DownloadCategory category); + Task UpdateAsync(DownloadCategory category); + Task DeleteAsync(int id); } public interface ISettingsRepository diff --git a/src/DownloadManager.Core/Engine/DownloadEngine.cs b/src/DownloadManager.Core/Engine/DownloadEngine.cs index 09b0bf9..3623aba 100644 --- a/src/DownloadManager.Core/Engine/DownloadEngine.cs +++ b/src/DownloadManager.Core/Engine/DownloadEngine.cs @@ -52,6 +52,25 @@ public class DownloadEngine private async Task ProcessDownloadAsync(DownloadItem item, CancellationToken ct) { + // Kuyruktan çıktıktan sonra güncel durumu veritabanından kontrol et + using (var scope = _serviceProvider.CreateScope()) + { + var repo = scope.ServiceProvider.GetRequiredService(); + var latest = await repo.GetByIdAsync(item.Id); + + if (latest == null || latest.Status == DownloadStatus.Paused) + { + Serilog.Log.Information("İndirme {Id} duraklatılmış veya artık mevcut değil, işlem iptal edildi.", item.Id); + _queue.Release(); + return; + } + + // Eğer veritabanındaki durum farklıysa (örneğin başka bir yerden güncellendiyse) nesneyi güncelle + item.Status = latest.Status; + item.SavePath = latest.SavePath; + item.FileName = latest.FileName; + } + var cts = CancellationTokenSource.CreateLinkedTokenSource(ct); _activeDownloads[item.Id] = cts; @@ -73,13 +92,6 @@ public class DownloadEngine item.DownloadedBytes = 0; // Yeni indirme } - // DURAKLATILMIŞSA İŞLEME (Kuyruktan yeni çıktıysa ve o sırada durdurulduysa) - if (item.Status == DownloadStatus.Paused) - { - Serilog.Log.Information("İndirme {Id} duraklatıldı, atlanıyor.", item.Id); - return; - } - item.Status = DownloadStatus.Downloading; // Notify UI that we are starting diff --git a/src/DownloadManager.Core/Engine/EngineOptions.cs b/src/DownloadManager.Core/Engine/EngineOptions.cs index 5b509f0..db6b50f 100644 --- a/src/DownloadManager.Core/Engine/EngineOptions.cs +++ b/src/DownloadManager.Core/Engine/EngineOptions.cs @@ -4,7 +4,7 @@ public class EngineOptions { public int MaxSegments { get; set; } = 8; public long MinSegmentBytes { get; set; } = 512 * 1024; // 512 KB - public int MaxRetries { get; set; } = 5; + public int MaxRetries { get; set; } = 30; public int RetryDelayMs { get; set; } = 2000; public int ConnectionTimeoutSeconds { get; set; } = 30; public long SpeedLimitBytesPerSec { get; set; } = 0; // 0 = limitsiz diff --git a/src/DownloadManager.Core/Engine/SegmentedDownloader.cs b/src/DownloadManager.Core/Engine/SegmentedDownloader.cs index f20c07d..333f055 100644 --- a/src/DownloadManager.Core/Engine/SegmentedDownloader.cs +++ b/src/DownloadManager.Core/Engine/SegmentedDownloader.cs @@ -128,21 +128,29 @@ public class SegmentedDownloader : IDownloader private async Task DownloadSegmentAsync(DownloadItem item, DownloadSegment segment, string tempDir, IProgress? progress, CancellationToken ct) { int retryCount = 0; - while (true) + Interlocked.Increment(ref _activeSegmentCount); + try { - try + while (true) { - await PerformSegmentDownloadAsync(item, segment, tempDir, progress, ct); - break; - } - catch (Exception ex) when (retryCount < _options.MaxRetries && !ct.IsCancellationRequested) - { - retryCount++; - Serilog.Log.Warning("Parça {Index} indirilemedi (Deneme {Count}/{Max}): {Error}", - segment.Index, retryCount, _options.MaxRetries, ex.Message); - await Task.Delay(_options.RetryDelayMs * retryCount, ct); + try + { + await PerformSegmentDownloadAsync(item, segment, tempDir, progress, ct); + break; + } + catch (Exception ex) when (retryCount < _options.MaxRetries && !ct.IsCancellationRequested) + { + retryCount++; + Serilog.Log.Warning("Parça {Index} indirilemedi (Deneme {Count}/{Max}): {Error}", + segment.Index, retryCount, _options.MaxRetries, ex.Message); + await Task.Delay((_options.RetryDelayMs * retryCount) + Random.Shared.Next(1000), ct); + } } } + finally + { + Interlocked.Decrement(ref _activeSegmentCount); + } } private async Task PerformSegmentDownloadAsync(DownloadItem item, DownloadSegment segment, string tempDir, IProgress? progress, CancellationToken ct) @@ -168,9 +176,15 @@ public class SegmentedDownloader : IDownloader var buffer = new byte[8192]; int read; - while ((read = await stream.ReadAsync(buffer, 0, buffer.Length, ct)) > 0) + while (true) { - await fileStream.WriteAsync(buffer, 0, read, ct); + // Read with timeout to prevent hanging on network loss + read = await stream.ReadAsync(buffer, ct).AsTask() + .WaitAsync(TimeSpan.FromSeconds(_options.ConnectionTimeoutSeconds), ct); + + if (read == 0) break; + + await fileStream.WriteAsync(buffer.AsMemory(0, read), ct); segment.Downloaded += read; lock (_progressLock) @@ -186,6 +200,8 @@ public class SegmentedDownloader : IDownloader segment.Status = SegmentStatus.Completed; } + private int _activeSegmentCount = 0; + private void ReportProgress(DownloadItem item, IProgress? progress) { if ((DateTime.UtcNow - _lastReport).TotalMilliseconds < 250) return; @@ -203,7 +219,8 @@ public class SegmentedDownloader : IDownloader ProgressPercent = percent, SpeedBytesPerSec = _speedCalculator.GetBytesPerSecond(), EstimatedRemaining = _speedCalculator.EstimateRemaining(item.TotalSize - downloaded), - Status = DownloadStatus.Downloading + Status = DownloadStatus.Downloading, + ActiveSegments = _activeSegmentCount }); } diff --git a/src/DownloadManager.Core/Engine/SingleDownloader.cs b/src/DownloadManager.Core/Engine/SingleDownloader.cs index 0bfd324..50741ab 100644 --- a/src/DownloadManager.Core/Engine/SingleDownloader.cs +++ b/src/DownloadManager.Core/Engine/SingleDownloader.cs @@ -43,7 +43,7 @@ public class SingleDownloader : IDownloader retryCount++; Serilog.Log.Warning("Tekil indirme başarısız (Deneme {Count}/{Max}): {Error}", retryCount, _options.MaxRetries, ex.Message); - await Task.Delay(_options.RetryDelayMs * retryCount, ct); + await Task.Delay((_options.RetryDelayMs * retryCount) + Random.Shared.Next(1000), ct); } } } @@ -87,9 +87,15 @@ public class SingleDownloader : IDownloader var buffer = new byte[8192]; int read; - while ((read = await contentStream.ReadAsync(buffer, 0, buffer.Length, ct)) > 0) + while (true) { - await fileStream.WriteAsync(buffer, 0, read, ct); + // Read with timeout to prevent hanging on network loss + read = await contentStream.ReadAsync(buffer, ct).AsTask() + .WaitAsync(TimeSpan.FromSeconds(_options.ConnectionTimeoutSeconds), ct); + + if (read <= 0) break; + + await fileStream.WriteAsync(buffer.AsMemory(0, read), ct); item.DownloadedBytes += read; _speedCalculator.AddSample(read); diff --git a/src/DownloadManager.Core/Events/DownloadProgressEvent.cs b/src/DownloadManager.Core/Events/DownloadProgressEvent.cs index a4ec767..9b8dc91 100644 --- a/src/DownloadManager.Core/Events/DownloadProgressEvent.cs +++ b/src/DownloadManager.Core/Events/DownloadProgressEvent.cs @@ -12,4 +12,5 @@ public class DownloadProgressEvent public long SpeedBytesPerSec { get; set; } public TimeSpan? EstimatedRemaining { get; set; } public DownloadStatus Status { get; set; } + public int ActiveSegments { get; set; } } diff --git a/src/DownloadManager.Core/Services/CategoryService.cs b/src/DownloadManager.Core/Services/CategoryService.cs index b9057de..0011fb2 100644 --- a/src/DownloadManager.Core/Services/CategoryService.cs +++ b/src/DownloadManager.Core/Services/CategoryService.cs @@ -1,6 +1,9 @@ using DownloadManager.Core.Data.Repositories; using DownloadManager.Core.Models; +using System; using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Threading.Tasks; namespace DownloadManager.Core.Services; @@ -8,6 +11,10 @@ namespace DownloadManager.Core.Services; public interface ICategoryService { Task> GetCategoriesAsync(); + Task AddCategoryAsync(DownloadCategory category); + Task UpdateCategoryAsync(DownloadCategory category); + Task DeleteCategoryAsync(int id); + Task GetCategoryIdByExtensionAsync(string fileName); } public class CategoryService : ICategoryService @@ -17,4 +24,34 @@ public class CategoryService : ICategoryService public Task> GetCategoriesAsync() => _repository.GetAllAsync(); + + public Task AddCategoryAsync(DownloadCategory category) + => _repository.AddAsync(category); + + public Task UpdateCategoryAsync(DownloadCategory category) + => _repository.UpdateAsync(category); + + public Task DeleteCategoryAsync(int id) + => _repository.DeleteAsync(id); + + public async Task GetCategoryIdByExtensionAsync(string fileName) + { + var ext = Path.GetExtension(fileName).TrimStart('.').ToLower(); + var categories = await _repository.GetAllAsync(); + + foreach (var cat in categories) + { + if (string.IsNullOrWhiteSpace(cat.Extensions)) continue; + + var extensions = cat.Extensions.Split(',', StringSplitOptions.RemoveEmptyEntries) + .Select(x => x.Trim().ToLower()); + if (extensions.Contains(ext)) + { + return cat.Id; + } + } + + var other = categories.FirstOrDefault(c => c.Name == "Other" || c.Name == "Diğer"); + return other?.Id ?? 6; + } } diff --git a/src/DownloadManager.Core/Services/DownloadService.cs b/src/DownloadManager.Core/Services/DownloadService.cs index 85dc9fd..ecb5a52 100644 --- a/src/DownloadManager.Core/Services/DownloadService.cs +++ b/src/DownloadManager.Core/Services/DownloadService.cs @@ -45,10 +45,15 @@ public class DownloadService : IDownloadService await _repository.UpdateAsync(item); } - public Task PauseDownloadAsync(Guid id) + public async Task PauseDownloadAsync(Guid id) { + var item = await _repository.GetByIdAsync(id); + if (item != null) + { + item.Status = Enums.DownloadStatus.Paused; + await _repository.UpdateAsync(item); + } _engine.CancelDownload(id); - return Task.CompletedTask; } public async Task ResumeDownloadAsync(Guid id) diff --git a/src/DownloadManager.Core/Services/SchedulerWatchdog.cs b/src/DownloadManager.Core/Services/SchedulerWatchdog.cs index 3fc8dcd..6a6b1a3 100644 --- a/src/DownloadManager.Core/Services/SchedulerWatchdog.cs +++ b/src/DownloadManager.Core/Services/SchedulerWatchdog.cs @@ -1,4 +1,5 @@ using DownloadManager.Core.Models; +using Microsoft.Extensions.DependencyInjection; using System; using System.Linq; using System.Threading; @@ -8,15 +9,13 @@ namespace DownloadManager.Core.Services; public class SchedulerWatchdog { - private readonly IScheduleService _scheduleService; - private readonly IDownloadService _downloadService; + private readonly IServiceProvider _serviceProvider; private Timer? _timer; private bool _isProcessing; - public SchedulerWatchdog(IScheduleService scheduleService, IDownloadService downloadService) + public SchedulerWatchdog(IServiceProvider serviceProvider) { - _scheduleService = scheduleService; - _downloadService = downloadService; + _serviceProvider = serviceProvider; } public void Start() @@ -39,7 +38,10 @@ public class SchedulerWatchdog try { - var jobs = await _scheduleService.GetJobsAsync(); + using var scope = _serviceProvider.CreateScope(); + var scheduleService = scope.ServiceProvider.GetRequiredService(); + + var jobs = await scheduleService.GetJobsAsync(); var activeJob = jobs.FirstOrDefault(j => j.IsActive); if (activeJob == null) return; @@ -49,9 +51,6 @@ public class SchedulerWatchdog // Gün kontrolü int dayIndex = (int)now.DayOfWeek; // 0=Pazar, 1=Pazartesi... - // Model Pt=0, Pz=6 şeklinde varsayılmıştı (1111111) - // .NET DayOfWeek: Sunday=0, Monday=1... - // Dönüştürelim: Pt=0 için int adjustedIndex = dayIndex == 0 ? 6 : dayIndex - 1; if (activeJob.DaysOfWeek[adjustedIndex] == '0') return; @@ -60,10 +59,9 @@ public class SchedulerWatchdog if (activeJob.StartTime.HasValue) { var startTime = activeJob.StartTime.Value.TimeOfDay; - // Başlangıç vaktinden sonraki 1 dakika içindeysek başlat (sürekli tetiklenmemesi için) if (currentTime >= startTime && currentTime < startTime.Add(TimeSpan.FromMinutes(1))) { - await StartScheduledDownloads(); + await StartScheduledDownloads(scope.ServiceProvider.GetRequiredService()); } } @@ -73,7 +71,7 @@ public class SchedulerWatchdog var endTime = activeJob.EndTime.Value.TimeOfDay; if (currentTime >= endTime && currentTime < endTime.Add(TimeSpan.FromMinutes(1))) { - await StopAllDownloads(); + await StopAllDownloads(scope.ServiceProvider.GetRequiredService()); } } } @@ -87,27 +85,27 @@ public class SchedulerWatchdog } } - private async Task StartScheduledDownloads() + private async Task StartScheduledDownloads(IDownloadService downloadService) { Serilog.Log.Information("Zamanlayıcı: İndirmeler başlatılıyor..."); - var downloads = await _downloadService.GetAllDownloadsAsync(); + var downloads = await downloadService.GetAllDownloadsAsync(); var pending = downloads.Where(d => d.Status == Enums.DownloadStatus.Paused || d.Status == Enums.DownloadStatus.Pending); foreach (var item in pending) { - await _downloadService.ResumeDownloadAsync(item.Id); + await downloadService.ResumeDownloadAsync(item.Id); } } - private async Task StopAllDownloads() + private async Task StopAllDownloads(IDownloadService downloadService) { Serilog.Log.Information("Zamanlayıcı: İndirmeler durduruluyor..."); - var downloads = await _downloadService.GetAllDownloadsAsync(); + var downloads = await downloadService.GetAllDownloadsAsync(); var active = downloads.Where(d => d.Status == Enums.DownloadStatus.Downloading || d.Status == Enums.DownloadStatus.Queued); foreach (var item in active) { - await _downloadService.PauseDownloadAsync(item.Id); + await downloadService.PauseDownloadAsync(item.Id); } } } diff --git a/src/DownloadManager.Core/bin/Debug/net8.0/DownloadManager.Core.dll b/src/DownloadManager.Core/bin/Debug/net8.0/DownloadManager.Core.dll index cf0f1c2..a87c957 100644 Binary files a/src/DownloadManager.Core/bin/Debug/net8.0/DownloadManager.Core.dll and b/src/DownloadManager.Core/bin/Debug/net8.0/DownloadManager.Core.dll differ diff --git a/src/DownloadManager.Core/bin/Debug/net8.0/DownloadManager.Core.pdb b/src/DownloadManager.Core/bin/Debug/net8.0/DownloadManager.Core.pdb index c94400a..d2311de 100644 Binary files a/src/DownloadManager.Core/bin/Debug/net8.0/DownloadManager.Core.pdb and b/src/DownloadManager.Core/bin/Debug/net8.0/DownloadManager.Core.pdb differ diff --git a/src/DownloadManager.Core/bin/Release/net8.0/DownloadManager.Core.dll b/src/DownloadManager.Core/bin/Release/net8.0/DownloadManager.Core.dll index 0107600..a5472d2 100644 Binary files a/src/DownloadManager.Core/bin/Release/net8.0/DownloadManager.Core.dll and b/src/DownloadManager.Core/bin/Release/net8.0/DownloadManager.Core.dll differ diff --git a/src/DownloadManager.Core/bin/Release/net8.0/DownloadManager.Core.pdb b/src/DownloadManager.Core/bin/Release/net8.0/DownloadManager.Core.pdb index 7a1897a..9847411 100644 Binary files a/src/DownloadManager.Core/bin/Release/net8.0/DownloadManager.Core.pdb and b/src/DownloadManager.Core/bin/Release/net8.0/DownloadManager.Core.pdb differ diff --git a/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.AssemblyInfo.cs b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.AssemblyInfo.cs index 2980be3..8d9e37f 100644 --- a/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.AssemblyInfo.cs +++ b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("DownloadManager.Core")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+81faa715a4eb11a2bf648f52891306b46ea7c256")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+561a953b1f10b7ec16bef81fdcd4030ad9d5f1e4")] [assembly: System.Reflection.AssemblyProductAttribute("DownloadManager.Core")] [assembly: System.Reflection.AssemblyTitleAttribute("DownloadManager.Core")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.AssemblyInfoInputs.cache b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.AssemblyInfoInputs.cache index c4f481d..8396c31 100644 --- a/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.AssemblyInfoInputs.cache +++ b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.AssemblyInfoInputs.cache @@ -1 +1 @@ -57eee8222b0d77ae6e394591882c8d91daaa59ea38bf4b29e8d5d32072290d1d +355e174528e4d22ee7c251d97b3ad390b2cefbca24bdd6f2d576299a7fce3925 diff --git a/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.dll b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.dll index cf0f1c2..a87c957 100644 Binary files a/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.dll and b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.dll differ diff --git a/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.pdb b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.pdb index c94400a..d2311de 100644 Binary files a/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.pdb and b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.pdb differ diff --git a/src/DownloadManager.Core/obj/Debug/net8.0/ref/DownloadManager.Core.dll b/src/DownloadManager.Core/obj/Debug/net8.0/ref/DownloadManager.Core.dll index 4d2cc8a..07f6824 100644 Binary files a/src/DownloadManager.Core/obj/Debug/net8.0/ref/DownloadManager.Core.dll and b/src/DownloadManager.Core/obj/Debug/net8.0/ref/DownloadManager.Core.dll differ diff --git a/src/DownloadManager.Core/obj/Debug/net8.0/refint/DownloadManager.Core.dll b/src/DownloadManager.Core/obj/Debug/net8.0/refint/DownloadManager.Core.dll index 4d2cc8a..07f6824 100644 Binary files a/src/DownloadManager.Core/obj/Debug/net8.0/refint/DownloadManager.Core.dll and b/src/DownloadManager.Core/obj/Debug/net8.0/refint/DownloadManager.Core.dll differ diff --git a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.AssemblyInfo.cs b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.AssemblyInfo.cs index f34646d..00b4966 100644 --- a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.AssemblyInfo.cs +++ b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.AssemblyInfo.cs @@ -1,7 +1,6 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -14,10 +13,10 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("DownloadManager.Core")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+81faa715a4eb11a2bf648f52891306b46ea7c256")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+561a953b1f10b7ec16bef81fdcd4030ad9d5f1e4")] [assembly: System.Reflection.AssemblyProductAttribute("DownloadManager.Core")] [assembly: System.Reflection.AssemblyTitleAttribute("DownloadManager.Core")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] -// Generated by the MSBuild WriteCodeFragment class. +// MSBuild WriteCodeFragment sınıfı tarafından oluşturuldu. diff --git a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.AssemblyInfoInputs.cache b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.AssemblyInfoInputs.cache index b3081aa..426a715 100644 --- a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.AssemblyInfoInputs.cache +++ b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.AssemblyInfoInputs.cache @@ -1 +1 @@ -86922a9eccfa1e5736aa220690f23d77712e45c8681c90dab58e4b60acfd7921 +62c36dfd3abfff411d19bf2d9f22e0bd666e57c1af0629fcae7d4ef188fe9e95 diff --git a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.dll b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.dll index 0107600..a5472d2 100644 Binary files a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.dll and b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.dll differ diff --git a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.pdb b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.pdb index 7a1897a..9847411 100644 Binary files a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.pdb and b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.pdb differ diff --git a/src/DownloadManager.Core/obj/Release/net8.0/ref/DownloadManager.Core.dll b/src/DownloadManager.Core/obj/Release/net8.0/ref/DownloadManager.Core.dll index 4bad732..ea1d5af 100644 Binary files a/src/DownloadManager.Core/obj/Release/net8.0/ref/DownloadManager.Core.dll and b/src/DownloadManager.Core/obj/Release/net8.0/ref/DownloadManager.Core.dll differ diff --git a/src/DownloadManager.Core/obj/Release/net8.0/refint/DownloadManager.Core.dll b/src/DownloadManager.Core/obj/Release/net8.0/refint/DownloadManager.Core.dll index 4bad732..ea1d5af 100644 Binary files a/src/DownloadManager.Core/obj/Release/net8.0/refint/DownloadManager.Core.dll and b/src/DownloadManager.Core/obj/Release/net8.0/refint/DownloadManager.Core.dll differ diff --git a/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.Core.dll b/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.Core.dll index 0107600..a5472d2 100644 Binary files a/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.Core.dll and b/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.Core.dll differ diff --git a/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.Core.pdb b/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.Core.pdb index 7a1897a..9847411 100644 Binary files a/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.Core.pdb and b/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.Core.pdb differ diff --git a/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.TestConsole.dll b/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.TestConsole.dll index 10879a8..337a2f3 100644 Binary files a/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.TestConsole.dll and b/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.TestConsole.dll differ diff --git a/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.TestConsole.exe b/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.TestConsole.exe index 3b70f07..70bf064 100644 Binary files a/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.TestConsole.exe and b/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.TestConsole.exe differ diff --git a/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.TestConsole.pdb b/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.TestConsole.pdb index 0acc271..fffcfb2 100644 Binary files a/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.TestConsole.pdb and b/src/DownloadManager.TestConsole/bin/Release/net8.0/DownloadManager.TestConsole.pdb differ diff --git a/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.AssemblyInfo.cs b/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.AssemblyInfo.cs index 6689b0b..78e51d7 100644 --- a/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.AssemblyInfo.cs +++ b/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.AssemblyInfo.cs @@ -1,7 +1,6 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -14,10 +13,10 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("DownloadManager.TestConsole")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+81faa715a4eb11a2bf648f52891306b46ea7c256")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+561a953b1f10b7ec16bef81fdcd4030ad9d5f1e4")] [assembly: System.Reflection.AssemblyProductAttribute("DownloadManager.TestConsole")] [assembly: System.Reflection.AssemblyTitleAttribute("DownloadManager.TestConsole")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] -// Generated by the MSBuild WriteCodeFragment class. +// MSBuild WriteCodeFragment sınıfı tarafından oluşturuldu. diff --git a/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.AssemblyInfoInputs.cache b/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.AssemblyInfoInputs.cache index b3061f7..f8ba201 100644 --- a/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.AssemblyInfoInputs.cache +++ b/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.AssemblyInfoInputs.cache @@ -1 +1 @@ -ca6e1ab4507e84385d05f14541ed3151a50c58ff919b0dc872c1409753ebe984 +eb1425e8d7f5855caa9e9266e09a3f32bbe7a7b2ce13f06d61c757365565f828 diff --git a/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.csproj.AssemblyReference.cache b/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.csproj.AssemblyReference.cache index 1b2997c..75f7d50 100644 Binary files a/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.csproj.AssemblyReference.cache and b/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.csproj.AssemblyReference.cache differ diff --git a/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.dll b/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.dll index 10879a8..337a2f3 100644 Binary files a/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.dll and b/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.dll differ diff --git a/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.pdb b/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.pdb index 0acc271..fffcfb2 100644 Binary files a/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.pdb and b/src/DownloadManager.TestConsole/obj/Release/net8.0/DownloadManager.TestConsole.pdb differ diff --git a/src/DownloadManager.TestConsole/obj/Release/net8.0/apphost.exe b/src/DownloadManager.TestConsole/obj/Release/net8.0/apphost.exe index 3b70f07..70bf064 100644 Binary files a/src/DownloadManager.TestConsole/obj/Release/net8.0/apphost.exe and b/src/DownloadManager.TestConsole/obj/Release/net8.0/apphost.exe differ diff --git a/src/DownloadManager.TestConsole/obj/Release/net8.0/ref/DownloadManager.TestConsole.dll b/src/DownloadManager.TestConsole/obj/Release/net8.0/ref/DownloadManager.TestConsole.dll index 87cd082..f27d432 100644 Binary files a/src/DownloadManager.TestConsole/obj/Release/net8.0/ref/DownloadManager.TestConsole.dll and b/src/DownloadManager.TestConsole/obj/Release/net8.0/ref/DownloadManager.TestConsole.dll differ diff --git a/src/DownloadManager.TestConsole/obj/Release/net8.0/refint/DownloadManager.TestConsole.dll b/src/DownloadManager.TestConsole/obj/Release/net8.0/refint/DownloadManager.TestConsole.dll index 87cd082..f27d432 100644 Binary files a/src/DownloadManager.TestConsole/obj/Release/net8.0/refint/DownloadManager.TestConsole.dll and b/src/DownloadManager.TestConsole/obj/Release/net8.0/refint/DownloadManager.TestConsole.dll differ diff --git a/src/DownloadManager.WPF/App.xaml.cs b/src/DownloadManager.WPF/App.xaml.cs index 842e1df..3dc0845 100644 --- a/src/DownloadManager.WPF/App.xaml.cs +++ b/src/DownloadManager.WPF/App.xaml.cs @@ -7,8 +7,10 @@ using DownloadManager.Core.Models; using DownloadManager.Core.Protocols; using DownloadManager.Core.Queue; using DownloadManager.Core.Services; +using DownloadManager.WPF.Helpers; using DownloadManager.WPF.ViewModels; using DownloadManager.WPF.Views; +// ... (rest of imports should be fine) using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -29,6 +31,7 @@ public partial class App : System.Windows.Application { private IHost _host; private CancellationTokenSource _pipeCts = new(); + private static Mutex? _mutex; private static string GetExceptionDetails(Exception? ex) { @@ -80,19 +83,19 @@ public partial class App : System.Windows.Application // Veritabanı var dbPath = Path.Combine(GetAppDataPath(), "downloadmanager.db"); services.AddDbContext(opt => - opt.UseSqlite($"Data Source={dbPath}"), ServiceLifetime.Singleton); + opt.UseSqlite($"Data Source={dbPath}"), ServiceLifetime.Transient); // Repositories - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); // Services - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddSingleton(); // Altyapı ve Motor @@ -137,6 +140,14 @@ public partial class App : System.Windows.Application protected override async void OnStartup(StartupEventArgs e) { + _mutex = new Mutex(true, "hDM_SingleInstance_Mutex", out bool createdNew); + if (!createdNew) + { + // Zaten bir örnek çalışıyor + System.Windows.Application.Current.Shutdown(); + return; + } + base.OnStartup(e); try @@ -164,13 +175,13 @@ public partial class App : System.Windows.Application var mainWindow = _host.Services.GetRequiredService(); var mainVm = _host.Services.GetRequiredService(); var watchdog = _host.Services.GetRequiredService(); - - mainWindow.DataContext = mainVm; - + var categoryService = _host.Services.GetRequiredService(); + + mainWindow.DataContext = mainVm; await Helpers.WindowStateHelper.LoadStateAsync(mainWindow, settings); // Browser Bridge için Named Pipe Sunucusunu Başlat - _ = StartPipeServerAsync(downloadService, protocol, settings, mainVm); + _ = StartPipeServerAsync(downloadService, protocol, settings, mainVm, categoryService); // Zamanlayıcıyı Başlat watchdog.Start(); @@ -206,7 +217,7 @@ public partial class App : System.Windows.Application System.Windows.Application.Current.Shutdown(); } - private async Task StartPipeServerAsync(IDownloadService service, IDownloadProtocol protocol, ISettingsService settings, MainViewModel mainVm) + private async Task StartPipeServerAsync(IDownloadService service, IDownloadProtocol protocol, ISettingsService settings, MainViewModel mainVm, ICategoryService categoryService) { Log.Information("Named Pipe sunucusu dinlemeye başladı..."); while (!_pipeCts.Token.IsCancellationRequested) @@ -249,20 +260,19 @@ public partial class App : System.Windows.Application var grabber = _host.Services.GetRequiredService(); var grabberWin = new Views.Dialogs.GrabberWindow(grabber, url) { Owner = win }; - if (grabberWin.ShowDialog() == true) + if (await grabberWin.ShowDialogAsyncSafe() == true) { // Sonuçları ekle (MainViewModel'deki OpenGrabberCommand mantığıyla aynı) var selected = grabberWin.SelectedResults; var defaultPath = await settings.GetAsync("DefaultSavePath"); foreach (var res in selected) { - var item = new DownloadItem { Url = res.Url, FileName = res.FileName, SavePath = Path.Combine(defaultPath ?? "", res.FileName), Status = DownloadStatus.Queued }; - var catName = Helpers.FileCategoryHelper.GetCategoryByExtension(item.FileName); - item.CategoryId = catName switch { "Software"=>1,"Document"=>2,"Audio"=>3,"Video"=>4,"Image"=>5,_=>6 }; + var item = new DownloadItem { Url = res.Url, FileName = res.FileName, SavePath = Path.Combine(defaultPath ?? "", res.FileName), Status = DownloadStatus.Paused }; + item.CategoryId = await categoryService.GetCategoryIdByExtensionAsync(item.FileName); await service.AddDownloadAsync(item); mainVm.AddDownloadItemViewModel(new DownloadItemViewModel { Id = item.Id, FileName = item.FileName, Url = item.Url, - Status = DownloadStatus.Queued, FormattedSize = "Bilinmiyor", + Status = DownloadStatus.Paused, FormattedSize = "Bilinmiyor", CreatedAt = item.CreatedAt, LastActivityAt = item.LastActivityAt }); @@ -279,43 +289,46 @@ public partial class App : System.Windows.Application defaultPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads"); } - // "Ekle" penceresini otomatik aç - var dialog = new Views.Dialogs.AddDownloadDialog(protocol, defaultPath, url, suggestedName); - var result = await dialog.ShowAsync(); - - if (result == ContentDialogResult.Primary) + try { - try + var item = await protocol.GetFileInfoAsync(url, CancellationToken.None); + + if (!string.IsNullOrWhiteSpace(suggestedName)) { - var item = await protocol.GetFileInfoAsync(dialog.Urls, CancellationToken.None); - - // Kullanıcı pencerede ismi değiştirdiyse onu kullan - if (!string.IsNullOrWhiteSpace(dialog.FileName)) - { - item.FileName = dialog.FileName; - } - - item.SavePath = Path.Combine(dialog.SavePath, item.FileName); - - // Kategori ata - var catName = Helpers.FileCategoryHelper.GetCategoryByExtension(item.FileName); - item.CategoryId = catName switch { "Software"=>1,"Document"=>2,"Audio"=>3,"Video"=>4,"Image"=>5,_=>6 }; - - await service.AddDownloadAsync(item); - - mainVm.AddDownloadItemViewModel(new DownloadItemViewModel { - Id = item.Id, FileName = item.FileName, Url = item.Url, - Status = DownloadStatus.Queued, - FormattedSize = mainVm.FormatSizeInternal(item.TotalSize), - CreatedAt = item.CreatedAt, - LastActivityAt = item.LastActivityAt - }); + item.FileName = suggestedName; } - catch (Exception ex) + + var targetPath = Path.Combine(defaultPath, item.FileName); + + // Çakışma kontrolü (dosya adını eşsiz yap) + var counter = 1; + var dir = Path.GetDirectoryName(targetPath) ?? ""; + var fn = Path.GetFileNameWithoutExtension(targetPath); + var ext = Path.GetExtension(targetPath); + while (File.Exists(targetPath)) { - Log.Error(ex, "Tarayıcıdan gelen URL eklenirken hata"); - System.Windows.MessageBox.Show($"Tarayıcıdan gelen indirme eklenemedi.\n\nURL: {url}\n\nHata: {ex.Message}", "Bağlantı Hatası", MessageBoxButton.OK, MessageBoxImage.Error); + targetPath = Path.Combine(dir, $"{fn} ({counter++}){ext}"); } + + item.FileName = Path.GetFileName(targetPath); + item.SavePath = targetPath; + + // Kategori ata + item.CategoryId = await categoryService.GetCategoryIdByExtensionAsync(item.FileName); + + await service.AddDownloadAsync(item); + + mainVm.AddDownloadItemViewModel(new DownloadItemViewModel { + Id = item.Id, FileName = item.FileName, Url = item.Url, + Status = DownloadStatus.Paused, + FormattedSize = mainVm.FormatSizeInternal(item.TotalSize), + CreatedAt = item.CreatedAt, + LastActivityAt = item.LastActivityAt + }); + } + catch (Exception ex) + { + Log.Error(ex, "Tarayıcıdan gelen URL otomatik eklenirken hata: {Url}", url); } } }); @@ -345,6 +358,9 @@ public partial class App : System.Windows.Application } } + _mutex?.ReleaseMutex(); + _mutex?.Dispose(); + base.OnExit(e); } } diff --git a/src/DownloadManager.WPF/Helpers/DialogHelper.cs b/src/DownloadManager.WPF/Helpers/DialogHelper.cs new file mode 100644 index 0000000..16975e8 --- /dev/null +++ b/src/DownloadManager.WPF/Helpers/DialogHelper.cs @@ -0,0 +1,38 @@ +using ModernWpf.Controls; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace DownloadManager.WPF.Helpers; + +public static class DialogHelper +{ + private static readonly SemaphoreSlim _dialogSemaphore = new(1, 1); + + public static async Task ShowAsyncSafe(this ContentDialog dialog) + { + await _dialogSemaphore.WaitAsync(); + try + { + return await dialog.ShowAsync(); + } + finally + { + await Task.Delay(200); // ModernWpf'nin iç durumunu (activeDialog) temizlemesi için zaman tanı + _dialogSemaphore.Release(); + } + } + + public static async Task ShowDialogAsyncSafe(this System.Windows.Window window) + { + await _dialogSemaphore.WaitAsync(); + try + { + return window.ShowDialog(); + } + finally + { + _dialogSemaphore.Release(); + } + } +} diff --git a/src/DownloadManager.WPF/ViewModels/DownloadItemViewModel.cs b/src/DownloadManager.WPF/ViewModels/DownloadItemViewModel.cs index d01493a..37ebb88 100644 --- a/src/DownloadManager.WPF/ViewModels/DownloadItemViewModel.cs +++ b/src/DownloadManager.WPF/ViewModels/DownloadItemViewModel.cs @@ -15,6 +15,7 @@ public partial class DownloadItemViewModel : ObservableObject [ObservableProperty] private string _formattedSize = "—"; [ObservableProperty] private double _progressPercent; [ObservableProperty] private string _speed = "—"; + [ObservableProperty] private long _rawSpeed; [ObservableProperty] private string _timeRemaining = "—"; [ObservableProperty] private DownloadStatus _status; [ObservableProperty] private int _categoryId; @@ -39,6 +40,7 @@ public partial class DownloadItemViewModel : ObservableObject System.Windows.Application.Current.Dispatcher.InvokeAsync(() => { ProgressPercent = e.ProgressPercent; + RawSpeed = e.SpeedBytesPerSec; Speed = FormatSpeed(e.SpeedBytesPerSec); TimeRemaining = FormatRemaining(e.EstimatedRemaining); Status = e.Status; diff --git a/src/DownloadManager.WPF/ViewModels/MainViewModel.cs b/src/DownloadManager.WPF/ViewModels/MainViewModel.cs index 18008da..6eee605 100644 --- a/src/DownloadManager.WPF/ViewModels/MainViewModel.cs +++ b/src/DownloadManager.WPF/ViewModels/MainViewModel.cs @@ -8,6 +8,7 @@ using DownloadManager.Core.Models; using DownloadManager.Core.Protocols; using DownloadManager.Core.Queue; using DownloadManager.Core.Services; +using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -18,6 +19,7 @@ using Newtonsoft.Json; using WpfApp = System.Windows.Application; using WpfMsg = System.Windows.MessageBox; using DownloadManager.WPF.Views; +using DownloadManager.WPF.Helpers; namespace DownloadManager.WPF.ViewModels; @@ -31,13 +33,25 @@ public partial class MainViewModel : ObservableObject private readonly EngineOptions _engineOptions; private readonly ISettingsService _settingsService; private readonly IScheduleService _scheduleService; + private readonly ICategoryService _categoryService; private readonly SiteGrabber _grabber; + private readonly IServiceProvider _serviceProvider; [ObservableProperty] private ObservableCollection _downloads = new(); + private readonly List _allDownloads = new(); + + [ObservableProperty] private ObservableCollection _categories = new(); + [ObservableProperty] private DownloadItemViewModel? _selectedDownload; [ObservableProperty] private DownloadCategory? _selectedCategory; [ObservableProperty] private string _totalSpeed = "Toplam: 0 B/s"; [ObservableProperty] private int _activeCount; + [ObservableProperty] private int _completedCount; + [ObservableProperty] private int _errorCount; + [ObservableProperty] private int _pausedCount; + [ObservableProperty] private int _queuedCount; + [ObservableProperty] private int _totalCount; + [ObservableProperty] private string _activeSegmentsTotal = "0/0"; [ObservableProperty] private string _diskFreeSpace = string.Empty; [ObservableProperty] private System.Windows.Media.PointCollection _speedPoints = new(); @@ -55,6 +69,22 @@ public partial class MainViewModel : ObservableObject ResumeDownloadCommand.NotifyCanExecuteChanged(); } + partial void OnSelectedCategoryChanged(DownloadCategory? value) + { + ApplyCategoryFilter(); + } + + private void ApplyCategoryFilter() + { + var list = SelectedCategory == null || SelectedCategory.Id == 0 + ? _allDownloads.ToList() + : _allDownloads.Where(x => x.CategoryId == SelectedCategory.Id).ToList(); + + Downloads.Clear(); + foreach(var item in list) Downloads.Add(item); + SortDownloads(SortColumn, IsSortAscending); + } + public MainViewModel( IDownloadService downloadService, IDownloadProtocol protocol, @@ -64,7 +94,9 @@ public partial class MainViewModel : ObservableObject EngineOptions engineOptions, ISettingsService settingsService, IScheduleService scheduleService, - SiteGrabber grabber) + ICategoryService categoryService, + SiteGrabber grabber, + IServiceProvider serviceProvider) { _downloadService = downloadService; _protocol = protocol; @@ -74,7 +106,9 @@ public partial class MainViewModel : ObservableObject _engineOptions = engineOptions; _settingsService = settingsService; _scheduleService = scheduleService; + _categoryService = categoryService; _grabber = grabber; + _serviceProvider = serviceProvider; _engine.ProgressChanged += OnEngineProgressChanged; @@ -139,15 +173,26 @@ public partial class MainViewModel : ObservableObject } } + var cats = await _categoryService.GetCategoriesAsync(); + WpfApp.Current.Dispatcher.Invoke(() => { - Downloads.Clear(); + Categories.Clear(); + // Add a virtual 'All' category + Categories.Add(new DownloadCategory { Id = 0, Name = "Tümü" }); + foreach (var cat in cats) + { + Categories.Add(cat); + } + SelectedCategory = Categories.FirstOrDefault(); + + _allDownloads.Clear(); foreach (var item in items) { var downloaded = Math.Min(item.DownloadedBytes, item.TotalSize); var progress = item.TotalSize > 0 ? (double)downloaded / item.TotalSize * 100 : 0; - Downloads.Add(new DownloadItemViewModel + _allDownloads.Add(new DownloadItemViewModel { Id = item.Id, FileName = item.FileName, @@ -155,11 +200,13 @@ public partial class MainViewModel : ObservableObject Status = item.Status, ProgressPercent = Math.Min(100, progress), FormattedSize = FormatSize(item.TotalSize), + CategoryId = item.CategoryId, CreatedAt = item.CreatedAt, LastActivityAt = item.LastActivityAt }); } - SortDownloads(SortColumn, IsSortAscending); + ApplyCategoryFilter(); + UpdateGlobalStatsInternal(); }); } @@ -193,12 +240,18 @@ public partial class MainViewModel : ObservableObject { WpfApp.Current.Dispatcher.Invoke(() => { - var vm = Downloads.FirstOrDefault(x => x.Id == e.Id); + var vm = _allDownloads.FirstOrDefault(x => x.Id == e.Id); if (vm != null) { vm.ApplyProgress(e); vm.LastActivityAt = DateTime.Now; + // Aktif segment sayısını güncelle + if (e.Status == DownloadStatus.Downloading) + _activeSegmentCounts[e.Id] = e.ActiveSegments; + else + _activeSegmentCounts.Remove(e.Id); + if (e.Status == DownloadStatus.Completed) { vm.LastActivityAt = DateTime.Now; @@ -209,13 +262,15 @@ public partial class MainViewModel : ObservableObject { try { - var downloads = await _downloadService.GetAllDownloadsAsync(); + using var scope = _serviceProvider.CreateScope(); + var service = scope.ServiceProvider.GetRequiredService(); + var downloads = await service.GetAllDownloadsAsync(); var item = downloads.FirstOrDefault(x => x.Id == vm.Id); if (item != null) { item.LastActivityAt = vm.LastActivityAt; item.Status = DownloadStatus.Completed; - await _downloadService.UpdateDownloadAsync(item); + await service.UpdateDownloadAsync(item); } } catch { /* Sessizce yut */ } @@ -226,43 +281,34 @@ public partial class MainViewModel : ObservableObject }); } + private readonly Dictionary _activeSegmentCounts = new(); + private void UpdateGlobalStatsInternal() { - var activeItems = Downloads.Where(x => x.Status == DownloadStatus.Downloading).ToList(); - ActiveCount = activeItems.Count; + var allItems = _allDownloads.ToList(); + TotalCount = allItems.Count; + ActiveCount = allItems.Count(x => x.Status == DownloadStatus.Downloading); + CompletedCount = allItems.Count(x => x.Status == DownloadStatus.Completed); + PausedCount = allItems.Count(x => x.Status == DownloadStatus.Paused); + ErrorCount = allItems.Count(x => x.Status == DownloadStatus.Error); + QueuedCount = allItems.Count(x => x.Status == DownloadStatus.Queued); + + var activeItems = _allDownloads.Where(x => x.Status == DownloadStatus.Downloading).ToList(); - double totalMbps = 0; - foreach (var item in activeItems) - { - if (string.IsNullOrEmpty(item.Speed) || item.Speed == "—") continue; - var parts = item.Speed.Split(' '); - if (parts.Length < 2) continue; - if (double.TryParse(parts[0], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out double val)) - { - if (parts[1].StartsWith("MB")) totalMbps += val; - else if (parts[1].StartsWith("KB")) totalMbps += val / 1024; - } - } - TotalSpeed = $"Toplam: {totalMbps:F1} MB/s"; + int totalActiveSegments = _activeSegmentCounts.Values.Sum(); + int maxPossibleSegments = activeItems.Count * _engineOptions.MaxSegments; + ActiveSegmentsTotal = $"{totalActiveSegments}/{maxPossibleSegments}"; + + long totalBytesPerSec = activeItems.Sum(x => x.RawSpeed); + TotalSpeed = $"Toplam: {FormatSize(totalBytesPerSec)}/s"; _ = UpdateDiskSpaceAsync(); } private void UpdateSpeedChart() { - var activeItems = Downloads.Where(x => x.Status == DownloadStatus.Downloading).ToList(); + var activeItems = _allDownloads.Where(x => x.Status == DownloadStatus.Downloading).ToList(); - double totalMbps = 0; - foreach (var item in activeItems) - { - if (string.IsNullOrEmpty(item.Speed) || item.Speed == "—") continue; - var parts = item.Speed.Split(' '); - if (parts.Length < 2) continue; - if (double.TryParse(parts[0], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out double val)) - { - if (parts[1].StartsWith("MB")) totalMbps += val; - else if (parts[1].StartsWith("KB")) totalMbps += val / 1024; - } - } + double totalMbps = activeItems.Sum(x => (double)x.RawSpeed / (1024 * 1024)); _speedHistory.Add(totalMbps); if (_speedHistory.Count > MaxChartPoints) _speedHistory.RemoveAt(0); @@ -272,12 +318,11 @@ public partial class MainViewModel : ObservableObject { double maxSpeed = _speedHistory.Max(); if (maxSpeed < 0.1) maxSpeed = 0.1; - //var w = ((System.Windows.Controls.Panel)Application.Current.MainWindow.Content).ActualWidth; - //var w = bannerbg.ActualWidth + int w = (int)System.Windows.SystemParameters.PrimaryScreenWidth; - double width = w; // 900; // Grafik genişliği - double height = 40; // Grafik yüksekliği + double width = w; + double height = 40; double stepX = width / (MaxChartPoints - 1); for (int i = 0; i < _speedHistory.Count; i++) @@ -315,8 +360,9 @@ public partial class MainViewModel : ObservableObject { WpfApp.Current.Dispatcher.Invoke(() => { - Downloads.Add(vm); - SortDownloads(SortColumn, IsSortAscending); + _allDownloads.Add(vm); + ApplyCategoryFilter(); + UpdateGlobalStatsInternal(); }); } @@ -340,7 +386,7 @@ public partial class MainViewModel : ObservableObject var defaultPath = await _settingsService.GetAsync("DefaultSavePath"); var dialog = new Views.Dialogs.AddDownloadDialog(_protocol, defaultPath, clipboardUrl); - var result = await dialog.ShowAsync(); + var result = await dialog.ShowAsyncSafe(); if (result == ModernWpf.Controls.ContentDialogResult.Primary) { @@ -349,7 +395,7 @@ public partial class MainViewModel : ObservableObject { try { - if (Downloads.Any(x => x.Url == url)) + if (_allDownloads.Any(x => x.Url == url)) { var msgResult = WpfMsg.Show("Bu URL zaten listede mevcut. Tekrar eklemek istiyor musunuz?", "Mükerrer Kayıt", System.Windows.MessageBoxButton.YesNo); if (msgResult == System.Windows.MessageBoxResult.No) continue; @@ -378,7 +424,7 @@ public partial class MainViewModel : ObservableObject var vm = new DownloadItemViewModel { Id = item.Id, FileName = item.FileName, Url = item.Url, - Status = DownloadStatus.Queued, FormattedSize = FormatSize(item.TotalSize), + Status = DownloadStatus.Paused, FormattedSize = FormatSize(item.TotalSize), CategoryId = item.CategoryId, CreatedAt = item.CreatedAt, LastActivityAt = item.LastActivityAt @@ -386,10 +432,11 @@ public partial class MainViewModel : ObservableObject WpfApp.Current.Dispatcher.Invoke(() => { - Downloads.Add(vm); - // Mevcut sıralamayı tekrar uygula - SortDownloads(SortColumn, IsSortAscending); + _allDownloads.Add(vm); + ApplyCategoryFilter(); + UpdateGlobalStatsInternal(); }); + item.Status = DownloadStatus.Paused; await _downloadService.AddDownloadAsync(item); } catch (Exception ex) @@ -411,6 +458,30 @@ public partial class MainViewModel : ObservableObject return filePath; } + [RelayCommand] + private async Task ResumePending() + { + var pendingItems = _allDownloads.Where(x => x.Status == DownloadStatus.Paused || x.Status == DownloadStatus.Error).ToList(); + foreach (var vm in pendingItems) + { + vm.Status = DownloadStatus.Queued; + await _downloadService.ResumeDownloadAsync(vm.Id); + } + UpdateGlobalStatsInternal(); + } + + [RelayCommand] + private async Task PauseAll() + { + var activeItems = _allDownloads.Where(x => x.Status == DownloadStatus.Downloading || x.Status == DownloadStatus.Queued).ToList(); + foreach (var vm in activeItems) + { + await _downloadService.PauseDownloadAsync(vm.Id); + vm.Status = DownloadStatus.Paused; + } + UpdateGlobalStatsInternal(); + } + [RelayCommand(CanExecute = nameof(CanPause))] private async Task PauseDownload(DownloadItemViewModel? vm) { @@ -419,6 +490,7 @@ public partial class MainViewModel : ObservableObject { await _downloadService.PauseDownloadAsync(target.Id); target.Status = DownloadStatus.Paused; + UpdateGlobalStatsInternal(); PauseDownloadCommand.NotifyCanExecuteChanged(); ResumeDownloadCommand.NotifyCanExecuteChanged(); } @@ -438,6 +510,7 @@ public partial class MainViewModel : ObservableObject { target.Status = DownloadStatus.Queued; await _downloadService.ResumeDownloadAsync(target.Id); + UpdateGlobalStatsInternal(); PauseDownloadCommand.NotifyCanExecuteChanged(); ResumeDownloadCommand.NotifyCanExecuteChanged(); } @@ -455,8 +528,7 @@ public partial class MainViewModel : ObservableObject if (vm == null) return; try { - var downloads = await _downloadService.GetAllDownloadsAsync(); - var item = downloads.FirstOrDefault(x => x.Id == vm.Id); + var item = (await _downloadService.GetAllDownloadsAsync()).FirstOrDefault(x => x.Id == vm.Id); if (item != null && File.Exists(item.SavePath)) System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(item.SavePath) { UseShellExecute = true }); else @@ -473,8 +545,7 @@ public partial class MainViewModel : ObservableObject if (vm == null) return; try { - var downloads = await _downloadService.GetAllDownloadsAsync(); - var item = downloads.FirstOrDefault(x => x.Id == vm.Id); + var item = (await _downloadService.GetAllDownloadsAsync()).FirstOrDefault(x => x.Id == vm.Id); if (item != null && File.Exists(item.SavePath)) System.Diagnostics.Process.Start("rundll32.exe", $"shell32.dll,OpenAs_RunDLL {item.SavePath}"); } @@ -487,8 +558,7 @@ public partial class MainViewModel : ObservableObject if (vm == null) return; try { - var downloads = await _downloadService.GetAllDownloadsAsync(); - var item = downloads.FirstOrDefault(x => x.Id == vm.Id); + var item = (await _downloadService.GetAllDownloadsAsync()).FirstOrDefault(x => x.Id == vm.Id); if (item != null) { if (File.Exists(item.SavePath)) @@ -508,7 +578,7 @@ public partial class MainViewModel : ObservableObject var item = (await _downloadService.GetAllDownloadsAsync()).FirstOrDefault(x => x.Id == vm.Id); if (item == null) return; var dialog = new Views.Dialogs.RenameDialog(item.SavePath); - var result = await dialog.ShowAsync(); + var result = await dialog.ShowAsyncSafe(); if (result == ModernWpf.Controls.ContentDialogResult.Primary) { string newPath = Path.Combine(dialog.NewPath, dialog.NewFileName); @@ -534,6 +604,7 @@ public partial class MainViewModel : ObservableObject await _downloadService.UpdateDownloadAsync(item); vm.ProgressPercent = 0; vm.Status = DownloadStatus.Queued; _queue.Enqueue(item); + UpdateGlobalStatsInternal(); } [RelayCommand] @@ -558,13 +629,13 @@ public partial class MainViewModel : ObservableObject { try { - // Önce arkaplan işlemini bitir await _downloadService.DeleteDownloadAsync(target.Id); - // UI listesinden güvenli bir şekilde çıkar WpfApp.Current.Dispatcher.Invoke(() => { - Downloads.Remove(target); + _allDownloads.Remove(target); + ApplyCategoryFilter(); + UpdateGlobalStatsInternal(); }); } catch (Exception ex) @@ -591,7 +662,9 @@ public partial class MainViewModel : ObservableObject WpfApp.Current.Dispatcher.Invoke(() => { - Downloads.Remove(target); + _allDownloads.Remove(target); + ApplyCategoryFilter(); + UpdateGlobalStatsInternal(); }); if (item != null && File.Exists(item.SavePath)) @@ -622,7 +695,7 @@ public partial class MainViewModel : ObservableObject if (item != null) { var dialog = new Views.Dialogs.PropertiesDialog(item, target.FormattedSize); - await dialog.ShowAsync(); + await dialog.ShowAsyncSafe(); } } catch (Exception ex) @@ -634,8 +707,8 @@ public partial class MainViewModel : ObservableObject [RelayCommand] private async Task OpenSettings() { - var dialog = new Views.Dialogs.SettingsDialog(_settingsService); - var result = await dialog.ShowAsync(); + var dialog = new Views.Dialogs.SettingsDialog(_settingsService, _categoryService); + var result = await dialog.ShowAsyncSafe(); if (result == ModernWpf.Controls.ContentDialogResult.Primary) { dialog.SaveSettings(); @@ -661,7 +734,7 @@ public partial class MainViewModel : ObservableObject private async Task OpenScheduler() { var dialog = new Views.Dialogs.SchedulerDialog(_scheduleService); - var result = await dialog.ShowAsync(); + var result = await dialog.ShowAsyncSafe(); if (result == ModernWpf.Controls.ContentDialogResult.Primary) { dialog.SaveJob(); } } @@ -673,25 +746,27 @@ public partial class MainViewModel : ObservableObject Owner = WpfApp.Current.MainWindow }; - if (dialog.ShowDialog() == true) + if (await dialog.ShowDialogAsyncSafe() == true) { var selected = dialog.SelectedResults; var defaultPath = await _settingsService.GetAsync("DefaultSavePath"); foreach (var res in selected) { - var item = new DownloadItem { Url = res.Url, FileName = res.FileName, SavePath = Path.Combine(defaultPath ?? "", res.FileName), Status = DownloadStatus.Queued }; - var catName = Helpers.FileCategoryHelper.GetCategoryByExtension(item.FileName); - item.CategoryId = catName switch { "Software"=>1,"Document"=>2,"Audio"=>3,"Video"=>4,"Image"=>5,_=>6 }; + var item = new DownloadItem { Url = res.Url, FileName = res.FileName, SavePath = Path.Combine(defaultPath ?? "", res.FileName), Status = DownloadStatus.Paused }; + item.CategoryId = await _categoryService.GetCategoryIdByExtensionAsync(item.FileName); await _downloadService.AddDownloadAsync(item); WpfApp.Current.Dispatcher.Invoke(() => { - Downloads.Add(new DownloadItemViewModel { + var vm = new DownloadItemViewModel { Id = item.Id, FileName = item.FileName, Url = item.Url, - Status = DownloadStatus.Queued, FormattedSize = "Bilinmiyor", + Status = DownloadStatus.Paused, FormattedSize = "Bilinmiyor", CreatedAt = item.CreatedAt, LastActivityAt = item.LastActivityAt - }); + }; + _allDownloads.Add(vm); }); } + ApplyCategoryFilter(); + UpdateGlobalStatsInternal(); } } diff --git a/src/DownloadManager.WPF/Views/Controls/CategoryPanel.xaml b/src/DownloadManager.WPF/Views/Controls/CategoryPanel.xaml index 7ba9169..70ee51a 100644 --- a/src/DownloadManager.WPF/Views/Controls/CategoryPanel.xaml +++ b/src/DownloadManager.WPF/Views/Controls/CategoryPanel.xaml @@ -3,12 +3,12 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ui="http://schemas.modernwpf.com/2019"> - - - - - - + + + + + diff --git a/src/DownloadManager.WPF/Views/Controls/StatusBarControl.xaml b/src/DownloadManager.WPF/Views/Controls/StatusBarControl.xaml index 66be2dd..02d4a1e 100644 --- a/src/DownloadManager.WPF/Views/Controls/StatusBarControl.xaml +++ b/src/DownloadManager.WPF/Views/Controls/StatusBarControl.xaml @@ -5,8 +5,20 @@ - - + + + + + + + + + + + + + + diff --git a/src/DownloadManager.WPF/Views/Dialogs/CategoryManagerDialog.xaml b/src/DownloadManager.WPF/Views/Dialogs/CategoryManagerDialog.xaml new file mode 100644 index 0000000..a2a4e07 --- /dev/null +++ b/src/DownloadManager.WPF/Views/Dialogs/CategoryManagerDialog.xaml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +