on master help sign in
Refactor chat view to use Grid layout and ItemsRepeater for messages
commit08721cb378b88601c1f4f6504fe125abffb7da1a authoriko <mail@iko.soy> dateTue 21 Apr 2026, 00:06 (6 months ago) parent7523d53
3 files changed+34−27
.github/workflows/build.yml+2−2 client/Skrepka.fsproj+1 client/ViewChat.fs+31−25
.github/workflows/build.yml+2−2
@@ -20,9 +20,9 @@ jobs:
2020 - runner: ubuntu-24.04-arm
2121 name: linux-arm64
2222 musl-target: aarch64-unknown-linux-musl
23− - runner: macos-latest
23+ - runner: macos-26
2424 name: macos-arm64
25− - runner: macos-13
25+ - runner: macos-26-intel
2626 name: macos-x86_64
2727 runs-on: ${{ matrix.runner }}
2828 steps:
client/Skrepka.fsproj+1
@@ -124,6 +124,7 @@
124124 <PackageReference Include="FSharp.Core" Version="11.0.100-preview3.26159.112" />
125125 <PackageReference Include="Fabulous" Version="3.0.0-pre22" />
126126 <PackageReference Include="Fabulous.Avalonia" Version="3.0.0-pre13" />
127+ <PackageReference Include="Fabulous.Avalonia.ItemsRepeater" Version="3.0.0-pre13" />
127128 <PackageReference Include="Sodium.Core" Version="1.4.0" />
128129 <PackageReference Include="Donald" Version="10.0.2" />
129130 <PackageReference Include="Microsoft.Data.Sqlite" Version="11.0.0-preview.2.26159.112" />
client/ViewChat.fs+31−25
@@ -1,5 +1,6 @@
11namespace Skrepka
22
3+open Avalonia.Layout
34open Fabulous.Avalonia
45
56open type Fabulous.Avalonia.View
@@ -14,37 +15,42 @@ module ViewChat =
1415 let name = contactName model.Contacts pk
1516 let msgs = messagesFor pk model.Messages
1617
17− (VStack(8.) {
18− HStack(8.) {
18+ (Grid([ Dimension.Auto; Dimension.Auto; Dimension.Star; Dimension.Auto ], [ Dimension.Star ]) {
19+ (HStack(8.) {
1920 backButton (SetPage Conversations)
2021
2122 TextBlock(name).fontSize(20.).centerVertical ()
22− }
23−
24− viewErrorBanner model.Error
25−
26− ScrollViewer(
27− VStack(4.) {
28− if msgs.IsEmpty then
29− TextBlock("No messages yet").padding(8.).fontSize (14.)
30− else
31− for m in msgs do
32− let prefix, tick =
33− match m.Direction with
34− | Outgoing DeliveryStatus.Delivered -> "You: ", " \u2713"
35− | Outgoing DeliveryStatus.Sent -> "You: ", ""
36− | Incoming -> "", ""
37−
38− TextBlock($"{prefix}{m.Body}{tick}").padding(8.).fontSize (14.)
39− }
40− )
41−
42− HStack(8.) {
23+ })
24+ .gridRow (0)
25+
26+ (viewErrorBanner model.Error).gridRow (1)
27+
28+ (if msgs.IsEmpty then
29+ AnyView(TextBlock("No messages yet").padding(8.).fontSize (14.))
30+ else
31+ let reversed = List.rev msgs
32+
33+ AnyView(
34+ ScrollViewer(
35+ ItemsRepeater(reversed, fun m ->
36+ let prefix, tick =
37+ match m.Direction with
38+ | Outgoing DeliveryStatus.Delivered -> "You: ", " \u2713"
39+ | Outgoing DeliveryStatus.Sent -> "You: ", ""
40+ | Incoming -> "", ""
41+
42+ TextBlock($"{prefix}{m.Body}{tick}").padding(8.).fontSize (14.))
43+ )
44+ ))
45+ .gridRow (2)
46+
47+ (HStack(8.) {
4348 TextBox(compose, fun text -> SetPage(Chat(pk, text)))
4449 .watermark("Message...")
45− .horizontalAlignment (Avalonia.Layout.HorizontalAlignment.Stretch)
50+ .horizontalAlignment (HorizontalAlignment.Stretch)
4651
4752 Button("Send", DoSend)
48− }
53+ })
54+ .gridRow (3)
4955 })
5056 .margin (12.)