Skip to content

Commit 504bc2c

Browse files
committed
fix: file manager improves
1 parent 1e795b0 commit 504bc2c

6 files changed

Lines changed: 170 additions & 20 deletions

File tree

TelegramDownloader/Data/FileService.cs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -527,9 +527,10 @@ public async Task oneItemDeleteAsync(string dbName, Syncfusion.Blazor.FileManage
527527
{
528528
if (!item.IsFile)
529529
{
530-
var result = await copyAllDirectoryFiles(dbName, item.Id, args.TargetData, args.TargetPath + item.Name + "/");
530+
// Pass args.IsCopy to handle internal files correctly (delete originals when moving)
531+
var result = await copyAllDirectoryFiles(dbName, item.Id, args.TargetData, args.TargetPath + item.Name + "/", args.IsCopy);
531532
lista.Add(result.toFileManagerContentInCopy());
532-
533+
// Note: copyAllDirectoryFiles now handles deletion of the folder when IsCopy=false
533534
}
534535
else
535536
{
@@ -539,7 +540,6 @@ public async Task oneItemDeleteAsync(string dbName, Syncfusion.Blazor.FileManage
539540
{
540541
await _db.deleteEntry(dbName, item.Id);
541542
}
542-
543543
}
544544
await _db.addBytesToFolder(dbName, item.ParentId, item.Size);
545545
}
@@ -573,12 +573,10 @@ public async Task oneItemDeleteAsync(string dbName, Syncfusion.Blazor.FileManage
573573
{
574574
if (!item.IsFile)
575575
{
576-
var result = await copyAllDirectoryFiles(dbName, item.Id, targetData, targetPath + item.Name + "/");
576+
// Pass isCopy to handle internal files correctly (delete originals when moving)
577+
var result = await copyAllDirectoryFiles(dbName, item.Id, targetData, targetPath + item.Name + "/", isCopy);
577578
lista.Add(result.toFileManagerContentInCopy());
578-
if (!isCopy)
579-
{
580-
await _db.deleteEntry(dbName, item.Id);
581-
}
579+
// Note: copyAllDirectoryFiles now handles deletion of the folder when isCopy=false
582580
}
583581
else
584582
{
@@ -626,11 +624,9 @@ private async Task<BsonFileManagerModel> copyAllDirectoryFiles(string dbName, st
626624
}
627625
else
628626
{
629-
await copyAllDirectoryFiles(dbName, file.Id, result.toFileManagerContent(), targetPath + file.Name + "/");
630-
if (!isCopy)
631-
{
632-
await _db.deleteEntry(dbName, file.Id);
633-
}
627+
// Pass isCopy to recursive call to handle nested folders correctly
628+
await copyAllDirectoryFiles(dbName, file.Id, result.toFileManagerContent(), targetPath + file.Name + "/", isCopy);
629+
// Note: recursive call handles deletion when isCopy=false, no need to delete here
634630
}
635631
}
636632
if (!isCopy)

TelegramDownloader/Data/db/DbService.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -489,10 +489,12 @@ public async Task<BsonFileManagerModel> copyItem(string dbName, string sourceId,
489489
result.Id = null;
490490
result.ParentId = target.Id;
491491
result.DateModified = DateTime.Now;
492-
result.FilterId = target.FilterId + target.Id + "/";
492+
result.FilterId = (target.FilterId ?? "") + target.Id + "/";
493493
result.ParentId = target.Id;
494-
result.FilterPath = target.FilterPath == "" ? "/" : target.FilterPath + target.Name + "/";
495-
result.FilePath = isFile ? targetPath + result.Name : targetPath;
494+
// Both empty string and "/" indicate root folder
495+
var isRootTarget = string.IsNullOrEmpty(target.FilterPath) || target.FilterPath == "/";
496+
result.FilterPath = isRootTarget ? "/" : target.FilterPath + target.Name + "/";
497+
result.FilePath = isFile ? targetPath + result.Name : targetPath.TrimEnd('/');
496498
await getDatabase(dbName).GetCollection<BsonFileManagerModel>(collectionName).InsertOneAsync(result);
497499
return result;
498500

TelegramDownloader/Pages/FileManager.razor

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@
5050
}
5151
}
5252

53+
<DropdownDivider />
54+
<DropdownItem @onclick="openDeleteChannelModal" Type="DropdownItemType.Button" Class="text-danger">
55+
<i class="bi bi-trash"></i> Delete Database
56+
</DropdownItem>
5357
</DropdownMenu>
5458
</Dropdown>
5559
@if (webDavService.IsRunning)
@@ -71,13 +75,15 @@
7175
<TelegramDownloader.Pages.Partials.impl.FileManagerImpl @ref="fileManagerImpl" id="@id"></TelegramDownloader.Pages.Partials.impl.FileManagerImpl>
7276
<TelegramDownloader.Pages.Modals.ImportDataModal id="@id" @ref="ImportModal"></TelegramDownloader.Pages.Modals.ImportDataModal>
7377
<TelegramDownloader.Pages.Modals.InfoModals.MediaUrlModal @ref="mediaUrlModal" title="WebDav URL" url="@webDavUrl"></TelegramDownloader.Pages.Modals.InfoModals.MediaUrlModal>
78+
<TelegramDownloader.Pages.Modals.InfoModals.DeleteChannelModal @ref="deleteChannelModal" ChannelId="@id" ChannelName="@chatName"></TelegramDownloader.Pages.Modals.InfoModals.DeleteChannelModal>
7479

7580
@code {
7681
private Modals.ImportDataModal ImportModal { get; set; }
7782
private TelegramDownloader.Pages.Partials.impl.FileManagerImpl fileManagerImpl { get; set; } = default!;
7883
[Parameter]
7984
public string id { get; set; }
8085
private MediaUrlModal mediaUrlModal { get; set; } = default!;
86+
private DeleteChannelModal deleteChannelModal { get; set; } = default!;
8187

8288
private WebbDavService webDavService = GeneralConfigStatic.config.webDav.webDavService ?? new WebbDavService();
8389
private String webDavUrl = "";
@@ -156,4 +162,9 @@
156162
await InvokeAsync(StateHasChanged);
157163
}
158164
}
165+
166+
public async Task openDeleteChannelModal()
167+
{
168+
await deleteChannelModal.ShowAsync();
169+
}
159170
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
@using TelegramDownloader.Data.db
2+
@inject IDbService DbService
3+
@inject NavigationManager NavigationManager
4+
5+
<Modal @ref="modal" Title="Delete Channel Database" Size="ModalSize.Regular">
6+
<BodyTemplate>
7+
<div class="alert alert-danger" role="alert">
8+
<i class="bi bi-exclamation-triangle-fill me-2"></i>
9+
<strong>Warning!</strong> This action cannot be undone. All files and folders in this channel's database will be permanently deleted.
10+
</div>
11+
12+
<div class="mb-3">
13+
<label class="form-label fw-bold">Channel ID:</label>
14+
<div class="form-control bg-light">@ChannelId</div>
15+
</div>
16+
17+
<div class="mb-3">
18+
<label class="form-label fw-bold">Channel Name:</label>
19+
<div class="form-control bg-light">@ChannelName</div>
20+
</div>
21+
22+
<hr />
23+
24+
<div class="mb-3">
25+
<label class="form-label">To confirm deletion, type the channel ID: <strong>@ChannelId</strong></label>
26+
<input type="text" class="form-control @(IsInputValid ? "" : "is-invalid")"
27+
@bind="ConfirmationInput"
28+
@bind:event="oninput"
29+
placeholder="Enter channel ID to confirm" />
30+
@if (!string.IsNullOrEmpty(ConfirmationInput) && !IsInputValid)
31+
{
32+
<div class="invalid-feedback">
33+
The channel ID does not match.
34+
</div>
35+
}
36+
</div>
37+
</BodyTemplate>
38+
<FooterTemplate>
39+
<Button Color="ButtonColor.Secondary" @onclick="OnHideModalClick">Cancel</Button>
40+
<Button Color="ButtonColor.Danger"
41+
@onclick="OnDeleteClick"
42+
Disabled="@(!IsInputValid || isDeleting)">
43+
@if (isDeleting)
44+
{
45+
<Spinner Type="SpinnerType.Border" Size="SpinnerSize.Small" Class="me-2" />
46+
<span>Deleting...</span>
47+
}
48+
else
49+
{
50+
<i class="bi bi-trash me-2"></i>
51+
<span>Delete Database</span>
52+
}
53+
</Button>
54+
</FooterTemplate>
55+
</Modal>
56+
57+
@code {
58+
[Parameter] public string ChannelId { get; set; } = string.Empty;
59+
[Parameter] public string ChannelName { get; set; } = string.Empty;
60+
[Inject] protected ToastService ToastService { get; set; } = default!;
61+
62+
private Modal modal = default!;
63+
private string ConfirmationInput { get; set; } = string.Empty;
64+
private bool isDeleting = false;
65+
66+
private bool IsInputValid => !string.IsNullOrEmpty(ConfirmationInput) &&
67+
ConfirmationInput.Trim() == ChannelId;
68+
69+
public async Task ShowAsync()
70+
{
71+
ConfirmationInput = string.Empty;
72+
isDeleting = false;
73+
await modal.ShowAsync();
74+
}
75+
76+
private async Task OnHideModalClick()
77+
{
78+
await modal.HideAsync();
79+
}
80+
81+
private async Task OnDeleteClick()
82+
{
83+
if (!IsInputValid || isDeleting)
84+
return;
85+
86+
isDeleting = true;
87+
StateHasChanged();
88+
89+
try
90+
{
91+
await DbService.deleteDatabase(ChannelId);
92+
await modal.HideAsync();
93+
94+
ToastService.Notify(new ToastMessage(ToastType.Success, $"Database for channel '{ChannelName}' has been deleted successfully.")
95+
{
96+
Title = "Database Deleted",
97+
AutoHide = true
98+
});
99+
100+
// Navigate to home page
101+
NavigationManager.NavigateTo("/fetchdata", forceLoad: true);
102+
}
103+
catch (Exception ex)
104+
{
105+
ToastService.Notify(new ToastMessage(ToastType.Danger, $"Error deleting database: {ex.Message}")
106+
{
107+
Title = "Error",
108+
AutoHide = true
109+
});
110+
isDeleting = false;
111+
StateHasChanged();
112+
}
113+
}
114+
}

TelegramDownloader/Shared/MobileFileManager/MobileFileManager.razor

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
@using Syncfusion.Blazor.FileManager
22
@using TelegramDownloader.Models
33
@inject ILogger<MobileFileManager> Logger
4+
@inject IJSRuntime JSRuntime
45

56
<div class="mobile-file-manager @(IsFullscreen ? "mfm-fullscreen" : "")">
67
@* Header con breadcrumb y acciones *@
@@ -497,7 +498,9 @@
497498
<div class="mfm-modal-overlay" @onclick="CloseNewFolderDialog">
498499
<div class="mfm-dialog" @onclick:stopPropagation="true">
499500
<h3>New folder</h3>
500-
<input type="text" @bind="NewFolderName" @ref="newFolderInput" class="mfm-input" placeholder="Folder name" />
501+
<input type="text" @bind="NewFolderName" @bind:event="oninput" @ref="newFolderInput"
502+
class="mfm-input" placeholder="Folder name"
503+
@onkeydown="OnNewFolderKeyDown" />
501504
<div class="mfm-dialog-actions">
502505
<button class="mfm-btn mfm-btn-secondary" @onclick="CloseNewFolderDialog">Cancel</button>
503506
<button class="mfm-btn mfm-btn-primary" @onclick="ConfirmNewFolder">Create</button>

TelegramDownloader/Shared/MobileFileManager/MobileFileManager.razor.cs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.AspNetCore.Components;
22
using Microsoft.AspNetCore.Components.Web;
3+
using Microsoft.JSInterop;
34
using Syncfusion.Blazor.FileManager;
45
using System.Timers;
56

@@ -637,8 +638,9 @@ private async Task PasteItems()
637638
{
638639
Id = CurrentFolder.Id,
639640
Name = CurrentFolder.Name,
640-
FilterPath = NormalizePath(CurrentFolder.FilterPath ?? ""),
641-
FilterId = CurrentFolder.FilterId,
641+
// Preserve empty FilterPath for root folder - don't normalize it to "/"
642+
FilterPath = string.IsNullOrEmpty(CurrentFolder.FilterPath) ? "" : NormalizePath(CurrentFolder.FilterPath),
643+
FilterId = CurrentFolder.FilterId ?? "",
642644
IsFile = false
643645
};
644646
}
@@ -780,11 +782,33 @@ private void CloseRenameDialog()
780782

781783
#region New Folder
782784

783-
private void CreateNewFolder()
785+
private async Task CreateNewFolder()
784786
{
785787
ShowFabMenu = false;
786788
NewFolderName = "New Folder";
787789
ShowNewFolderDialog = true;
790+
StateHasChanged();
791+
792+
// Wait for the dialog to render, then focus and select all text
793+
await Task.Delay(50);
794+
try
795+
{
796+
await newFolderInput.FocusAsync();
797+
await JSRuntime.InvokeVoidAsync("eval", "document.activeElement.select()");
798+
}
799+
catch { }
800+
}
801+
802+
private async Task OnNewFolderKeyDown(KeyboardEventArgs e)
803+
{
804+
if (e.Key == "Enter")
805+
{
806+
await ConfirmNewFolder();
807+
}
808+
else if (e.Key == "Escape")
809+
{
810+
CloseNewFolderDialog();
811+
}
788812
}
789813

790814
private async Task ConfirmNewFolder()

0 commit comments

Comments
 (0)