on master help sign in
Improve client type safety and simplify async handling: add typed Envelope DU, exhaustive status mappings, extract sendDeliveryAcks
fec9263iko
client/ApiClient.fs+6
@@ -51,6 +51,12 @@ module ApiClient =
51 | Unauthorized -> "unauthorized"
51 | Unauthorized -> "unauthorized"
52 | UnknownStatus s -> s)
52 | UnknownStatus s -> s)
53
53
54+ let messageStatusToError = function
55+ | Delivered | Federated | Queued -> None
56+ | Rejected -> Some "Message rejected by server"
57+ | Unauthorized -> Some "Not authorized to deliver message"
58+ | UnknownStatus s -> Some $"Unexpected status: {s}"
59+
54 [<CLIMutable>]
60 [<CLIMutable>]
55 type private SendResult = { Status: MessageStatus }
61 type private SendResult = { Status: MessageStatus }
56
62
client/App.fs+61−46
@@ -81,6 +81,7 @@ module App =
81 | DoDisconnect
81 | DoDisconnect
82 | DoSend
82 | DoSend
83 | SendFailed of string
83 | SendFailed of string
84+ | SendOk
84 | DoSaveContact
85 | DoSaveContact
85 | PollResult of events: DecryptedEvent list * status: PollStatus * cursor: int64
86 | PollResult of events: DecryptedEvent list * status: PollStatus * cursor: int64
86 | CopyPubKey
87 | CopyPubKey
@@ -161,7 +162,7 @@ module App =
161 | NoIdentity -> model
162 | NoIdentity -> model
162
163
163 let private saveCmdMsg model =
164 let private saveCmdMsg model =
164− CmdSaveData { Contacts = model.Contacts; Messages = model.Messages; ServerUrl = model.ServerUrl; PollCursor = model.PollCursor }
165+ CmdSaveData { Contacts = model.Contacts; Messages = model.Messages; ServerUrl = Some model.ServerUrl; PollCursor = model.PollCursor }
165
166
166 let private connStatusLabel = function
167 let private connStatusLabel = function
167 | NoIdentity | Identified(_, Offline) -> "OFFLINE"
168 | NoIdentity | Identified(_, Offline) -> "OFFLINE"
@@ -245,6 +246,7 @@ module App =
245 | _ -> model, []
246 | _ -> model, []
246
247
247 | SendFailed err -> { model with Error = Some err }, []
248 | SendFailed err -> { model with Error = Some err }, []
249+ | SendOk -> model, []
248
250
249 | PollResult(events, status, newCursor) ->
251 | PollResult(events, status, newCursor) ->
250 let model' =
252 let model' =
@@ -295,7 +297,7 @@ module App =
295 Auth = Identified(identity, Connecting)
297 Auth = Identified(identity, Connecting)
296 Contacts = data.Contacts
298 Contacts = data.Contacts
297 Messages = data.Messages
299 Messages = data.Messages
298− ServerUrl = if data.ServerUrl <> "" then data.ServerUrl else model.ServerUrl
300+ ServerUrl = data.ServerUrl |> Option.defaultValue model.ServerUrl
299 PollCursor = data.PollCursor
301 PollCursor = data.PollCursor
300 Page = Conversations }
302 Page = Conversations }
301 model', [ CmdConnect(model'.ServerUrl, identity) ]
303 model', [ CmdConnect(model'.ServerUrl, identity) ]
@@ -313,36 +315,65 @@ module App =
313 }
315 }
314 |> Async.Start)
316 |> Async.Start)
315
317
318+ type private Envelope =
319+ | TextMessage of id: string * body: string
320+ | DeliveryAck of id: string * ackIds: string list
321+
322+ let private serializeEnvelope = function
323+ | TextMessage(id, body) ->
324+ JsonSerializer.Serialize({| ``type`` = "text"; id = id; body = body |})
325+ | DeliveryAck(id, ackIds) ->
326+ JsonSerializer.Serialize({| ``type`` = "delivery.ack"; id = id; ack_ids = ackIds |})
327+
328+ let private parseEnvelope (json: string) =
329+ use doc = JsonDocument.Parse(json)
330+ let root = doc.RootElement
331+ match root.GetProperty("type").GetString() with
332+ | "text" ->
333+ Some(TextMessage(root.GetProperty("id").GetString(), root.GetProperty("body").GetString()))
334+ | "delivery.ack" ->
335+ let ackIds = root.GetProperty("ack_ids").EnumerateArray() |> Seq.map _.GetString() |> Seq.toList
336+ Some(DeliveryAck(root.GetProperty("id").GetString(), ackIds))
337+ | _ -> None
338+
316 let private decryptEvent (privKey: byte[]) (payload: EventPayload) =
339 let private decryptEvent (privKey: byte[]) (payload: EventPayload) =
317 try
340 try
318 let blob = Crypto.fromHex payload.EncryptedBlob
341 let blob = Crypto.fromHex payload.EncryptedBlob
319
342
320 match Crypto.decrypt privKey blob with
343 match Crypto.decrypt privKey blob with
321 | Some(plaintext, senderHex) ->
344 | Some(plaintext, senderHex) ->
322− use doc = JsonDocument.Parse(plaintext)
345+ match parseEnvelope plaintext with
323− let root = doc.RootElement
346+ | Some(TextMessage(id, body)) ->
324−
325− match root.GetProperty("type").GetString() with
326− | "text" ->
327 Ok(IncomingChat
347 Ok(IncomingChat
328 { SenderPubkey = senderHex
348 { SenderPubkey = senderHex
329 Message =
349 Message =
330− { Id = root.GetProperty("id").GetString()
350+ { Id = id; Body = body
331− Body = root.GetProperty("body").GetString()
332 Timestamp = DateTimeOffset.FromUnixTimeSeconds(payload.Timestamp)
351 Timestamp = DateTimeOffset.FromUnixTimeSeconds(payload.Timestamp)
333 IsOutgoing = false
352 IsOutgoing = false
334 Status = DeliveryStatus.Delivered } })
353 Status = DeliveryStatus.Delivered } })
335− | "delivery.ack" ->
354+ | Some(DeliveryAck(_, ackIds)) ->
336− let ackIds =
337− root.GetProperty("ack_ids").EnumerateArray()
338− |> Seq.map _.GetString()
339− |> Seq.toList
340 Ok(IncomingDeliveryAck(senderHex, ackIds))
355 Ok(IncomingDeliveryAck(senderHex, ackIds))
341− | t -> Error $"unknown envelope type: {t}"
356+ | None -> Error "unknown envelope type"
342 | None -> Error "decrypt failed"
357 | None -> Error "decrypt failed"
343 with ex ->
358 with ex ->
344 Error $"parse: {ex.Message}"
359 Error $"parse: {ex.Message}"
345
360
361+ let private sendDeliveryAcks (session: Session) (events: DecryptedEvent list) =
362+ async {
363+ let chatsBySender =
364+ events
365+ |> List.choose (function IncomingChat msg -> Some(msg.SenderPubkey, msg.Message.Id) | _ -> None)
366+ |> List.groupBy fst
367+ |> List.map (fun (sender, pairs) -> sender, List.map snd pairs)
368+
369+ for sender, msgIds in chatsBySender do
370+ try
371+ let ackPayload = serializeEnvelope (DeliveryAck(Guid.NewGuid().ToString(), msgIds))
372+ let blob = Crypto.encrypt session.Identity.PrivKey (Crypto.fromHex sender) ackPayload
373+ do! sendMessage session.Url session.Token sender (Crypto.toHex blob) (DateTimeOffset.UtcNow.ToUnixTimeSeconds()) |> Async.Ignore
374+ with _ -> ()
375+ }
376+
346 let mapCmd cmdMsg =
377 let mapCmd cmdMsg =
347 match cmdMsg with
378 match cmdMsg with
348 | CmdConnect(url, identity) ->
379 | CmdConnect(url, identity) ->
@@ -355,24 +386,20 @@ module App =
355 })
386 })
356
387
357 | CmdSend(session, recipientHex, text, messageId) ->
388 | CmdSend(session, recipientHex, text, messageId) ->
358− Cmd.ofEffect (fun dispatch ->
359− async {
389+ asyncCmd (async {
360− try
390+ try
361− let recipPub = Crypto.fromHex recipientHex
391+ let recipPub = Crypto.fromHex recipientHex
362− let ts = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
392+ let ts = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
363− let payload = JsonSerializer.Serialize({| ``type`` = "text"; id = messageId; body = text |})
393+ let payload = serializeEnvelope (TextMessage(messageId, text))
364− let blob = Crypto.encrypt session.Identity.PrivKey recipPub payload
394+ let blob = Crypto.encrypt session.Identity.PrivKey recipPub payload
365− let! status = sendMessage session.Url session.Token recipientHex (Crypto.toHex blob) ts
395+ let! status = sendMessage session.Url session.Token recipientHex (Crypto.toHex blob) ts
366−
396+
367− match status with
397+ match messageStatusToError status with
368− | Delivered | Federated | Queued -> ()
398+ | Some err -> return SendFailed err
369− | Rejected -> dispatch (SendFailed "Message rejected by server")
399+ | None -> return SendOk
370− | Unauthorized -> dispatch (SendFailed "Not authorized to deliver message")
371− | UnknownStatus s -> dispatch (SendFailed $"Unexpected status: {s}")
372− with ex ->
400+ with ex ->
373− dispatch (SendFailed $"Send failed: {ex.Message}")
401+ return SendFailed $"Send failed: {ex.Message}"
374− }
402+ })
375− |> Async.Start)
376
403
377 | CmdPoll(session, cursor) ->
404 | CmdPoll(session, cursor) ->
378 asyncCmd (async {
405 asyncCmd (async {
@@ -396,19 +423,7 @@ module App =
396 try do! ackMessages session.Url session.Token ackIds
423 try do! ackMessages session.Url session.Token ackIds
397 with _ -> ()
424 with _ -> ()
398
425
399− // Send delivery.ack for received chat messages (not for delivery.ack messages — no infinite loop)
426+ do! sendDeliveryAcks session events
400− let chatsBySender =
401− events
402− |> List.choose (function IncomingChat msg -> Some(msg.SenderPubkey, msg.Message.Id) | _ -> None)
403− |> List.groupBy fst
404− |> List.map (fun (sender, pairs) -> sender, List.map snd pairs)
405−
406− for sender, msgIds in chatsBySender do
407− try
408− let ackPayload = JsonSerializer.Serialize({| ``type`` = "delivery.ack"; id = Guid.NewGuid().ToString(); ack_ids = msgIds |})
409− let blob = Crypto.encrypt session.Identity.PrivKey (Crypto.fromHex sender) ackPayload
410− do! sendMessage session.Url session.Token sender (Crypto.toHex blob) (DateTimeOffset.UtcNow.ToUnixTimeSeconds()) |> Async.Ignore
411− with _ -> ()
412
427
413 let chatCount = events |> List.sumBy (function IncomingChat _ -> 1 | _ -> 0)
428 let chatCount = events |> List.sumBy (function IncomingChat _ -> 1 | _ -> 0)
414 let status = Received { Events = response.Events.Length; Messages = chatCount; Errors = errors.Length; FirstError = List.tryHead errors }
429 let status = Received { Events = response.Events.Length; Messages = chatCount; Errors = errors.Length; FirstError = List.tryHead errors }
client/Store.fs+4−4
@@ -25,7 +25,7 @@ module Store =
25 type Data =
25 type Data =
26 { Contacts: Contact list
26 { Contacts: Contact list
27 Messages: Map<string, ChatMessage list>
27 Messages: Map<string, ChatMessage list>
28− ServerUrl: string
28+ ServerUrl: string option
29 PollCursor: int64 }
29 PollCursor: int64 }
30
30
31 [<CLIMutable>]
31 [<CLIMutable>]
@@ -45,7 +45,7 @@ module Store =
45
45
46 let private toChatMessage (d: MessageDoc) : ChatMessage =
46 let private toChatMessage (d: MessageDoc) : ChatMessage =
47 { Id = d.Id; Body = d.Body; Timestamp = DateTimeOffset.FromUnixTimeSeconds d.TimestampUnix; IsOutgoing = d.IsOutgoing
47 { Id = d.Id; Body = d.Body; Timestamp = DateTimeOffset.FromUnixTimeSeconds d.TimestampUnix; IsOutgoing = d.IsOutgoing
48− Status = if d.Status = 1 then DeliveryStatus.Delivered else DeliveryStatus.Sent }
48+ Status = match d.Status with 0 -> DeliveryStatus.Sent | 1 -> DeliveryStatus.Delivered | n -> failwith $"Unknown delivery status: {n}" }
49
49
50 let private toMessageDoc convId (m: ChatMessage) : MessageDoc =
50 let private toMessageDoc convId (m: ChatMessage) : MessageDoc =
51 { Id = m.Id; ConversationId = convId; Body = m.Body; TimestampUnix = m.Timestamp.ToUnixTimeSeconds(); IsOutgoing = m.IsOutgoing
51 { Id = m.Id; ConversationId = convId; Body = m.Body; TimestampUnix = m.Timestamp.ToUnixTimeSeconds(); IsOutgoing = m.IsOutgoing
@@ -89,7 +89,7 @@ module Store =
89
89
90 { Contacts = contacts
90 { Contacts = contacts
91 Messages = messages
91 Messages = messages
92− ServerUrl = settings.ServerUrl |> Option.ofObj |> Option.defaultValue ""
92+ ServerUrl = settings.ServerUrl |> Option.ofObj
93 PollCursor = settings.PollCursor })
93 PollCursor = settings.PollCursor })
94 with _ ->
94 with _ ->
95 None
95 None
@@ -111,7 +111,7 @@ module Store =
111
111
112 settings.Upsert
112 settings.Upsert
113 { Id = "settings"
113 { Id = "settings"
114− ServerUrl = data.ServerUrl
114+ ServerUrl = data.ServerUrl |> Option.defaultValue ""
115 PollCursor = data.PollCursor }
115 PollCursor = data.PollCursor }
116 |> ignore
116 |> ignore
117 with _ ->
117 with _ ->
client/bin/Debug/net10.0-ios/iossimulator-arm64/Skrepka.app/Skrepka.dll

Binary file not shown.

client/bin/Debug/net10.0-ios/iossimulator-arm64/Skrepka.app/Skrepka.pdb

Binary file not shown.

client/bin/Debug/net10.0-ios/iossimulator-arm64/Skrepka.app/_CodeSignature/CodeResources+4−4
@@ -166,11 +166,11 @@
166 </data>
166 </data>
167 <key>Skrepka.dll</key>
167 <key>Skrepka.dll</key>
168 <data>
168 <data>
169− gaFYhy31V7Yzc0za1Sj1puG03t0=
169+ ZSBquSe7af7XpQvv6oqXWEK9H74=
170 </data>
170 </data>
171 <key>Skrepka.pdb</key>
171 <key>Skrepka.pdb</key>
172 <data>
172 <data>
173− CJPccXCHHBmb+U3gBGs9lyyHKkw=
173+ VivAVxtEMi2FHBPFF09uQi1418U=
174 </data>
174 </data>
175 <key>Sodium.Core.dll</key>
175 <key>Sodium.Core.dll</key>
176 <data>
176 <data>
@@ -1393,14 +1393,14 @@
1393 <dict>
1393 <dict>
1394 <key>hash2</key>
1394 <key>hash2</key>
1395 <data>
1395 <data>
1396− /REP/HoHjlxEG4EILkQsxLRTzNPyUb0OPrgeH7X+ysg=
1396+ Bd6/5/MU6L0SMz/GVfv2R6VSAXUbiQJI32j7+lnsJ4w=
1397 </data>
1397 </data>
1398 </dict>
1398 </dict>
1399 <key>Skrepka.pdb</key>
1399 <key>Skrepka.pdb</key>
1400 <dict>
1400 <dict>
1401 <key>hash2</key>
1401 <key>hash2</key>
1402 <data>
1402 <data>
1403− ZbgMQL3trkYdSHBJ4m83nCenAnLY6W3xoI3w1+2M1xc=
1403+ YuSpnbETdRksRCmKP9GMRFzwQi1n0Oc1JqlXdMOZiyE=
1404 </data>
1404 </data>
1405 </dict>
1405 </dict>
1406 <key>Sodium.Core.dll</key>
1406 <key>Sodium.Core.dll</key>
client/bin/Debug/net10.0-ios/iossimulator-arm64/Skrepka.dll

Binary file not shown.

client/bin/Debug/net10.0-ios/iossimulator-arm64/Skrepka.pdb

Binary file not shown.

client/bin/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.app/Contents/MonoBundle/Skrepka.dll

Binary file not shown.

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

Binary file not shown.

client/bin/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.app/Contents/_CodeSignature/CodeResources+2−2
@@ -251,14 +251,14 @@
251 <dict>
251 <dict>
252 <key>hash2</key>
252 <key>hash2</key>
253 <data>
253 <data>
254− ZDY0RMPXDKaTDBgy9myo16G9HTQ00CFMBnGOxyxo8IQ=
254+ F2ovogGs5gdnmuhl7I35TXBYBHvkWSc5l3Eb3dz5/Eo=
255 </data>
255 </data>
256 </dict>
256 </dict>
257 <key>MonoBundle/Skrepka.pdb</key>
257 <key>MonoBundle/Skrepka.pdb</key>
258 <dict>
258 <dict>
259 <key>hash2</key>
259 <key>hash2</key>
260 <data>
260 <data>
261− sA8vqaz6By9kGWnIhXN4vmv2saJVvZVG4L5qa8GAqxE=
261+ LL4NPXSPKwyqo6TCZ4Xmt3aHdsBLcNeTGcuqqNI6GIA=
262 </data>
262 </data>
263 </dict>
263 </dict>
264 <key>MonoBundle/Sodium.Core.dll</key>
264 <key>MonoBundle/Sodium.Core.dll</key>
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-ios/iossimulator-arm64/Skrepka.AssemblyInfo.fs+1−1
@@ -10,7 +10,7 @@ open System.Reflection
10[<assembly: System.Reflection.AssemblyCompanyAttribute("Skrepka")>]
10[<assembly: System.Reflection.AssemblyCompanyAttribute("Skrepka")>]
11[<assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")>]
11[<assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")>]
12[<assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")>]
12[<assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")>]
13−[<assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0+a5a5e7c5bac92a6f1d566920ab29663bfc3aad5f")>]
13+[<assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0+57cf03bb5cc8c778e01a2c8e1a8da7ec32e919da")>]
14[<assembly: System.Reflection.AssemblyProductAttribute("Skrepka")>]
14[<assembly: System.Reflection.AssemblyProductAttribute("Skrepka")>]
15[<assembly: System.Reflection.AssemblyTitleAttribute("Skrepka")>]
15[<assembly: System.Reflection.AssemblyTitleAttribute("Skrepka")>]
16[<assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")>]
16[<assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")>]
client/obj/Debug/net10.0-ios/iossimulator-arm64/Skrepka.AssemblyInfoInputs.cache+1−1
@@ -1 +1 @@
1−3de6148967a5feacb10209c6b84280448e0d8b2682259d470ffc1bcb59c62da5
1+07f51a22ce67924703904ac63354f57452f4a0f68bfe8fef4528a96892e114a1
client/obj/Debug/net10.0-ios/iossimulator-arm64/Skrepka.dll

Binary file not shown.

client/obj/Debug/net10.0-ios/iossimulator-arm64/Skrepka.fsproj.FileListAbsolute.txt+23
@@ -334,3 +334,26 @@
334/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/Skrepka.genruntimeconfig.cache
334/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/Skrepka.genruntimeconfig.cache
335/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/ref/Skrepka.dll
335/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/ref/Skrepka.dll
336/Users/iko/Developer/skrepka/client/bin/Debug/net10.0-ios/iossimulator-arm64/LiteDB.dll
336/Users/iko/Developer/skrepka/client/bin/Debug/net10.0-ios/iossimulator-arm64/LiteDB.dll
337+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Fabulous.stamp
338+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Fabulous.MauiControls.stamp
339+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/FSharp.Core.stamp
340+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/LiteDB.stamp
341+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Extensions.Configuration.Abstractions.stamp
342+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Extensions.Configuration.stamp
343+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Extensions.DependencyInjection.Abstractions.stamp
344+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Extensions.DependencyInjection.stamp
345+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Extensions.Diagnostics.Abstractions.stamp
346+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Extensions.FileProviders.Abstractions.stamp
347+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Extensions.Hosting.Abstractions.stamp
348+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Extensions.Logging.Abstractions.stamp
349+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Extensions.Logging.stamp
350+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Extensions.Options.stamp
351+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Extensions.Primitives.stamp
352+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Maui.Controls.Compatibility.stamp
353+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Maui.Controls.stamp
354+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Maui.Controls.Xaml.stamp
355+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Maui.stamp
356+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Maui.Essentials.stamp
357+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Microsoft.Maui.Graphics.stamp
358+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/resourcestamps/Sodium.Core.stamp
359+/Users/iko/Developer/skrepka/client/obj/Debug/net10.0-ios/iossimulator-arm64/unpack/Microsoft.Maui.Essentials/BundleResource/xml/microsoft_maui_essentials_fileprovider_file_paths.xml
client/obj/Debug/net10.0-ios/iossimulator-arm64/Skrepka.pdb

Binary file not shown.

client/obj/Debug/net10.0-ios/iossimulator-arm64/Skrepka.sourcelink.json+1−1
@@ -1 +1 @@
1−{"documents":{"/Users/iko/Developer/skrepka/*":"https://raw.githubusercontent.com/ilyakooo0/skrepka/a5a5e7c5bac92a6f1d566920ab29663bfc3aad5f/*"}}
1+{"documents":{"/Users/iko/Developer/skrepka/*":"https://raw.githubusercontent.com/ilyakooo0/skrepka/57cf03bb5cc8c778e01a2c8e1a8da7ec32e919da/*"}}
client/obj/Debug/net10.0-ios/iossimulator-arm64/ref/Skrepka.dll

Binary file not shown.

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

Binary file not shown.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfo.fs+1−1
@@ -10,7 +10,7 @@ open System.Reflection
10[<assembly: System.Reflection.AssemblyCompanyAttribute("Skrepka")>]
10[<assembly: System.Reflection.AssemblyCompanyAttribute("Skrepka")>]
11[<assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")>]
11[<assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")>]
12[<assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")>]
12[<assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")>]
13−[<assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0+476d6fff9f9f011c32feb31bb758bb823b925727")>]
13+[<assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0+57cf03bb5cc8c778e01a2c8e1a8da7ec32e919da")>]
14[<assembly: System.Reflection.AssemblyProductAttribute("Skrepka")>]
14[<assembly: System.Reflection.AssemblyProductAttribute("Skrepka")>]
15[<assembly: System.Reflection.AssemblyTitleAttribute("Skrepka")>]
15[<assembly: System.Reflection.AssemblyTitleAttribute("Skrepka")>]
16[<assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")>]
16[<assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")>]
client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfoInputs.cache+1−1
@@ -1 +1 @@
1−550dc360b827f626a376d9130941cd662e759b45c0cedce7f4830d75a313325f
1+034a8eb90add363ed97907a65fdd8257ea50d7e41bd6c1fea1e566215afb5a16
client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.dll

Binary file not shown.

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/476d6fff9f9f011c32feb31bb758bb823b925727/*"}}
1+{"documents":{"/Users/iko/Developer/skrepka/*":"https://raw.githubusercontent.com/ilyakooo0/skrepka/57cf03bb5cc8c778e01a2c8e1a8da7ec32e919da/*"}}
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.