@@ -516,8 +516,74 @@ module App =
516 match app.ApplicationLifetime with
516 match app.ApplicationLifetime with
517 | :? Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime as desktop ->
517 | :? Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime as desktop ->
518 desktop.MainWindow |> Option.ofObj |> Option.map (fun w -> w.StorageProvider)
518 desktop.MainWindow |> Option.ofObj |> Option.map (fun w -> w.StorageProvider)
519+ | :? Avalonia.Controls.ApplicationLifetimes.ISingleViewApplicationLifetime as singleView ->
522+ |> Option.bind (fun v -> Avalonia.Controls.TopLevel.GetTopLevel(v) |> Option.ofObj)
523+ |> Option.map (fun tl -> tl.StorageProvider)
519 | _ -> None
524 | _ -> None
526+ let private cropToSquarePng (imageBytes: byte[]) =
527+ use skBmp = SkiaSharp.SKBitmap.Decode(imageBytes)
528+ let size = min skBmp.Width skBmp.Height
529+ let x = (skBmp.Width - size) / 2
530+ let y = (skBmp.Height - size) / 2
531+ use cropped = new SkiaSharp.SKBitmap(size, size)
532+ skBmp.ExtractSubset(cropped, SkiaSharp.SKRectI(x, y, x + size, y + size)) |> ignore
533+ use img = SkiaSharp.SKImage.FromBitmap(cropped)
534+ use data = img.Encode(SkiaSharp.SKEncodedImageFormat.Png, 90)
538+ let private pickPhotoCmd =
539+ Cmd.ofEffect (fun dispatch ->
542+ let! bytes = Skrepka.iOS.PhotoPicker.pick ()
545+ | Some b -> dispatch (PhotoPicked(Some(cropToSquarePng b)))
546+ | None -> dispatch (PhotoPicked None)
548+ dispatch (PhotoPicked None)
552+ let private pickPhotoCmd =
553+ Cmd.ofEffect (fun dispatch ->
554+ Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(fun () ->
557+ match getStorageProvider () with
560+ Avalonia.Platform.Storage.FilePickerOpenOptions(
561+ AllowMultiple = false,
562+ Title = "Pick Photo",
564+ [ Avalonia.Platform.Storage.FilePickerFileType(
566+ Patterns = [ "*.png"; "*.jpg"; "*.jpeg"; "*.gif"; "*.bmp" ]
570+ let! files = sp.OpenFilePickerAsync(opts)
572+ match files |> Seq.tryHead with
573+ | None -> dispatch (PhotoPicked None)
575+ use! stream = file.OpenReadAsync()
576+ use ms = new MemoryStream()
577+ do! stream.CopyToAsync(ms)
578+ dispatch (PhotoPicked(Some(cropToSquarePng (ms.ToArray()))))
579+ | None -> dispatch (PhotoPicked None)
581+ dispatch (PhotoPicked None)
583+ :> System.Threading.Tasks.Task)
521 let mapCmd cmdMsg =
587 let mapCmd cmdMsg =
522 match cmdMsg with
588 match cmdMsg with
523 | CmdConnect(url, identity) ->
589 | CmdConnect(url, identity) ->
@@ -634,50 +700,7 @@ module App =
635 | CmdSaveData data -> Cmd.ofEffect (fun _ -> Store.saveData data)
701 | CmdSaveData data -> Cmd.ofEffect (fun _ -> Store.saveData data)
637− | CmdPickPhoto ->
703+ | CmdPickPhoto -> pickPhotoCmd
638− Cmd.ofEffect (fun dispatch ->
639− Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(fun () ->
642− match getStorageProvider () with
645− Avalonia.Platform.Storage.FilePickerOpenOptions(
646− AllowMultiple = false,
647− Title = "Pick Photo",
649− [ Avalonia.Platform.Storage.FilePickerFileType(
651− Patterns = [ "*.png"; "*.jpg"; "*.jpeg"; "*.gif"; "*.bmp" ]
655− let! files = sp.OpenFilePickerAsync(opts)
657− match files |> Seq.tryHead with
658− | None -> dispatch (PhotoPicked None)
660− use! stream = file.OpenReadAsync()
661− use ms = new MemoryStream()
662− do! stream.CopyToAsync(ms)
663− use skBmp = SkiaSharp.SKBitmap.Decode(ms.ToArray())
664− let size = min skBmp.Width skBmp.Height
665− let x = (skBmp.Width - size) / 2
666− let y = (skBmp.Height - size) / 2
667− use cropped = new SkiaSharp.SKBitmap(size, size)
669− skBmp.ExtractSubset(cropped, SkiaSharp.SKRectI(x, y, x + size, y + size))
672− use img = SkiaSharp.SKImage.FromBitmap(cropped)
673− use data = img.Encode(SkiaSharp.SKEncodedImageFormat.Png, 90)
674− dispatch (PhotoPicked(Some(data.ToArray())))
675− | None -> dispatch (PhotoPicked None)
677− dispatch (PhotoPicked None)
679− :> System.Threading.Tasks.Task)
682 | CmdSaveProfile profile -> Cmd.ofEffect (fun _ -> Store.saveProfile profile)
705 | CmdSaveProfile profile -> Cmd.ofEffect (fun _ -> Store.saveProfile profile)