@@ -40,7 +40,7 @@ module App =
4040
4141 type ConnState =
4242 | Offline
43− | Connecting of Identity
43+ | Connecting
4444 | Online of Session
4545
4646 type PollResultData =
@@ -178,12 +178,12 @@ module App =
178178 | DoConnect ->
179179 match model.Identity with
180180 | Some id ->
181− { model with Conn = Connecting id }, [ CmdConnect(model.ServerUrl, id) ]
181+ { model with Conn = Connecting }, [ CmdConnect(model.ServerUrl, id) ]
182182 | None -> { model with Error = Some "No identity generated" }, []
183183
184184 | AuthOk token ->
185− match model.Conn with
186− | Connecting id ->
185+ match model.Conn, model.Identity with
186+ | Connecting, Some id ->
187187 let session = { Url = model.ServerUrl; Token = token; Identity = id }
188188 { model with Conn = Online session; Page = Conversations; Error = None },
189189 [ CmdPoll(session, model.PollCursor) ]
@@ -252,7 +252,7 @@ module App =
252252
253253 | DoSaveContact ->
254254 if model.NewPubkey <> "" && model.NewNickname <> "" then
255− let contact =
255+ let contact: Contact =
256256 { Pubkey = model.NewPubkey
257257 Nickname = model.NewNickname }
258258
@@ -281,38 +281,36 @@ module App =
281281
282282 | DismissError -> { model with Error = None }, []
283283
284− | StateLoaded { Identity = identityOpt; Data = dataOpt } ->
285− match identityOpt with
286− | None -> model, []
287− | Some identity ->
288− let model' = { model with Identity = Some identity; Conn = Connecting identity }
284+ | StateLoaded { Identity = None } -> model, []
285+ | StateLoaded { Identity = Some identity; Data = dataOpt } ->
286+ let model' = { model with Identity = Some identity; Conn = Connecting }
289287
290− let model' =
291− match dataOpt with
292− | Some data ->
293− let messages =
294− data.Messages
295− |> Seq.map (fun (KeyValue(pk, dtos)) ->
296− pk,
297− dtos
298− |> Array.toList
299− |> List.map (fun m ->
300− { Id = m.Id
301− Body = m.Body
302− Timestamp = DateTimeOffset.FromUnixTimeSeconds m.TimestampUnix
303− IsOutgoing = m.IsOutgoing }))
304− |> Map.ofSeq
305−
306− { model' with
307− Contacts = data.Contacts |> Array.toList
308− Messages = messages
309− ServerUrl = if data.ServerUrl <> "" then data.ServerUrl else model.ServerUrl
310− PollCursor = data.PollCursor
311− Page = Conversations }
312−
313− | None -> { model' with Page = Settings }
314−
315− model', [ CmdConnect(model'.ServerUrl, identity) ]
288+ let model' =
289+ match dataOpt with
290+ | Some data ->
291+ let messages =
292+ data.Messages
293+ |> Seq.map (fun (KeyValue(pk, dtos)) ->
294+ pk,
295+ dtos
296+ |> Array.toList
297+ |> List.map (fun m ->
298+ { Id = m.Id
299+ Body = m.Body
300+ Timestamp = DateTimeOffset.FromUnixTimeSeconds m.TimestampUnix
301+ IsOutgoing = m.IsOutgoing }))
302+ |> Map.ofSeq
303+
304+ { model' with
305+ Contacts = data.Contacts |> Array.toList
306+ Messages = messages
307+ ServerUrl = if data.ServerUrl <> "" then data.ServerUrl else model.ServerUrl
308+ PollCursor = data.PollCursor
309+ Page = Conversations }
310+
311+ | None -> { model' with Page = Settings }
312+
313+ model', [ CmdConnect(model'.ServerUrl, identity) ]
316314
317315 // ── mapCmd ──
318316
@@ -325,24 +323,19 @@ module App =
325323 }))
326324 |> ignore)
327325
328− let private decryptEvent (privKey: byte[]) (payload: JsonElement) =
326+ let private decryptEvent (privKey: byte[]) (payload: ApiClient.EventPayload) =
329327 try
330− let blobHex = payload.GetProperty("encryptedBlob").GetString()
331− let tsEl = payload.GetProperty("timestamp")
332− let ts =
333− if tsEl.ValueKind = JsonValueKind.String then Int64.Parse(tsEl.GetString())
334− else tsEl.GetInt64()
335− let blob = Crypto.fromHex blobHex
328+ let blob = Crypto.fromHex payload.EncryptedBlob
336329
337330 match Crypto.decrypt privKey blob with
338331 | Some(plaintext, senderHex) ->
339− let ptDoc = JsonDocument.Parse(plaintext)
340− let ptRoot = ptDoc.RootElement
332+ let pt = JsonDocument.Parse(plaintext).RootElement
341333
342− if ptRoot.GetProperty("type").GetString() = "text" then
343− let msgId = ptRoot.GetProperty("id").GetString()
344− let body = ptRoot.GetProperty("body").GetString()
345− Ok { FromPubkey = senderHex; Body = body; Timestamp = ts; MessageId = msgId }
334+ if pt.GetProperty("type").GetString() = "text" then
335+ Ok { FromPubkey = senderHex
336+ Body = pt.GetProperty("body").GetString()
337+ Timestamp = payload.Timestamp
338+ MessageId = pt.GetProperty("id").GetString() }
346339 else
347340 Error "unknown type"
348341 | None -> Error "decrypt failed"
@@ -376,7 +369,7 @@ module App =
376369 let ts = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
377370
378371 let payload =
379− $"""{{ "type": "text", "id": "{messageId}", "timestamp": {ts}, "body": {JsonSerializer.Serialize(text)} }}"""
372+ JsonSerializer.Serialize({| ``type`` = "text"; id = messageId; timestamp = ts; body = text |})
380373
381374 let blob = Crypto.encrypt session.Identity.PrivKey recipPub payload
382375 let blobHex = Crypto.toHex blob
@@ -503,7 +496,7 @@ module App =
503496
504497 match model.Conn with
505498 | Offline -> Button("Connect", DoConnect)
506− | Connecting _ -> Label("Connecting...").centerTextHorizontal()
499+ | Connecting -> Label("Connecting...").centerTextHorizontal()
507500 | Online _ ->
508501 Button("Disconnect", DoDisconnect)
509502 Button("Go to Conversations", Nav Conversations)
@@ -516,7 +509,7 @@ module App =
516509 let connStr =
517510 match model.Conn with
518511 | Offline -> "OFFLINE"
519− | Connecting _ -> "CONNECTING"
512+ | Connecting -> "CONNECTING"
520513 | Online _ -> "ONLINE"
521514
522515 let contactNames =