Skip to content

Commit ff2786e

Browse files
committed
Added task syncing with todo
1 parent 8a52990 commit ff2786e

File tree

3 files changed

+152
-69
lines changed

3 files changed

+152
-69
lines changed

ContosoNotes/Models/TaskNoteItemModel.cs

Lines changed: 141 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2,115 +2,196 @@
22
using CommunityToolkit.Net.Graph.Extensions;
33
using ContosoNotes.Common;
44
using Microsoft.Graph;
5+
using Microsoft.Toolkit.Uwp.UI;
56
using Newtonsoft.Json;
6-
using System.Threading.Tasks;
7+
using System;
8+
using System.ComponentModel;
9+
using System.Threading;
10+
using Windows.System;
711

812
namespace ContosoNotes.Models
913
{
1014
public class TaskNoteItemModel : NoteItemModel
1115
{
12-
public bool IsCompleted { get; protected set; }
16+
private static SemaphoreSlim _mutex = new SemaphoreSlim(1);
1317

1418
public string TodoTaskId { get; set; }
1519

1620
public string TodoTaskListId { get; set; }
1721

22+
private bool _isCompleted;
23+
public bool IsCompleted
24+
{
25+
get => _isCompleted;
26+
set => SetProperty(ref _isCompleted, value);
27+
}
28+
1829
[JsonIgnore]
1930
public TodoTask TodoTask { get; protected set; }
2031

2132
[JsonIgnore]
2233
public LoadingState LoadingState { get; protected set; }
2334

24-
public TaskNoteItemModel(string text = "") : base(text)
35+
private DispatcherQueueTimer _timer;
36+
37+
public TaskNoteItemModel()
2538
{
2639
LoadingState = LoadingState.Unloaded;
40+
_timer = DispatcherQueue.GetForCurrentThread().CreateTimer();
41+
42+
Load();
2743
}
2844

29-
protected async void Load(bool force = false)
45+
public TaskNoteItemModel(string text = null) : base(text)
3046
{
31-
if (LoadingState == LoadingState.Loading)
32-
{
33-
return;
34-
}
35-
if (LoadingState == LoadingState.Loaded && !force)
47+
LoadingState = LoadingState.Unloaded;
48+
_timer = DispatcherQueue.GetForCurrentThread().CreateTimer();
49+
50+
Load();
51+
}
52+
53+
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
54+
{
55+
switch (e.PropertyName)
3656
{
37-
return;
57+
case nameof(IsCompleted):
58+
case nameof(Text):
59+
_timer.Debounce(() => Save(), TimeSpan.FromSeconds(3));
60+
break;
3861
}
3962

40-
LoadingState = LoadingState.Loading;
63+
base.OnPropertyChanged(e);
64+
}
4165

42-
if (TodoTaskId == null || TodoTaskListId == null)
43-
{
44-
TodoTask = null;
45-
IsCompleted = false;
46-
}
47-
else
66+
protected async void Load(bool force = false)
67+
{
68+
await _mutex.WaitAsync();
69+
70+
try
4871
{
49-
var provider = ProviderManager.Instance.GlobalProvider;
50-
if (provider != null && provider.State == ProviderState.SignedIn)
72+
if (LoadingState == LoadingState.Loading)
5173
{
52-
var graph = ProviderManager.Instance.GlobalProvider.Graph();
74+
return;
75+
}
76+
if (LoadingState == LoadingState.Loaded && !force)
77+
{
78+
return;
79+
}
5380

54-
try
55-
{
56-
// Retrieve the task.
57-
TodoTask = await graph.Me.Todo.Lists[TodoTaskListId].Tasks[TodoTaskId].Request().GetAsync();
58-
IsCompleted = TodoTask.Status == Microsoft.Graph.TaskStatus.Completed;
59-
}
60-
catch
81+
LoadingState = LoadingState.Loading;
82+
83+
if (TodoTaskId == null || TodoTaskListId == null)
84+
{
85+
TodoTask = null;
86+
IsCompleted = false;
87+
}
88+
else
89+
{
90+
var provider = ProviderManager.Instance.GlobalProvider;
91+
if (provider != null && provider.State == ProviderState.SignedIn)
6192
{
62-
// Task must not exist.
63-
TodoTask = null;
64-
IsCompleted = false;
93+
var graph = ProviderManager.Instance.GlobalProvider.Graph();
94+
95+
try
96+
{
97+
// Retrieve the task.
98+
TodoTask = await graph.Me.Todo.Lists[TodoTaskListId].Tasks[TodoTaskId].Request().GetAsync();
99+
IsCompleted = TodoTask.Status == Microsoft.Graph.TaskStatus.Completed;
100+
}
101+
catch
102+
{
103+
// Task must not exist.
104+
TodoTask = null;
105+
IsCompleted = false;
106+
}
65107
}
66108
}
67-
}
68109

69-
LoadingState = LoadingState.Loaded;
110+
LoadingState = LoadingState.Loaded;
111+
}
112+
catch
113+
{
114+
LoadingState = LoadingState.Unloaded;
115+
}
116+
finally
117+
{
118+
_mutex.Release();
119+
}
70120
}
71121

72-
public async Task Save()
122+
protected async void Save()
73123
{
74-
var provider = ProviderManager.Instance.GlobalProvider;
75-
if (provider != null && provider.State == ProviderState.SignedIn)
124+
await _mutex.WaitAsync();
125+
126+
try
76127
{
77-
var graph = ProviderManager.Instance.GlobalProvider.Graph();
78-
79-
if (TodoTaskId == null)
128+
var provider = ProviderManager.Instance.GlobalProvider;
129+
if (provider != null && provider.State == ProviderState.SignedIn)
80130
{
81-
// Create a new task.
82-
TodoTask newTask = await graph.Me.Todo.Lists[TodoTaskListId].Tasks.Request().AddAsync(new TodoTask()
131+
var graph = ProviderManager.Instance.GlobalProvider.Graph();
132+
133+
if (TodoTaskListId == null)
83134
{
84-
Body = new ItemBody()
135+
try
136+
{
137+
var existingLists = await graph.Me.Todo.Lists.Request().Filter("displayName eq 'ContosoNotes'").GetAsync();
138+
if (existingLists.Count == 0)
139+
{
140+
TodoTaskList newTaskList = await graph.Me.Todo.Lists.Request().AddAsync(new TodoTaskList()
141+
{
142+
ODataType = null, // Magic, don't remove
143+
DisplayName = "ContosoNotes"
144+
});
145+
146+
TodoTaskListId = newTaskList.Id;
147+
}
148+
else
149+
{
150+
TodoTaskListId = existingLists[0].Id;
151+
}
152+
}
153+
catch
85154
{
86-
Content = Text
87-
},
88-
});
155+
// Unable to retrieve or create the TodoTaskList. Bail.
156+
return;
157+
}
158+
}
89159

90-
TodoTaskId = newTask.Id;
91-
}
92-
else
93-
{
94-
// Update the existing task.
95-
var taskForUpdate = new TodoTask()
160+
if (TodoTaskId == null)
96161
{
97-
Id = TodoTaskId,
98-
Body = new ItemBody()
162+
// Create a new task.
163+
TodoTask newTask = await graph.Me.Todo.Lists[TodoTaskListId].Tasks.Request().AddAsync(new TodoTask()
99164
{
100-
Content = Text,
101-
},
102-
};
165+
ODataType = null, // Magic, don't remove
166+
Title = Text,
167+
});
103168

104-
if (IsCompleted)
169+
TodoTask = newTask;
170+
TodoTaskId = newTask.Id;
171+
}
172+
else
105173
{
106-
taskForUpdate.Status = Microsoft.Graph.TaskStatus.Completed;
174+
// Update the existing task.
175+
var taskForUpdate = new TodoTask()
176+
{
177+
Id = TodoTaskId,
178+
Body = new ItemBody()
179+
{
180+
Content = Text,
181+
},
182+
Status = IsCompleted ? TaskStatus.Completed : TaskStatus.NotStarted
183+
};
184+
185+
TodoTask = await graph.Me.Todo.Lists[TodoTaskListId].Tasks[TodoTaskId].Request().UpdateAsync(taskForUpdate);
107186
}
108187

109-
TodoTask = await graph.Me.Todo.Lists[TodoTaskListId].Tasks[TodoTaskId].Request().UpdateAsync(taskForUpdate);
110-
111-
IsCompleted = TodoTask.Status == Microsoft.Graph.TaskStatus.Completed;
188+
IsCompleted = TodoTask.Status == TaskStatus.Completed;
112189
}
113190
}
191+
finally
192+
{
193+
_mutex.Release();
194+
}
114195
}
115196
}
116197
}

ContosoNotes/UI/TaskNoteItemView.xaml.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,17 @@ public TaskNoteItemView()
4848

4949
private void TaskNoteItemView_GettingFocus(UIElement sender, GettingFocusEventArgs args)
5050
{
51-
if (args.OldFocusedElement != ItemText)
51+
try
5252
{
53-
args.NewFocusedElement = ItemText;
53+
if (args.OldFocusedElement != ItemText)
54+
{
55+
args.NewFocusedElement = ItemText;
56+
}
57+
}
58+
catch
59+
{
60+
// There is some problem here causing an Arguement exception to be thrown when settings the newly focused element.
61+
// Need to investigate.
5462
}
5563
}
5664

ContosoNotes/Views/MainViewModel.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
11
using CommunityToolkit.Net.Authentication;
2-
using CommunityToolkit.Uwp.Graph.Helpers.RoamingSettings;
3-
using ContosoNotes.Common;
42
using ContosoNotes.Models;
53
using Microsoft.Toolkit.Mvvm.ComponentModel;
64
using Microsoft.Toolkit.Mvvm.Input;
7-
using Microsoft.Toolkit.Uwp.Helpers;
8-
using System.Collections.Generic;
5+
using System;
96
using System.Collections.ObjectModel;
107
using System.Threading;
11-
using System.Threading.Tasks;
12-
using Windows.System;
13-
using Windows.UI.Xaml.Input;
148

159
namespace ContosoNotes.Views
1610
{

0 commit comments

Comments
 (0)