diff --git a/src/InboxIntel.Api/Controllers/WidgetLayoutController.cs b/src/InboxIntel.Api/Controllers/WidgetLayoutController.cs index 0dc1dec..fc3ee67 100644 --- a/src/InboxIntel.Api/Controllers/WidgetLayoutController.cs +++ b/src/InboxIntel.Api/Controllers/WidgetLayoutController.cs @@ -42,8 +42,15 @@ public class WidgetLayoutController : ApiControllerBase { _db.WidgetLayouts.Add(new WidgetLayout { - UserId = UserId, WidgetKey = dto.WidgetKey, X = dto.X, Y = dto.Y, W = dto.W, H = dto.H, - Visible = dto.Visible, SortOrder = dto.SortOrder, SettingsJson = dto.SettingsJson + UserId = UserId, + WidgetKey = dto.WidgetKey, + X = dto.X, + Y = dto.Y, + W = dto.W, + H = dto.H, + Visible = dto.Visible, + SortOrder = dto.SortOrder, + SettingsJson = dto.SettingsJson }); } } diff --git a/src/InboxIntel.Infrastructure/Analytics/AnalyticsService.cs b/src/InboxIntel.Infrastructure/Analytics/AnalyticsService.cs index 17a0e2e..7cb9fe2 100644 --- a/src/InboxIntel.Infrastructure/Analytics/AnalyticsService.cs +++ b/src/InboxIntel.Infrastructure/Analytics/AnalyticsService.cs @@ -133,13 +133,13 @@ public class AnalyticsService : IAnalyticsService var emails = _db.Emails.Where(e => e.UserId == userId); var allMail = await emails.CountAsync(ct); - var inbox = await emails.CountAsync(e => e.IsInInbox, ct); - var unread = await emails.CountAsync(e => e.IsUnread, ct); + var inbox = await emails.CountAsync(e => e.IsInInbox, ct); + var unread = await emails.CountAsync(e => e.IsUnread, ct); var starred = await emails.CountAsync(e => e.IsStarred, ct); - var trash = await emails.CountAsync(e => e.IsTrashed, ct); - var large = await emails.CountAsync(e => e.SizeEstimateBytes > 5_000_000, ct); - var cutoff = DateTimeOffset.UtcNow.AddYears(-1); - var old = await emails.CountAsync(e => e.SentAtUtc < cutoff, ct); + var trash = await emails.CountAsync(e => e.IsTrashed, ct); + var large = await emails.CountAsync(e => e.SizeEstimateBytes > 5_000_000, ct); + var cutoff = DateTimeOffset.UtcNow.AddYears(-1); + var old = await emails.CountAsync(e => e.SentAtUtc < cutoff, ct); // Label-backed counts (SENT / DRAFT / SPAM are system Gmail labels) async Task LabelCount(string gmailId) @@ -153,9 +153,9 @@ public class AnalyticsService : IAnalyticsService : 0; } - var sent = await LabelCount("SENT"); + var sent = await LabelCount("SENT"); var drafts = await LabelCount("DRAFT"); - var spam = await LabelCount("SPAM"); + var spam = await LabelCount("SPAM"); // Category → smart-folder slug mapping var catCounts = await emails @@ -167,31 +167,31 @@ public class AnalyticsService : IAnalyticsService var smartFolders = new Dictionary { - ["automated"] = Cat(EmailCategory.Notification), - ["finance"] = Cat(EmailCategory.Finance), - ["social"] = Cat(EmailCategory.Social), - ["shopping"] = Cat(EmailCategory.Shopping) + Cat(EmailCategory.Promotional), - ["noreply"] = Cat(EmailCategory.Notification), - ["gaming"] = Cat(EmailCategory.Gaming), - ["sales"] = Cat(EmailCategory.SeasonalSales), - ["ridesharing"] = Cat(EmailCategory.RideSharing), - ["food"] = Cat(EmailCategory.FoodDelivery), - ["wellness"] = Cat(EmailCategory.Wellness), + ["automated"] = Cat(EmailCategory.Notification), + ["finance"] = Cat(EmailCategory.Finance), + ["social"] = Cat(EmailCategory.Social), + ["shopping"] = Cat(EmailCategory.Shopping) + Cat(EmailCategory.Promotional), + ["noreply"] = Cat(EmailCategory.Notification), + ["gaming"] = Cat(EmailCategory.Gaming), + ["sales"] = Cat(EmailCategory.SeasonalSales), + ["ridesharing"] = Cat(EmailCategory.RideSharing), + ["food"] = Cat(EmailCategory.FoodDelivery), + ["wellness"] = Cat(EmailCategory.Wellness), // New categories - ["travel"] = Cat(EmailCategory.Travel), + ["travel"] = Cat(EmailCategory.Travel), ["subscriptions"] = Cat(EmailCategory.Subscriptions), - ["parcels"] = Cat(EmailCategory.Parcels), - ["recruitment"] = Cat(EmailCategory.Recruitment), - ["events"] = Cat(EmailCategory.Events), - ["security"] = Cat(EmailCategory.SecurityAlerts), - ["healthcare"] = Cat(EmailCategory.Healthcare), - ["education"] = Cat(EmailCategory.Education), - ["news"] = Cat(EmailCategory.NewsMedia), - ["property"] = Cat(EmailCategory.PropertyUtilities), - ["charity"] = Cat(EmailCategory.Charity), - ["government"] = Cat(EmailCategory.Government), - ["crypto"] = Cat(EmailCategory.CryptoInvesting), - ["family"] = Cat(EmailCategory.FamilySchool), + ["parcels"] = Cat(EmailCategory.Parcels), + ["recruitment"] = Cat(EmailCategory.Recruitment), + ["events"] = Cat(EmailCategory.Events), + ["security"] = Cat(EmailCategory.SecurityAlerts), + ["healthcare"] = Cat(EmailCategory.Healthcare), + ["education"] = Cat(EmailCategory.Education), + ["news"] = Cat(EmailCategory.NewsMedia), + ["property"] = Cat(EmailCategory.PropertyUtilities), + ["charity"] = Cat(EmailCategory.Charity), + ["government"] = Cat(EmailCategory.Government), + ["crypto"] = Cat(EmailCategory.CryptoInvesting), + ["family"] = Cat(EmailCategory.FamilySchool), }; return new SidebarCountsDto(inbox, allMail, unread, starred, sent, drafts, trash, spam, large, old, smartFolders); diff --git a/src/InboxIntel.Infrastructure/Search/SearchService.cs b/src/InboxIntel.Infrastructure/Search/SearchService.cs index ef3b0b4..601f8ce 100644 --- a/src/InboxIntel.Infrastructure/Search/SearchService.cs +++ b/src/InboxIntel.Infrastructure/Search/SearchService.cs @@ -79,7 +79,10 @@ public class SearchService : ISearchService return new PagedResult { - Items = items, Page = r.Page, PageSize = r.PageSize, TotalCount = total + Items = items, + Page = r.Page, + PageSize = r.PageSize, + TotalCount = total }; } } diff --git a/src/InboxIntel.Infrastructure/Sync/HeuristicClassifier.cs b/src/InboxIntel.Infrastructure/Sync/HeuristicClassifier.cs index 445deb5..bf8d8a4 100644 --- a/src/InboxIntel.Infrastructure/Sync/HeuristicClassifier.cs +++ b/src/InboxIntel.Infrastructure/Sync/HeuristicClassifier.cs @@ -412,7 +412,7 @@ public static class HeuristicClassifier public static EmailCategory Classify(GmailMessageDetail d) { var subject = (d.Subject ?? string.Empty).ToLowerInvariant(); - var from = d.FromAddress.ToLowerInvariant(); + var from = d.FromAddress.ToLowerInvariant(); // 1. Security alerts — highest priority, overrides everything if (SecuritySubjectHints.Any(h => subject.Contains(h))) diff --git a/src/InboxIntel.Infrastructure/Sync/SyncService.cs b/src/InboxIntel.Infrastructure/Sync/SyncService.cs index 7b7f15a..27798e9 100644 --- a/src/InboxIntel.Infrastructure/Sync/SyncService.cs +++ b/src/InboxIntel.Infrastructure/Sync/SyncService.cs @@ -268,8 +268,12 @@ public class SyncService : ISyncService { _db.Attachments.Add(new Attachment { - UserId = userId, EmailId = email.Id, FileName = Trunc(fileName, 512) ?? string.Empty, - MimeType = Trunc(mime, 255), SizeBytes = size, GmailAttachmentId = attId + UserId = userId, + EmailId = email.Id, + FileName = Trunc(fileName, 512) ?? string.Empty, + MimeType = Trunc(mime, 255), + SizeBytes = size, + GmailAttachmentId = attId }); } @@ -338,8 +342,11 @@ public class SyncService : ISyncService if (thread is not null) return thread; thread = new MailThread { - UserId = userId, GmailThreadId = gmailThreadId, Subject = Trunc(subject, 1024), - Snippet = Trunc(snippet, 2048), FirstMessageUtc = sentAt + UserId = userId, + GmailThreadId = gmailThreadId, + Subject = Trunc(subject, 1024), + Snippet = Trunc(snippet, 2048), + FirstMessageUtc = sentAt }; _db.Threads.Add(thread); return thread;