Skip to content

Commit 59925b8

Browse files
committed
Polishing
1 parent 1f51ef8 commit 59925b8

9 files changed

+136
-40
lines changed

ContosoNotes/Models/TaskNoteItemModel.cs

+22-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public TaskNoteItemModel(string text = null) : base(text)
4646
{
4747
LoadingState = LoadingState.Unloaded;
4848
_timer = DispatcherQueue.GetForCurrentThread().CreateTimer();
49-
49+
5050
Load();
5151
}
5252

@@ -142,7 +142,7 @@ protected async void Save()
142142
ODataType = null, // Magic, don't remove
143143
DisplayName = "ContosoNotes"
144144
});
145-
145+
146146
TodoTaskListId = newTaskList.Id;
147147
}
148148
else
@@ -193,5 +193,25 @@ protected async void Save()
193193
_mutex.Release();
194194
}
195195
}
196+
197+
public async void Delete()
198+
{
199+
await _mutex.WaitAsync();
200+
201+
try
202+
{
203+
var provider = ProviderManager.Instance.GlobalProvider;
204+
if (provider != null && provider.State == ProviderState.SignedIn)
205+
{
206+
var graph = ProviderManager.Instance.GlobalProvider.Graph();
207+
208+
await graph.Me.Todo.Lists[TodoTaskListId].Tasks[TodoTaskId].Request().DeleteAsync();
209+
}
210+
}
211+
finally
212+
{
213+
_mutex.Release();
214+
}
215+
}
196216
}
197217
}

ContosoNotes/StorageManager.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ namespace ContosoNotes
1010
{
1111
public class StorageManager
1212
{
13-
private IObjectSerializer _serializer;
14-
private LocalObjectStorageHelper _localStorageHelper;
13+
private readonly IObjectSerializer _serializer;
14+
private readonly LocalObjectStorageHelper _localStorageHelper;
1515
private RoamingSettingsHelper _roamingStorageHelper;
1616

1717
public StorageManager()

ContosoNotes/UI/NoteItemView.xaml

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<Setter Property="BorderThickness" Value="0" />
1515
<Setter Property="IsSpellCheckEnabled" Value="True" />
1616
<Setter Property="TextWrapping" Value="Wrap" />
17+
<Setter Property="FontSize" Value="14" />
1718
</Style>
1819
</UserControl.Resources>
1920

ContosoNotes/UI/NoteItemView.xaml.cs

-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using ContosoNotes.Models;
2-
using System.ComponentModel;
3-
using System.Runtime.CompilerServices;
42
using Windows.UI.Xaml;
53
using Windows.UI.Xaml.Controls;
64

@@ -11,8 +9,6 @@ public sealed partial class NoteItemView : UserControl
119
public static readonly DependencyProperty NoteItemProperty =
1210
DependencyProperty.Register(nameof(NoteItem), typeof(NoteItemModel), typeof(NoteItemView), new PropertyMetadata(null));
1311

14-
public event PropertyChangedEventHandler PropertyChanged;
15-
1612
public NoteItemModel NoteItem
1713
{
1814
get => (NoteItemModel)GetValue(NoteItemProperty);

ContosoNotes/UI/NotePageRenderer.xaml

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
<TextBox
3939
VerticalAlignment="Center"
4040
BorderThickness="0"
41+
FontSize="16"
4142
FontWeight="SemiBold"
4243
PlaceholderText="Title"
4344
Text="{x:Bind NotePage.PageTitle, Mode=TwoWay}" />

ContosoNotes/UI/NotePageRenderer.xaml.cs

-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using ContosoNotes.Models;
2-
using System.ComponentModel;
3-
using System.Runtime.CompilerServices;
42
using System.Windows.Input;
53
using Windows.UI.Xaml;
64
using Windows.UI.Xaml.Controls;
@@ -12,8 +10,6 @@ public sealed partial class NotePageRenderer : UserControl
1210
public static readonly DependencyProperty NotePageProperty =
1311
DependencyProperty.Register(nameof(NotePage), typeof(NotePageModel), typeof(NotePageRenderer), new PropertyMetadata(null));
1412

15-
public event PropertyChangedEventHandler PropertyChanged;
16-
1713
public NotePageModel NotePage
1814
{
1915
get => (NotePageModel)GetValue(NotePageProperty);

ContosoNotes/UI/TaskNoteItemView.xaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
<Setter Property="IsSpellCheckEnabled" Value="True" />
1616
<Setter Property="TextWrapping" Value="Wrap" />
1717
<Setter Property="VerticalAlignment" Value="Center" />
18+
<Setter Property="FontSize" Value="14" />
1819
</Style>
1920

2021
<Style TargetType="CheckBox">
2122
<Setter Property="MinWidth" Value="0" />
22-
<Setter Property="Margin" Value="0,0,0,0" />
23+
<Setter Property="Margin" Value="10,0,0,0" />
2324
<Setter Property="VerticalAlignment" Value="Center" />
2425
</Style>
2526
</UserControl.Resources>

ContosoNotes/Views/MainPage.xaml

+37-23
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
xmlns:local="using:ContosoNotes.Views"
99
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
1010
xmlns:models="using:ContosoNotes.Models"
11-
xmlns:ui="using:ContosoNotes.UI"
11+
xmlns:ui="using:ContosoNotes.UI" xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
1212
d:DataContext="{d:DesignInstance Type=local:MainViewModel}"
1313
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
1414
mc:Ignorable="d">
@@ -64,7 +64,7 @@
6464
</Button>
6565

6666
<StackPanel Grid.Column="1" Orientation="Horizontal">
67-
<Button Style="{StaticResource CustomButtonStyle}">
67+
<!--<Button Style="{StaticResource CustomButtonStyle}">
6868
<Image Source="ms-appx:///Assets/Translate.png" />
6969
</Button>
7070
<Button Style="{StaticResource CustomButtonStyle}">
@@ -76,21 +76,23 @@
7676
<Button Style="{StaticResource CustomButtonStyle}">
7777
<Image Source="ms-appx:///Assets/Attach.png" />
7878
</Button>
79-
<Button Command="{x:Bind ViewModel.SaveCommand}" Style="{StaticResource CustomButtonStyle}">
79+
<Button Style="{StaticResource CustomButtonStyle}">
8080
<Image Source="ms-appx:///Assets/More.png" />
81-
</Button>
81+
</Button>-->
8282
</StackPanel>
8383

8484
<StackPanel Grid.Column="3" Orientation="Horizontal">
85-
<Button Style="{StaticResource CustomButtonStyle}">
85+
<!--<Button Style="{StaticResource CustomButtonStyle}">
8686
<Image Source="ms-appx:///Assets/Outlook.png" />
87-
</Button>
88-
<Button Style="{StaticResource CustomButtonStyle}">
87+
</Button>-->
88+
<Button
89+
Command="{x:Bind ViewModel.LaunchMicrosoftTodoCommand}"
90+
Style="{StaticResource CustomButtonStyle}">
8991
<Image Source="ms-appx:///Assets/Todo.png" />
9092
</Button>
91-
<Button Style="{StaticResource CustomButtonStyle}">
93+
<!--<Button Style="{StaticResource CustomButtonStyle}">
9294
<Image Source="ms-appx:///Assets/Excel.png" />
93-
</Button>
95+
</Button>-->
9496
</StackPanel>
9597

9698
<graphcontrols:LoginButton Grid.Column="4" />
@@ -102,7 +104,8 @@
102104
Padding="12,0,0,12"
103105
BorderBrush="#717171"
104106
BorderThickness="0,0,1,0"
105-
Visibility="{x:Bind ViewModel.IsPaneOpen, Mode=OneWay}">
107+
Visibility="{x:Bind ViewModel.IsPaneOpen, Mode=OneWay}"
108+
Width="300">
106109
<Grid.RowDefinitions>
107110
<RowDefinition />
108111
<RowDefinition Height="48" />
@@ -113,17 +116,20 @@
113116
<ListView.ItemTemplate>
114117
<DataTemplate x:DataType="models:NotesListItemModel">
115118
<Grid>
116-
<TextBlock Text="{x:Bind NotePageTitle, Mode=OneWay}" />
119+
<TextBlock
120+
Text="{x:Bind NotePageTitle, Mode=OneWay}"
121+
TextTrimming="WordEllipsis"
122+
TextWrapping="NoWrap" />
117123
</Grid>
118124
</DataTemplate>
119125
</ListView.ItemTemplate>
120126
</ListView>
121127

122128
<!-- Notes list footer panel -->
123129
<StackPanel Grid.Row="1" Orientation="Horizontal">
124-
<Button Style="{StaticResource CustomButtonStyle}">
130+
<!--<Button Style="{StaticResource CustomButtonStyle}">
125131
<Image Source="ms-appx:///Assets/NewNote.png" />
126-
</Button>
132+
</Button>-->
127133
</StackPanel>
128134
</Grid>
129135

@@ -150,27 +156,35 @@
150156
</Grid.ColumnDefinitions>
151157

152158
<StackPanel Orientation="Horizontal">
153-
<Button Style="{StaticResource CustomButtonStyle}" Visibility="{x:Bind ViewModel.IsPaneOpen, Converter={StaticResource InverseBoolToVisibilityConverter}, Mode=OneWay}">
159+
<!--<Button Style="{StaticResource CustomButtonStyle}" Visibility="{x:Bind ViewModel.IsPaneOpen, Converter={StaticResource InverseBoolToVisibilityConverter}, Mode=OneWay}">
154160
<Image Source="ms-appx:///Assets/NewNote.png" />
155161
</Button>
156162
<Button Style="{StaticResource CustomButtonStyle}">
157163
<Image Source="ms-appx:///Assets/Undo.png" />
158164
</Button>
159165
<Button Style="{StaticResource CustomButtonStyle}">
160166
<Image Source="ms-appx:///Assets/Redo.png" />
161-
</Button>
167+
</Button>-->
162168
</StackPanel>
163169

164170
<!-- Sync indicator -->
165171
<Grid Grid.Column="2">
166-
<TextBlock
167-
VerticalAlignment="Bottom"
168-
Text="Sign in to sync your notes"
169-
Visibility="{x:Bind ViewModel.IsSignedIn, Converter={StaticResource InverseBoolToVisibilityConverter}, Mode=OneWay}" />
170-
<TextBlock
171-
VerticalAlignment="Bottom"
172-
Text="Synced, Date, Time"
173-
Visibility="{x:Bind ViewModel.IsSignedIn, Mode=OneWay}" />
172+
<controls:SwitchPresenter Value="{x:Bind ViewModel.IsSignedIn, Mode=OneWay}">
173+
<controls:Case IsDefault="True">
174+
<TextBlock
175+
VerticalAlignment="Bottom"
176+
Text="Sign in to sync your notes" />
177+
</controls:Case>
178+
<controls:Case>
179+
<controls:Case.Value>
180+
<x:Boolean>True</x:Boolean>
181+
</controls:Case.Value>
182+
<TextBlock VerticalAlignment="Bottom">
183+
<Run Text="Synced, " />
184+
<Run Text="{x:Bind ViewModel.LastSync.Value.ToShortTimeString(), Mode=OneWay}" />
185+
</TextBlock>
186+
</controls:Case>
187+
</controls:SwitchPresenter>
174188
</Grid>
175189
</Grid>
176190
</Grid>

ContosoNotes/Views/MainViewModel.cs

+71-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
using CommunityToolkit.Net.Authentication;
2+
using CommunityToolkit.Net.Graph.Extensions;
23
using ContosoNotes.Models;
34
using Microsoft.Toolkit.Mvvm.ComponentModel;
45
using Microsoft.Toolkit.Mvvm.Input;
6+
using Microsoft.Toolkit.Uwp.UI;
57
using System;
68
using System.Collections.ObjectModel;
9+
using System.ComponentModel;
710
using System.Threading;
11+
using Windows.System;
812

913
namespace ContosoNotes.Views
1014
{
1115
public class MainViewModel : ObservableObject
1216
{
1317
private static SemaphoreSlim _mutex = new SemaphoreSlim(1);
1418

19+
public RelayCommand LaunchMicrosoftTodoCommand { get; }
1520
public RelayCommand TogglePaneCommand { get; }
1621
public RelayCommand SaveCommand { get; }
1722

@@ -45,19 +50,32 @@ public NotePageModel CurrentNotePage
4550
set => SetProperty(ref _currentNotePage, value);
4651
}
4752

53+
private DateTime? _lastSync;
54+
public DateTime? LastSync
55+
{
56+
get => _lastSync;
57+
set => SetProperty(ref _lastSync, value);
58+
}
59+
4860
private StorageManager _storageManager;
61+
private DispatcherQueue _dispatcherQueue;
62+
private DispatcherQueueTimer _timer;
4963

5064
public MainViewModel()
5165
{
66+
LaunchMicrosoftTodoCommand = new(LaunchMicrosoftTodo);
5267
TogglePaneCommand = new(TogglePane);
5368
SaveCommand = new(Save);
5469
DeleteTaskCommand = new(DeleteTask);
5570

71+
_currentNotePage = null;
5672
_isSignedIn = ProviderManager.Instance.GlobalProvider?.State == ProviderState.SignedIn;
57-
_isPaneOpen = true;
73+
_isPaneOpen = false;
74+
_lastSync = null;
5875
_notesList = null;
59-
_currentNotePage = null;
6076
_storageManager = new StorageManager();
77+
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
78+
_timer = _dispatcherQueue.CreateTimer();
6179

6280
KeywordDetector.Instance.RegisterKeyword("todo:");
6381
KeywordDetector.Instance.KeywordDetected += OnKeywordDetected;
@@ -68,6 +86,32 @@ public MainViewModel()
6886
ProviderManager.Instance.ProviderUpdated += OnProviderUpdated;
6987
}
7088

89+
private async void LaunchMicrosoftTodo()
90+
{
91+
string taskListId = string.Empty;
92+
93+
var provider = ProviderManager.Instance.GlobalProvider;
94+
if (provider != null && provider.State == ProviderState.SignedIn)
95+
{
96+
var graph = ProviderManager.Instance.GlobalProvider.Graph();
97+
98+
try
99+
{
100+
var existingLists = await graph.Me.Todo.Lists.Request().Filter("displayName eq 'ContosoNotes'").GetAsync();
101+
if (existingLists.Count > 0)
102+
{
103+
taskListId = existingLists[0].Id;
104+
}
105+
}
106+
catch
107+
{
108+
}
109+
}
110+
111+
var uri = new Uri("https://to-do.live.com/tasks/" + taskListId);
112+
await Windows.System.Launcher.LaunchUriAsync(uri);
113+
}
114+
71115
private void TogglePane()
72116
{
73117
IsPaneOpen = !IsPaneOpen;
@@ -146,13 +190,32 @@ public async void Load()
146190
NotePageTitle = CurrentNotePage.PageTitle,
147191
});
148192
}
193+
194+
InitSaveTimer();
149195
}
150196
finally
151197
{
152198
_mutex.Release();
153199
}
154200
}
155201

202+
private void InitSaveTimer()
203+
{
204+
if (!_timer.IsRunning)
205+
{
206+
_timer.Tick += OnTimerTick;
207+
_timer.Interval = TimeSpan.FromSeconds(10);
208+
_timer.IsRepeating = true;
209+
210+
_timer.Start();
211+
}
212+
}
213+
214+
private void OnTimerTick(DispatcherQueueTimer timer, object e)
215+
{
216+
Save();
217+
}
218+
156219
private async void Save()
157220
{
158221
foreach (var item in _notesList.Items)
@@ -169,6 +232,8 @@ private async void Save()
169232

170233
// Update the NotesList
171234
await _storageManager.SaveNotesListAsync(_notesList);
235+
236+
LastSync = DateTime.Now;
172237
}
173238

174239
private void OnKeywordDetected(object sender, KeywordDetectedEventArgs e)
@@ -223,8 +288,6 @@ private void DeleteTask(TaskNoteItemModel task)
223288
{
224289
var taskIndex = CurrentNotePage.NoteItems.IndexOf(task);
225290

226-
// TODO: Do we need to delete the task in the Graph here as well?
227-
228291
CurrentNotePage.NoteItems.RemoveAt(taskIndex);
229292

230293
// Check if we see a text note before us and after to merge
@@ -236,6 +299,10 @@ private void DeleteTask(TaskNoteItemModel task)
236299

237300
CurrentNotePage.NoteItems.RemoveAt(taskIndex);
238301
}
302+
303+
304+
// TODO: Do we need to delete the task in the Graph here as well?
305+
task.Delete();
239306
}
240307
}
241308
}

0 commit comments

Comments
 (0)