Merge lp:~rockstar/ubuntuone-ios-music/albumart-loading into lp:~ubuntuone-ios-client-team/ubuntuone-ios-music/moriarty
- albumart-loading
- Merge into moriarty
Proposed by
Paul Hummer
Status: | Merged |
---|---|
Merge reported by: | Paul Hummer |
Merged at revision: | not available |
Proposed branch: | lp:~rockstar/ubuntuone-ios-music/albumart-loading |
Merge into: | lp:~ubuntuone-ios-client-team/ubuntuone-ios-music/moriarty |
Prerequisite: | lp:~rockstar/ubuntuone-ios-music/dial-down |
Diff against target: |
705 lines (+226/-30) 19 files modified
Music/AppDelegate.h (+4/-0) Music/AppDelegate.m (+18/-2) Music/Categories/NSString+Extras.m (+5/-3) Music/Models/Album.h (+2/-2) Music/Models/Album.m (+12/-3) Music/Models/Artist.h (+1/-1) Music/Models/Artist.m (+9/-1) Music/Models/Song.h (+0/-1) Music/Models/Song.m (+17/-1) Music/Models/UOModel.h (+8/-0) Music/Models/UOModel.m (+31/-0) Music/Storyboard_iPhone.storyboard (+64/-11) Music/UOMusic.xcdatamodeld/UOMusic.xcdatamodel/contents (+4/-4) Music/Utilities/UOWebServiceController.m (+2/-0) Music/View Controllers/AlbumViewController.m (+8/-0) Music/View Controllers/ArtistViewController.m (+8/-0) Music/View Controllers/Table Cells/AlbumCell.m (+11/-0) Music/View Controllers/Table Cells/ArtistCell.m (+10/-0) Music/View Controllers/Table Cells/SongCell.m (+12/-1) |
To merge this branch: | bzr merge lp:~rockstar/ubuntuone-ios-music/albumart-loading |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michał Karnicki (community) | Approve | ||
Review via email: mp+141685@code.launchpad.net |
Commit message
Description of the change
This branch adds the album art fetching and display to the views in the places
they are prescribed. I think they're a little awkward now, but it's not
polishing time.
To post a comment you must log in.
Revision history for this message
Michał Karnicki (karni) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'Music/AppDelegate.h' |
2 | --- Music/AppDelegate.h 2013-01-02 23:52:23 +0000 |
3 | +++ Music/AppDelegate.h 2013-01-02 23:52:23 +0000 |
4 | @@ -16,8 +16,12 @@ |
5 | @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; |
6 | @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; |
7 | |
8 | +@property (nonatomic, retain) NSOperationQueue *queue; |
9 | + |
10 | - (void)saveContext; |
11 | - (NSURL *)applicationDocumentsDirectory; |
12 | +- (NSURL *)applicationCachesDirectory; |
13 | +- (NSURL *)albumArtDirectory; |
14 | |
15 | + (AppDelegate *)delegate; |
16 | |
17 | |
18 | === modified file 'Music/AppDelegate.m' |
19 | --- Music/AppDelegate.m 2013-01-02 23:52:23 +0000 |
20 | +++ Music/AppDelegate.m 2013-01-02 23:52:23 +0000 |
21 | @@ -38,6 +38,7 @@ |
22 | |
23 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { |
24 | |
25 | + self.queue = [[NSOperationQueue alloc] init]; |
26 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; |
27 | |
28 | /* rockstar - WTF? This should just work with the target settings. */ |
29 | @@ -172,11 +173,26 @@ |
30 | #pragma mark - Application's Documents directory |
31 | |
32 | // Returns the URL to the application's Documents directory. |
33 | -- (NSURL *)applicationDocumentsDirectory |
34 | -{ |
35 | +- (NSURL *)applicationDocumentsDirectory { |
36 | return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; |
37 | } |
38 | |
39 | +- (NSURL *)applicationCachesDirectory { |
40 | + return [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject]; |
41 | +} |
42 | + |
43 | +- (NSURL *)albumArtDirectory { |
44 | + NSURL *path = [[self applicationCachesDirectory] URLByAppendingPathComponent:@"albumArt"]; |
45 | + if (![[NSFileManager defaultManager] fileExistsAtPath:[path path]]) { |
46 | + NSError *error; |
47 | + [[NSFileManager defaultManager] createDirectoryAtPath:[path path] withIntermediateDirectories:YES attributes:nil error:&error]; |
48 | + if (error) { |
49 | + abort(); |
50 | + } |
51 | + } |
52 | + return path; |
53 | +} |
54 | + |
55 | - (void)checkAuthentication { |
56 | if (![[UOAuthManager sharedAuthManager] hasCredentials]) { |
57 | UITabBarController *rootViewController = (UITabBarController *)self.window.rootViewController; |
58 | |
59 | === modified file 'Music/Categories/NSString+Extras.m' |
60 | --- Music/Categories/NSString+Extras.m 2013-01-02 23:52:23 +0000 |
61 | +++ Music/Categories/NSString+Extras.m 2013-01-02 23:52:23 +0000 |
62 | @@ -45,9 +45,11 @@ |
63 | return [[self dearticlizedString] substringToIndex:1]; |
64 | } |
65 | |
66 | -- (NSString *)urlParameterEncodedString; |
67 | -{ |
68 | - NSString *result = (__bridge id)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)self, NULL, (__bridge CFStringRef)@":/?#[]@!$&’()*+,;=", kCFStringEncodingUTF8); |
69 | +- (NSString *)urlParameterEncodedString { |
70 | + CFStringRef resultRef = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)self, NULL, (__bridge CFStringRef)@":/?#[]@!$&’()*+,;=", kCFStringEncodingUTF8); |
71 | + NSString *result = [(__bridge id)resultRef copy]; |
72 | + CFRelease(resultRef); |
73 | + |
74 | return result; |
75 | } |
76 | |
77 | |
78 | === modified file 'Music/Models/Album.h' |
79 | --- Music/Models/Album.h 2013-01-02 23:52:23 +0000 |
80 | +++ Music/Models/Album.h 2013-01-02 23:52:23 +0000 |
81 | @@ -16,8 +16,7 @@ |
82 | @property (nonatomic, retain) NSString *albumId; |
83 | @property (nonatomic, retain) NSString *title; |
84 | @property (nonatomic, retain) NSString *url; |
85 | -@property (nonatomic, retain) NSString *artUrl; |
86 | -@property (nonatomic, retain) NSString *art; |
87 | +@property (nonatomic, retain) NSString *artHash; |
88 | |
89 | @property (nonatomic, retain, readonly) NSString *dearticlizedTitle; |
90 | @property (nonatomic, retain, readonly) NSString *index; |
91 | @@ -26,4 +25,5 @@ |
92 | @property (nonatomic, retain, readonly) Artist *artist; |
93 | |
94 | @property (nonatomic, retain) NSSet *songs; |
95 | + |
96 | @end |
97 | |
98 | === modified file 'Music/Models/Album.m' |
99 | --- Music/Models/Album.m 2013-01-02 23:52:23 +0000 |
100 | +++ Music/Models/Album.m 2013-01-02 23:52:23 +0000 |
101 | @@ -11,13 +11,13 @@ |
102 | #import <RestKit/CoreData.h> |
103 | #import "Artist.h" |
104 | #import "NSString+Extras.h" |
105 | +#import "AppDelegate.h" |
106 | |
107 | @implementation Album |
108 | @dynamic albumId; |
109 | @dynamic title; |
110 | @dynamic url; |
111 | -@dynamic art; |
112 | -@dynamic artUrl; |
113 | +@dynamic artHash; |
114 | @dynamic dearticlizedTitle; |
115 | |
116 | @synthesize index; |
117 | @@ -27,6 +27,8 @@ |
118 | |
119 | @dynamic songs; |
120 | |
121 | +#pragma mark - UOModel methods |
122 | + |
123 | + (RKEntityMapping *)objectMapping { |
124 | RKObjectManager *manager = [RKObjectManager sharedManager]; |
125 | |
126 | @@ -35,7 +37,7 @@ |
127 | [mapping addAttributeMappingsFromDictionary:@{ |
128 | @"id": @"albumId", |
129 | @"album_url": @"url", |
130 | - @"cover_art": @"art", |
131 | + @"cover_art": @"artHash", |
132 | @"album_art_url": @"artUrl", |
133 | @"title": @"title", |
134 | @"artist_id": @"artistId" |
135 | @@ -48,6 +50,12 @@ |
136 | return @"response.albums"; |
137 | } |
138 | |
139 | +- (NSString *)artPath { |
140 | + return [[[[AppDelegate delegate] albumArtDirectory] URLByAppendingPathComponent:[NSString stringWithFormat:@"album-%@.jpg", self.albumId]] path]; |
141 | +} |
142 | + |
143 | +#pragma mark - Model specific methods |
144 | + |
145 | - (void)setTitle:(NSString *)title { |
146 | [self setPrimitiveValue:title forKey:@"title"]; |
147 | [self setValue:[[title dearticlizedString] uppercaseString] forKey:@"dearticlizedTitle"]; |
148 | @@ -82,4 +90,5 @@ |
149 | return _index; |
150 | } |
151 | |
152 | + |
153 | @end |
154 | |
155 | === modified file 'Music/Models/Artist.h' |
156 | --- Music/Models/Artist.h 2013-01-02 23:52:23 +0000 |
157 | +++ Music/Models/Artist.h 2013-01-02 23:52:23 +0000 |
158 | @@ -15,10 +15,10 @@ |
159 | @property (nonatomic, retain) NSString *artistId; |
160 | @property (nonatomic, retain) NSString *name; |
161 | @property (nonatomic, retain) NSString *url; |
162 | -@property (nonatomic, retain) NSString *artUrl; |
163 | |
164 | @property (nonatomic, retain, readonly) NSString *dearticlizedName; |
165 | @property (nonatomic, retain, readonly) NSString *index; |
166 | |
167 | @property (nonatomic, retain) NSSet *albums; |
168 | + |
169 | @end |
170 | |
171 | === modified file 'Music/Models/Artist.m' |
172 | --- Music/Models/Artist.m 2013-01-02 23:52:23 +0000 |
173 | +++ Music/Models/Artist.m 2013-01-02 23:52:23 +0000 |
174 | @@ -9,17 +9,19 @@ |
175 | #import "Artist.h" |
176 | #import <RestKit/RestKit.h> |
177 | #import "NSString+Extras.h" |
178 | +#import "AppDelegate.h" |
179 | |
180 | @implementation Artist |
181 | @dynamic artistId; |
182 | @dynamic name; |
183 | @dynamic url; |
184 | -@dynamic artUrl; |
185 | @dynamic albums; |
186 | @dynamic dearticlizedName; |
187 | |
188 | @synthesize index; |
189 | |
190 | +#pragma mark - UOModel methods |
191 | + |
192 | + (RKEntityMapping *)objectMapping { |
193 | RKObjectManager *manager = [RKObjectManager sharedManager]; |
194 | |
195 | @@ -38,6 +40,12 @@ |
196 | return @"response.artists"; |
197 | } |
198 | |
199 | +- (NSString *)artPath { |
200 | + return [[[[AppDelegate delegate] albumArtDirectory] URLByAppendingPathComponent:[NSString stringWithFormat:@"artist-%@.jpg", self.artistId]] path]; |
201 | +} |
202 | + |
203 | +#pragma mark - Model specific methods |
204 | + |
205 | - (void)setName:(NSString *)name { |
206 | [self setPrimitiveValue:name forKey:@"name"]; |
207 | [self setValue:[[name dearticlizedString] uppercaseString] forKey:@"dearticlizedName"]; |
208 | |
209 | === modified file 'Music/Models/Song.h' |
210 | --- Music/Models/Song.h 2013-01-02 23:52:23 +0000 |
211 | +++ Music/Models/Song.h 2013-01-02 23:52:23 +0000 |
212 | @@ -15,7 +15,6 @@ |
213 | @interface Song : UOModel |
214 | |
215 | @property (nonatomic, retain) NSString *url; |
216 | -@property (nonatomic, retain) NSString *artUrl; |
217 | @property (nonatomic, retain) NSString *suffix; |
218 | @property (nonatomic, retain) NSString *track; |
219 | @property (nonatomic, retain) NSString *title; |
220 | |
221 | === modified file 'Music/Models/Song.m' |
222 | --- Music/Models/Song.m 2013-01-02 23:52:23 +0000 |
223 | +++ Music/Models/Song.m 2013-01-02 23:52:23 +0000 |
224 | @@ -11,11 +11,11 @@ |
225 | #import "Artist.h" |
226 | #import "Album.h" |
227 | #import "NSString+Extras.h" |
228 | +#import "AppDelegate.h" |
229 | |
230 | @implementation Song |
231 | |
232 | @dynamic url; |
233 | -@dynamic artUrl; |
234 | @dynamic suffix; |
235 | @dynamic track; |
236 | @dynamic title; |
237 | @@ -32,11 +32,15 @@ |
238 | @dynamic dearticlizedTitle; |
239 | |
240 | @synthesize index; |
241 | +/* Override to fall through to album's artUrl */ |
242 | +@synthesize artUrl; |
243 | |
244 | @dynamic album; |
245 | @dynamic artist; |
246 | @dynamic albumArtist; |
247 | |
248 | +#pragma mark - UOModel methods |
249 | + |
250 | + (RKEntityMapping *)objectMapping { |
251 | RKObjectManager *manager = [RKObjectManager sharedManager]; |
252 | |
253 | @@ -44,7 +48,9 @@ |
254 | [mapping setIdentificationAttributes:@[@"songId"]]; |
255 | [mapping addAttributeMappingsFromDictionary:@{ |
256 | @"song_url": @"url", |
257 | + /* Disabled, since we want to fall through to album's art. |
258 | @"song_art_url": @"artUrl", |
259 | + */ |
260 | @"suffix": @"suffix", |
261 | @"track": @"track", |
262 | @"title": @"title", |
263 | @@ -69,6 +75,16 @@ |
264 | return @"response.songs"; |
265 | } |
266 | |
267 | +- (NSString *)artPath { |
268 | + return self.album.artPath; |
269 | +} |
270 | + |
271 | +#pragma mark - Model specific methods |
272 | + |
273 | +- (NSString *)artUrl { |
274 | + return self.album.artUrl; |
275 | +} |
276 | + |
277 | - (void)setTitle:(NSString *)_title { |
278 | [self setPrimitiveValue:_title forKey:@"title"]; |
279 | [self setValue:[[_title dearticlizedString] uppercaseString] forKey:@"dearticlizedTitle"]; |
280 | |
281 | === modified file 'Music/Models/UOModel.h' |
282 | --- Music/Models/UOModel.h 2013-01-02 23:52:23 +0000 |
283 | +++ Music/Models/UOModel.h 2013-01-02 23:52:23 +0000 |
284 | @@ -14,4 +14,12 @@ |
285 | + (void)registerMapping; |
286 | + (RKEntityMapping *)objectMapping; |
287 | + (NSString *)keyPath; |
288 | + |
289 | +/* Not used for playlist */ |
290 | +@property (nonatomic, retain) NSString *artUrl; |
291 | + |
292 | +/* Used for fetching art */ |
293 | +@property (nonatomic, readonly) UIImage *art; |
294 | +- (NSString *)artPath; |
295 | +- (void)fetchArt:(void (^)(UIImage *))completionBlock; |
296 | @end |
297 | |
298 | === modified file 'Music/Models/UOModel.m' |
299 | --- Music/Models/UOModel.m 2013-01-02 23:52:23 +0000 |
300 | +++ Music/Models/UOModel.m 2013-01-02 23:52:23 +0000 |
301 | @@ -8,9 +8,13 @@ |
302 | |
303 | #import "UOModel.h" |
304 | #import <RestKit/RestKit.h> |
305 | +#import "AppDelegate.h" |
306 | +#import "UOAuthManager.h" |
307 | |
308 | @implementation UOModel |
309 | |
310 | +@dynamic artUrl; |
311 | + |
312 | + (void)registerMapping { |
313 | RKObjectManager *manager = [RKObjectManager sharedManager]; |
314 | |
315 | @@ -32,4 +36,31 @@ |
316 | return @""; |
317 | } |
318 | |
319 | +- (UIImage *)art { |
320 | + NSString *path = [self artPath]; |
321 | + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { |
322 | + return nil; |
323 | + } |
324 | + return [UIImage imageWithContentsOfFile:path]; |
325 | +} |
326 | + |
327 | +- (void)fetchArt:(void (^)(UIImage *))completionBlock { |
328 | + NSOperationQueue *queue = [[AppDelegate delegate] queue]; |
329 | + NSString *path = [self artPath]; |
330 | + NSURLRequest *echo = [UOAuthManager oauthRequestForPath:self.artUrl]; |
331 | + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:self.artUrl]]; |
332 | + [request setHTTPMethod:@"GET"]; |
333 | + [request addValue:[echo valueForHTTPHeaderField:@"Authorization"] forHTTPHeaderField:@"Authorization"]; |
334 | + |
335 | + [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { |
336 | + UIImage *image = [UIImage imageWithData:data]; |
337 | + [UIImageJPEGRepresentation(image, 1) writeToFile:path atomically:YES]; |
338 | + completionBlock(image); |
339 | + }]; |
340 | +} |
341 | + |
342 | +- (NSString *)artPath { |
343 | + return nil; |
344 | +} |
345 | + |
346 | @end |
347 | |
348 | === modified file 'Music/Storyboard_iPhone.storyboard' |
349 | --- Music/Storyboard_iPhone.storyboard 2013-01-02 23:52:23 +0000 |
350 | +++ Music/Storyboard_iPhone.storyboard 2013-01-02 23:52:23 +0000 |
351 | @@ -36,7 +36,7 @@ |
352 | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
353 | <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
354 | <prototypes> |
355 | - <tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="Wy4-11-qhh" detailTextLabel="PUO-bG-eLt" style="IBUITableViewCellStyleSubtitle" id="TCk-Kb-c61" customClass="ArtistCell"> |
356 | + <tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="Wy4-11-qhh" detailTextLabel="PUO-bG-eLt" imageView="EvX-DO-a8s" style="IBUITableViewCellStyleSubtitle" id="TCk-Kb-c61" customClass="ArtistCell"> |
357 | <rect key="frame" x="0.0" y="22" width="320" height="44"/> |
358 | <autoresizingMask key="autoresizingMask"/> |
359 | <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> |
360 | @@ -44,19 +44,23 @@ |
361 | <autoresizingMask key="autoresizingMask"/> |
362 | <subviews> |
363 | <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Wy4-11-qhh"> |
364 | - <rect key="frame" x="10" y="2" width="38" height="22"/> |
365 | + <rect key="frame" x="53" y="2" width="38" height="22"/> |
366 | <autoresizingMask key="autoresizingMask"/> |
367 | <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> |
368 | <color key="textColor" cocoaTouchSystemColor="darkTextColor"/> |
369 | <color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/> |
370 | </label> |
371 | <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="PUO-bG-eLt"> |
372 | - <rect key="frame" x="10" y="24" width="47" height="18"/> |
373 | + <rect key="frame" x="53" y="24" width="47" height="18"/> |
374 | <autoresizingMask key="autoresizingMask"/> |
375 | <fontDescription key="fontDescription" type="system" pointSize="14"/> |
376 | <color key="textColor" red="0.50196078431372548" green="0.50196078431372548" blue="0.50196078431372548" alpha="1" colorSpace="calibratedRGB"/> |
377 | <color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/> |
378 | </label> |
379 | + <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" image="default-album-art-120.png" id="EvX-DO-a8s"> |
380 | + <rect key="frame" x="0.0" y="0.0" width="43" height="43"/> |
381 | + <autoresizingMask key="autoresizingMask"/> |
382 | + </imageView> |
383 | </subviews> |
384 | <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> |
385 | </view> |
386 | @@ -85,12 +89,32 @@ |
387 | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
388 | <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
389 | <prototypes> |
390 | - <tableViewCell contentMode="scaleToFill" selectionStyle="blue" indentationWidth="10" reuseIdentifier="Cell" id="Y5x-0G-rno" customClass="AlbumCell"> |
391 | + <tableViewCell contentMode="scaleToFill" selectionStyle="blue" indentationWidth="10" reuseIdentifier="Cell" textLabel="G72-IX-jh9" detailTextLabel="VIc-Rn-YXm" imageView="F2l-py-JAO" style="IBUITableViewCellStyleSubtitle" id="Y5x-0G-rno" customClass="AlbumCell"> |
392 | <rect key="frame" x="0.0" y="22" width="320" height="44"/> |
393 | <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> |
394 | <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> |
395 | <rect key="frame" x="0.0" y="0.0" width="320" height="43"/> |
396 | <autoresizingMask key="autoresizingMask"/> |
397 | + <subviews> |
398 | + <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="G72-IX-jh9"> |
399 | + <rect key="frame" x="53" y="2" width="38" height="22"/> |
400 | + <autoresizingMask key="autoresizingMask"/> |
401 | + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> |
402 | + <color key="textColor" cocoaTouchSystemColor="darkTextColor"/> |
403 | + <color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/> |
404 | + </label> |
405 | + <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="VIc-Rn-YXm"> |
406 | + <rect key="frame" x="53" y="24" width="47" height="18"/> |
407 | + <autoresizingMask key="autoresizingMask"/> |
408 | + <fontDescription key="fontDescription" type="system" pointSize="14"/> |
409 | + <color key="textColor" red="0.50196078431372548" green="0.50196078431372548" blue="0.50196078431372548" alpha="1" colorSpace="calibratedRGB"/> |
410 | + <color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/> |
411 | + </label> |
412 | + <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" image="default-album-art-120.png" id="F2l-py-JAO"> |
413 | + <rect key="frame" x="0.0" y="0.0" width="43" height="43"/> |
414 | + <autoresizingMask key="autoresizingMask"/> |
415 | + </imageView> |
416 | + </subviews> |
417 | <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> |
418 | </view> |
419 | <connections> |
420 | @@ -146,12 +170,32 @@ |
421 | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
422 | <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
423 | <prototypes> |
424 | - <tableViewCell contentMode="scaleToFill" selectionStyle="blue" indentationWidth="10" reuseIdentifier="Cell" id="vAU-q1-3Z9" customClass="SongCell"> |
425 | + <tableViewCell contentMode="scaleToFill" selectionStyle="blue" indentationWidth="10" reuseIdentifier="Cell" textLabel="0Be-Uu-e1M" detailTextLabel="cgX-vu-iNg" imageView="xX5-x4-y65" style="IBUITableViewCellStyleSubtitle" id="vAU-q1-3Z9" customClass="SongCell"> |
426 | <rect key="frame" x="0.0" y="22" width="320" height="44"/> |
427 | <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> |
428 | <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> |
429 | <rect key="frame" x="0.0" y="0.0" width="320" height="43"/> |
430 | <autoresizingMask key="autoresizingMask"/> |
431 | + <subviews> |
432 | + <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="0Be-Uu-e1M"> |
433 | + <rect key="frame" x="53" y="2" width="38" height="22"/> |
434 | + <autoresizingMask key="autoresizingMask"/> |
435 | + <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> |
436 | + <color key="textColor" cocoaTouchSystemColor="darkTextColor"/> |
437 | + <color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/> |
438 | + </label> |
439 | + <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="cgX-vu-iNg"> |
440 | + <rect key="frame" x="53" y="24" width="47" height="18"/> |
441 | + <autoresizingMask key="autoresizingMask"/> |
442 | + <fontDescription key="fontDescription" type="system" pointSize="14"/> |
443 | + <color key="textColor" red="0.50196078431372548" green="0.50196078431372548" blue="0.50196078431372548" alpha="1" colorSpace="calibratedRGB"/> |
444 | + <color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/> |
445 | + </label> |
446 | + <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" image="default-album-art-120.png" id="xX5-x4-y65"> |
447 | + <rect key="frame" x="0.0" y="0.0" width="43" height="43"/> |
448 | + <autoresizingMask key="autoresizingMask"/> |
449 | + </imageView> |
450 | + </subviews> |
451 | <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> |
452 | </view> |
453 | </tableViewCell> |
454 | @@ -218,7 +262,7 @@ |
455 | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
456 | <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
457 | <prototypes> |
458 | - <tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="lHq-bS-Zm9" detailTextLabel="03B-YT-E7s" style="IBUITableViewCellStyleSubtitle" id="5s2-Qn-BOB" customClass="AlbumCell"> |
459 | + <tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="lHq-bS-Zm9" detailTextLabel="03B-YT-E7s" imageView="apM-jL-xHe" style="IBUITableViewCellStyleSubtitle" id="5s2-Qn-BOB" customClass="AlbumCell"> |
460 | <rect key="frame" x="0.0" y="22" width="320" height="44"/> |
461 | <autoresizingMask key="autoresizingMask"/> |
462 | <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> |
463 | @@ -226,19 +270,23 @@ |
464 | <autoresizingMask key="autoresizingMask"/> |
465 | <subviews> |
466 | <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="lHq-bS-Zm9"> |
467 | - <rect key="frame" x="10" y="2" width="38" height="22"/> |
468 | + <rect key="frame" x="53" y="2" width="38" height="22"/> |
469 | <autoresizingMask key="autoresizingMask"/> |
470 | <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> |
471 | <color key="textColor" cocoaTouchSystemColor="darkTextColor"/> |
472 | <color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/> |
473 | </label> |
474 | <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="03B-YT-E7s"> |
475 | - <rect key="frame" x="10" y="24" width="47" height="18"/> |
476 | + <rect key="frame" x="53" y="24" width="47" height="18"/> |
477 | <autoresizingMask key="autoresizingMask"/> |
478 | <fontDescription key="fontDescription" type="system" pointSize="14"/> |
479 | <color key="textColor" red="0.50196078431372548" green="0.50196078431372548" blue="0.50196078431372548" alpha="1" colorSpace="calibratedRGB"/> |
480 | <color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/> |
481 | </label> |
482 | + <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" image="default-album-art-120.png" id="apM-jL-xHe"> |
483 | + <rect key="frame" x="0.0" y="0.0" width="43" height="43"/> |
484 | + <autoresizingMask key="autoresizingMask"/> |
485 | + </imageView> |
486 | </subviews> |
487 | <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> |
488 | </view> |
489 | @@ -263,7 +311,7 @@ |
490 | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
491 | <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
492 | <prototypes> |
493 | - <tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="OwY-7W-CUV" detailTextLabel="ORO-PT-T6b" style="IBUITableViewCellStyleSubtitle" id="jpK-Yt-5Y9" customClass="SongCell"> |
494 | + <tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="OwY-7W-CUV" detailTextLabel="ORO-PT-T6b" imageView="Ynd-vW-pQI" style="IBUITableViewCellStyleSubtitle" id="jpK-Yt-5Y9" customClass="SongCell"> |
495 | <rect key="frame" x="0.0" y="22" width="320" height="44"/> |
496 | <autoresizingMask key="autoresizingMask"/> |
497 | <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> |
498 | @@ -271,19 +319,23 @@ |
499 | <autoresizingMask key="autoresizingMask"/> |
500 | <subviews> |
501 | <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="OwY-7W-CUV"> |
502 | - <rect key="frame" x="10" y="2" width="38" height="22"/> |
503 | + <rect key="frame" x="53" y="2" width="38" height="22"/> |
504 | <autoresizingMask key="autoresizingMask"/> |
505 | <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/> |
506 | <color key="textColor" cocoaTouchSystemColor="darkTextColor"/> |
507 | <color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/> |
508 | </label> |
509 | <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ORO-PT-T6b"> |
510 | - <rect key="frame" x="10" y="24" width="47" height="18"/> |
511 | + <rect key="frame" x="53" y="24" width="47" height="18"/> |
512 | <autoresizingMask key="autoresizingMask"/> |
513 | <fontDescription key="fontDescription" type="system" pointSize="14"/> |
514 | <color key="textColor" red="0.50196078431372548" green="0.50196078431372548" blue="0.50196078431372548" alpha="1" colorSpace="calibratedRGB"/> |
515 | <color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/> |
516 | </label> |
517 | + <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" image="default-album-art-120.png" id="Ynd-vW-pQI"> |
518 | + <rect key="frame" x="0.0" y="0.0" width="43" height="43"/> |
519 | + <autoresizingMask key="autoresizingMask"/> |
520 | + </imageView> |
521 | </subviews> |
522 | <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> |
523 | </view> |
524 | @@ -559,6 +611,7 @@ |
525 | <resources> |
526 | <image name="albums.png" width="30" height="30"/> |
527 | <image name="artists.png" width="30" height="30"/> |
528 | + <image name="default-album-art-120.png" width="60" height="60"/> |
529 | <image name="playlists.png" width="30" height="30"/> |
530 | <image name="settings.png" width="30" height="30"/> |
531 | <image name="songs.png" width="30" height="30"/> |
532 | |
533 | === modified file 'Music/UOMusic.xcdatamodeld/UOMusic.xcdatamodel/contents' |
534 | --- Music/UOMusic.xcdatamodeld/UOMusic.xcdatamodel/contents 2013-01-02 23:52:23 +0000 |
535 | +++ Music/UOMusic.xcdatamodeld/UOMusic.xcdatamodel/contents 2013-01-02 23:52:23 +0000 |
536 | @@ -2,7 +2,7 @@ |
537 | <model name="" userDefinedModelVersionIdentifier="UOMusic0" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="1811" systemVersion="12C60" minimumToolsVersion="Xcode 4.3" macOSVersion="Automatic" iOSVersion="Automatic"> |
538 | <entity name="Album" representedClassName="Album" syncable="YES"> |
539 | <attribute name="albumId" attributeType="String" indexed="YES" syncable="YES"/> |
540 | - <attribute name="art" optional="YES" attributeType="String" syncable="YES"/> |
541 | + <attribute name="artHash" optional="YES" attributeType="String" syncable="YES"/> |
542 | <attribute name="artUrl" optional="YES" attributeType="String" syncable="YES"/> |
543 | <attribute name="dearticlizedTitle" attributeType="String" syncable="YES"/> |
544 | <attribute name="index" optional="YES" transient="YES" attributeType="String" syncable="YES"/> |
545 | @@ -12,6 +12,7 @@ |
546 | <relationship name="songs" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Song" inverseName="album" inverseEntity="Song" syncable="YES"/> |
547 | </entity> |
548 | <entity name="Artist" representedClassName="Artist" syncable="YES"> |
549 | + <attribute name="art" optional="YES" transient="YES" attributeType="Transformable" syncable="YES"/> |
550 | <attribute name="artistId" attributeType="String" indexed="YES" syncable="YES"/> |
551 | <attribute name="artUrl" optional="YES" attributeType="String" syncable="YES"/> |
552 | <attribute name="dearticlizedName" attributeType="String" syncable="YES"/> |
553 | @@ -30,7 +31,6 @@ |
554 | <attribute name="url" attributeType="String" syncable="YES"/> |
555 | </entity> |
556 | <entity name="Song" representedClassName="Song" syncable="YES"> |
557 | - <attribute name="artUrl" optional="YES" attributeType="String" syncable="YES"/> |
558 | <attribute name="bitRate" optional="YES" attributeType="String" syncable="YES"/> |
559 | <attribute name="contentType" optional="YES" attributeType="String" syncable="YES"/> |
560 | <attribute name="dearticlizedTitle" attributeType="String" syncable="YES"/> |
561 | @@ -53,8 +53,8 @@ |
562 | </entity> |
563 | <elements> |
564 | <element name="Album" positionX="468" positionY="180" width="128" height="180"/> |
565 | - <element name="Artist" positionX="160" positionY="195" width="128" height="165"/> |
566 | + <element name="Artist" positionX="160" positionY="195" width="128" height="180"/> |
567 | <element name="Playlist" positionX="160" positionY="192" width="128" height="135"/> |
568 | - <element name="Song" positionX="160" positionY="192" width="128" height="345"/> |
569 | + <element name="Song" positionX="160" positionY="192" width="128" height="330"/> |
570 | </elements> |
571 | </model> |
572 | \ No newline at end of file |
573 | |
574 | === modified file 'Music/Utilities/UOWebServiceController.m' |
575 | --- Music/Utilities/UOWebServiceController.m 2013-01-02 23:52:23 +0000 |
576 | +++ Music/Utilities/UOWebServiceController.m 2013-01-02 23:52:23 +0000 |
577 | @@ -169,6 +169,7 @@ |
578 | } |
579 | |
580 | - (void)initRestKit { |
581 | + RKLogConfigureByName("RestKit/Network", RKLogLevelWarning); |
582 | |
583 | NSURL *baseUrl = [NSURL URLWithString:@"https://one.ubuntu.com/api/music/v2/"]; |
584 | RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseUrl]; |
585 | @@ -190,6 +191,7 @@ |
586 | NSError *error; |
587 | [managedObjectStore addSQLitePersistentStoreAtPath:[RKApplicationDataDirectory() stringByAppendingPathComponent:@"UOMusic.sqlite"] fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error]; |
588 | if (error) { |
589 | + NSLog(@"Database model is out of date"); |
590 | abort(); |
591 | } |
592 | [objectManager setManagedObjectStore:managedObjectStore]; |
593 | |
594 | === modified file 'Music/View Controllers/AlbumViewController.m' |
595 | --- Music/View Controllers/AlbumViewController.m 2013-01-02 23:52:23 +0000 |
596 | +++ Music/View Controllers/AlbumViewController.m 2013-01-02 23:52:23 +0000 |
597 | @@ -38,6 +38,14 @@ |
598 | |
599 | [_albumTitle setText:album.title]; |
600 | [_albumDescription setText:album.artist.name]; |
601 | + if (!album.art) { |
602 | + [album fetchArt:^(UIImage *image) { |
603 | + [self.albumArt setImage:image]; |
604 | + [self.albumArt setNeedsDisplay]; |
605 | + }]; |
606 | + } else { |
607 | + [self.albumArt setImage:album.art]; |
608 | + } |
609 | |
610 | if ([album.songs count]) { |
611 | NSArray *sortDescriptors = [NSArray arrayWithObjects:[[NSSortDescriptor alloc] initWithKey:@"track" ascending:NO], nil]; |
612 | |
613 | === modified file 'Music/View Controllers/ArtistViewController.m' |
614 | --- Music/View Controllers/ArtistViewController.m 2013-01-02 23:52:23 +0000 |
615 | +++ Music/View Controllers/ArtistViewController.m 2013-01-02 23:52:23 +0000 |
616 | @@ -41,6 +41,14 @@ |
617 | [self fetchArtist]; |
618 | |
619 | [_artistName setText:artist.name]; |
620 | + if (!artist.art) { |
621 | + [artist fetchArt:^(UIImage *image) { |
622 | + [self.albumArt setImage:image]; |
623 | + [self.albumArt setNeedsDisplay]; |
624 | + }]; |
625 | + } else { |
626 | + [self.albumArt setImage:artist.art]; |
627 | + } |
628 | |
629 | NSString *pluralizedNoun = @"albums"; |
630 | if ([artist.albums count] == 1) { |
631 | |
632 | === modified file 'Music/View Controllers/Table Cells/AlbumCell.m' |
633 | --- Music/View Controllers/Table Cells/AlbumCell.m 2013-01-02 23:52:23 +0000 |
634 | +++ Music/View Controllers/Table Cells/AlbumCell.m 2013-01-02 23:52:23 +0000 |
635 | @@ -13,6 +13,17 @@ |
636 | |
637 | - (void)setAlbum:(Album *)album { |
638 | _album = album; |
639 | + |
640 | + if (!album.art) { |
641 | + [self.imageView setImage:[UIImage imageNamed:@"default-album-art-120.png"]]; |
642 | + [album fetchArt:^(UIImage *image) { |
643 | + [self.imageView setImage:image]; |
644 | + [self setNeedsDisplay]; |
645 | + }]; |
646 | + } else { |
647 | + [self.imageView setImage:album.art]; |
648 | + } |
649 | + |
650 | [self.textLabel setText:album.title]; |
651 | |
652 | [self.detailTextLabel setText:album.artist.name]; |
653 | |
654 | === modified file 'Music/View Controllers/Table Cells/ArtistCell.m' |
655 | --- Music/View Controllers/Table Cells/ArtistCell.m 2013-01-02 23:52:23 +0000 |
656 | +++ Music/View Controllers/Table Cells/ArtistCell.m 2013-01-02 23:52:23 +0000 |
657 | @@ -14,6 +14,16 @@ |
658 | - (void)setArtist:(Artist *)artist { |
659 | _artist = artist; |
660 | |
661 | + if (!artist.art) { |
662 | + [self.imageView setImage:[UIImage imageNamed:@"default-album-art-120.png"]]; |
663 | + [artist fetchArt:^(UIImage *image) { |
664 | + [self.imageView setImage:image]; |
665 | + [self setNeedsDisplay]; |
666 | + }]; |
667 | + } else { |
668 | + [self.imageView setImage:artist.art]; |
669 | + } |
670 | + |
671 | [self.textLabel setText:artist.name]; |
672 | if ([artist.albums count] > 0) { |
673 | NSString *pluralizedNoun = @"albums"; |
674 | |
675 | === modified file 'Music/View Controllers/Table Cells/SongCell.m' |
676 | --- Music/View Controllers/Table Cells/SongCell.m 2013-01-02 23:52:23 +0000 |
677 | +++ Music/View Controllers/Table Cells/SongCell.m 2013-01-02 23:52:23 +0000 |
678 | @@ -7,6 +7,7 @@ |
679 | // |
680 | |
681 | #import "SongCell.h" |
682 | +#import "Artist.h" |
683 | |
684 | @implementation SongCell |
685 | @synthesize song = _song; |
686 | @@ -14,8 +15,18 @@ |
687 | - (void)setSong:(Song *)song { |
688 | _song = song; |
689 | |
690 | + if (!song.art) { |
691 | + [self.imageView setImage:[UIImage imageNamed:@"default-album-art-120.png"]]; |
692 | + [song fetchArt:^(UIImage *image) { |
693 | + [self.imageView setImage:image]; |
694 | + [self setNeedsDisplay]; |
695 | + }]; |
696 | + } else { |
697 | + [self.imageView setImage:song.art]; |
698 | + } |
699 | + |
700 | [self.textLabel setText:song.title]; |
701 | - //[self.detailTextLabel setText:song.artist]; |
702 | + [self.detailTextLabel setText:song.artist.name]; |
703 | } |
704 | |
705 | @end |