-
Notifications
You must be signed in to change notification settings - Fork 1
/
MainViewModel.fs
193 lines (157 loc) · 6.34 KB
/
MainViewModel.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
namespace AidenDesktop.ViewModels
open Elmish
open ReactiveElmish
open ReactiveElmish.Avalonia
open FluentAvalonia.UI.Controls
open FluentAvalonia.FluentIcons
open ReactiveUI
open Avalonia.Media
open System.Threading.Tasks
open App
open Avalonia.Layout
// TODO: Move to a shared module - I have a Models folder in my branch for base types, which is where I'd put this... thoughts?
type NavItem() =
(* NOTE: FluentAvalonia.NavigationView Icons support:
BitmapIconSource, PathIconSource, and SymbolIconSource
It DOES NOT SUPPORT FontIconSource... ><
As Well: Icon size is inflexible at the moment, with talk of adding a resource: https://github.com/microsoft/microsoft-ui-xaml/issues/1710
*)
(* TODO: If we want multiple icon type support, a converter may be a better option
at the moment, it can be only one type, so for the short term we'll have to choose one
*)
let createTestIcon() =
(* let symbolIcon = SymbolIconSource()
symbolIcon.Symbol <- Symbol.Home
symbolIcon *)
(* let pathIcon = PathIconSource()
pathIcon.Data <- Geometry.Parse("M0,0 L0,1 1,1 1,0 z M0.5,0.5 L0.5,0 L0,0.5 L0.5,1 L1,0.5 L0.5,0 z")
pathIcon *)
let i = new BitmapIconSource()
i.UriSource <- System.Uri("avares://AidenDesktop/Assets/test.png")
i
let createBadge() =
let b = InfoBadge()
b.Value <- 0
b.FontSize <- 8.0
b.Foreground <- SolidColorBrush(Colors.White)
b.Background <- SolidColorBrush(Colors.DarkOrange)
b.HorizontalAlignment <- HorizontalAlignment.Left
b.VerticalAlignment <- VerticalAlignment.Top
b.IsVisible <- false
b
let mutable _testIcon = createTestIcon()
let mutable _badge = createBadge()
member val Name = "" with get, set
member val Badge = _badge with get, set
member this.Icon
with get() = _testIcon
and set(value) = _testIcon <- value
member this.SetBadgeValue(value : int) =
this.Badge.Value <- value
if value > 0 then
this.Badge.IsVisible <- true
else
this.Badge.IsVisible <- false
new(name : string, icon : string) as self =
NavItem() then
do
self.Name <- name
let i = new BitmapIconSource()
i.UriSource <- System.Uri(sprintf "avares://AidenDesktop/Assets/%s.png" icon)
self.Icon <- i
new(name: string, icon: string, badgeValue: int) as self =
NavItem() then
do
self.Name <- name
let i = new BitmapIconSource()
i.UriSource <- System.Uri(sprintf "avares://AidenDesktop/Assets/%s.png" icon)
self.Icon <- i
self.SetBadgeValue(badgeValue)
(* new(name : string, icon : Symbol) as self =
NavItem() then
do
self.Name <- name
self.Icon <- SymbolIconSource()
self.Icon.Symbol <- icon *)
module MainViewModule =
type Model =
{
ChatOpen: bool
ChatAlertCount: int
ShowChatBadge: bool
SelectedNavItem: NavItem
NavigationList: NavItem list
}
type Msg =
| ToggleChat of bool
| SetChatAlertCount of int
| SelectedNavItemChanged of NavItem
let init() =
{
ChatOpen = false
ChatAlertCount = 2
ShowChatBadge = true
SelectedNavItem = NavItem("Home", "Home")
NavigationList = [
NavItem("Home", "FA_Home")
NavItem("Counter", "FA_Counter")
NavItem("Chart", "FA_Chart")
NavItem("Dashboard", "FA_Map", 2)
NavItem("File Picker", "FA_File")
NavItem("About", "FA_Info")
]
}
let update (msg: Msg) (model: Model) =
match msg with
| ToggleChat b ->
// Clear chat badge on close
if b = false then
for item in model.NavigationList do
item.SetBadgeValue(0)
{ model with ChatOpen = b; ChatAlertCount = 0; ShowChatBadge = false }
else
{ model with ChatOpen = b }
| SetChatAlertCount count ->
// Set badge as active
{ model with ChatAlertCount = count }
| SelectedNavItemChanged item ->
match item.Name with
| "Counter" -> app.Dispatch (SetView CounterView)
| "Chart" -> app.Dispatch (SetView ChartView)
| "Dashboard" -> app.Dispatch (SetView DoughnutView)
| "File Picker" -> app.Dispatch (SetView FilePickerView)
| "About" -> app.Dispatch (SetView AboutView)
| "Home" -> app.Dispatch (SetView HomeView)
| _ -> ()
{ model with SelectedNavItem = item }
open MainViewModule
type MainViewModel(root: CompositionRoot) =
inherit ReactiveElmishViewModel()
let local =
Program.mkAvaloniaSimple init update
|> Program.withErrorHandler (fun (_, ex) -> printfn "Error: %s" ex.Message)
|> Program.mkStore
member self.ChatOpen
with get() = self.Bind(local, _.ChatOpen)
and set(value) = local.Dispatch (ToggleChat value)
member self.ChatAlertCount
with get() = self.Bind(local, _.ChatAlertCount)
and set(value) = local.Dispatch (SetChatAlertCount value)
member self.ShowChatBadge
with get() = self.Bind(local, _.ShowChatBadge)
member self.SelectedNavItem
with get() = self.Bind(local, _.SelectedNavItem)
and set(value) = local.Dispatch (SelectedNavItemChanged value)
member self.NavigationList = self.Bind(local, _.NavigationList)
member self.ChatView = root.GetView<ChatViewModel>()
member self.ContentView =
self.BindOnChanged (app, _.View, fun m ->
match m.View with
| CounterView -> root.GetView<CounterViewModel>()
| DoughnutView -> root.GetView<DoughnutViewModel>()
| ChartView -> root.GetView<ChartViewModel>()
| FilePickerView -> root.GetView<FilePickerViewModel>()
| AboutView -> root.GetView<AboutViewModel>()
| HomeView -> root.GetView<HomeViewModel>()
)
static member DesignVM = new MainViewModel(Design.stub)