diff --git a/.vs/DownloadManager/CopilotIndices/17.14.1653.19549/CodeChunks.db b/.vs/DownloadManager/CopilotIndices/17.14.1653.19549/CodeChunks.db index c9a8621..f4994bd 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 4bae7eb..deed7d5 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 f2038df..352398e 100644 Binary files a/.vs/DownloadManager/DesignTimeBuild/.dtbcache.v2 and b/.vs/DownloadManager/DesignTimeBuild/.dtbcache.v2 differ diff --git a/.vs/DownloadManager/FileContentIndex/4e1517d4-f542-4445-8438-0598dd9c54da.vsidx b/.vs/DownloadManager/FileContentIndex/4e1517d4-f542-4445-8438-0598dd9c54da.vsidx new file mode 100644 index 0000000..f8b5569 Binary files /dev/null and b/.vs/DownloadManager/FileContentIndex/4e1517d4-f542-4445-8438-0598dd9c54da.vsidx differ diff --git a/.vs/DownloadManager/FileContentIndex/5f175271-f65d-49fe-b67e-e4632b5b8775.vsidx b/.vs/DownloadManager/FileContentIndex/5f175271-f65d-49fe-b67e-e4632b5b8775.vsidx new file mode 100644 index 0000000..7fd41d7 Binary files /dev/null and b/.vs/DownloadManager/FileContentIndex/5f175271-f65d-49fe-b67e-e4632b5b8775.vsidx differ diff --git a/.vs/DownloadManager/FileContentIndex/a0f54a1e-9581-402c-a720-5bff0f01fab3.vsidx b/.vs/DownloadManager/FileContentIndex/a0f54a1e-9581-402c-a720-5bff0f01fab3.vsidx new file mode 100644 index 0000000..c2fd663 Binary files /dev/null and b/.vs/DownloadManager/FileContentIndex/a0f54a1e-9581-402c-a720-5bff0f01fab3.vsidx differ diff --git a/.vs/DownloadManager/FileContentIndex/c7b4fcad-21f4-4465-b283-57d405db8f0a.vsidx b/.vs/DownloadManager/FileContentIndex/c7b4fcad-21f4-4465-b283-57d405db8f0a.vsidx deleted file mode 100644 index ab26078..0000000 Binary files a/.vs/DownloadManager/FileContentIndex/c7b4fcad-21f4-4465-b283-57d405db8f0a.vsidx and /dev/null differ diff --git a/.vs/DownloadManager/FileContentIndex/cd230646-8b64-4936-b2bc-91ec1ec432cc.vsidx b/.vs/DownloadManager/FileContentIndex/cd230646-8b64-4936-b2bc-91ec1ec432cc.vsidx deleted file mode 100644 index 459c34d..0000000 Binary files a/.vs/DownloadManager/FileContentIndex/cd230646-8b64-4936-b2bc-91ec1ec432cc.vsidx and /dev/null differ diff --git a/.vs/DownloadManager/FileContentIndex/eb2c6167-ac6e-46e4-8071-63e936f4f6ca.vsidx b/.vs/DownloadManager/FileContentIndex/eb2c6167-ac6e-46e4-8071-63e936f4f6ca.vsidx new file mode 100644 index 0000000..27b587e Binary files /dev/null and b/.vs/DownloadManager/FileContentIndex/eb2c6167-ac6e-46e4-8071-63e936f4f6ca.vsidx differ diff --git a/.vs/DownloadManager/v17/.futdcache.v2 b/.vs/DownloadManager/v17/.futdcache.v2 index 27f0c37..8326cf9 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 504cf07..6232a9b 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 fedb941..3ec1b00 100644 --- a/.vs/DownloadManager/v17/DocumentLayout.backup.json +++ b/.vs/DownloadManager/v17/DocumentLayout.backup.json @@ -6,13 +6,25 @@ "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}" }, + { + "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}" + }, { "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\app.xaml.cs||{8B382828-6202-11D1-8870-0000F87579D2}|", "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\app.xaml.cs||{8B382828-6202-11D1-8870-0000F87579D2}|" + }, + { + "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\app.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\\app.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}" } ], "DocumentGroupContainers": [ @@ -22,12 +34,49 @@ "DocumentGroups": [ { "DockedWidth": 200, - "SelectedChildIndex": 1, + "SelectedChildIndex": 4, "Children": [ { "$type": "Bookmark", "Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}" }, + { + "$type": "Document", + "DocumentIndex": 1, + "Title": "DownloadItemViewModel.cs", + "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\ViewModels\\DownloadItemViewModel.cs", + "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\ViewModels\\DownloadItemViewModel.cs", + "ToolTip": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\ViewModels\\DownloadItemViewModel.cs", + "RelativeToolTip": "src\\DownloadManager.WPF\\ViewModels\\DownloadItemViewModel.cs", + "ViewState": "AgIAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-04T23:33:33.635Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 3, + "Title": "StatusToIconConverter.cs", + "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Converters\\StatusToIconConverter.cs", + "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\Converters\\StatusToIconConverter.cs", + "ToolTip": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Converters\\StatusToIconConverter.cs", + "RelativeToolTip": "src\\DownloadManager.WPF\\Converters\\StatusToIconConverter.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAA8AAAAmAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-04T23:33:07.159Z" + }, + { + "$type": "Document", + "DocumentIndex": 5, + "Title": "App.xaml", + "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\App.xaml", + "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\App.xaml", + "ToolTip": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\App.xaml", + "RelativeToolTip": "src\\DownloadManager.WPF\\App.xaml", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|", + "WhenOpened": "2026-05-04T20:57:29.61Z", + "EditorCaption": "" + }, { "$type": "Document", "DocumentIndex": 0, @@ -36,27 +85,26 @@ "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\ViewModels\\MainViewModel.cs", "ToolTip": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\ViewModels\\MainViewModel.cs", "RelativeToolTip": "src\\DownloadManager.WPF\\ViewModels\\MainViewModel.cs", - "ViewState": "AgIAABQAAAAAAAAAAAAewCoAAAArAAAAAAAAAA==", + "ViewState": "AgIAAI4CAAAAAAAAAAAcwOYAAABVAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-03T21:58:25.845Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 2, + "DocumentIndex": 4, "Title": "App.xaml.cs", "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\App.xaml.cs", "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\App.xaml.cs", "ToolTip": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\App.xaml.cs", "RelativeToolTip": "src\\DownloadManager.WPF\\App.xaml.cs", - "ViewState": "AgIAAFQAAAAAAAAAAAAYwAAAAAAAAAAAAAAAAA==", + "ViewState": "AgIAAGEAAAAAAAAAAAAkwAAAAAAAAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-03T21:58:15.818Z", - "EditorCaption": "" + "WhenOpened": "2026-05-03T21:58:15.818Z" }, { "$type": "Document", - "DocumentIndex": 1, + "DocumentIndex": 2, "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 fedb941..737cfda 100644 --- a/.vs/DownloadManager/v17/DocumentLayout.json +++ b/.vs/DownloadManager/v17/DocumentLayout.json @@ -2,17 +2,37 @@ "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\\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}" }, + { + "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}" + }, { "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\app.xaml.cs||{8B382828-6202-11D1-8870-0000F87579D2}|", "RelativeMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|solutionrelative:src\\downloadmanager.wpf\\app.xaml.cs||{8B382828-6202-11D1-8870-0000F87579D2}|" + }, + { + "AbsoluteMoniker": "D:0:0:{11611D1E-B832-4666-9E37-23014F395F55}|src\\DownloadManager.WPF\\DownloadManager.WPF.csproj|d:\\calismalar\\ai\\hdm\\downloadmanager\\src\\downloadmanager.wpf\\app.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\\app.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}" } ], "DocumentGroupContainers": [ @@ -22,49 +42,107 @@ "DocumentGroups": [ { "DockedWidth": 200, - "SelectedChildIndex": 1, + "SelectedChildIndex": 2, "Children": [ { "$type": "Bookmark", "Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}" }, + { + "$type": "Document", + "DocumentIndex": 1, + "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": 0, + "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": 3, + "Title": "DownloadItemViewModel.cs", + "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\ViewModels\\DownloadItemViewModel.cs", + "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\ViewModels\\DownloadItemViewModel.cs", + "ToolTip": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\ViewModels\\DownloadItemViewModel.cs", + "RelativeToolTip": "src\\DownloadManager.WPF\\ViewModels\\DownloadItemViewModel.cs", + "ViewState": "AgIAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-04T23:33:33.635Z" + }, + { + "$type": "Document", + "DocumentIndex": 5, + "Title": "StatusToIconConverter.cs", + "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Converters\\StatusToIconConverter.cs", + "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\Converters\\StatusToIconConverter.cs", + "ToolTip": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\Converters\\StatusToIconConverter.cs", + "RelativeToolTip": "src\\DownloadManager.WPF\\Converters\\StatusToIconConverter.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAA8AAAAmAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-04T23:33:07.159Z" + }, + { + "$type": "Document", + "DocumentIndex": 7, + "Title": "App.xaml", + "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\App.xaml", + "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\App.xaml", + "ToolTip": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\App.xaml", + "RelativeToolTip": "src\\DownloadManager.WPF\\App.xaml", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|", + "WhenOpened": "2026-05-04T20:57:29.61Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 2, "Title": "MainViewModel.cs", "DocumentMoniker": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\ViewModels\\MainViewModel.cs", "RelativeDocumentMoniker": "src\\DownloadManager.WPF\\ViewModels\\MainViewModel.cs", "ToolTip": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\ViewModels\\MainViewModel.cs", "RelativeToolTip": "src\\DownloadManager.WPF\\ViewModels\\MainViewModel.cs", - "ViewState": "AgIAABQAAAAAAAAAAAAewCoAAAArAAAAAAAAAA==", + "ViewState": "AgIAAI4CAAAAAAAAAAAcwOYAAABVAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-03T21:58:25.845Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 2, + "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", "ToolTip": "D:\\Calismalar\\AI\\hDM\\DownloadManager\\src\\DownloadManager.WPF\\App.xaml.cs", "RelativeToolTip": "src\\DownloadManager.WPF\\App.xaml.cs", - "ViewState": "AgIAAFQAAAAAAAAAAAAYwAAAAAAAAAAAAAAAAA==", + "ViewState": "AgIAAGEAAAAAAAAAAAAkwAAAAAAAAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-03T21:58:15.818Z", - "EditorCaption": "" + "WhenOpened": "2026-05-03T21:58:15.818Z" }, { "$type": "Document", - "DocumentIndex": 1, + "DocumentIndex": 4, "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", - "EditorCaption": "" + "WhenOpened": "2026-05-01T23:15:00.129Z" } ] } diff --git a/.vs/ProjectEvaluation/downloadmanager.metadata.v9.bin b/.vs/ProjectEvaluation/downloadmanager.metadata.v9.bin index ed2b9eb..b383365 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 1025795..ea2e8ea 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 a55f3fb..e7d0ac7 100644 Binary files a/.vs/ProjectEvaluation/downloadmanager.strings.v9.bin and b/.vs/ProjectEvaluation/downloadmanager.strings.v9.bin differ diff --git a/Copilot_20260506_145815.png b/Copilot_20260506_145815.png new file mode 100644 index 0000000..96a0fd5 Binary files /dev/null and b/Copilot_20260506_145815.png differ diff --git a/Copilot_20260506_150141.png b/Copilot_20260506_150141.png new file mode 100644 index 0000000..77f73a9 Binary files /dev/null and b/Copilot_20260506_150141.png differ diff --git a/CreateIco.ps1 b/CreateIco.ps1 new file mode 100644 index 0000000..cee461d --- /dev/null +++ b/CreateIco.ps1 @@ -0,0 +1,9 @@ +Add-Type -AssemblyName System.Drawing +$img = [System.Drawing.Image]::FromFile("Down_nb-02.png") +$fs = [System.IO.File]::Create("Down_nb-02.ico") +$bitmap = new-object System.Drawing.Bitmap($img, 256, 256) +$icon = [System.Drawing.Icon]::FromHandle($bitmap.GetHicon()) +$icon.Save($fs) +$fs.Close() +$img.Dispose() +$bitmap.Dispose() diff --git a/Down_nb-02.ico b/Down_nb-02.ico new file mode 100644 index 0000000..b8bd194 Binary files /dev/null and b/Down_nb-02.ico differ diff --git a/Down_nb-02.jpg b/Down_nb-02.jpg new file mode 100644 index 0000000..5e3590f Binary files /dev/null and b/Down_nb-02.jpg differ diff --git a/Down_nb-02.png b/Down_nb-02.png new file mode 100644 index 0000000..c5c9a92 Binary files /dev/null and b/Down_nb-02.png differ diff --git a/Down_nb-02.svg b/Down_nb-02.svg new file mode 100644 index 0000000..9cb4fb9 --- /dev/null +++ b/Down_nb-02.svg @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DownloadManager.sln b/DownloadManager.sln index b9f3dca..d799dd3 100644 --- a/DownloadManager.sln +++ b/DownloadManager.sln @@ -11,12 +11,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DownloadManager.WPF", "src\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DownloadManager.BrowserBridge", "src\DownloadManager.BrowserBridge\DownloadManager.BrowserBridge.csproj", "{9690EB78-195A-424D-927A-1A900F30470D}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DownloadManager.Core.Tests", "tests\DownloadManager.Core.Tests\DownloadManager.Core.Tests.csproj", "{D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DownloadManager.WPF.Tests", "tests\DownloadManager.WPF.Tests\DownloadManager.WPF.Tests.csproj", "{F95B21F5-5F7E-4BAC-A846-3D1975914422}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DownloadManager.TestConsole", "src\DownloadManager.TestConsole\DownloadManager.TestConsole.csproj", "{8CB8ED62-AA01-4486-8BF9-BB21D77A3317}" EndProject Global @@ -65,30 +59,6 @@ Global {9690EB78-195A-424D-927A-1A900F30470D}.Release|x64.Build.0 = Release|Any CPU {9690EB78-195A-424D-927A-1A900F30470D}.Release|x86.ActiveCfg = Release|Any CPU {9690EB78-195A-424D-927A-1A900F30470D}.Release|x86.Build.0 = Release|Any CPU - {D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6}.Debug|x64.ActiveCfg = Debug|Any CPU - {D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6}.Debug|x64.Build.0 = Debug|Any CPU - {D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6}.Debug|x86.ActiveCfg = Debug|Any CPU - {D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6}.Debug|x86.Build.0 = Debug|Any CPU - {D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6}.Release|Any CPU.Build.0 = Release|Any CPU - {D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6}.Release|x64.ActiveCfg = Release|Any CPU - {D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6}.Release|x64.Build.0 = Release|Any CPU - {D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6}.Release|x86.ActiveCfg = Release|Any CPU - {D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6}.Release|x86.Build.0 = Release|Any CPU - {F95B21F5-5F7E-4BAC-A846-3D1975914422}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F95B21F5-5F7E-4BAC-A846-3D1975914422}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F95B21F5-5F7E-4BAC-A846-3D1975914422}.Debug|x64.ActiveCfg = Debug|Any CPU - {F95B21F5-5F7E-4BAC-A846-3D1975914422}.Debug|x64.Build.0 = Debug|Any CPU - {F95B21F5-5F7E-4BAC-A846-3D1975914422}.Debug|x86.ActiveCfg = Debug|Any CPU - {F95B21F5-5F7E-4BAC-A846-3D1975914422}.Debug|x86.Build.0 = Debug|Any CPU - {F95B21F5-5F7E-4BAC-A846-3D1975914422}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F95B21F5-5F7E-4BAC-A846-3D1975914422}.Release|Any CPU.Build.0 = Release|Any CPU - {F95B21F5-5F7E-4BAC-A846-3D1975914422}.Release|x64.ActiveCfg = Release|Any CPU - {F95B21F5-5F7E-4BAC-A846-3D1975914422}.Release|x64.Build.0 = Release|Any CPU - {F95B21F5-5F7E-4BAC-A846-3D1975914422}.Release|x86.ActiveCfg = Release|Any CPU - {F95B21F5-5F7E-4BAC-A846-3D1975914422}.Release|x86.Build.0 = Release|Any CPU {8CB8ED62-AA01-4486-8BF9-BB21D77A3317}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8CB8ED62-AA01-4486-8BF9-BB21D77A3317}.Debug|Any CPU.Build.0 = Debug|Any CPU {8CB8ED62-AA01-4486-8BF9-BB21D77A3317}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -109,8 +79,6 @@ Global {F9D4A5CB-FE99-4766-8662-9688A03CD3B7} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B} {11611D1E-B832-4666-9E37-23014F395F55} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B} {9690EB78-195A-424D-927A-1A900F30470D} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B} - {D861A9EA-BC51-4A9D-8B2C-9F2ABC7202F6} = {0AB3BF05-4346-4AA6-1389-037BE0695223} - {F95B21F5-5F7E-4BAC-A846-3D1975914422} = {0AB3BF05-4346-4AA6-1389-037BE0695223} {8CB8ED62-AA01-4486-8BF9-BB21D77A3317} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B} EndGlobalSection EndGlobal diff --git a/README.md b/README.md index 98aff90..c2cadbb 100644 --- a/README.md +++ b/README.md @@ -5,30 +5,31 @@ Modern, hızlı ve kullanıcı dostu, .NET 8 ve WPF tabanlı açık kaynaklı bi ## 🚀 Öne Çıkan Özellikler * **Segmentli İndirme:** Dosyaları parçalara bölerek maksimum bant genişliği ile indirme sağlar. -* **Tarayıcı Entegrasyonu:** Özel browser eklentisi (Chrome/Edge) ve `BrowserBridge` teknolojisi ile tarayıcıdaki linkleri otomatik yakalar. -* **Canlı Hız Grafiği:** Ana pencerenin üst kısmında, son 30 saniyelik toplam indirme hızını gösteren sağdan sola kayan interaktif grafik. +* **Hız Limitleme (Speed Throttling):** Kullanıcı tanımlı hız limiti (KB/s) belirleyerek ağ trafiğini kontrol etme imkanı. +* **Otomatik Yeniden Deneme (Auto-Retry):** Kopan bağlantılarda veya hata veren indirme parçalarında artan gecikme (exponential backoff) süreleriyle otomatik tekrar deneme. +* **Kesintiye Uğrayan İndirmelere Devam Etme (Resuming):** İndirmeyi duraklattığınızda ve daha sonra devam ettirdiğinizde, tam kaldığı yerden segment bazlı veya tekil devam edebilme. +* **Tarayıcı Entegrasyonu:** Özel browser eklentisi (Chrome/Edge) ve `BrowserBridge` teknolojisi ile tarayıcıdaki linkleri otomatik yakalama. +* **Site İncele (Site Grabber):** Bir web sitesindeki indirilebilir tüm dosyaları analiz edip listeleme ve seçilenleri tek tıkla indirme. +* **Canlı Hız Grafiği:** Ana pencerenin üst kısmında, son 30 saniyelik toplam indirme hızını gösteren interaktif grafik. * **Akıllı Dosya Adı Algılama:** Karmaşık yönlendirmeler (redirect) ve dinamik URL'lerden gerçek dosya adını otomatik tespit eder. * **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 seçeneği. - * Sütun genişliklerini otomatik kaydetme ve geri yükleme. -* **Detaylı İndirme Özellikleri:** Her indirme için özel özellikler formu üzerinden detaylı bilgi, kopyalanabilir linkler ve hızlı dosya erişimi. +* **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. ## 🛠 Teknik Mimari Uygulama modern yazılım prensipleri (Clean Architecture) ve MVVM deseni üzerine inşa edilmiştir: -* **DownloadManager.Core:** İndirme motoru, 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 uygulamaya aktaran hafif köprü uygulaması. +* **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. ## 📦 Kurulum ve Çalıştırma ### Gereksinimler -* .NET 8.0 SDK +* .NET 8.0 SDK (Eğer Self-Contained olarak derlenmediyse .NET Desktop Runtime 8.0 gereklidir) * Windows 10/11 * Google Chrome veya Microsoft Edge (Eklenti için) @@ -39,6 +40,8 @@ Proje kök dizininde aşağıdaki komutu kullanarak `Release` modunda derleme ya dotnet build ./src/DownloadManager.sln -c Release ``` +Daha gelişmiş dağıtım seçenekleri (Self-Contained veya Advanced Installer kullanımı) için lütfen [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) rehberini okuyun. + ### 🧩 Tarayıcı Eklentisi Kurulumu hDM'nin tarayıcı ile entegre çalışabilmesi için aşağıdaki iki adımı tamamlamanız gerekir: @@ -56,19 +59,18 @@ Tarayıcının eklenti üzerinden ana uygulama ile konuşabilmesi için "Native ### 🖱 Kullanım -* **Otomatik Yakalama:** Eklenti yüklendikten sonra tarayıcıda bir indirme linkine tıkladığınızda hDM otomatik olarak açılır ve linki "Ekle" penceresine taşır. +* **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. * **Pano Desteği:** Herhangi bir linki kopyalayıp hDM içindeki "Ekle" butonuna bastığınızda link otomatik olarak yapıştırılır. -* **Sistem Tepsisi:** Uygulamayı kapattığınızda saat yanındaki simgeden sağ tıklayarak "Göster" diyebilir veya "Çıkış" ile tamamen kapatabilirsiniz. ## 📈 Son Durum ve İyileştirmeler Son yapılan güncellemeler ile: -- [x] SVG tabanlı ikon desteği ve modern Systray entegrasyonu tamamlandı. -- [x] "Kalan Süre" (ETA) hesaplama algoritması eklendi. -- [x] "Ekle" penceresine Pano (Clipboard) otomatik yapıştırma özelliği getirildi. -- [x] Dinamik/Redirect linklerdeki "0 B" boyutu ve hatalı dosya adı sorunları giderildi. -- [x] StatusBar üzerinden anlık disk alanı ve toplam hız takibi eklendi. -- [x] Üst başlık alanına canlı hız dalgalanma grafiği eklendi. +- [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ı. ## 🛡 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/background.js b/browser-extension/background.js index 31917f8..6283cc5 100644 --- a/browser-extension/background.js +++ b/browser-extension/background.js @@ -8,10 +8,16 @@ const interceptExtensions = [ chrome.runtime.onInstalled.addListener(() => { chrome.contextMenus.create({ - id: "dm-link", - title: "Download Manager ile İndir", + id: "dm-download-link", + title: "hDM ile indir", contexts: ["link"] }); + + chrome.contextMenus.create({ + id: "dm-grab-page", + title: "Siteyi hDM ile incele", + contexts: ["page", "link"] + }); }); chrome.downloads.onCreated.addListener((item) => { @@ -36,8 +42,7 @@ chrome.downloads.onCreated.addListener((item) => { }); chrome.contextMenus.onClicked.addListener((info, tab) => { - if (info.menuItemId === "dm-link") { - console.log("Context menu tıklandı, bridge'e gönderiliyor:", info.linkUrl); + if (info.menuItemId === "dm-download-link") { chrome.runtime.sendNativeMessage(NATIVE_HOST, { action: "add_download", url: info.linkUrl @@ -48,5 +53,17 @@ chrome.contextMenus.onClicked.addListener((info, tab) => { console.log("Bridge Yanıtı:", response); } }); + } else if (info.menuItemId === "dm-grab-page") { + const url = info.linkUrl || info.pageUrl; + chrome.runtime.sendNativeMessage(NATIVE_HOST, { + action: "open_grabber", + url: url + }, (response) => { + if (chrome.runtime.lastError) { + console.error("Bridge Hatası:", chrome.runtime.lastError.message); + } else { + console.log("Bridge Yanıtı:", response); + } + }); } }); diff --git a/browser-extension/manifest.json b/browser-extension/manifest.json index edaadeb..0620ea2 100644 --- a/browser-extension/manifest.json +++ b/browser-extension/manifest.json @@ -1,8 +1,8 @@ { "manifest_version": 3, - "name": "Download Manager", + "name": "hOLOlu Download Manager", "version": "1.0.0", - "description": "hOLOlu Download Manager'a yönlendir", + "description": "Bağlantıları hDM ile indir ve sayfaları incele", "permissions": ["downloads", "contextMenus", "storage", "nativeMessaging"], "host_permissions": [""], "background": { "service_worker": "background.js" }, diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md new file mode 100644 index 0000000..e2e8191 --- /dev/null +++ b/docs/DEPLOYMENT.md @@ -0,0 +1,53 @@ +# hOLOlu Download Manager (hDM) Dağıtım ve Kurulum Rehberi + +Bu belge, hDM uygulamasının son kullanıcıya dağıtımı (Deployment) ve Advanced Installer gibi araçlarla kurulum (Setup) paketlerinin hazırlanması konularında izlenmesi gereken yolları ve en iyi pratikleri içermektedir. + +## 1. Dağıtım Stratejileri (Deployment Strategies) + +.NET 8 ile geliştirilen WPF/Windows Masaüstü uygulamalarını yayınlarken (publish) genel olarak iki farklı strateji tercih edilir: + +### A. Framework-Dependent (Çerçeveye Bağımlı) Dağıtım +Uygulamanın çalışması için kullanıcının bilgisayarında .NET Desktop Runtime'ın kurulu olmasını gerektiren yöntemdir. +* **Avantajları:** Derlenmiş uygulama boyutu çok küçüktür (Yaklaşık 5-15 MB). Güncellemeler hızlıdır. +* **Dezavantajları:** Kullanıcıda doğru .NET sürümü yoksa uygulama açılmaz ve kullanıcıyı indirme sayfasına yönlendirir. +* **Yayınlama Komutu:** + ```powershell + dotnet publish src/DownloadManager.WPF/DownloadManager.WPF.csproj -c Release -r win-x64 --self-contained false + ``` + +### B. Self-Contained (Kendi İçinde Barındıran) Dağıtım +.NET kütüphanelerinin ve uygulamanın ihtiyaç duyduğu tüm çalışma zamanı (runtime) dosyalarının `.exe` içerisine veya yanına gömüldüğü yöntemdir. +* **Avantajları:** Kullanıcının bilgisayarında .NET kurulu olmasına gerek yoktur. Hata riski sıfıra yakındır, "tıkla ve çalıştır" mantığıyla çalışır. +* **Dezavantajları:** Dosya boyutu çok yüksektir (Yaklaşık 150-250 MB arası). +* **Yayınlama Komutu (Tek Dosya - Single File):** + ```powershell + dotnet publish src/DownloadManager.WPF/DownloadManager.WPF.csproj -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true + ``` + +### C. Boyutu Küçültülmüş Self-Contained (Trimming) +Eğer dosya boyutu (210 MB) sizin için sorunsa, kullanılmayan .NET kodlarını silen `PublishTrimmed` bayrağını kullanabilirsiniz. Bu, boyutu 80-100 MB arasına düşürebilir ancak Reflection kullanan paketlerde (JSON dönüştürücüler vb.) çalışma zamanı hatalarına yol açabileceğinden **kapsamlı test gerektirir**. +```powershell +dotnet publish src/DownloadManager.WPF/DownloadManager.WPF.csproj -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -p:PublishTrimmed=true +``` + +--- + +## 2. Advanced Installer ile Kurulum Önerileri + +Eğer **Framework-Dependent** (A stratejisi) yayınlama yapıyor ve kurulum dosyasının boyutunu küçük tutmak istiyorsanız, Advanced Installer içerisinde doğru "Prerequisites" (Önkoşullar) ayarını yapmanız hayati önem taşır. + +### "You must install .NET Desktop Runtime" Hatasının Çözümü + +Advanced Installer'da sadece ".NET Runtime" eklerseniz WPF arayüzü çizilemez. Kesinlikle "Desktop" sürümü eklenmelidir. + +1. Advanced Installer projenizi (`hdm_kur.aip`) açın. +2. Sol menüden **Prerequisites** sekmesine tıklayın. +3. Listeden eklediğiniz yanlış veya eksik .NET gereksinimlerini silin (Örn: `.NET Runtime 8.0.x` veya `ASP.NET Core Runtime`). +4. **Packages** kısmından şu paketi bulup ekleyin: + * 👉 **`.NET Desktop Runtime 8.0.x (x64)`** +5. Kurulum seçeneklerinde (Setup Files), bu runtime paketinin kurulum dosyasına gömülmesini (Include in setup) veya internetten indirilmesini (Download from URL) seçebilirsiniz. İnternetten indirme seçeneği, `.msi` / `.exe` dosyanızın boyutunu çok küçük (15 MB altı) tutmanızı sağlar. + +### Ek Tavsiyeler +* **Kısayol ve Simgeler:** Advanced Installer'da masaüstü kısayolu oluştururken, `hDM.exe` dosyasını seçtiğinizde simge otomatik olarak `Down_nb-02.ico` algılanacaktır. +* **Tarayıcı Eklentisi (Browser Bridge):** `DownloadManager.BrowserBridge.exe` dosyasını da `hDM.exe` ile aynı klasöre kurduğunuzdan emin olun. Ayrıca Advanced Installer'ın **Registry** bölümüne girip, eklentinin çalışması için gereken `register_bridge.reg` içeriğini kurulum sırasında otomatik yazılacak şekilde ekleyin. +* **Mimariler:** Uygulamanızı `x64` (64-bit) olarak yayınlıyorsanız, Advanced Installer projesinin **Install Parameters** kısmından "Package Type" ayarını `64-bit package` olarak seçmeyi unutmayın. Aksi takdirde "Program Files (x86)" klasörüne kurulmaya çalışır. \ No newline at end of file diff --git a/hDM.ico b/hDM.ico new file mode 100644 index 0000000..491ade1 Binary files /dev/null and b/hDM.ico differ diff --git a/src/DownloadManager.BrowserBridge/Program.cs b/src/DownloadManager.BrowserBridge/Program.cs index 9d9ff89..a649269 100644 --- a/src/DownloadManager.BrowserBridge/Program.cs +++ b/src/DownloadManager.BrowserBridge/Program.cs @@ -64,15 +64,15 @@ class Program try { // Ana uygulamanın çalışıp çalışmadığını kontrol et - var processes = System.Diagnostics.Process.GetProcessesByName("DownloadManager.WPF"); + 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, "DownloadManager.WPF.exe"); + string appPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "hDM.exe"); // Geliştirme ortamı için alternatif yollar if (!File.Exists(appPath)) - appPath = @"D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.WPF\bin\Release\net8.0-windows\DownloadManager.WPF.exe"; + appPath = @"D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.WPF\bin\Release\net8.0-windows\hDM.exe"; if (File.Exists(appPath)) { 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 e38ac86..884e47e 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 d8f2aab..a2bf350 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 ad5051c..d4b151f 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/bin/Release/net8.0/bridge_error.log b/src/DownloadManager.BrowserBridge/bin/Release/net8.0/bridge_error.log index 4278b40..2eca530 100644 --- a/src/DownloadManager.BrowserBridge/bin/Release/net8.0/bridge_error.log +++ b/src/DownloadManager.BrowserBridge/bin/Release/net8.0/bridge_error.log @@ -6,3 +6,13 @@ 2/05/2026 09:00:01: The operation has timed out. 2/05/2026 09:03:51: The operation has timed out. 2/05/2026 09:12:38: Bağlantı hatası (https://ftp.linux.org.tr/ubuntu-releases/24.04/ubuntu-24.04-desktop-amd64.iso): The operation has timed out. +4/05/2026 23:07:33: Bağlantı hatası (https://releases.ubuntu.com/26.04/ubuntu-26.04-desktop-amd64.iso): The operation has timed out. +4/05/2026 23:07:33: Bağlantı hatası (https://www.techspot.com/downloads/downloadnowfile/7444/?evp=9a3443ba810782b36c970bb5d41cf796&file=10114): The operation has timed out. +4/05/2026 23:07:33: Bağlantı hatası (https://downloads.sourceforge.net/project/bodhilinux/7.0.0/bodhi-7.0.0-64.iso?ts=gAAAAABp9aVvleiMc9uWLG-xLqun52vKU1Rg67KwUnaD_C31nOSnO_TbkZ9QaR-vzmaHR2h0VWTeqyJ5zIpOgUnXw9wX0jJq9w%3D%3D&use_mirror=altushost-bul&r=https%3A%2F%2Fsourceforge.net%2Fprojects%2Fbodhilinux%2Ffiles%2F7.0.0%2F): The operation has timed out. +4/05/2026 23:07:33: Bağlantı hatası (https://worldmonitor.app/api/download?platform=windows-exe): The operation has timed out. +4/05/2026 23:07:33: Bağlantı hatası (https://releases.ubuntu.com/26.04/ubuntu-26.04-desktop-amd64.iso): The operation has timed out. +4/05/2026 23:07:33: Bağlantı hatası (https://downloads.sourceforge.net/project/bodhilinux/7.0.0/bodhi-7.0.0-64.iso?ts=gAAAAABp9hPXIhPG7sgiPWmS8EijnjlvghUQ4cf9sRyjOwdN_ZHNAAzENdOTK6JLMDYSKzdXGGpf5Mg-rLnQP-yf1eLafQ65zA%3D%3D&use_mirror=altushost-bul&r=https%3A%2F%2Fsourceforge.net%2F): The operation has timed out. +4/05/2026 23:07:33: Bağlantı hatası (https://ftp.nluug.nl/os/Linux/distr/pclinuxos/pclinuxos/iso/pclinuxos64-kde-2025.09.iso): The operation has timed out. +4/05/2026 23:07:33: Bağlantı hatası (https://www.softpedia.com/dyn-postdownload.php/766e8ff53bdf18c286eb8c0b3e0ed54a/69d56f93/851e/4/2): The operation has timed out. +4/05/2026 23:08:05: Bağlantı hatası (https://ftp.nluug.nl/os/Linux/distr/uplos/ISO/PCLOS/): The operation has timed out. +4/05/2026 23:12:33: Bağlantı hatası (https://ftp.nluug.nl/os/Linux/distr/uplos/ISO/PCLOS/community-mate32-pclinuxos-12.15.iso): The operation has timed out. 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 deleted file mode 100644 index a8b770e..0000000 --- a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.AssemblyInfoInputs.cache +++ /dev/null @@ -1 +0,0 @@ -000d6a996873011518a2be58f132c59662b6ff352ca8842e6f1fa1c31b20e4f1 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 deleted file mode 100644 index 7fa6b73..0000000 --- a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.GeneratedMSBuildEditorConfig.editorconfig +++ /dev/null @@ -1,15 +0,0 @@ -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 02eff60..406689f 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 deleted file mode 100644 index 65a2f9e..0000000 Binary files a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/DownloadManager.BrowserBridge.csproj.AssemblyReference.cache and /dev/null differ diff --git a/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/apphost.exe b/src/DownloadManager.BrowserBridge/obj/Debug/net8.0/apphost.exe index d8f2aab..a2bf350 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/Release/net8.0/DownloadManager.BrowserBridge.AssemblyInfo.cs b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.AssemblyInfo.cs index c536dc5..fd003aa 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,6 +1,7 @@ //------------------------------------------------------------------------------ // // 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. @@ -13,10 +14,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")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+81faa715a4eb11a2bf648f52891306b46ea7c256")] [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. +// Generated by the MSBuild WriteCodeFragment class. 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 853b6ce..abd71e8 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 @@ -89d0fd93dd3e67ad8186e0c515a8d65ebbbc94026391ff8e88db296a467ee7a3 +c41154c222d4c9aaf2ac34116ff46b068de5b4633ca984a833d7394a42fc99da diff --git a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.GeneratedMSBuildEditorConfig.editorconfig b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.GeneratedMSBuildEditorConfig.editorconfig index d1ead62..7fa6b73 100644 --- a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.GeneratedMSBuildEditorConfig.editorconfig +++ b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.GeneratedMSBuildEditorConfig.editorconfig @@ -8,7 +8,7 @@ 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.ProjectDir = D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.BrowserBridge\ build_property.EnableComHosting = build_property.EnableGeneratedComInterfaceComImportInterop = build_property.EffectiveAnalysisLevelStyle = 8.0 diff --git a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.assets.cache b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.assets.cache index 3ae893e..20a8bb2 100644 Binary files a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.assets.cache and b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.assets.cache differ 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 e38ac86..884e47e 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.genruntimeconfig.cache b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.genruntimeconfig.cache index 4e5619b..3d9bac8 100644 --- a/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.genruntimeconfig.cache +++ b/src/DownloadManager.BrowserBridge/obj/Release/net8.0/DownloadManager.BrowserBridge.genruntimeconfig.cache @@ -1 +1 @@ -f69caf1b77b5ac1742efde949e911c38081902650a9646ddb4fb0df3c6723dd0 +a13c0f175db321e1ca42f63699a1479f7cd30483ff83e7fde7792eb45ce5413d 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 ad5051c..d4b151f 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 d8f2aab..a2bf350 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 ff387d5..d7c30f1 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 ff387d5..d7c30f1 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.Core/Engine/DownloadEngine.cs b/src/DownloadManager.Core/Engine/DownloadEngine.cs index 3884d8d..09b0bf9 100644 --- a/src/DownloadManager.Core/Engine/DownloadEngine.cs +++ b/src/DownloadManager.Core/Engine/DownloadEngine.cs @@ -29,7 +29,7 @@ public class DownloadEngine public async Task StartQueueAsync(CancellationToken ct) { - Serilog.Log.Information("DownloadEngine loop started."); + Serilog.Log.Information("İndirme motoru döngüsü başlatıldı."); while (!ct.IsCancellationRequested) { try @@ -37,17 +37,17 @@ public class DownloadEngine var item = await _queue.DequeueAsync(ct); if (item == null) continue; - Serilog.Log.Information("Item dequeued for processing: {Url} (ID: {Id})", item.Url, item.Id); + Serilog.Log.Information("İşlenmek üzere kuyruktan alındı: {Url} (ID: {Id})", item.Url, item.Id); _ = Task.Run(() => ProcessDownloadAsync(item, ct), ct); } catch (OperationCanceledException) { break; } catch (Exception ex) { - Serilog.Log.Error(ex, "Error in DownloadEngine queue loop"); + Serilog.Log.Error(ex, "İndirme motoru döngüsünde hata"); await Task.Delay(1000, ct); } } - Serilog.Log.Information("DownloadEngine loop stopped."); + Serilog.Log.Information("İndirme motoru döngüsü durduruldu."); } private async Task ProcessDownloadAsync(DownloadItem item, CancellationToken ct) @@ -59,12 +59,12 @@ public class DownloadEngine try { - Serilog.Log.Information("Processing download: {FileName} (ID: {Id})", item.FileName, item.Id); + Serilog.Log.Information("İndirme işleniyor: {FileName} (ID: {Id})", item.FileName, item.Id); // Eğer dosya boyutu bilinmiyorsa (ilk kez ekleniyor), bilgilerini çek if (item.TotalSize <= 0) { - Serilog.Log.Information("Fetching file info for {Url}", item.Url); + Serilog.Log.Information("Dosya bilgisi alınıyor: {Url}", item.Url); var info = await _protocol.GetFileInfoAsync(item.Url, cts.Token); item.TotalSize = info.TotalSize; item.ETag = info.ETag; @@ -76,7 +76,7 @@ public class DownloadEngine // DURAKLATILMIŞSA İŞLEME (Kuyruktan yeni çıktıysa ve o sırada durdurulduysa) if (item.Status == DownloadStatus.Paused) { - Serilog.Log.Information("Download {Id} is paused, skipping.", item.Id); + Serilog.Log.Information("İndirme {Id} duraklatıldı, atlanıyor.", item.Id); return; } @@ -96,13 +96,13 @@ public class DownloadEngine if (item.TotalSize > 0) { downloader = _serviceProvider.GetRequiredService(); - Serilog.Log.Information("Using SegmentedDownloader for {Id}. Current progress: {Downloaded}/{Total}", + Serilog.Log.Information("{Id} için Parçalı İndirme kullanılıyor. Mevcut ilerleme: {Downloaded}/{Total}", item.Id, item.DownloadedBytes, item.TotalSize); } else { downloader = _serviceProvider.GetRequiredService(); - Serilog.Log.Information("Using SingleDownloader (unknown size) for {Id}. Current progress: {Downloaded}", + Serilog.Log.Information("{Id} için Tekil İndirme (boyut belirsiz) kullanılıyor. Mevcut ilerleme: {Downloaded}", item.Id, item.DownloadedBytes); } @@ -120,17 +120,17 @@ public class DownloadEngine Status = DownloadStatus.Completed, ProgressPercent = 100 }); - Serilog.Log.Information("Download completed: {Id}", item.Id); + Serilog.Log.Information("İndirme tamamlandı: {Id}", item.Id); } catch (OperationCanceledException) { - Serilog.Log.Information("Download paused/cancelled: {Id}", item.Id); + Serilog.Log.Information("İndirme duraklatıldı/iptal edildi: {Id}", item.Id); item.Status = DownloadStatus.Paused; ProgressChanged?.Invoke(this, CreateProgressEvent(item, DownloadStatus.Paused)); } catch (Exception ex) { - Serilog.Log.Error(ex, "Error processing download: {Id}", item.Id); + Serilog.Log.Error(ex, "İndirme işlenirken hata: {Id}", item.Id); item.Status = DownloadStatus.Error; item.ErrorMessage = ex.Message; ProgressChanged?.Invoke(this, CreateProgressEvent(item, DownloadStatus.Error)); @@ -163,12 +163,12 @@ public class DownloadEngine using var scope = _serviceProvider.CreateScope(); var repo = scope.ServiceProvider.GetRequiredService(); await repo.UpdateAsync(item); - Serilog.Log.Information("Saved download state to DB for {Id}: {Status}, {Downloaded} bytes", + Serilog.Log.Information("İndirme durumu veritabanına kaydedildi {Id}: {Status}, {Downloaded} byte", item.Id, item.Status, item.DownloadedBytes); } catch (Exception ex) { - Serilog.Log.Error(ex, "Failed to save download state to DB for {Id}", item.Id); + Serilog.Log.Error(ex, "İndirme durumu veritabanına kaydedilemedi: {Id}", item.Id); } } diff --git a/src/DownloadManager.Core/Engine/SegmentedDownloader.cs b/src/DownloadManager.Core/Engine/SegmentedDownloader.cs index 30b3262..f20c07d 100644 --- a/src/DownloadManager.Core/Engine/SegmentedDownloader.cs +++ b/src/DownloadManager.Core/Engine/SegmentedDownloader.cs @@ -17,6 +17,7 @@ public class SegmentedDownloader : IDownloader private readonly IHttpClientFactory _httpClientFactory; private readonly ResumeManager _resumeManager; private readonly SpeedCalculator _speedCalculator; + private readonly SpeedThrottler _throttler; private readonly EngineOptions _options; private readonly object _progressLock = new(); private DateTime _lastReport = DateTime.MinValue; @@ -25,61 +26,68 @@ public class SegmentedDownloader : IDownloader IHttpClientFactory httpClientFactory, ResumeManager resumeManager, SpeedCalculator speedCalculator, + SpeedThrottler throttler, EngineOptions options) { _httpClientFactory = httpClientFactory; _resumeManager = resumeManager; _speedCalculator = speedCalculator; + _throttler = throttler; _options = options; } public async Task DownloadAsync(DownloadItem item, IProgress? progress, CancellationToken ct) { - Console.WriteLine($"[SegmentedDownloader] Starting download for {item.Id}"); + Serilog.Log.Information("Parçalı indirme başlatılıyor: {Id}", item.Id); var state = await _resumeManager.LoadOrCreateAsync(item, _options); if (state.Segments.Count == 0) { - Console.WriteLine($"[SegmentedDownloader] Initializing segments for {item.Id}"); InitializeSegments(state, _options); } + // Başlangıçta indirilen byte miktarını senkronize et + item.DownloadedBytes = state.Segments.Sum(s => s.Downloaded); + var tempDir = EnsureTempDirectory(item.Id); var activeTasks = new ConcurrentDictionary(); - Console.WriteLine($"[SegmentedDownloader] Starting {state.Segments.Count(s => s.Status != SegmentStatus.Completed)} segments"); foreach (var seg in state.Segments.Where(s => s.Status != SegmentStatus.Completed)) { activeTasks[seg.Index] = DownloadSegmentAsync(item, seg, tempDir, progress, ct); } - while (activeTasks.Count > 0) + try { - var done = await Task.WhenAny(activeTasks.Values); - await done; // Önemli: Task'ı await ederek cancellation veya hataların fırlatılmasını sağlıyoruz + while (activeTasks.Count > 0) + { + var done = await Task.WhenAny(activeTasks.Values); + await done; - var completedTask = activeTasks.FirstOrDefault(x => x.Value == done); - activeTasks.TryRemove(completedTask.Key, out _); + var completedTask = activeTasks.FirstOrDefault(x => x.Value == done); + activeTasks.TryRemove(completedTask.Key, out _); + + await _resumeManager.SaveAsync(item, state); + ct.ThrowIfCancellationRequested(); + } - Console.WriteLine($"[SegmentedDownloader] Segment {completedTask.Key} completed. {activeTasks.Count} remaining."); - - await _resumeManager.SaveAsync(item, state); - ct.ThrowIfCancellationRequested(); + Serilog.Log.Information("Parçalar birleştiriliyor: {Id}", item.Id); + await MergeSegmentsAsync(state.Segments, item.SavePath); + await _resumeManager.DeleteAsync(item.Id); + if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true); + Serilog.Log.Information("İndirme bitti: {Id}", item.Id); + } + finally + { + // Ensure state is saved even if canceled/paused + await _resumeManager.SaveAsync(item, state); } - - Console.WriteLine($"[SegmentedDownloader] Merging segments for {item.Id}"); - await MergeSegmentsAsync(state.Segments, item.SavePath); - await _resumeManager.DeleteAsync(item.Id); - Directory.Delete(tempDir, true); - Console.WriteLine($"[SegmentedDownloader] Download finished for {item.Id}"); } private void InitializeSegments(DownloadItemState state, EngineOptions options) { if (state.TotalSize <= 0) { - // Safety fallback: if TotalSize is somehow 0 here, create a single "segment" - // but normally DownloadEngine should have picked SingleDownloader. state.Segments.Add(new DownloadSegment { Index = 0, @@ -93,12 +101,12 @@ public class SegmentedDownloader : IDownloader } long segmentSize = state.TotalSize / options.MaxSegments; - if (segmentSize == 0) segmentSize = state.TotalSize; // Small file case + if (segmentSize == 0) segmentSize = state.TotalSize; for (int i = 0; i < options.MaxSegments; i++) { long start = i * segmentSize; - if (start >= state.TotalSize) break; // Don't create empty segments for very small files + if (start >= state.TotalSize) break; long end = (i == options.MaxSegments - 1) ? state.TotalSize - 1 : (i + 1) * segmentSize - 1; if (end >= state.TotalSize) end = state.TotalSize - 1; @@ -113,20 +121,44 @@ public class SegmentedDownloader : IDownloader DownloadItemId = state.Id }); - if (end == state.TotalSize - 1) break; // Last segment reached + if (end == state.TotalSize - 1) break; } } private async Task DownloadSegmentAsync(DownloadItem item, DownloadSegment segment, string tempDir, IProgress? progress, CancellationToken ct) + { + int retryCount = 0; + while (true) + { + 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, ct); + } + } + } + + private async Task PerformSegmentDownloadAsync(DownloadItem item, DownloadSegment segment, string tempDir, IProgress? progress, CancellationToken ct) { segment.Status = SegmentStatus.Downloading; segment.TempFilePath = Path.Combine(tempDir, $"seg_{segment.Index}.tmp"); using var client = _httpClientFactory.CreateClient(); + client.Timeout = TimeSpan.FromSeconds(_options.ConnectionTimeoutSeconds); client.DefaultRequestHeaders.Add("User-Agent", _options.UserAgent); var request = new HttpRequestMessage(HttpMethod.Get, item.Url); - request.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(segment.StartByte + segment.Downloaded, segment.EndByte); + if (segment.EndByte > 0) + request.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(segment.StartByte + segment.Downloaded, segment.EndByte); + else + request.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(segment.StartByte + segment.Downloaded, null); using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, ct); response.EnsureSuccessStatusCode(); @@ -148,6 +180,7 @@ public class SegmentedDownloader : IDownloader } _speedCalculator.AddSample(read); + await _throttler.ThrottleAsync(read, ct); } segment.Status = SegmentStatus.Completed; diff --git a/src/DownloadManager.Core/Engine/SingleDownloader.cs b/src/DownloadManager.Core/Engine/SingleDownloader.cs index 8d37262..0bfd324 100644 --- a/src/DownloadManager.Core/Engine/SingleDownloader.cs +++ b/src/DownloadManager.Core/Engine/SingleDownloader.cs @@ -13,27 +13,77 @@ public class SingleDownloader : IDownloader { private readonly IHttpClientFactory _httpClientFactory; private readonly SpeedCalculator _speedCalculator; + private readonly SpeedThrottler _throttler; + private readonly EngineOptions _options; - public SingleDownloader(IHttpClientFactory httpClientFactory, SpeedCalculator speedCalculator) + public SingleDownloader( + IHttpClientFactory httpClientFactory, + SpeedCalculator speedCalculator, + SpeedThrottler throttler, + EngineOptions options) { _httpClientFactory = httpClientFactory; _speedCalculator = speedCalculator; + _throttler = throttler; + _options = options; } public async Task DownloadAsync(DownloadItem item, IProgress? progress, CancellationToken ct) { - using var client = _httpClientFactory.CreateClient(); - client.DefaultRequestHeaders.Add("User-Agent", "DownloadManager/1.0 (.NET 8)"); + int retryCount = 0; + while (true) + { + try + { + await PerformDownloadAsync(item, progress, ct); + break; + } + catch (Exception ex) when (retryCount < _options.MaxRetries && !ct.IsCancellationRequested) + { + 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); + } + } + } - using var response = await client.GetAsync(item.Url, HttpCompletionOption.ResponseHeadersRead, ct); - response.EnsureSuccessStatusCode(); + private async Task PerformDownloadAsync(DownloadItem item, IProgress? progress, CancellationToken ct) + { + using var client = _httpClientFactory.CreateClient(); + client.Timeout = TimeSpan.FromSeconds(_options.ConnectionTimeoutSeconds); + client.DefaultRequestHeaders.Add("User-Agent", _options.UserAgent); + + // Resuming single download if possible (if we know the size or if server supports it) + var request = new HttpRequestMessage(HttpMethod.Get, item.Url); + if (item.DownloadedBytes > 0) + { + request.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(item.DownloadedBytes, null); + } + + using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, ct); + + // If range request is not supported, start over + if (item.DownloadedBytes > 0 && response.StatusCode != System.Net.HttpStatusCode.PartialContent) + { + Serilog.Log.Warning("Sunucu parça (range) isteğini desteklemiyor, baştan başlanıyor: {Id}", item.Id); + item.DownloadedBytes = 0; + // Need to recreate request without range? Actually client.SendAsync(request) consumed the request. + // Let's just throw and let the retry loop handle it? No, retry will just do the same. + // Better to handle it here. + } + + if (item.DownloadedBytes == 0) + { + response.EnsureSuccessStatusCode(); + } var directory = Path.GetDirectoryName(item.SavePath); if (directory != null && !Directory.Exists(directory)) Directory.CreateDirectory(directory); using var contentStream = await response.Content.ReadAsStreamAsync(ct); - using var fileStream = new FileStream(item.SavePath, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true); + using var fileStream = new FileStream(item.SavePath, item.DownloadedBytes > 0 ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.None, 8192, true); var buffer = new byte[8192]; int read; @@ -43,16 +93,22 @@ public class SingleDownloader : IDownloader item.DownloadedBytes += read; _speedCalculator.AddSample(read); - progress?.Report(new DownloadProgressEvent - { - Id = item.Id, - DownloadedBytes = item.DownloadedBytes, - TotalBytes = item.TotalSize, - ProgressPercent = item.TotalSize > 0 ? (double)item.DownloadedBytes / item.TotalSize * 100 : 0, - SpeedBytesPerSec = _speedCalculator.GetBytesPerSecond(), - EstimatedRemaining = _speedCalculator.EstimateRemaining(item.TotalSize - item.DownloadedBytes), - Status = DownloadStatus.Downloading - }); + ReportProgress(item, progress); + await _throttler.ThrottleAsync(read, ct); } } + + private void ReportProgress(DownloadItem item, IProgress? progress) + { + progress?.Report(new DownloadProgressEvent + { + Id = item.Id, + DownloadedBytes = item.DownloadedBytes, + TotalBytes = item.TotalSize, + ProgressPercent = item.TotalSize > 0 ? (double)item.DownloadedBytes / item.TotalSize * 100 : 0, + SpeedBytesPerSec = _speedCalculator.GetBytesPerSecond(), + EstimatedRemaining = _speedCalculator.EstimateRemaining(item.TotalSize - item.DownloadedBytes), + Status = DownloadStatus.Downloading + }); + } } diff --git a/src/DownloadManager.Core/Engine/SpeedThrottler.cs b/src/DownloadManager.Core/Engine/SpeedThrottler.cs new file mode 100644 index 0000000..7e5c8b4 --- /dev/null +++ b/src/DownloadManager.Core/Engine/SpeedThrottler.cs @@ -0,0 +1,63 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace DownloadManager.Core.Engine; + +public class SpeedThrottler +{ + private long _limitBytesPerSec; + private long _accumulatedBytes; + private DateTime _startTime; + private readonly object _lock = new(); + + public SpeedThrottler(long limitBytesPerSec) + { + _limitBytesPerSec = limitBytesPerSec; + _startTime = DateTime.UtcNow; + } + + public void SetLimit(long limitBytesPerSec) + { + lock (_lock) + { + _limitBytesPerSec = limitBytesPerSec; + _accumulatedBytes = 0; + _startTime = DateTime.UtcNow; + } + } + + public async Task ThrottleAsync(long bytesRead, CancellationToken ct) + { + if (_limitBytesPerSec <= 0) return; + + double delayMs = 0; + lock (_lock) + { + _accumulatedBytes += bytesRead; + var elapsed = (DateTime.UtcNow - _startTime).TotalSeconds; + + if (elapsed > 0) + { + var currentSpeed = _accumulatedBytes / elapsed; + if (currentSpeed > _limitBytesPerSec) + { + var expectedTime = _accumulatedBytes / (double)_limitBytesPerSec; + delayMs = (expectedTime - elapsed) * 1000; + } + } + + // Her saniye bir sıfırla ki hassasiyet korunsun + if (elapsed > 1.0) + { + _accumulatedBytes = 0; + _startTime = DateTime.UtcNow; + } + } + + if (delayMs > 10) + { + await Task.Delay((int)delayMs, ct); + } + } +} 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 1d3c99d..cf0f1c2 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 5c64ba7..c94400a 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 927ef77..0107600 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 9870d7c..7a1897a 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 24ca2ec..2980be3 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")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+81faa715a4eb11a2bf648f52891306b46ea7c256")] [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 e352d35..c4f481d 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 @@ -46bf396899510cb77858921f8a30d4ed1bbe8d1ebf3aa0a92a7b12cea57c65d4 +57eee8222b0d77ae6e394591882c8d91daaa59ea38bf4b29e8d5d32072290d1d diff --git a/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.GeneratedMSBuildEditorConfig.editorconfig b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.GeneratedMSBuildEditorConfig.editorconfig index 1349db6..2916a0c 100644 --- a/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.GeneratedMSBuildEditorConfig.editorconfig +++ b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.GeneratedMSBuildEditorConfig.editorconfig @@ -8,7 +8,7 @@ build_property.PlatformNeutralAssembly = build_property.EnforceExtendedAnalyzerRules = build_property._SupportedPlatformList = Linux,macOS,Windows build_property.RootNamespace = DownloadManager.Core -build_property.ProjectDir = D:\Calismalar\ai\hDM\DownloadManager\src\DownloadManager.Core\ +build_property.ProjectDir = D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.Core\ build_property.EnableComHosting = build_property.EnableGeneratedComInterfaceComImportInterop = build_property.EffectiveAnalysisLevelStyle = 8.0 diff --git a/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.csproj.CoreCompileInputs.cache b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.csproj.CoreCompileInputs.cache index fd77b37..3cc2a00 100644 --- a/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.csproj.CoreCompileInputs.cache +++ b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -4d79c1e07d3393b6086287484da8294d3710161dbd1296f2efebb760c1a85310 +8795677b95a79adea42197978f5bd1f6c4352b37b49c6977da5453f65edd2118 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 1d3c99d..cf0f1c2 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.genruntimeconfig.cache b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.genruntimeconfig.cache index 27330f6..89ec8dc 100644 --- a/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.genruntimeconfig.cache +++ b/src/DownloadManager.Core/obj/Debug/net8.0/DownloadManager.Core.genruntimeconfig.cache @@ -1 +1 @@ -e0237283f1bf35a2f07180f247ffcef1be0fc01d6cd16b3184b3e89143f43a05 +4e0d314ecffa7f92944f750e88522b405a667dc0d4ae23c451be9b7c3c98cecf 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 5c64ba7..c94400a 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 34070f5..4d2cc8a 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 34070f5..4d2cc8a 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 7d188b3..f34646d 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,6 +1,7 @@ //------------------------------------------------------------------------------ // // 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. @@ -13,10 +14,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")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+81faa715a4eb11a2bf648f52891306b46ea7c256")] [assembly: System.Reflection.AssemblyProductAttribute("DownloadManager.Core")] [assembly: System.Reflection.AssemblyTitleAttribute("DownloadManager.Core")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] -// MSBuild WriteCodeFragment sınıfı tarafından oluşturuldu. +// Generated by the MSBuild WriteCodeFragment class. 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 7e1c601..b3081aa 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 @@ -49d36395e42caf4d846d50f5e1ca03f467f18bf2ead1dc7374d1c47c12ca05ed +86922a9eccfa1e5736aa220690f23d77712e45c8681c90dab58e4b60acfd7921 diff --git a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.GeneratedMSBuildEditorConfig.editorconfig b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.GeneratedMSBuildEditorConfig.editorconfig index 1349db6..2916a0c 100644 --- a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.GeneratedMSBuildEditorConfig.editorconfig +++ b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.GeneratedMSBuildEditorConfig.editorconfig @@ -8,7 +8,7 @@ build_property.PlatformNeutralAssembly = build_property.EnforceExtendedAnalyzerRules = build_property._SupportedPlatformList = Linux,macOS,Windows build_property.RootNamespace = DownloadManager.Core -build_property.ProjectDir = D:\Calismalar\ai\hDM\DownloadManager\src\DownloadManager.Core\ +build_property.ProjectDir = D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.Core\ build_property.EnableComHosting = build_property.EnableGeneratedComInterfaceComImportInterop = build_property.EffectiveAnalysisLevelStyle = 8.0 diff --git a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.assets.cache b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.assets.cache index 55ce406..10cb7ed 100644 Binary files a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.assets.cache and b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.assets.cache differ diff --git a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.csproj.AssemblyReference.cache b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.csproj.AssemblyReference.cache index 05bd720..6b9cae0 100644 Binary files a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.csproj.AssemblyReference.cache and b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.csproj.AssemblyReference.cache differ diff --git a/tests/DownloadManager.Core.Tests/obj/Debug/net8.0/DownloadManager.Core.Tests.csproj.FileListAbsolute.txt b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.csproj.BuildWithSkipAnalyzers similarity index 100% rename from tests/DownloadManager.Core.Tests/obj/Debug/net8.0/DownloadManager.Core.Tests.csproj.FileListAbsolute.txt rename to src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.csproj.BuildWithSkipAnalyzers diff --git a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.csproj.CoreCompileInputs.cache b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.csproj.CoreCompileInputs.cache index 7740bd8..b645bec 100644 --- a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.csproj.CoreCompileInputs.cache +++ b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -5d5ad68b9763065900c4e7e4bfbc0da49780450260a912803ce1fc8e535f4d95 +967849b6b3795276a76ec36da5c37cf08741dc0ed2f772c542be409b9c9f33a4 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 927ef77..0107600 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.genruntimeconfig.cache b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.genruntimeconfig.cache index 69ce85d..d4fbbf8 100644 --- a/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.genruntimeconfig.cache +++ b/src/DownloadManager.Core/obj/Release/net8.0/DownloadManager.Core.genruntimeconfig.cache @@ -1 +1 @@ -5b56d147ddedcff2d06ea77bcb0b0538bfe842eba6bdd8bbc7ba797bcb612cfa +9c0bb50180b3c956f2309448e0c12405847b070c2c6cffa0722b9b1b7f8ca98b 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 9870d7c..7a1897a 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 4628d12..4bad732 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 4628d12..4bad732 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 cea4cfd..0107600 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 e002dd9..7a1897a 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 edb8067..10879a8 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 521d35b..3b70f07 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 3e04670..0acc271 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/Debug/net8.0/DownloadManager.TestConsole.AssemblyInfoInputs.cache b/src/DownloadManager.TestConsole/obj/Debug/net8.0/DownloadManager.TestConsole.AssemblyInfoInputs.cache deleted file mode 100644 index d12439a..0000000 --- a/src/DownloadManager.TestConsole/obj/Debug/net8.0/DownloadManager.TestConsole.AssemblyInfoInputs.cache +++ /dev/null @@ -1 +0,0 @@ -507cb2c5ddfa77afd788c1dc5cc5d2e7476fc391ac1f1e508da7d937ebaeee83 diff --git a/src/DownloadManager.TestConsole/obj/Debug/net8.0/DownloadManager.TestConsole.GeneratedMSBuildEditorConfig.editorconfig b/src/DownloadManager.TestConsole/obj/Debug/net8.0/DownloadManager.TestConsole.GeneratedMSBuildEditorConfig.editorconfig deleted file mode 100644 index ff3f79c..0000000 --- a/src/DownloadManager.TestConsole/obj/Debug/net8.0/DownloadManager.TestConsole.GeneratedMSBuildEditorConfig.editorconfig +++ /dev/null @@ -1,15 +0,0 @@ -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.TestConsole -build_property.ProjectDir = D:\Calismalar\AI\hDM\DownloadManager\src\DownloadManager.TestConsole\ -build_property.EnableComHosting = -build_property.EnableGeneratedComInterfaceComImportInterop = -build_property.EffectiveAnalysisLevelStyle = 8.0 -build_property.EnableCodeStyleSeverity = diff --git a/src/DownloadManager.TestConsole/obj/Debug/net8.0/DownloadManager.TestConsole.assets.cache b/src/DownloadManager.TestConsole/obj/Debug/net8.0/DownloadManager.TestConsole.assets.cache index caeda53..8003513 100644 Binary files a/src/DownloadManager.TestConsole/obj/Debug/net8.0/DownloadManager.TestConsole.assets.cache and b/src/DownloadManager.TestConsole/obj/Debug/net8.0/DownloadManager.TestConsole.assets.cache differ diff --git a/src/DownloadManager.TestConsole/obj/Debug/net8.0/DownloadManager.TestConsole.csproj.AssemblyReference.cache b/src/DownloadManager.TestConsole/obj/Debug/net8.0/DownloadManager.TestConsole.csproj.AssemblyReference.cache deleted file mode 100644 index 3b39538..0000000 Binary files a/src/DownloadManager.TestConsole/obj/Debug/net8.0/DownloadManager.TestConsole.csproj.AssemblyReference.cache and /dev/null differ diff --git a/src/DownloadManager.TestConsole/obj/Debug/net8.0/apphost.exe b/src/DownloadManager.TestConsole/obj/Debug/net8.0/apphost.exe index 521d35b..3b70f07 100644 Binary files a/src/DownloadManager.TestConsole/obj/Debug/net8.0/apphost.exe and b/src/DownloadManager.TestConsole/obj/Debug/net8.0/apphost.exe 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 966ee15..6689b0b 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,6 +1,7 @@ //------------------------------------------------------------------------------ // // 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. @@ -13,10 +14,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")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+81faa715a4eb11a2bf648f52891306b46ea7c256")] [assembly: System.Reflection.AssemblyProductAttribute("DownloadManager.TestConsole")] [assembly: System.Reflection.AssemblyTitleAttribute("DownloadManager.TestConsole")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] -// MSBuild WriteCodeFragment sınıfı tarafından oluşturuldu. +// Generated by the MSBuild WriteCodeFragment class. 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 66257d7..b3061f7 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 @@ -0d52ecd1aec0f96823f1841c5b5686521d136d0b5c598693844c050f49e7862e +ca6e1ab4507e84385d05f14541ed3151a50c58ff919b0dc872c1409753ebe984 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 9de2c9f..1b2997c 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 edb8067..10879a8 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 3e04670..0acc271 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 521d35b..3b70f07 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 e460748..87cd082 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 e460748..87cd082 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 9123381..842e1df 100644 --- a/src/DownloadManager.WPF/App.xaml.cs +++ b/src/DownloadManager.WPF/App.xaml.cs @@ -3,6 +3,7 @@ using DownloadManager.Core.Data.Repositories; using DownloadManager.Core.Engine; using DownloadManager.Core.Enums; using DownloadManager.Core.Grabber; +using DownloadManager.Core.Models; using DownloadManager.Core.Protocols; using DownloadManager.Core.Queue; using DownloadManager.Core.Services; @@ -29,16 +30,51 @@ public partial class App : System.Windows.Application private IHost _host; private CancellationTokenSource _pipeCts = new(); + private static string GetExceptionDetails(Exception? ex) + { + if (ex == null) return string.Empty; + var sb = new StringBuilder(); + sb.AppendLine(ex.Message); + sb.AppendLine(ex.StackTrace); + if (ex.InnerException != null) + { + sb.AppendLine("\n--- Inner Exception ---"); + sb.AppendLine(GetExceptionDetails(ex.InnerException)); + } + return sb.ToString(); + } + public App() { - InitializeComponent(); - _host = Host.CreateDefaultBuilder() + AppDomain.CurrentDomain.UnhandledException += (s, e) => + { + var ex = e.ExceptionObject as Exception; + System.Windows.MessageBox.Show($"Kritik Hata (AppDomain): {GetExceptionDetails(ex)}", "Çökme", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); + }; + + this.DispatcherUnhandledException += (s, e) => + { + System.Windows.MessageBox.Show($"UI Hatası (Dispatcher): {GetExceptionDetails(e.Exception)}", "Çökme", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); + e.Handled = true; // Uygulamanın kapanmasını engellemeye çalış + }; + + TaskScheduler.UnobservedTaskException += (s, e) => + { + System.Windows.MessageBox.Show($"Arka Plan Görev Hatası (Task): {GetExceptionDetails(e.Exception)}", "Hata", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Warning); + e.SetObserved(); + }; + + try + { + InitializeComponent(); + _host = Host.CreateDefaultBuilder() .UseSerilog((ctx, cfg) => cfg .WriteTo.File(Path.Combine(GetAppDataPath(), "logs", "log-.txt"), rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7) .WriteTo.Debug() - .MinimumLevel.Information()) + .MinimumLevel.Information() + .MinimumLevel.Override("Microsoft.EntityFrameworkCore.Database.Command", Serilog.Events.LogEventLevel.Warning)) .ConfigureServices((_, services) => { // Veritabanı @@ -62,6 +98,11 @@ public partial class App : System.Windows.Application // Altyapı ve Motor services.AddHttpClient(); services.AddSingleton(); + services.AddSingleton(sp => + { + var opt = sp.GetRequiredService(); + return new SpeedThrottler(opt.SpeedLimitBytesPerSec); + }); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -79,6 +120,12 @@ public partial class App : System.Windows.Application services.AddSingleton(); }) .Build(); + } + catch (Exception ex) + { + System.Windows.MessageBox.Show($"Kritik Başlatma Hatası: {ex.Message}\n{ex.StackTrace}", "Çökme", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); + Environment.Exit(1); + } } private static string GetAppDataPath() @@ -176,19 +223,14 @@ public partial class App : System.Windows.Application if (string.IsNullOrEmpty(json)) continue; var data = JsonConvert.DeserializeObject(json); - if (data != null && data.url != null) + if (data != null) { - string url = data.url; + string? action = data.action; + string? url = data.url; string? suggestedName = data.filename; await System.Windows.Application.Current.Dispatcher.InvokeAsync(async () => { - var defaultPath = await settings.GetAsync("DefaultSavePath"); - if (string.IsNullOrEmpty(defaultPath)) - { - defaultPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads"); - } - // Pencereyi ön plana çıkar var win = System.Windows.Application.Current.MainWindow; if (win != null) @@ -198,46 +240,82 @@ public partial class App : System.Windows.Application win.Activate(); win.Topmost = true; - win.Topmost = false; // Odaklanmayı sağlamak için aç-kapat + win.Topmost = false; win.Focus(); } - // "Ekle" penceresini otomatik aç - var dialog = new Views.Dialogs.AddDownloadDialog(protocol, defaultPath, url, suggestedName); - var result = await dialog.ShowAsync(); - - if (result == ContentDialogResult.Primary) + if (action == "open_grabber") { - try + var grabber = _host.Services.GetRequiredService(); + var grabberWin = new Views.Dialogs.GrabberWindow(grabber, url) { Owner = win }; + + if (grabberWin.ShowDialog() == true) { - var item = await protocol.GetFileInfoAsync(dialog.Urls, CancellationToken.None); - - // Kullanıcı pencerede ismi değiştirdiyse onu kullan - if (!string.IsNullOrWhiteSpace(dialog.FileName)) + // Sonuçları ekle (MainViewModel'deki OpenGrabberCommand mantığıyla aynı) + var selected = grabberWin.SelectedResults; + var defaultPath = await settings.GetAsync("DefaultSavePath"); + foreach (var res in selected) { - item.FileName = dialog.FileName; + 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 }; + await service.AddDownloadAsync(item); + mainVm.AddDownloadItemViewModel(new DownloadItemViewModel { + Id = item.Id, FileName = item.FileName, Url = item.Url, + Status = DownloadStatus.Queued, FormattedSize = "Bilinmiyor", + CreatedAt = item.CreatedAt, + LastActivityAt = item.LastActivityAt + }); } - - 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 - }); } - catch (Exception ex) + return; + } + + if (!string.IsNullOrEmpty(url)) + { + var defaultPath = await settings.GetAsync("DefaultSavePath"); + if (string.IsNullOrEmpty(defaultPath)) { - 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); + 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 + { + 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 + }); + } + catch (Exception ex) + { + 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); + } } } }); @@ -253,16 +331,20 @@ public partial class App : System.Windows.Application protected override async void OnExit(ExitEventArgs e) { - _pipeCts.Cancel(); + _pipeCts?.Cancel(); - // Zamanlayıcıyı durdur - var watchdog = _host.Services.GetService(); - watchdog?.Stop(); - - using (_host) + if (_host != null) { - await _host.StopAsync(); + // Zamanlayıcıyı durdur + var watchdog = _host.Services.GetService(); + watchdog?.Stop(); + + using (_host) + { + await _host.StopAsync(); + } } + base.OnExit(e); } } diff --git a/src/DownloadManager.WPF/ViewModels/DownloadItemViewModel.cs b/src/DownloadManager.WPF/ViewModels/DownloadItemViewModel.cs index eecb735..d01493a 100644 --- a/src/DownloadManager.WPF/ViewModels/DownloadItemViewModel.cs +++ b/src/DownloadManager.WPF/ViewModels/DownloadItemViewModel.cs @@ -21,6 +21,18 @@ public partial class DownloadItemViewModel : ObservableObject [ObservableProperty] private DateTime _createdAt; [ObservableProperty] private DateTime? _lastActivityAt; + public string StatusText => Status switch + { + DownloadStatus.Pending => "Bekliyor", + DownloadStatus.Queued => "Sırada", + DownloadStatus.Downloading => "İndiriliyor", + DownloadStatus.Paused => "Duraklatıldı", + DownloadStatus.Completed => "Tamamlandı", + DownloadStatus.Error => "Hata", + DownloadStatus.Cancelled => "İptal Edildi", + _ => Status.ToString() + }; + /// Motor event'ından UI thread'e marshal edilerek çağrılır public void ApplyProgress(DownloadProgressEvent e) { @@ -30,6 +42,7 @@ public partial class DownloadItemViewModel : ObservableObject Speed = FormatSpeed(e.SpeedBytesPerSec); TimeRemaining = FormatRemaining(e.EstimatedRemaining); Status = e.Status; + OnPropertyChanged(nameof(StatusText)); }, DispatcherPriority.Normal); } diff --git a/src/DownloadManager.WPF/ViewModels/MainViewModel.cs b/src/DownloadManager.WPF/ViewModels/MainViewModel.cs index 2402930..18008da 100644 --- a/src/DownloadManager.WPF/ViewModels/MainViewModel.cs +++ b/src/DownloadManager.WPF/ViewModels/MainViewModel.cs @@ -27,6 +27,8 @@ public partial class MainViewModel : ObservableObject private readonly IDownloadProtocol _protocol; private readonly DownloadEngine _engine; private readonly DownloadQueue _queue; + private readonly SpeedThrottler _throttler; + private readonly EngineOptions _engineOptions; private readonly ISettingsService _settingsService; private readonly IScheduleService _scheduleService; private readonly SiteGrabber _grabber; @@ -40,7 +42,7 @@ public partial class MainViewModel : ObservableObject [ObservableProperty] private System.Windows.Media.PointCollection _speedPoints = new(); private readonly List _speedHistory = new(); - private const int MaxChartPoints = 480; //60 - 30 saniyelik veri (500ms sample) + private const int MaxChartPoints = 600; //60 - 30 saniyelik veri (500ms sample) private readonly System.Windows.Threading.DispatcherTimer _chartTimer; [ObservableProperty] private string _sortColumn = "CreatedAt"; @@ -58,6 +60,8 @@ public partial class MainViewModel : ObservableObject IDownloadProtocol protocol, DownloadEngine engine, DownloadQueue queue, + SpeedThrottler throttler, + EngineOptions engineOptions, ISettingsService settingsService, IScheduleService scheduleService, SiteGrabber grabber) @@ -66,6 +70,8 @@ public partial class MainViewModel : ObservableObject _protocol = protocol; _engine = engine; _queue = queue; + _throttler = throttler; + _engineOptions = engineOptions; _settingsService = settingsService; _scheduleService = scheduleService; _grabber = grabber; @@ -93,6 +99,13 @@ public partial class MainViewModel : ObservableObject if (int.TryParse(max, out var maxVal)) _queue.SetConcurrencyLimit(maxVal); + var speedLimit = await _settingsService.GetAsync("SpeedLimit", "0"); + if (long.TryParse(speedLimit, out var limitKbps)) + { + _engineOptions.SpeedLimitBytesPerSec = limitKbps * 1024; + _throttler.SetLimit(_engineOptions.SpeedLimitBytesPerSec); + } + var theme = await _settingsService.GetAsync("AppTheme", "System"); ApplyTheme(theme ?? "System"); @@ -163,7 +176,7 @@ public partial class MainViewModel : ObservableObject var sorted = column switch { "FileName" => ascending ? Downloads.OrderBy(x => x.FileName) : Downloads.OrderByDescending(x => x.FileName), - "Status" => ascending ? Downloads.OrderBy(x => x.Status) : Downloads.OrderByDescending(x => x.Status), + "Status" => ascending ? Downloads.OrderBy(x => x.StatusText) : Downloads.OrderByDescending(x => x.StatusText), "CreatedAt" => ascending ? Downloads.OrderBy(x => x.CreatedAt) : Downloads.OrderByDescending(x => x.CreatedAt), "LastActivityAt" => ascending ? Downloads.OrderBy(x => x.LastActivityAt) : Downloads.OrderByDescending(x => x.LastActivityAt), "Progress" => ascending ? Downloads.OrderBy(x => x.ProgressPercent) : Downloads.OrderByDescending(x => x.ProgressPercent), @@ -237,6 +250,7 @@ public partial class MainViewModel : ObservableObject private void UpdateSpeedChart() { var activeItems = Downloads.Where(x => x.Status == DownloadStatus.Downloading).ToList(); + double totalMbps = 0; foreach (var item in activeItems) { @@ -260,7 +274,7 @@ public partial class MainViewModel : ObservableObject if (maxSpeed < 0.1) maxSpeed = 0.1; //var w = ((System.Windows.Controls.Panel)Application.Current.MainWindow.Content).ActualWidth; //var w = bannerbg.ActualWidth - int w = System.Windows.Forms.SystemInformation.PrimaryMonitorSize.Width;; + int w = (int)System.Windows.SystemParameters.PrimaryScreenWidth; double width = w; // 900; // Grafik genişliği double height = 40; // Grafik yüksekliği @@ -435,9 +449,10 @@ public partial class MainViewModel : ObservableObject return target != null && (target.Status == DownloadStatus.Paused || target.Status == DownloadStatus.Error); } - [RelayCommand] - private async Task OpenFile(DownloadItemViewModel vm) + [RelayCommand(CanExecute = nameof(CanOpenFile))] + private async Task OpenFile(DownloadItemViewModel? vm) { + if (vm == null) return; try { var downloads = await _downloadService.GetAllDownloadsAsync(); @@ -450,9 +465,12 @@ public partial class MainViewModel : ObservableObject catch (Exception ex) { Serilog.Log.Error(ex, "Dosya açılamadı"); } } - [RelayCommand] - private async Task OpenWith(DownloadItemViewModel vm) + private bool CanOpenFile(DownloadItemViewModel? vm) => vm != null && vm.Status == DownloadStatus.Completed; + + [RelayCommand(CanExecute = nameof(CanOpenFile))] + private async Task OpenWith(DownloadItemViewModel? vm) { + if (vm == null) return; try { var downloads = await _downloadService.GetAllDownloadsAsync(); @@ -463,9 +481,10 @@ public partial class MainViewModel : ObservableObject catch { } } - [RelayCommand] - private async Task OpenFolder(DownloadItemViewModel vm) + [RelayCommand(CanExecute = nameof(CanOpenFolder))] + private async Task OpenFolder(DownloadItemViewModel? vm) { + if (vm == null) return; try { var downloads = await _downloadService.GetAllDownloadsAsync(); @@ -481,6 +500,8 @@ public partial class MainViewModel : ObservableObject catch { } } + private bool CanOpenFolder(DownloadItemViewModel? vm) => vm != null; + [RelayCommand] private async Task Rename(DownloadItemViewModel vm) { @@ -620,6 +641,13 @@ public partial class MainViewModel : ObservableObject dialog.SaveSettings(); var max = await _settingsService.GetAsync("MaxConcurrent", "3"); if (int.TryParse(max, out var maxVal)) _queue.SetConcurrencyLimit(maxVal); + + var speedLimit = await _settingsService.GetAsync("SpeedLimit", "0"); + if (long.TryParse(speedLimit, out var limitKbps)) + { + _engineOptions.SpeedLimitBytesPerSec = limitKbps * 1024; + _throttler.SetLimit(_engineOptions.SpeedLimitBytesPerSec); + } var theme = await _settingsService.GetAsync("AppTheme", "System"); ApplyTheme(theme ?? "System"); diff --git a/src/DownloadManager.WPF/Views/Dialogs/AddDownloadDialog.xaml.cs b/src/DownloadManager.WPF/Views/Dialogs/AddDownloadDialog.xaml.cs index 4b78e6e..3dd89a3 100644 --- a/src/DownloadManager.WPF/Views/Dialogs/AddDownloadDialog.xaml.cs +++ b/src/DownloadManager.WPF/Views/Dialogs/AddDownloadDialog.xaml.cs @@ -98,16 +98,15 @@ public partial class AddDownloadDialog : ContentDialog private void BrowseButton_Click(object sender, System.Windows.RoutedEventArgs e) { - using var dialog = new System.Windows.Forms.FolderBrowserDialog + var dialog = new Microsoft.Win32.OpenFolderDialog { - Description = "Kayıt klasörünü seçiniz", - UseDescriptionForTitle = true, - SelectedPath = PathTextBox.Text + Title = "Kayıt klasörünü seçiniz", + InitialDirectory = PathTextBox.Text }; - if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) + if (dialog.ShowDialog() == true) { - PathTextBox.Text = dialog.SelectedPath; + PathTextBox.Text = dialog.FolderName; } } } diff --git a/src/DownloadManager.WPF/Views/Dialogs/GrabberWindow.xaml.cs b/src/DownloadManager.WPF/Views/Dialogs/GrabberWindow.xaml.cs index cfdcfef..10e543f 100644 --- a/src/DownloadManager.WPF/Views/Dialogs/GrabberWindow.xaml.cs +++ b/src/DownloadManager.WPF/Views/Dialogs/GrabberWindow.xaml.cs @@ -17,11 +17,16 @@ public partial class GrabberWindow : Window public List SelectedResults { get; private set; } = new(); private CancellationTokenSource? _cts; - public GrabberWindow(SiteGrabber grabber) + public GrabberWindow(SiteGrabber grabber, string? initialUrl = null) { InitializeComponent(); _grabber = grabber; ResultList.ItemsSource = Results; + + if (!string.IsNullOrEmpty(initialUrl)) + { + UrlBox.Text = initialUrl; + } } private async void StartButton_Click(object sender, RoutedEventArgs e) diff --git a/src/DownloadManager.WPF/Views/Dialogs/PropertiesDialog.xaml b/src/DownloadManager.WPF/Views/Dialogs/PropertiesDialog.xaml index 41f4f81..4ea153b 100644 --- a/src/DownloadManager.WPF/Views/Dialogs/PropertiesDialog.xaml +++ b/src/DownloadManager.WPF/Views/Dialogs/PropertiesDialog.xaml @@ -7,9 +7,9 @@ PrimaryButtonText="Kapat" CloseButtonText=""> - + - + @@ -38,17 +38,17 @@ - + - + - + @@ -64,7 +64,7 @@ - +