-
Notifications
You must be signed in to change notification settings - Fork 451
/
AppImageSet.cs
208 lines (178 loc) · 6.47 KB
/
AppImageSet.cs
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
namespace UniversalDemo.ViewModel
{
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
/// <summary>
/// The view model for the set of images in the user's Dropbox.
/// </summary>
public class AppImageSet : ViewModelBase
{
/// <summary>
/// Initializes a new instance of the <see cref="AppImageSet"/> class.
/// </summary>
public AppImageSet()
{
this.App.DropboxClientChanged += this.AppDropboxClientChanged;
this.Images = new ObservableCollection<AppImage>();
var task = this.UpdateImageSet();
}
/// <summary>
/// Gets the images.
/// </summary>
public ObservableCollection<AppImage> Images { get; private set; }
/// <summary>
/// Gets the current image.
/// </summary>
public AppImage CurrentImage { get; private set; }
/// <summary>
/// Gets the next image.
/// </summary>
public AppImage NextImage { get; private set; }
/// <summary>
/// Gets the previous image.
/// </summary>
public AppImage PreviousImage { get; private set; }
/// <summary>
/// Moves to the next image.
/// </summary>
public void MoveToNextImage()
{
this.DoChangeImage(1);
}
/// <summary>
/// Moves to the previous image.
/// </summary>
public void MoveToPreviousImage()
{
this.DoChangeImage(-1);
}
/// <summary>
/// Updates the image set.
/// </summary>
/// <remarks>
/// This fetches the list of files from Dropbox and, for each file that is an image
/// ensures that it is in the <see cref="Images"/> property. This method contains
/// logic to handle removing and updating files that have been deleted or updated
/// respectively.
/// </remarks>
/// <returns>An asynchronous task.</returns>
public async Task UpdateImageSet()
{
var initiallyEmpty = this.Images.Count == 0;
var client = this.App.DropboxClient;
if (client == null)
{
return;
}
var list = await client.Files.ListFolderAsync(string.Empty);
var previous = this.Images.Select(i => i.Name).ToList();
foreach (var entry in list.Entries.Where(e => e.IsFile))
{
var ext = Path.GetExtension(entry.Name).ToLowerInvariant();
if (!IsImageExtension(ext))
{
continue;
}
var rev = entry.AsFile.Rev;
var existing = this.Images.FirstOrDefault(i => i.Name == entry.Name);
if (existing == null)
{
var image = new AppImage(entry.Name, rev);
this.Images.Add(image);
}
else if (existing.Rev != entry.AsFile.Rev)
{
existing.UpdateRev(rev);
}
previous.Remove(entry.Name);
}
if (initiallyEmpty && this.Images.Count > 0)
{
this.DoChangeImage(0);
}
else if (previous.Count > 0)
{
foreach (var name in previous)
{
var existing = this.Images.FirstOrDefault(i => i.Name == name);
if (existing != null)
{
this.Images.Remove(existing);
}
}
this.DoChangeImage(0);
}
}
/// <summary>
/// Determines whether the specified extension is an image file extension.
/// </summary>
/// <param name="ext">The extension to check.</param>
/// <returns><c>true</c> if <paramref name="ext"/> is the extension for an image file format;
/// <c>false</c> otherwise.</returns>
private static bool IsImageExtension(string ext)
{
return ext == ".jpg" || ext == ".png" || ext == ".gif" || ext == ".jpeg";
}
/// <summary>
/// Handles the event raised when <see cref="App.DropboxClient"/> changes.
/// </summary>
/// <remarks>If the client is <c>null</c>, then this clears all data.</remarks>
/// <param name="sender">The sender.</param>
/// <param name="args">The <see cref="EventArgs"/> instance containing the event data.</param>
private void AppDropboxClientChanged(object sender, EventArgs args)
{
if (this.App.DropboxClient == null)
{
this.CurrentImage = null;
this.PreviousImage = null;
this.NextImage = null;
this.Images.Clear();
this.NotifyPropertyChanged();
}
else
{
var t = this.UpdateImageSet();
}
}
/// <summary>
/// Changes the currently selected image, or if no image is currently selected,
/// selects the first.
/// </summary>
/// <param name="increment">The amount to change the current index by.</param>
private void DoChangeImage(int increment)
{
int index = 0;
if (this.CurrentImage == null)
{
if (this.Images.Count == 0)
{
return;
}
}
else
{
index = this.Images.IndexOf(this.CurrentImage);
if (index == -1)
{
index = 0;
}
index = (index + this.Images.Count + increment) % this.Images.Count;
}
this.CurrentImage = this.Images[index];
this.NotifyPropertyChanged("CurrentImage");
this.PreviousImage = this.Images[(index - 1 + this.Images.Count) % this.Images.Count];
this.NotifyPropertyChanged("PreviousImage");
this.NextImage = this.Images[(index + 1) % this.Images.Count];
this.NotifyPropertyChanged("NextImage");
var task = this.InvokeAsync(async () =>
{
await this.CurrentImage.Update();
await this.NextImage.Update();
await this.PreviousImage.Update();
});
}
}
}