on master help sign in
Fix iOS clipboard support and resolve Fabulous.Avalonia version incompatibility
db5a276iko
client/App.fs+5
@@ -529,6 +529,11 @@ module App =
529 desktop.MainWindow
529 desktop.MainWindow
530 |> Option.ofObj
530 |> Option.ofObj
531 |> Option.bind (fun w -> w.Clipboard |> Option.ofObj)
531 |> Option.bind (fun w -> w.Clipboard |> Option.ofObj)
532+ | :? Avalonia.Controls.ApplicationLifetimes.ISingleViewApplicationLifetime as singleView ->
533+ singleView.MainView
534+ |> Option.ofObj
535+ |> Option.bind (fun v -> Avalonia.Controls.TopLevel.GetTopLevel(v) |> Option.ofObj)
536+ |> Option.bind (fun tl -> tl.Clipboard |> Option.ofObj)
532 | _ -> None
537 | _ -> None
533
538
534 let private getStorageProvider () =
539 let private getStorageProvider () =
client/Platform/iOS/Info.plist−2
@@ -19,8 +19,6 @@
19 <integer>1</integer>
19 <integer>1</integer>
20 <integer>2</integer>
20 <integer>2</integer>
21 </array>
21 </array>
22− <key>UILaunchStoryboardName</key>
23− <string>LaunchScreen</string>
24 <key>UILaunchScreen</key>
22 <key>UILaunchScreen</key>
25 <dict/>
23 <dict/>
26 <key>UIRequiredDeviceCapabilities</key>
24 <key>UIRequiredDeviceCapabilities</key>
client/Skrepka.app/Contents/MacOS/Skrepka+1−1
@@ -1 +1 @@
1−../../../Skrepka.dll
1+../../../Skrepka
client/Skrepka.fsproj+31−7
@@ -63,7 +63,6 @@
63 <ItemGroup Condition="$(AvaloniaPlatform) == 'iOS'">
63 <ItemGroup Condition="$(AvaloniaPlatform) == 'iOS'">
64 <None Include="$(iOSPlatformFolder)Entitlements.plist" />
64 <None Include="$(iOSPlatformFolder)Entitlements.plist" />
65 <None Include="$(iOSPlatformFolder)Info.plist" LogicalName="Info.plist" />
65 <None Include="$(iOSPlatformFolder)Info.plist" LogicalName="Info.plist" />
66− <InterfaceDefinition Include="$(iOSPlatformFolder)Resources\LaunchScreen.storyboard" />
67 <ImageAsset Include="$(iOSPlatformFolder)Resources\Assets.xcassets\Contents.json" />
66 <ImageAsset Include="$(iOSPlatformFolder)Resources\Assets.xcassets\Contents.json" />
68 <ImageAsset Include="$(iOSPlatformFolder)Resources\Assets.xcassets\AppIcon.appiconset\Contents.json" />
67 <ImageAsset Include="$(iOSPlatformFolder)Resources\Assets.xcassets\AppIcon.appiconset\Contents.json" />
69 <ImageAsset Include="$(iOSPlatformFolder)Resources\Assets.xcassets\AppIcon.appiconset\*.png" />
68 <ImageAsset Include="$(iOSPlatformFolder)Resources\Assets.xcassets\AppIcon.appiconset\*.png" />
@@ -71,8 +70,33 @@
71 <PackageReference Include="Avalonia.iOS" Version="11.3.0" />
70 <PackageReference Include="Avalonia.iOS" Version="11.3.0" />
72 </ItemGroup>
71 </ItemGroup>
73
72
74− <Target Name="AddLaunchScreenToPlist" AfterTargets="_CompileAppManifest" Condition="$(AvaloniaPlatform) == 'iOS'">
73+ <Target Name="FixBundlePlist" AfterTargets="Build" Condition="$(AvaloniaPlatform) == 'iOS'">
75− <Exec Command="/usr/libexec/PlistBuddy -c 'Add :UILaunchStoryboardName string LaunchScreen' '$(AppBundleDir)/Info.plist'" ContinueOnError="true" />
74+ <PropertyGroup>
75+ <_Plist>$(AppBundleDir)/Info.plist</_Plist>
76+ <_PB>/usr/libexec/PlistBuddy</_PB>
77+ </PropertyGroup>
78+ <!-- Launch screen (full-screen, no letterboxing) -->
79+ <Exec Command="$(_PB) -c 'Delete :UILaunchStoryboardName' '$(_Plist)'" ContinueOnError="true" />
80+ <Exec Command="$(_PB) -c 'Add :UILaunchScreen dict' '$(_Plist)'" ContinueOnError="true" />
81+ <!-- Privacy descriptions -->
82+ <Exec Command="$(_PB) -c 'Add :NSPhotoLibraryUsageDescription string Skrepka needs access to your photo library to set a profile photo.' '$(_Plist)'" ContinueOnError="true" />
83+ <!-- App icon (fallback when actool produces empty output) -->
84+ <Exec Command="$(_PB) -c 'Add :CFBundleIcons dict' '$(_Plist)'" ContinueOnError="true" />
85+ <Exec Command="$(_PB) -c 'Add :CFBundleIcons:CFBundlePrimaryIcon dict' '$(_Plist)'" ContinueOnError="true" />
86+ <Exec Command="$(_PB) -c 'Add :CFBundleIcons:CFBundlePrimaryIcon:CFBundleIconFiles array' '$(_Plist)'" ContinueOnError="true" />
87+ <Exec Command="$(_PB) -c 'Add :CFBundleIcons:CFBundlePrimaryIcon:CFBundleIconFiles:0 string AppIcon60x60' '$(_Plist)'" ContinueOnError="true" />
88+ <Exec Command="$(_PB) -c 'Add :CFBundleIcons:CFBundlePrimaryIcon:CFBundleIconName string AppIcon' '$(_Plist)'" ContinueOnError="true" />
89+ <Exec Command="$(_PB) -c 'Add :CFBundleIcons~ipad dict' '$(_Plist)'" ContinueOnError="true" />
90+ <Exec Command="$(_PB) -c 'Add :CFBundleIcons~ipad:CFBundlePrimaryIcon dict' '$(_Plist)'" ContinueOnError="true" />
91+ <Exec Command="$(_PB) -c 'Add :CFBundleIcons~ipad:CFBundlePrimaryIcon:CFBundleIconFiles array' '$(_Plist)'" ContinueOnError="true" />
92+ <Exec Command="$(_PB) -c 'Add :CFBundleIcons~ipad:CFBundlePrimaryIcon:CFBundleIconFiles:0 string AppIcon60x60' '$(_Plist)'" ContinueOnError="true" />
93+ <Exec Command="$(_PB) -c 'Add :CFBundleIcons~ipad:CFBundlePrimaryIcon:CFBundleIconFiles:1 string AppIcon76x76' '$(_Plist)'" ContinueOnError="true" />
94+ <Exec Command="$(_PB) -c 'Add :CFBundleIcons~ipad:CFBundlePrimaryIcon:CFBundleIconName string AppIcon' '$(_Plist)'" ContinueOnError="true" />
95+ <!-- Copy icon PNGs to bundle (fallback when actool doesn't produce Assets.car) -->
96+ <Copy SourceFiles="$(iOSPlatformFolder)Resources/Assets.xcassets/AppIcon.appiconset/icon-120.png" DestinationFiles="$(AppBundleDir)/AppIcon60x60@2x.png" SkipUnchangedFiles="true" />
97+ <Copy SourceFiles="$(iOSPlatformFolder)Resources/Assets.xcassets/AppIcon.appiconset/icon-180.png" DestinationFiles="$(AppBundleDir)/AppIcon60x60@3x.png" SkipUnchangedFiles="true" />
98+ <Copy SourceFiles="$(iOSPlatformFolder)Resources/Assets.xcassets/AppIcon.appiconset/icon-152.png" DestinationFiles="$(AppBundleDir)/AppIcon76x76@2x~ipad.png" SkipUnchangedFiles="true" />
99+ <Copy SourceFiles="$(iOSPlatformFolder)Resources/Assets.xcassets/AppIcon.appiconset/icon-167.png" DestinationFiles="$(AppBundleDir)/AppIcon83.5x83.5@2x~ipad.png" SkipUnchangedFiles="true" />
76 </Target>
100 </Target>
77
101
78 <ItemGroup Condition="$(AvaloniaPlatform) == 'iOS' And $(RuntimeIdentifier.StartsWith('iossimulator'))">
102 <ItemGroup Condition="$(AvaloniaPlatform) == 'iOS' And $(RuntimeIdentifier.StartsWith('iossimulator'))">
@@ -84,12 +108,12 @@
84
108
85 <ItemGroup>
109 <ItemGroup>
86 <PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.0" />
110 <PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.0" />
87− <PackageReference Include="FSharp.Core" Version="9.0.100" />
111+ <PackageReference Include="FSharp.Core" Version="11.0.100-preview3.26159.112" />
88 <PackageReference Include="Fabulous" Version="3.0.0-pre22" />
112 <PackageReference Include="Fabulous" Version="3.0.0-pre22" />
89 <PackageReference Include="Fabulous.Avalonia" Version="3.0.0-pre13" />
113 <PackageReference Include="Fabulous.Avalonia" Version="3.0.0-pre13" />
90− <PackageReference Include="Sodium.Core" Version="1.4.0" />
114+ <PackageReference Include="Sodium.Core" Version="1.4.1-preview.1" />
91− <PackageReference Include="Dapper.FSharp" Version="4.5.1" />
115+ <PackageReference Include="Dapper.FSharp" Version="4.10.0" />
92− <PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.5" />
116+ <PackageReference Include="Microsoft.Data.Sqlite" Version="11.0.0-preview.2.26159.112" />
93 </ItemGroup>
117 </ItemGroup>
94
118
95</Project>
119</Project>
client/msbuild.binlognew file

Binary file not shown.

server.knot+4−6
@@ -119,7 +119,6 @@ data AckResult = AckUnauthorized {} | AckDone {pendingAcks: [AckedEntry], evicte
119data PollResult = PollUnauthorized {} | PollOk {events: [PollEvent], cursor: Timestamp}
119data PollResult = PollUnauthorized {} | PollOk {events: [PollEvent], cursor: Timestamp}
120data ForwardResult = ForwardDuplicate {} | ForwardRejected {} | ForwardStored {}
120data ForwardResult = ForwardDuplicate {} | ForwardRejected {} | ForwardStored {}
121
121
122−
123-- ============================================
122-- ============================================
124-- Persisted State
123-- Persisted State
125-- ============================================
124-- ============================================
@@ -566,7 +565,6 @@ countMessagesFor = \messages toKey t ->
566hasMessage : MessageIdHex -> PubkeyHex -> [{messageId: MessageIdHex, toKey: PubkeyHex | a}] -> Bool
565hasMessage : MessageIdHex -> PubkeyHex -> [{messageId: MessageIdHex, toKey: PubkeyHex | a}] -> Bool
567hasMessage = \mid toKey items -> any items (\x -> x.messageId == mid && x.toKey == toKey)
566hasMessage = \mid toKey items -> any items (\x -> x.messageId == mid && x.toKey == toKey)
568
567
569−
570validGossipEvents : [GossipEvent] -> Timestamp -> {online: [ValidGossipEntry], offline: [ValidGossipEntry]}
568validGossipEvents : [GossipEvent] -> Timestamp -> {online: [ValidGossipEntry], offline: [ValidGossipEntry]}
571validGossipEvents = \events t ->
569validGossipEvents = \events t ->
572 let validate = \e ->
570 let validate = \e ->
@@ -686,6 +684,10 @@ mergeGossipPresence = \presence deduped trustedOffline fromServer t ->
686 gossipPeerServers: collectPeerServers capResult.finalPresence (\p -> p.server),
684 gossipPeerServers: collectPeerServers capResult.finalPresence (\p -> p.server),
687 withinCapacity: capResult.withinCapacity}
685 withinCapacity: capResult.withinCapacity}
688
686
687+maybePruneAndBroadcast = \t -> do
688+ pruneResult <- atomic do maybePrune t
689+ forkBroadcastOffline t pruneResult
690+
689withFederationAuth = \authorization t respond precondition action ->
691withFederationAuth = \authorization t respond precondition action ->
690 if not (verifyFederationAuth authorization) || not precondition
692 if not (verifyFederationAuth authorization) || not precondition
691 then do
693 then do
@@ -693,10 +695,6 @@ withFederationAuth = \authorization t respond precondition action ->
693 yield (respond {ok: False {}})
695 yield (respond {ok: False {}})
694 else action
696 else action
695
697
696−maybePruneAndBroadcast = \t -> do
697− pruneResult <- atomic do maybePrune t
698− forkBroadcastOffline t pruneResult
699−
700withSessionAuth = \authorization t onUnauth onAuth -> do
698withSessionAuth = \authorization t onUnauth onAuth -> do
701 sessions <- *sessions
699 sessions <- *sessions
702 case extractToken authorization of
700 case extractToken authorization of