Remove sqlite base64 contact store from AccountContact.

This commit is contained in:
Burak Kaan Köse
2026-03-07 11:43:56 +01:00
parent 8e8b123aa6
commit 09f1cee3a5
18 changed files with 136 additions and 103 deletions
+42 -2
View File
@@ -42,6 +42,7 @@ public class AccountService : BaseDatabaseService, IAccountService
private readonly IAuthenticationProvider _authenticationProvider;
private readonly IMimeFileService _mimeFileService;
private readonly IPreferencesService _preferencesService;
private readonly IContactPictureFileService _contactPictureFileService;
private readonly ILogger _logger = Log.ForContext<AccountService>();
@@ -49,12 +50,14 @@ public class AccountService : BaseDatabaseService, IAccountService
ISignatureService signatureService,
IAuthenticationProvider authenticationProvider,
IMimeFileService mimeFileService,
IPreferencesService preferencesService) : base(databaseService)
IPreferencesService preferencesService,
IContactPictureFileService contactPictureFileService) : base(databaseService)
{
_signatureService = signatureService;
_authenticationProvider = authenticationProvider;
_mimeFileService = mimeFileService;
_preferencesService = preferencesService;
_contactPictureFileService = contactPictureFileService;
}
@@ -399,11 +402,19 @@ public class AccountService : BaseDatabaseService, IAccountService
}
// Forcefully add or update a contact data with the provided information.
var existingContact = await Connection.Table<AccountContact>()
.FirstOrDefaultAsync(a => a.Address == account.Address)
.ConfigureAwait(false);
var contactPictureFileId = await SaveProfilePictureAsync(
account.Base64ProfilePictureData,
existingContact?.ContactPictureFileId).ConfigureAwait(false);
var accountContact = new AccountContact()
{
Address = account.Address,
Name = account.SenderName,
Base64ContactPicture = account.Base64ProfilePictureData,
ContactPictureFileId = contactPictureFileId,
IsRootContact = true
};
@@ -413,6 +424,35 @@ public class AccountService : BaseDatabaseService, IAccountService
}
}
private async Task<Guid?> SaveProfilePictureAsync(string base64ProfilePictureData, Guid? existingFileId)
{
if (string.IsNullOrWhiteSpace(base64ProfilePictureData))
{
if (existingFileId.HasValue)
await _contactPictureFileService.DeleteContactPictureAsync(existingFileId.Value).ConfigureAwait(false);
return null;
}
byte[] bytes;
try
{
bytes = Convert.FromBase64String(base64ProfilePictureData);
}
catch (FormatException ex)
{
_logger.Warning(ex, "Failed to decode account profile picture for contact migration.");
return existingFileId;
}
var newFileId = await _contactPictureFileService.SaveContactPictureAsync(bytes).ConfigureAwait(false);
if (existingFileId.HasValue)
await _contactPictureFileService.DeleteContactPictureAsync(existingFileId.Value).ConfigureAwait(false);
return newFileId;
}
public async Task<MailAccount> GetAccountAsync(Guid accountId)
{
var account = await Connection.Table<MailAccount>().FirstOrDefaultAsync(a => a.Id == accountId);
+12 -6
View File
@@ -13,6 +13,12 @@ namespace Wino.Services;
/// </summary>
public class ContactPictureFileService : BaseDatabaseService, IContactPictureFileService
{
private sealed class LegacyAccountContactPictureRow
{
public string Address { get; set; }
public string Base64ContactPicture { get; set; }
}
private const string ContactsSubFolder = "contacts";
private readonly string _contactPicturesFolder;
@@ -52,8 +58,8 @@ public class ContactPictureFileService : BaseDatabaseService, IContactPictureFil
try
{
var contacts = await Connection
.QueryAsync<AccountContact>(
"SELECT * FROM AccountContact WHERE Base64ContactPicture IS NOT NULL AND ContactPictureFileId IS NULL")
.QueryAsync<LegacyAccountContactPictureRow>(
"SELECT Address, Base64ContactPicture FROM AccountContact WHERE Base64ContactPicture IS NOT NULL AND ContactPictureFileId IS NULL")
.ConfigureAwait(false);
foreach (var contact in contacts)
@@ -67,10 +73,10 @@ public class ContactPictureFileService : BaseDatabaseService, IContactPictureFil
var bytes = Convert.FromBase64String(base64);
var fileId = await SaveContactPictureAsync(bytes).ConfigureAwait(false);
contact.ContactPictureFileId = fileId;
contact.Base64ContactPicture = null;
await Connection.UpdateAsync(contact, typeof(AccountContact)).ConfigureAwait(false);
await Connection.ExecuteAsync(
"UPDATE AccountContact SET ContactPictureFileId = ?, Base64ContactPicture = NULL WHERE Address = ?",
fileId,
contact.Address).ConfigureAwait(false);
}
catch (Exception ex)
{
+26 -8
View File
@@ -465,14 +465,21 @@ public class MailService : BaseDatabaseService, IMailService
// Self-sent mails (e.g. Sent folder): construct contact from account meta
// to get the up-to-date profile picture without a DB roundtrip.
if (!string.IsNullOrEmpty(mail.FromAddress) && mail.FromAddress == account.Address)
if (!string.IsNullOrEmpty(mail.FromAddress) &&
string.Equals(mail.FromAddress, account.Address, StringComparison.OrdinalIgnoreCase))
{
mail.SenderContact = new AccountContact
if (contactCache.TryGetValue(mail.FromAddress, out var ownContact))
{
Address = account.Address,
Name = account.SenderName,
Base64ContactPicture = account.Base64ProfilePictureData
};
mail.SenderContact = ownContact;
}
else
{
mail.SenderContact = new AccountContact
{
Address = account.Address,
Name = account.SenderName
};
}
}
else
{
@@ -543,9 +550,9 @@ public class MailService : BaseDatabaseService, IMailService
private Task<AccountContact> GetSenderContactForAccountAsync(MailAccount account, string fromAddress)
{
// Make sure to return the latest up to date contact information for the original account.
if (fromAddress == account.Address)
if (string.Equals(fromAddress, account.Address, StringComparison.OrdinalIgnoreCase))
{
return Task.FromResult(new AccountContact() { Address = account.Address, Name = account.SenderName, Base64ContactPicture = account.Base64ProfilePictureData });
return GetOwnSenderContactAsync(account);
}
else
{
@@ -553,6 +560,17 @@ public class MailService : BaseDatabaseService, IMailService
}
}
private async Task<AccountContact> GetOwnSenderContactAsync(MailAccount account)
{
var contact = await _contactService.GetAddressInformationByAddressAsync(account.Address).ConfigureAwait(false);
return contact ?? new AccountContact
{
Address = account.Address,
Name = account.SenderName
};
}
private async Task LoadAssignedPropertiesAsync(MailCopy mailCopy)
{
if (mailCopy == null) return;