~not/sonar

9a49b85268d6cabbbf9174bac1afe1751726ceb9 — b123400 a month ago 6f0c4fd
Local search
2 files changed, 74 insertions(+), 0 deletions(-)

M Sonar/MediaDB/MediaDB.h
M Sonar/MediaDB/MediaDB.m
M Sonar/MediaDB/MediaDB.h => Sonar/MediaDB/MediaDB.h +4 -0
@@ 58,6 58,10 @@ NS_ASSUME_NONNULL_BEGIN
- (void)listStarredItems:(void (^)(NSError * _Nullable error, NSArray<BaseModel*>* _Nullable items))callback
             fetchRemote:(BOOL)fetch;

- (void)searchWithKeyword:(NSString *)keyword
               completion:(void (^)(NSError * _Nullable error, NSArray<BaseModel*>* _Nullable items))callback
              fetchRemote:(BOOL)fetch;

- (void)starItem:(BaseModel *)item
      completion:(void (^) (NSError * _Nullable error, id updatedItem))callback;


M Sonar/MediaDB/MediaDB.m => Sonar/MediaDB/MediaDB.m +70 -0
@@ 284,6 284,40 @@
    }];
}

- (void)searchWithKeyword:(NSString *)keyword
               completion:(void (^)(NSError * _Nullable error, NSArray<BaseModel*>* _Nullable items))callback
              fetchRemote:(BOOL)fetch {
    BRSonicAPICredential *c = [[PreferencesManager shared] credential];
    if (!c) return;
    NSArray *cached = [self localSearchResultWithQuery:keyword];
    callback(nil, cached);
    if (!fetch) return;
    typeof(self) __weak weakSelf = self;
    [[BRSonicAPIClient shared] searchWithKeyword:keyword
                                      credential:c
                                      completion:^(NSError * _Nullable error, BRSonicAPIResponseSearchResult * _Nonnull response) {
        if (error) {
            callback(error, nil);
            return;
        }
        if (response) {
            for (id item in response.items) {
                if ([item isKindOfClass:[BRSonicAPISong class]]) {
                    weakSelf.songById[[item id]] = item;
                } else if ([item isKindOfClass:[BRSonicAPIAlbum class]]) {
                    weakSelf.albumById[[item id]] = item;
                } else if ([item isKindOfClass:[BRSonicAPIArtist class]]) {
                    weakSelf.artistById[[item id]] = item;
                }
            }
            NSArray *newItems = [self localSearchResultWithQuery:keyword];
            if (![cached isEqualTo:newItems]) {
                callback(nil, newItems);
            }
        }
    }];
}

- (void)starItem:(BaseModel *)item
      completion:(void (^) (NSError * _Nullable error, id updatedItem))callback {
    BRSonicAPICredential *c = [[PreferencesManager shared] credential];


@@ 534,4 568,40 @@
    return result;
}

- (NSArray *)localSearchResultWithQuery:(NSString *)query {
    BRSonicAPICredential *c = [[PreferencesManager shared] credential];
    NSMutableArray *result = [NSMutableArray array];
    query = query.lowercaseString;
    for (NSString *key in self.artistById) {
        BRSonicAPIArtist *a = self.artistById[key];
        if ([a.name.lowercaseString containsString:query]) {
            Artist *artist = [[Artist alloc] initWithAPIResponse:a];
            artist.albums = [self localAlbumsOfArtist:a];
            [result addObject:artist];
        }
    }
    for (NSString *key in self.albumById) {
        BRSonicAPIAlbum *a = self.albumById[key];
        if ([a.name.lowercaseString containsString:query]) {
            Album *album = [[Album alloc] initWithAPIResponse:a
                                                  coverArtURL:[[BRSonicAPIClient shared] urlForCoverArtId:a.coverArt
                                                                                           withCredential:c]];
            album.songs = [self localSongsOfAlbum:a];
            [result addObject:album];
        }
    }
    for (NSString *key in self.songById) {
        BRSonicAPISong *s = self.songById[key];
        if ([s.title.lowercaseString containsString:query]) {
            Song *song = [[Song alloc] initWithAPIResponse:s
                                               coverArtURL:[[BRSonicAPIClient shared] urlForCoverArtId:s.coverArt
                                                                                        withCredential:c]
                                                 streamURL:[[BRSonicAPIClient shared] urlForStreaming:s
                                                                                       withCredential:c]];
            [result addObject:song];
        }
    }
    return result;
}

@end