on master help sign in
Fix button disabled state display and simplify contact naming logic
d6c4b4eiko
client/App.fs+74−68
@@ -171,7 +171,10 @@ module App =
171
171
172 { model with
172 { model with
173 Auth = Identified(id, Online token)
173 Auth = Identified(id, Online token)
174+ Page =
174− Page = match model.Page with Setup -> Conversations | p -> p
175+ match model.Page with
176+ | Setup -> Conversations
177+ | p -> p
175 Error = None
178 Error = None
176 PollStatus = "polling..."
179 PollStatus = "polling..."
177 FlushingOutbox = true },
180 FlushingOutbox = true },
@@ -189,7 +192,10 @@ module App =
189 match model.Auth with
192 match model.Auth with
190 | Identified(id, Online _) ->
193 | Identified(id, Online _) ->
191 let m = setConn Connecting model
194 let m = setConn Connecting model
195+
196+ { m with
192− { m with FlushingOutbox = false; PollRetries = 0 },
197+ FlushingOutbox = false
198+ PollRetries = 0 },
193 [ CmdConnect(model.ServerUrl, id) ]
199 [ CmdConnect(model.ServerUrl, id) ]
194 | _ -> model, []
200 | _ -> model, []
195
201
@@ -273,17 +279,17 @@ module App =
273 | Some bytes ->
279 | Some bytes ->
274 let hex = Crypto.toHex bytes
280 let hex = Crypto.toHex bytes
275
281
276− let contact =
277− match Map.tryFind hex model.Contacts with
282+ match Map.tryFind hex model.Contacts with
278− | Some e -> { e with Nickname = cpk }
283+ | Some e -> model, []
284+ | None ->
279− | None -> newContact hex cpk
285+ let contact = newContact hex cpk
280
286
281− let model' =
287+ let model' =
282− { model with
288+ { model with
283− Contacts = Map.add hex contact model.Contacts
289+ Contacts = Map.add hex contact model.Contacts
284− Page = Conversations }
290+ Page = Conversations }
285
291
286− model', [ saveCmdMsg model' ]
292+ model', [ saveCmdMsg model' ]
287 | None ->
293 | None ->
288 { model with
294 { model with
289 Error = Some "Invalid public key" },
295 Error = Some "Invalid public key" },
@@ -519,68 +525,68 @@ module App =
519 dispatch TokenExpired
525 dispatch TokenExpired
520 else
526 else
521
527
522− let ackIds = response.Events |> Array.map _.Id |> Array.toList
528+ let ackIds = response.Events |> Array.map _.Id |> Array.toList
523−
524− let results =
525− response.Events
526− |> Array.choose (fun evt ->
527− match evt.EventType with
528− | Message -> Some(decryptEvent session.Identity.PrivKey evt.Payload)
529− | UnknownEvent s ->
530− log $"unknown event type: {s}"
531− None)
532−
533− let events = results |> Array.choose Result.toOption |> Array.toList
534−
535− let errors =
536− results
537− |> Array.choose (function
538− | Error e -> Some e
539− | _ -> None)
540− |> Array.toList
541−
542− for e in errors do
543− log $"decrypt error: {e}"
544−
545− if not ackIds.IsEmpty then
546− try
547− do! ackMessages session.Url session.Token ackIds
548− with ex ->
549− log $"ack error: {ex.Message}"
550−
551− if not events.IsEmpty then
552− let acksBySender =
553− events
554− |> List.choose (fun evt ->
555− match evt.Envelope with
556− | Envelope.TextMessage(id, _) -> Some(evt.Sender, id)
557− | _ -> None)
558− |> List.groupBy fst
559− |> List.map (fun (sender, pairs) -> sender, List.map snd pairs)
560
529
561− for sender, msgIds in acksBySender do
530+ let results =
562− try
531+ response.Events
563− do! sendEnvelope session sender (Envelope.DeliveryAck msgIds)
532+ |> Array.choose (fun evt ->
564− with ex ->
533+ match evt.EventType with
565− log $"delivery ack error: {ex.Message}"
534+ | Message -> Some(decryptEvent session.Identity.PrivKey evt.Payload)
535+ | UnknownEvent s ->
536+ log $"unknown event type: {s}"
537+ None)
566
538
567− if response.Events.Length = 0 then
539+ let events = results |> Array.choose Result.toOption |> Array.toList
568− do! Async.Sleep Constants.pollEmptyDelayMs
569
540
570− let chatCount =
541+ let errors =
571− events
542+ results
572− |> List.sumBy (fun e ->
543+ |> Array.choose (function
573− match e.Envelope with
544+ | Error e -> Some e
574− | Envelope.TextMessage _ -> 1
545+ | _ -> None)
575− | _ -> 0)
546+ |> Array.toList
576
547
577− let status =
548+ for e in errors do
578− $"evts:{response.Events.Length} msgs:{chatCount} errs:{errors.Length}"
549+ log $"decrypt error: {e}"
579− + (match List.tryHead errors with
580− | Some e -> $" [{e}]"
581− | None -> "")
582
550
551+ if not ackIds.IsEmpty then
552+ try
553+ do! ackMessages session.Url session.Token ackIds
554+ with ex ->
555+ log $"ack error: {ex.Message}"
556+
557+ if not events.IsEmpty then
558+ let acksBySender =
559+ events
560+ |> List.choose (fun evt ->
561+ match evt.Envelope with
562+ | Envelope.TextMessage(id, _) -> Some(evt.Sender, id)
563+ | _ -> None)
564+ |> List.groupBy fst
565+ |> List.map (fun (sender, pairs) -> sender, List.map snd pairs)
566+
567+ for sender, msgIds in acksBySender do
568+ try
569+ do! sendEnvelope session sender (Envelope.DeliveryAck msgIds)
570+ with ex ->
571+ log $"delivery ack error: {ex.Message}"
572+
573+ if response.Events.Length = 0 then
574+ do! Async.Sleep Constants.pollEmptyDelayMs
575+
576+ let chatCount =
577+ events
578+ |> List.sumBy (fun e ->
579+ match e.Envelope with
580+ | Envelope.TextMessage _ -> 1
581+ | _ -> 0)
582+
583+ let status =
584+ $"evts:{response.Events.Length} msgs:{chatCount} errs:{errors.Length}"
585+ + (match List.tryHead errors with
586+ | Some e -> $" [{e}]"
587+ | None -> "")
588+
583− dispatch (PollResult(events, status, response.Cursor))
589+ dispatch (PollResult(events, status, response.Cursor))
584 with
590 with
585 | :? TimeoutException ->
591 | :? TimeoutException ->
586 log "poll timeout"
592 log "poll timeout"
client/AppTypes.fs+2−3
@@ -117,9 +117,8 @@ module AppTypes =
117
117
118 let contactName (contacts: Map<string, Contact>) (pk: string) =
118 let contactName (contacts: Map<string, Contact>) (pk: string) =
119 match Map.tryFind pk contacts with
119 match Map.tryFind pk contacts with
120− | Some c when c.Nickname <> "" -> c.Nickname
121− | Some c when c.DisplayName <> "" -> c.DisplayName
120+ | Some c -> c.DisplayName
122− | _ -> truncKey pk
121+ | _ -> pk
123
122
124 let messagesFor (pk: string) (messages: Map<string, ChatMessage list>) =
123 let messagesFor (pk: string) (messages: Map<string, ChatMessage list>) =
125 messages |> Map.tryFind pk |> Option.defaultValue []
124 messages |> Map.tryFind pk |> Option.defaultValue []
client/Buttons.fs+2−10
@@ -35,24 +35,16 @@ module Buttons =
35 Rectangle().stroke(Colors.Black).strokeThickness (4.)
35 Rectangle().stroke(Colors.Black).strokeThickness (4.)
36
36
37 let private textButton fontSize pressOffset restOffset margin priority (text: string) (msg: 'msg) disabled =
37 let private textButton fontSize pressOffset restOffset margin priority (text: string) (msg: 'msg) disabled =
38− // Start from the opposite state's offset so the transition animates
39− let initialOffset = if disabled then restOffset else 0.
40−
41 Component($"{text}-{disabled}") {
38 Component($"{text}-{disabled}") {
42 let! pressed = Context.State(false)
39 let! pressed = Context.State(false)
43− let! animOffset = Context.State(initialOffset)
44
40
45− let target =
41+ let offset =
46 if disabled then 0.
42 if disabled then 0.
47 elif pressed.Current then pressOffset
43 elif pressed.Current then pressOffset
48 else restOffset
44 else restOffset
49
45
50− do
51− if animOffset.Current <> target then
52− Avalonia.Threading.Dispatcher.UIThread.Post(fun () -> animOffset.Set target)
53−
54 (Grid() {
46 (Grid() {
55− shadowRect animOffset.Current
47+ shadowRect offset
56
48
57 Rectangle()
49 Rectangle()
58 .fill (
50 .fill (
client/Store.fs+10−6
@@ -88,7 +88,12 @@ module Store =
88 if not isOutgoing then
88 if not isOutgoing then
89 Incoming
89 Incoming
90 else
90 else
91+ Outgoing(
92+ if status = 1 then
91− Outgoing(if status = 1 then DeliveryStatus.Delivered else DeliveryStatus.Sent) }
93+ DeliveryStatus.Delivered
94+ else
95+ DeliveryStatus.Sent
96+ ) }
92
97
93 // ── Schema ──
98 // ── Schema ──
94
99
@@ -142,7 +147,9 @@ module Store =
142
147
143 conn
148 conn
144 |> Db.newCommand "INSERT OR REPLACE INTO schema_meta (key, value) VALUES (@key, @value)"
149 |> Db.newCommand "INSERT OR REPLACE INTO schema_meta (key, value) VALUES (@key, @value)"
150+ |> Db.setParams
151+ [ "key", SqlType.String "schema_version"
145− |> Db.setParams [ "key", SqlType.String "schema_version"; "value", SqlType.String(string Constants.schemaVersion) ]
152+ "value", SqlType.String(string Constants.schemaVersion) ]
146 |> Db.exec
153 |> Db.exec
147
154
148 // ── Identity ──
155 // ── Identity ──
@@ -203,10 +210,7 @@ module Store =
203 [ "Id", SqlType.String Constants.profileId
210 [ "Id", SqlType.String Constants.profileId
204 "DisplayName", SqlType.String profile.DisplayName
211 "DisplayName", SqlType.String profile.DisplayName
205 "Bio", SqlType.String profile.Bio
212 "Bio", SqlType.String profile.Bio
206− "Photo",
207− (match profile.Photo with
213+ "Photo", SqlType.sqlBytesOrNull profile.Photo ]
208− | Some bytes -> SqlType.Bytes bytes
209− | None -> SqlType.Null) ]
210 |> Db.exec
214 |> Db.exec
211 with ex ->
215 with ex ->
212 log $"saveProfile error: {ex.Message}"
216 log $"saveProfile error: {ex.Message}"