on master help sign in
Simplify code and improve type safety: dedup capPerKey, refactor authenticateSession with headOf, nest when conditions, use any instead of single, type SendResult.status as MessageStatus
commitf4311e3ec7c47d3491f648d03dad91cf7a73b5d9 authoriko <mail@iko.soy> dateFri 10 Apr 2026, 11:54 (6 months ago) parente692eb5
36 files changed+76−125
client/ApiClient.fs+2−2 client/App.fs+49−55 client/Store.fs+6−6 client/bin/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.dll client/bin/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.pdb client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfo.fs+1−1 client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfoInputs.cache+1−1 client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.dll client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.fsproj.FileListAbsolute.txt−23 client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.pdb client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.sourcelink.json+1−1 client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/ref/Skrepka.dll client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/refint/Skrepka.dll client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/FSharp.Core.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Fabulous.MauiControls.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Fabulous.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Configuration.Abstractions.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Configuration.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.DependencyInjection.Abstractions.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.DependencyInjection.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Diagnostics.Abstractions.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.FileProviders.Abstractions.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Hosting.Abstractions.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Logging.Abstractions.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Logging.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Options.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Primitives.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Controls.Compatibility.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Controls.Xaml.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Controls.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Essentials.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Graphics.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Sodium.Core.stamp client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/unpack/Microsoft.Maui.Essentials/BundleResource/xml/microsoft_maui_essentials_fileprovider_file_paths.xml−6 server.knot+16−30
client/ApiClient.fs+2−2
@@ -19,7 +19,7 @@ module ApiClient =
1919 type SendResult = { Status: string; MessageId: string }
2020
2121 [<CLIMutable>]
22− type PollResponse = { Cursor: uint64; Events: PollEvent array }
22+ type PollResponse = { Cursor: int64; Events: PollEvent array }
2323
2424 [<CLIMutable>]
2525 type private ChallengeResponse = { challenge: string }
@@ -108,7 +108,7 @@ module ApiClient =
108108 return! postJson<SendResult> client $"{serverUrl}/messages" body (Some token)
109109 }
110110
111− let poll (serverUrl: string) (token: string) (cursor: uint64) =
111+ let poll (serverUrl: string) (token: string) (cursor: int64) =
112112 async {
113113 let body = JsonSerializer.Serialize({| cursor = cursor; timeout = 30000 |})
114114 let! response = postJson<PollResponse> pollClient $"{serverUrl}/poll" body (Some token)
client/App.fs+49−55
@@ -26,15 +26,15 @@ module App =
2626 type Page =
2727 | Setup
2828 | Conversations
29− | Chat of pubkey: string
30− | AddContact
29+ | Chat of pubkey: string * compose: string
30+ | AddContact of pubkey: string * nickname: string
3131 | Settings
3232
3333 type Session = { Url: string; Token: string; Identity: Identity }
3434
3535 type ConnState =
3636 | Offline
37− | Connecting of Identity
37+ | Connecting
3838 | Online of Session
3939
4040 // ── Model ──
@@ -47,12 +47,8 @@ module App =
4747 Contacts: Contact list
4848 PollStatus: string
4949 Messages: Map<string, ChatMessage list>
50− ComposeText: string
51− NewPubkey: string
52− NewNickname: string
5350 Error: string option
54− PollCursor: uint64
55− LastSendStatus: string }
51+ PollCursor: int64 }
5652
5753 // ── Msg ──
5854
@@ -67,11 +63,11 @@ module App =
6763 | DoDisconnect
6864 | SetCompose of string
6965 | DoSend
70− | Sent of ApiClient.SendResult
66+ | Sent of Result<ApiClient.SendResult, string>
7167 | SetNewPubkey of string
7268 | SetNewNickname of string
7369 | DoSaveContact
74− | PollResult of messages: (string * ChatMessage) list * status: string * cursor: uint64
70+ | PollResult of messages: (string * ChatMessage) list * status: string * cursor: int64
7571 | CopyPubKey
7672 | DismissError
7773 | StateLoaded of Identity * Data option
@@ -82,7 +78,7 @@ module App =
8278 | CmdGenIdentity
8379 | CmdConnect of url: string * identity: Identity
8480 | CmdSend of session: Session * recipientHex: string * text: string * messageId: string
85− | CmdPoll of session: Session * cursor: uint64
81+ | CmdPoll of session: Session * cursor: int64
8682 | CmdCopyToClipboard of string
8783 | CmdLoadState
8884 | CmdSaveIdentity of Identity
@@ -136,12 +132,8 @@ module App =
136132 PollStatus = ""
137133 Contacts = []
138134 Messages = Map.empty
139− ComposeText = ""
140− NewPubkey = ""
141− NewNickname = ""
142135 Error = None
143− PollCursor = 0UL
144− LastSendStatus = "" },
136+ PollCursor = 0L },
145137 [ CmdLoadState ]
146138
147139 // ── Update ──
@@ -161,12 +153,12 @@ module App =
161153 | DoConnect ->
162154 match model.Identity with
163155 | Some id ->
164− { model with Conn = Connecting id }, [ CmdConnect(model.ServerUrl, id) ]
156+ { model with Conn = Connecting }, [ CmdConnect(model.ServerUrl, id) ]
165157 | None -> { model with Error = Some "No identity generated" }, []
166158
167159 | AuthOk token ->
168− match model.Conn with
169− | Connecting id ->
160+ match model.Identity, model.Conn with
161+ | Some id, Connecting ->
170162 let session = { Url = model.ServerUrl; Token = token; Identity = id }
171163 { model with Conn = Online session; Page = Conversations; Error = None },
172164 [ CmdPoll(session, model.PollCursor) ]
@@ -176,28 +168,31 @@ module App =
176168
177169 | DoDisconnect -> { model with Conn = Offline }, []
178170
179− | SetCompose text -> { model with ComposeText = text }, []
171+ | SetCompose text ->
172+ match model.Page with
173+ | Chat(pk, _) -> { model with Page = Chat(pk, text) }, []
174+ | _ -> model, []
180175
181176 | DoSend ->
182177 match model.Page, trySession model with
183− | Chat pk, Some session when model.ComposeText <> "" ->
184− let text = model.ComposeText
178+ | Chat(pk, compose), Some session when compose <> "" ->
185179 let id = Guid.NewGuid().ToString()
186180 let outMsg =
187181 { Id = id
188− Body = text
182+ Body = compose
189183 Timestamp = DateTimeOffset.UtcNow
190184 IsOutgoing = true }
191185
192186 let model' =
193187 { model with
194− ComposeText = ""
188+ Page = Chat(pk, "")
195189 Messages = model.Messages |> appendMessage pk outMsg }
196190
197− model', CmdSend(session, pk, text, id) :: saveCmd model'
191+ model', CmdSend(session, pk, compose, id) :: saveCmd model'
198192 | _ -> model, []
199193
200− | Sent result -> { model with LastSendStatus = $"{result.Status}:{result.MessageId}" }, []
194+ | Sent(Ok _) -> model, []
195+ | Sent(Error err) -> { model with Error = Some $"Send failed: {err}" }, []
201196
202197 | PollResult(incoming, status, newCursor) ->
203198 let model' =
@@ -219,25 +214,28 @@ module App =
219214
220215 model', cmds @ (if not incoming.IsEmpty then saveCmd model' else [])
221216
222− | SetNewPubkey pk -> { model with NewPubkey = pk }, []
223− | SetNewNickname nn -> { model with NewNickname = nn }, []
217+ | SetNewPubkey pk ->
218+ match model.Page with
219+ | AddContact(_, nn) -> { model with Page = AddContact(pk, nn) }, []
220+ | _ -> model, []
221+
222+ | SetNewNickname nn ->
223+ match model.Page with
224+ | AddContact(pk, _) -> { model with Page = AddContact(pk, nn) }, []
225+ | _ -> model, []
224226
225227 | DoSaveContact ->
226− if model.NewPubkey <> "" && model.NewNickname <> "" then
227− let contact: Contact =
228− { Pubkey = model.NewPubkey
229− Nickname = model.NewNickname }
228+ match model.Page with
229+ | AddContact(pk, nn) when pk <> "" && nn <> "" ->
230+ let contact: Contact = { Pubkey = pk; Nickname = nn }
230231
231232 let model' =
232233 { model with
233234 Contacts = model.Contacts |> upsertContact contact
234− NewPubkey = ""
235− NewNickname = ""
236235 Page = Conversations }
237236
238237 model', saveCmd model'
239− else
240− model, []
238+ | _ -> model, []
241239
242240 | CopyPubKey ->
243241 match model.Identity with
@@ -247,7 +245,7 @@ module App =
247245 | DismissError -> { model with Error = None }, []
248246
249247 | StateLoaded(identity, dataOpt) ->
250− let model' = { model with Identity = Some identity; Conn = Connecting identity }
248+ let model' = { model with Identity = Some identity; Conn = Connecting }
251249
252250 let model' =
253251 match dataOpt with
@@ -319,9 +317,9 @@ module App =
319317 let blob = Crypto.encrypt session.Identity.PrivKey recipPub payload
320318 let blobHex = Crypto.toHex blob
321319 let! result = ApiClient.sendMessage session.Url session.Token recipientHex blobHex ts
322− return Sent result
320+ return Sent(Ok result)
323321 with ex ->
324− return DismissError // TODO: show send errors properly
322+ return Sent(Error ex.Message)
325323 })
326324
327325 | CmdPoll(session, cursor) ->
@@ -373,7 +371,7 @@ module App =
373371 |> Async.Start)
374372
375373 | CmdSaveIdentity identity ->
376− Cmd.ofEffect (fun _ -> Store.saveIdentity identity |> ignore)
374+ Cmd.ofEffect (fun _ -> Store.saveIdentity identity |> Async.Start)
377375
378376 | CmdSaveData data ->
379377 Cmd.ofEffect (fun _ -> Store.saveData data)
@@ -428,7 +426,7 @@ module App =
428426
429427 match model.Conn with
430428 | Offline -> Button("Connect", DoConnect)
431− | Connecting _ -> Label("Connecting...").centerTextHorizontal()
429+ | Connecting -> Label("Connecting...").centerTextHorizontal()
432430 | Online _ ->
433431 Button("Disconnect", DoDisconnect)
434432 Button("Go to Conversations", Nav Conversations)
@@ -441,7 +439,7 @@ module App =
441439 let connStr =
442440 match model.Conn with
443441 | Offline -> "OFFLINE"
444− | Connecting _ -> "CONNECTING"
442+ | Connecting -> "CONNECTING"
445443 | Online _ -> "ONLINE"
446444
447445 let contactNames =
@@ -459,7 +457,7 @@ module App =
459457 Label("Conversations")
460458 .font(size = 24.)
461459
462− Button("+", Nav AddContact)
460+ Button("+", Nav(AddContact("", "")))
463461 Button("Settings", Nav Settings)
464462 }
465463
@@ -492,13 +490,13 @@ module App =
492490 let preview =
493491 if lastMsg.Length > 40 then lastMsg.[..39] + "..." else lastMsg
494492
495− Button($"{c.Nickname}\n{preview}", Nav(Chat c.Pubkey))
493+ Button($"{c.Nickname}\n{preview}", Nav(Chat(c.Pubkey, "")))
496494 })
497495 .padding(20.)
498496 )
499497 )
500498
501− let private viewChat model pk =
499+ let private viewChat model pk compose =
502500 let name = contactName model.Contacts pk
503501 let msgs = messagesFor pk model.Messages
504502
@@ -519,10 +517,6 @@ module App =
519517 .font(size = 11.)
520518 | None -> ()
521519
522− Label($"[{msgs.Length} message(s), compose: \"{model.ComposeText}\", send: \"{model.LastSendStatus}\"]")
523− .textColor(Colors.Gray)
524− .font(size = 10.)
525−
526520 let allMessages =
527521 msgs
528522 |> List.map (fun m ->
@@ -534,7 +528,7 @@ module App =
534528 .font(size = 14.)
535529
536530 HStack(spacing = 8.) {
537− Entry(model.ComposeText, SetCompose)
531+ Entry(compose, SetCompose)
538532 .placeholder("Message...")
539533
540534 Button("Send", DoSend)
@@ -543,7 +537,7 @@ module App =
543537 .padding(12.)
544538 )
545539
546− let private viewAddContact model =
540+ let private viewAddContact pk nn =
547541 ContentPage(
548542 (VStack(spacing = 16.) {
549543 HStack(spacing = 8.) {
@@ -554,10 +548,10 @@ module App =
554548 }
555549
556550 Label("Public Key (hex):")
557− Entry(model.NewPubkey, SetNewPubkey)
551+ Entry(pk, SetNewPubkey)
558552
559553 Label("Nickname:")
560− Entry(model.NewNickname, SetNewNickname)
554+ Entry(nn, SetNewNickname)
561555
562556 Button("Save Contact", DoSaveContact)
563557 .centerHorizontal()
@@ -571,8 +565,8 @@ module App =
571565 | Setup -> viewSetup ()
572566 | Settings -> viewSettings model
573567 | Conversations -> viewConversations model
574− | Chat pk -> viewChat model pk
575− | AddContact -> viewAddContact model
568+ | Chat(pk, compose) -> viewChat model pk compose
569+ | AddContact(pk, nn) -> viewAddContact pk nn
576570
577571 Application() { Window(page) }
578572
client/Store.fs+6−6
@@ -22,7 +22,7 @@ module Store =
2222 { Contacts: Contact list
2323 Messages: Map<string, ChatMessage list>
2424 ServerUrl: string
25− PollCursor: uint64 }
25+ PollCursor: int64 }
2626
2727 [<CLIMutable>]
2828 type private MessageDoc =
@@ -61,9 +61,9 @@ module Store =
6161 }
6262
6363 let saveIdentity (identity: Crypto.Identity) =
64− task {
65− do! SecureStorage.Default.SetAsync("identity_privkey", Convert.ToBase64String identity.PrivKey)
66− do! SecureStorage.Default.SetAsync("identity_pubkey", identity.PubKeyHex)
64+ async {
65+ do! SecureStorage.Default.SetAsync("identity_privkey", Convert.ToBase64String identity.PrivKey) |> Async.AwaitTask
66+ do! SecureStorage.Default.SetAsync("identity_pubkey", identity.PubKeyHex) |> Async.AwaitTask
6767 }
6868
6969 let loadData () : Data option =
@@ -95,7 +95,7 @@ module Store =
9595 { Contacts = contacts
9696 Messages = messages
9797 ServerUrl = settings.ServerUrl
98− PollCursor = uint64 settings.PollCursor }
98+ PollCursor = settings.PollCursor }
9999 with _ ->
100100 None
101101
@@ -123,7 +123,7 @@ module Store =
123123 settings.Upsert
124124 { Id = "settings"
125125 ServerUrl = data.ServerUrl
126− PollCursor = int64 data.PollCursor }
126+ PollCursor = data.PollCursor }
127127 |> ignore
128128 with _ ->
129129 ()
client/bin/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.dll

Binary file not shown.

client/bin/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.pdb

Binary file not shown.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfo.fs+1−1
@@ -10,7 +10,7 @@ open System.Reflection
1010[<assembly: System.Reflection.AssemblyCompanyAttribute("Skrepka")>]
1111[<assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")>]
1212[<assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")>]
13−[<assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0+64e0fdcd67fd42117a3538c089bb99c276931127")>]
13+[<assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0+e692eb5d42ef866622de97d2bc08d09fdb62a11b")>]
1414[<assembly: System.Reflection.AssemblyProductAttribute("Skrepka")>]
1515[<assembly: System.Reflection.AssemblyTitleAttribute("Skrepka")>]
1616[<assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")>]
client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfoInputs.cache+1−1
@@ -1 +1 @@
1−be435fd044969cb8957c158b5e1a656e1e9260e869cd5e4059efeccf555209e5
1+4dcdec3fa3f1ebbb1a84fb886e9dd06477af7c654b1d2094630d80c574da8beb
client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.dll

Binary file not shown.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.fsproj.FileListAbsolute.txt−23
@@ -322,27 +322,4 @@
322322/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.pdb
323323/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.genruntimeconfig.cache
324324/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/ref/Skrepka.dll
325−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Fabulous.stamp
326−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Fabulous.MauiControls.stamp
327−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/FSharp.Core.stamp
328−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Configuration.Abstractions.stamp
329−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Configuration.stamp
330−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.DependencyInjection.Abstractions.stamp
331−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.DependencyInjection.stamp
332−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Diagnostics.Abstractions.stamp
333−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.FileProviders.Abstractions.stamp
334−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Hosting.Abstractions.stamp
335−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Logging.Abstractions.stamp
336−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Logging.stamp
337−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Options.stamp
338−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Primitives.stamp
339−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Controls.Compatibility.stamp
340−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Controls.stamp
341−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Controls.Xaml.stamp
342−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.stamp
343−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Essentials.stamp
344−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Graphics.stamp
345−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Sodium.Core.stamp
346−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/unpack/Microsoft.Maui.Essentials/BundleResource/xml/microsoft_maui_essentials_fileprovider_file_paths.xml
347325/Users/iko/Developer/skrepka/client/bin/Debug/net10.0-maccatalyst/maccatalyst-arm64/LiteDB.dll
348−/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/LiteDB.stamp
client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.pdb

Binary file not shown.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.sourcelink.json+1−1
@@ -1 +1 @@
1−{"documents":{"/Users/iko/Developer/skrepka/*":"https://raw.githubusercontent.com/ilyakooo0/skrepka/64e0fdcd67fd42117a3538c089bb99c276931127/*"}}
1+{"documents":{"/Users/iko/Developer/skrepka/*":"https://raw.githubusercontent.com/ilyakooo0/skrepka/e692eb5d42ef866622de97d2bc08d09fdb62a11b/*"}}
client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/ref/Skrepka.dll

Binary file not shown.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/refint/Skrepka.dll

Binary file not shown.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/FSharp.Core.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Fabulous.MauiControls.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Fabulous.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Configuration.Abstractions.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Configuration.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.DependencyInjection.Abstractions.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.DependencyInjection.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Diagnostics.Abstractions.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.FileProviders.Abstractions.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Hosting.Abstractions.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Logging.Abstractions.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Logging.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Options.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Extensions.Primitives.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Controls.Compatibility.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Controls.Xaml.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Controls.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Essentials.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.Graphics.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Microsoft.Maui.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/resourcestamps/Sodium.Core.stampdeleted

No changes to the content.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/unpack/Microsoft.Maui.Essentials/BundleResource/xml/microsoft_maui_essentials_fileprovider_file_paths.xmldeleted−6
@@ -1,6 +0,0 @@
1−<?xml version="1.0" encoding="UTF-8" ?>
2−<paths>
3− <external-path name="external_files" path="." />
4− <cache-path name="internal_cache" path="." />
5− <external-cache-path name="external_cache" path="." />
6−</paths>
server.knot+16−30
@@ -72,7 +72,7 @@ type AuthResult = Authorized {pubkey: PubkeyHex} | Unauthorized {}
7272type PruneResult = {expiredLocal: [PresenceEntry], peerServers: [Text]}
7373type PollResult = PollUnauthorized {} | PollAuthorized {events: [PollEvent], cursor: Timestamp}
7474type VerifyResult = VerifyFailed {} | VerifyOk {peerServers: [Text]}
75−type SendResult = SendUnauthorized {} | SendRejected {} | SendDone {status: Text, remoteServers: [Text], fromKey: PubkeyHex}
75+type SendResult = SendUnauthorized {} | SendRejected {} | SendDone {status: MessageStatus, remoteServers: [Text], fromKey: PubkeyHex}
7676type AckResult = AckUnauthorized {} | AckDone {pendingAcks: [AckedEntry], evictedEntries: [AckedEntry]}
7777type LookupResult = LookupUnauthorized {} | LookupDone {foundServer: Text}
7878
@@ -368,13 +368,9 @@ isBadServerName = \s ->
368368
369369authenticateSession : [Session] -> Text -> Timestamp -> AuthResult
370370authenticateSession = \sessions token t ->
371− fold (\acc s ->
372− case acc of
373− Authorized _ -> acc
374− Unauthorized {} ->
375− if safeCompare s.token token && s.expiresAt > t
376− then Authorized {pubkey: s.pubkey}
377− else acc) Unauthorized {} sessions
371+ case headOf (do s <- sessions; where safeCompare s.token token && s.expiresAt > t; yield s) of
372+ Nothing {} -> Unauthorized {}
373+ Just {value: s} -> Authorized {pubkey: s.pubkey}
378374
379375extractToken = \authHeader ->
380376 if toLower (take 7 authHeader) == "bearer "
@@ -463,10 +459,9 @@ evictOneOldest = \items getKey ->
463459
464460capPerKey = \items matchKey maxPerKey getExpiry t ->
465461 let active = do x <- items; where getExpiry x > t; yield x in
466− let activeForKeyCount = count (do x <- active; where matchKey x; yield x) in
467− if activeForKeyCount >= maxPerKey
468− then let forKey = do x <- active; where matchKey x; yield x in
469− let others = do x <- active; where not (matchKey x); yield x in
462+ let forKey = do x <- active; where matchKey x; yield x in
463+ if count forKey >= maxPerKey
464+ then let others = do x <- active; where not (matchKey x); yield x in
470465 union others (evictOneOldest forKey getExpiry)
471466 else active
472467
@@ -630,9 +625,7 @@ retryForwardsForServer = \entries remaining ->
630625 timestamp: f.timestamp, originServer: serverHostN, messageId: f.messageId,
631626 authorization: "Bearer " ++ federationSecret})
632627 case result of
633− Ok _ -> do
634− removeForward f.messageId f.toServer
635− yield {}
628+ Ok _ -> removeForward f.messageId f.toServer
636629 Err _ -> yield {}
637630 retryForwardsForServer rest (remaining - 1)
638631
@@ -755,15 +748,8 @@ serve = \req -> case req of
755748 challenges <- *challenges
756749 sessions <- *sessions
757750 presence <- *presence
758− let matched = single (do
759− c <- challenges
760− where c.pubkey == pubkey
761− where c.challenge == challenge
762− where c.expiresAt > t
763− yield c)
764− let sigValid = case matched of
765− Nothing {} -> False {}
766− _ -> verify (bytesFromHex pubkey) (textToBytes challenge) (bytesFromHex signature)
751+ let hasMatch = any challenges (\c -> c.pubkey == pubkey && c.challenge == challenge && c.expiresAt > t)
752+ let sigValid = if hasMatch then verify (bytesFromHex pubkey) (textToBytes challenge) (bytesFromHex signature) else False {}
767753 if not sigValid
768754 then yield {pr: pr, verify: VerifyFailed {}}
769755 else do
@@ -854,18 +840,18 @@ serve = \req -> case req of
854840 yield {pr: pr, send: SendDone {status: status, remoteServers: remoteServers, fromKey: fromKey}}
855841 fork (do
856842 case result.send of
857− SendDone {status, remoteServers, fromKey} -> do
858− when (count remoteServers > 0 && federationEnabled)
859− (sendToEach remoteServers (\server -> do
843+ SendDone {status, remoteServers, fromKey} ->
844+ when (count remoteServers > 0 && federationEnabled) (do
845+ sendToEach remoteServers (\server -> do
860846 fwdResult <- fetch (federationScheme ++ server) (ForwardMessage {
861847 toKey: to, fromKey: fromKey, encryptedBlob: encryptedBlob,
862848 timestamp: clampedTs, originServer: serverHostN, messageId: msgId,
863849 authorization: "Bearer " ++ federationSecret})
864850 case fwdResult of
865851 Ok _ -> removeForward msgId server
866− Err _ -> yield {}))
867− when (status == "queued" && count remoteServers > 0 && federationEnabled)
868− (println ("sendMessage: forwards at capacity (" ++ show maxForwardsEntries ++ "), skipping forward tracking"))
852+ Err _ -> yield {})
853+ when (status == "queued")
854+ (println ("sendMessage: forwards at capacity (" ++ show maxForwardsEntries ++ "), skipping forward tracking")))
869855 SendUnauthorized {} -> yield {}
870856 SendRejected {} -> yield {}
871857 broadcastOfflineGossip t result.pr.peerServers result.pr.expiredLocal)