Teams-style chat list, contact name resolution, and fixes
UI:
- Rework the conversation list to a Teams/Outlook-style row: single-line
preview, right-aligned timestamp, unread dot, and a neutral elevated
rounded fill (drawn by a Border that wraps the whole row) for hover/select.
- Smooth the Chats/Calls/Stories rail indicator by suppressing the content
frame's transition, which competed with the indicator animation.
Contact names:
- Fetch + decrypt Signal profile names (ProfileCipher, ProfileService,
ProfileNameStore, GET /v1/profile) when a peer has no synced name.
- Capture each contact's profileKey from the link'n'sync backup and the
contacts sync (un-reserve ContactDetails.profileKey) so names can be
resolved; fall back to the phone number before a raw ACI.
Other:
- Report the device to Signal as "Wingnal: {machine name}".
- Resolve build warnings: target Wingnal.Service at net8.0-windows (CA1416),
initialize zkgroup credential fields (CS8618), hoist a stackalloc (CA2014).
- Skip the live chat-connect diagnostic test by default (it logged in as the
real account and disconnected the app).
- Bump app version 1.0.1.0 -> 1.0.2.0.
This commit is contained in:
@@ -46,13 +46,13 @@ public sealed class ShoSha256
|
||||
{
|
||||
if (_absorbing) throw new InvalidOperationException("ShoSha256: must ratchet before squeezing");
|
||||
var output = new byte[outlen];
|
||||
Span<byte> ctr = stackalloc byte[8]; // hoisted out of the loop; fully rewritten each iteration
|
||||
for (int i = 0; i * HashLen < outlen; i++)
|
||||
{
|
||||
using var h = IncrementalHash.CreateHash(HashAlgorithmName.SHA256);
|
||||
h.AppendData(new byte[BlockLen - 1]); // 63 zero bytes
|
||||
h.AppendData(new byte[] { 0x01 });
|
||||
h.AppendData(_cv);
|
||||
Span<byte> ctr = stackalloc byte[8];
|
||||
BinaryPrimitives.WriteUInt64BigEndian(ctr, (ulong)i);
|
||||
h.AppendData(ctr);
|
||||
byte[] digest = h.GetHashAndReset();
|
||||
|
||||
@@ -16,7 +16,8 @@ public static class CredentialSystem
|
||||
|
||||
public sealed class SystemParams
|
||||
{
|
||||
public Ristretto255 GW, GWprime, GX0, GX1, GV, GZ;
|
||||
// Always populated by Generate()'s object initializer (null! silences the constructor-exit check).
|
||||
public Ristretto255 GW = null!, GWprime = null!, GX0 = null!, GX1 = null!, GV = null!, GZ = null!;
|
||||
public Ristretto255[] GY = new Ristretto255[NumSupportedAttrs];
|
||||
|
||||
public static readonly SystemParams Hardcoded = Generate();
|
||||
@@ -84,7 +85,7 @@ public sealed class Credential
|
||||
public sealed class CredentialPrivateKey
|
||||
{
|
||||
public Scalar25519 W, Wprime, X0, X1;
|
||||
public Ristretto255 BigW;
|
||||
public Ristretto255 BigW = null!; // set by Generate()/FromPrivate() before use
|
||||
public Scalar25519[] Y = new Scalar25519[CredentialSystem.NumSupportedAttrs];
|
||||
|
||||
public static CredentialPrivateKey Generate(byte[] randomness)
|
||||
@@ -120,7 +121,7 @@ public sealed class CredentialPrivateKey
|
||||
/// <summary>The server's public credential key the client uses to receive + present credentials.</summary>
|
||||
public sealed class CredentialPublicKey
|
||||
{
|
||||
public Ristretto255 CW;
|
||||
public Ristretto255 CW = null!; // set by FromPrivate() before use
|
||||
public Ristretto255[] I = new Ristretto255[CredentialSystem.NumSupportedAttrs - 1]; // I_2 .. I_7
|
||||
|
||||
/// <summary>I for a credential with <paramref name="numAttrs"/> attribute points (≥2).</summary>
|
||||
|
||||
Reference in New Issue
Block a user