Sync phone contacts and enable chat deletion

This commit is contained in:
Курнат Андрей
2026-07-13 21:10:10 +03:00
parent ff3f139889
commit 582f99ed0e
17 changed files with 636 additions and 49 deletions
@@ -11,6 +11,18 @@ public interface IMaxBridgeClient
{
return Task.FromResult<IReadOnlyList<MaxContact>>(Array.Empty<MaxContact>());
}
Task<IReadOnlyList<MaxContact>> ImportContactsAsync(IReadOnlyList<MaxPhoneContact> contacts, CancellationToken cancellationToken)
{
return Task.FromResult<IReadOnlyList<MaxContact>>(Array.Empty<MaxContact>());
}
Task<MaxContact?> AddContactAsync(string userId, CancellationToken cancellationToken)
{
return Task.FromResult<MaxContact?>(null);
}
Task<MaxActionResult> RemoveContactAsync(string userId, CancellationToken cancellationToken)
{
return Task.FromResult(new MaxActionResult(false, "Contact removal is not supported."));
}
Task<MaxChatUpdate?> FetchChatHistoryAsync(string externalChatId, string? chatUrl, CancellationToken cancellationToken);
Task<MaxChatPresence?> FetchChatPresenceAsync(string externalChatId, string? chatUrl, CancellationToken cancellationToken);
Task<MaxChatUrlResult> ResolveChatUrlAsync(string externalChatId, CancellationToken cancellationToken);
@@ -80,4 +80,7 @@ public sealed record MaxContact(
string DisplayName,
string? AvatarUrl,
string? PhoneNumber,
string? Status);
string? Status,
bool IsSavedContact = false);
public sealed record MaxPhoneContact(string PhoneNumber, string FirstName, string? LastName);
@@ -48,10 +48,25 @@ public sealed class MockMaxBridgeClient : IMaxBridgeClient
public Task<IReadOnlyList<MaxContact>> FetchContactsAsync(CancellationToken cancellationToken)
{
return Task.FromResult<IReadOnlyList<MaxContact>>([
new MaxContact("mock-user", "mock-direct", "Mock contact", null, "+70000000000", "online")
new MaxContact("mock-user", "mock-direct", "Mock contact", null, "+70000000000", "online", true)
]);
}
public Task<IReadOnlyList<MaxContact>> ImportContactsAsync(IReadOnlyList<MaxPhoneContact> contacts, CancellationToken cancellationToken)
{
return FetchContactsAsync(cancellationToken);
}
public async Task<MaxContact?> AddContactAsync(string userId, CancellationToken cancellationToken)
{
return (await FetchContactsAsync(cancellationToken)).FirstOrDefault();
}
public Task<MaxActionResult> RemoveContactAsync(string userId, CancellationToken cancellationToken)
{
return Task.FromResult(new MaxActionResult(true, null));
}
public Task<MaxChatUpdate?> FetchChatHistoryAsync(string externalChatId, string? chatUrl, CancellationToken cancellationToken)
{
var update = _updates.FirstOrDefault(x => x.ExternalId == externalChatId);
@@ -75,9 +90,7 @@ public sealed class MockMaxBridgeClient : IMaxBridgeClient
public Task<MaxActionResult> DeleteChatAsync(string externalChatId, string? chatUrl, CancellationToken cancellationToken)
{
return Task.FromResult(new MaxActionResult(
false,
"Chat deletion is disabled because MAX does not remove chats from the web client."));
return Task.FromResult(new MaxActionResult(true, null));
}
public Task<MaxSendResult> SendTextAsync(string externalChatId, string? chatUrl, string text, CancellationToken cancellationToken)
@@ -49,6 +49,29 @@ public sealed class WorkerMaxBridgeClient(
?? Array.Empty<MaxContact>();
}
public async Task<IReadOnlyList<MaxContact>> ImportContactsAsync(
IReadOnlyList<MaxPhoneContact> contacts,
CancellationToken cancellationToken)
{
return await SendAsync<IReadOnlyList<MaxContact>>(
HttpMethod.Post,
"/contacts/import",
new { contacts },
cancellationToken)
?? Array.Empty<MaxContact>();
}
public async Task<MaxContact?> AddContactAsync(string userId, CancellationToken cancellationToken)
{
return await SendAsync<MaxContact>(HttpMethod.Post, "/contacts/add", new { userId }, cancellationToken);
}
public async Task<MaxActionResult> RemoveContactAsync(string userId, CancellationToken cancellationToken)
{
return await SendAsync<MaxActionResult>(HttpMethod.Post, "/contacts/remove", new { userId }, cancellationToken)
?? new MaxActionResult(false, "Worker returned an empty contact removal result.");
}
public async Task<MaxChatUpdate?> FetchChatHistoryAsync(string externalChatId, string? chatUrl, CancellationToken cancellationToken)
{
return await SendAsync<MaxChatUpdate>(HttpMethod.Post, "/chat/history", new { externalChatId, chatUrl }, cancellationToken);
@@ -75,11 +98,14 @@ public sealed class WorkerMaxBridgeClient(
?? new MaxActionResult(false, "Worker returned an empty clear history result.");
}
public Task<MaxActionResult> DeleteChatAsync(string externalChatId, string? chatUrl, CancellationToken cancellationToken)
public async Task<MaxActionResult> DeleteChatAsync(string externalChatId, string? chatUrl, CancellationToken cancellationToken)
{
return Task.FromResult(new MaxActionResult(
false,
"Chat deletion is disabled because MAX does not remove chats from the web client."));
return await SendAsync<MaxActionResult>(
HttpMethod.Post,
"/chat/delete",
new { externalChatId, chatUrl },
cancellationToken)
?? new MaxActionResult(false, "Worker returned an empty chat deletion result.");
}
public async Task<MaxSendResult> SendTextAsync(string externalChatId, string? chatUrl, string text, CancellationToken cancellationToken)