Skip to content

Commit

Permalink
Change the Elmish music player example to use IStorageProvider instea… (
Browse files Browse the repository at this point in the history
#407)

* Change the Elmish music player example to use IStorageProvider instead of the obsoleted OpenFileDialog/OpenFolderDialog

* Remove the hard coded path separators for the music player sample icon

* Update LibVLCSharp
  • Loading branch information
Numpsy authored Jul 24, 2024
1 parent 580f09d commit bb21b83
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 45 deletions.
55 changes: 30 additions & 25 deletions src/Examples/Elmish Examples/Examples.Elmish.MusicPlayer/Dialogs.fs
Original file line number Diff line number Diff line change
@@ -1,34 +1,39 @@
namespace Examples.MusicPlayer


module Dialogs =
open System
open Avalonia.Controls
open Avalonia
open Avalonia.Platform.Storage
open Avalonia.Threading
open System.Collections.Generic

let getMusicFilesDialog (filters: FileDialogFilter seq option) =
let dialog = OpenFileDialog()
let showMusicFilesDialog(provider: IStorageProvider, filters: FilePickerFileType list option) =

let filters =
match filters with
| Some filter -> filter
| None ->
let filter = FileDialogFilter()
filter.Extensions <-
Collections.Generic.List
(seq {
"mp3"
"wav" })
filter.Name <- "Music"
seq { filter }

dialog.AllowMultiple <- true
dialog.Directory <- Environment.GetFolderPath(Environment.SpecialFolder.MyMusic)
dialog.Title <- "Select Your Music Files"
dialog.Filters <- System.Collections.Generic.List(filters)
dialog

let getFolderDialog =
let dialog = OpenFolderDialog()
dialog.Directory <- Environment.GetFolderPath(Environment.SpecialFolder.MyMusic)
dialog.Title <- "Choose where to look up for music"
dialog
let patterns = [ "*.mp3"; "*.wav" ]
let filter = FilePickerFileType("Music", Patterns = patterns)
[ filter ]

let options = FilePickerOpenOptions(AllowMultiple = true, Title = "Select Your Music Files", FileTypeFilter = filters)

async {
let! musicFolder = provider.TryGetWellKnownFolderAsync Platform.Storage.WellKnownFolder.Music |> Async.AwaitTask
options.SuggestedStartLocation <- musicFolder

return!
Dispatcher.UIThread.InvokeAsync<IReadOnlyList<IStorageFile>>
(fun _ -> provider.OpenFilePickerAsync(options)) |> Async.AwaitTask
}

let showMusicFolderDialog(provider: IStorageProvider) =
async {
let! musicFolder = provider.TryGetWellKnownFolderAsync Platform.Storage.WellKnownFolder.Music |> Async.AwaitTask
let options = FolderPickerOpenOptions(Title = "Choose where to look up for music", SuggestedStartLocation = musicFolder)

return!
Dispatcher.UIThread.InvokeAsync<IReadOnlyList<IStorageFolder>>
(fun _ -> provider.OpenFolderPickerAsync(options)) |> Async.AwaitTask

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<PackageReference Include="VideoLAN.LibVLC.Mac" Version="3.1.3.1" />
<ProjectReference Include="..\..\..\Avalonia.FuncUI.Elmish\Avalonia.FuncUI.Elmish.fsproj" />
<ProjectReference Include="..\..\..\Avalonia.FuncUI\Avalonia.FuncUI.fsproj" />
<PackageReference Include="LibVLCSharp" Version="3.4.2" />
<PackageReference Include="VideoLAN.LibVLC.Windows" Version="3.0.8.1" />
<PackageReference Include="LibVLCSharp" Version="3.8.5" />
<PackageReference Include="VideoLAN.LibVLC.Windows" Version="3.0.20" />
</ItemGroup>
</Project>
24 changes: 13 additions & 11 deletions src/Examples/Elmish Examples/Examples.Elmish.MusicPlayer/Shell.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ module Shell =
open Avalonia.Controls
open Avalonia.Input
open Avalonia.Layout
open Avalonia.Platform.Storage
open Avalonia.FuncUI.Elmish
open Avalonia.FuncUI.Hosts
open Avalonia.FuncUI.DSL
open LibVLCSharp.Shared
open Examples.MusicPlayer
open System.Collections.Generic

type State =
{ title: string
Expand All @@ -24,8 +26,8 @@ module Shell =
| SetTitle of string
| OpenFiles
| OpenFolder
| AfterSelectFolder of string
| AfterSelectFiles of string array
| AfterSelectFolder of IReadOnlyList<IStorageFolder>
| AfterSelectFiles of IReadOnlyList<IStorageFile>
(* Handle Media Player Events *)
| Playing
| Paused
Expand Down Expand Up @@ -122,15 +124,13 @@ module Shell =
window.Title <- title
{ state with title = title }, Cmd.none
| OpenFiles ->
let dialog = Dialogs.getMusicFilesDialog None
let showDialog window = dialog.ShowAsync(window) |> Async.AwaitTask
state, Cmd.OfAsync.perform showDialog window AfterSelectFiles
let showDialog storageProvider = Dialogs.showMusicFilesDialog (storageProvider, None)
state, Cmd.OfAsync.perform showDialog window.StorageProvider AfterSelectFiles
| OpenFolder ->
let dialog = Dialogs.getFolderDialog
let showDialog window = dialog.ShowAsync(window) |> Async.AwaitTask
state, Cmd.OfAsync.perform showDialog window AfterSelectFolder
| AfterSelectFolder path ->
let songs = Songs.populateFromDirectory path |> Array.toList
let showDialog storageProvider = Dialogs.showMusicFolderDialog storageProvider
state, Cmd.OfAsync.perform showDialog window.StorageProvider AfterSelectFolder
| AfterSelectFolder paths ->
let songs = Songs.populateFromFolders paths |> Array.toList
state, Cmd.map PlaylistMsg (Cmd.ofMsg (Playlist.Msg.AddFiles songs))
| AfterSelectFiles paths ->
let songs = Songs.populateSongs paths |> Array.toList
Expand Down Expand Up @@ -185,8 +185,10 @@ module Shell =
type ShellWindow() as this =
inherit HostWindow()
do
let iconPath = System.IO.Path.Combine("Assets", "Icons", "icon.ico")

base.Title <- "Music Player in F# :)"
base.Icon <- WindowIcon("Assets\Icons\icon.ico")
base.Icon <- WindowIcon(iconPath)
base.Width <- 800.0
base.Height <- 600.0
base.MinWidth <- 526.0
Expand Down
19 changes: 12 additions & 7 deletions src/Examples/Elmish Examples/Examples.Elmish.MusicPlayer/Songs.fs
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
namespace Examples.MusicPlayer


module Songs =
open System
open System.IO
open Types
open Avalonia.Platform.Storage

let populateSongs (paths: string array): Types.SongRecord array =
let populateSongs (paths: IStorageFile seq): Types.SongRecord array =
paths
|> Array.Parallel.map FileInfo
|> Array.Parallel.map (fun info -> info.Name, info.FullName)
|> Array.Parallel.map (fun (name, path) ->
|> Seq.map (fun storageFile ->
{ id = Guid.NewGuid()
name = name
path = path
name = storageFile.Name
path = storageFile.Path.LocalPath
createdAt = DateTime.Now })
|> Array.ofSeq

let populateFromDirectory (path: string): Types.SongRecord array =
match String.IsNullOrEmpty path with
Expand All @@ -29,3 +28,9 @@ module Songs =
name = name
path = path
createdAt = DateTime.Now })

let populateFromFolders(folders: IStorageFolder seq) =
folders
|> Seq.map _.Path.LocalPath
|> Seq.map populateFromDirectory
|> Array.concat

0 comments on commit bb21b83

Please sign in to comment.