From 7fb1f8107d73419589b8a6c01d1f6c19e93c33cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eddy=20Lelie=CC=80vre-Berna?= Date: Mon, 29 May 2017 22:55:28 +0200 Subject: [PATCH 1/2] Fixes #130 and cleaner code --- piwigo/AlbumImagesViewController.m | 35 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/piwigo/AlbumImagesViewController.m b/piwigo/AlbumImagesViewController.m index 4a1291d4b..003e75eab 100644 --- a/piwigo/AlbumImagesViewController.m +++ b/piwigo/AlbumImagesViewController.m @@ -135,7 +135,7 @@ -(void)viewDidAppear:(BOOL)animated -(void)refresh:(UIRefreshControl*)refreshControl { - [self.albumData reloadAlbumOnCompletion:^{ + [self.albumData loadAllImagesOnCompletion:^{ [refreshControl endRefreshing]; [self.imagesCollection reloadData]; }]; @@ -426,27 +426,28 @@ -(UICollectionReusableView*)collectionView:(UICollectionView *)collectionView vi { if(indexPath.section == 1) { - SortHeaderCollectionReusableView *header = nil; - - if(kind == UICollectionElementKindSectionHeader) + self.noImagesLabel = [UILabel new]; + self.noImagesLabel.translatesAutoresizingMaskIntoConstraints = NO; + self.noImagesLabel.font = [UIFont piwigoFontNormal]; + self.noImagesLabel.font = [self.noImagesLabel.font fontWithSize:20]; + self.noImagesLabel.textColor = [UIColor piwigoWhiteCream]; + self.noImagesLabel.text = NSLocalizedString(@"noImages", @"No Images"); + self.noImagesLabel.hidden = self.albumData.images.count != 0; + + SortHeaderCollectionReusableView *header = nil; + + if(kind == UICollectionElementKindSectionHeader) { header = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header" forIndexPath:indexPath]; header.currentSortLabel.text = [CategorySortViewController getNameForCategorySortType:self.currentSortCategory]; [header addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didSelectCollectionViewHeader)]]; + + [header addSubview:self.noImagesLabel]; + [header addConstraint:[NSLayoutConstraint constraintViewFromBottom:self.noImagesLabel amount:-40]]; + [header addConstraint:[NSLayoutConstraint constraintCenterVerticalView:self.noImagesLabel]]; + + return header; } - - self.noImagesLabel = [UILabel new]; - self.noImagesLabel.translatesAutoresizingMaskIntoConstraints = NO; - self.noImagesLabel.font = [UIFont piwigoFontNormal]; - self.noImagesLabel.font = [self.noImagesLabel.font fontWithSize:20]; - self.noImagesLabel.textColor = [UIColor piwigoWhiteCream]; - self.noImagesLabel.text = NSLocalizedString(@"noImages", @"No Images"); - self.noImagesLabel.hidden = self.albumData.images.count != 0; - [header addSubview:self.noImagesLabel]; - [header addConstraint:[NSLayoutConstraint constraintViewFromBottom:self.noImagesLabel amount:-40]]; - [header addConstraint:[NSLayoutConstraint constraintCenterVerticalView:self.noImagesLabel]]; - - return header; } UICollectionReusableView *view = [[UICollectionReusableView alloc] initWithFrame:CGRectZero]; From 98505117ca76087370b18aede0f15e70ceb3783d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eddy=20Lelie=CC=80vre-Berna?= Date: Mon, 29 May 2017 23:00:08 +0200 Subject: [PATCH 2/2] Fixes issue #113 by reopening automatically a session after connection lost. --- piwigo.xcodeproj/project.pbxproj | 6 ++ piwigo/AppDelegate.m | 83 +++++++++++++++++++++++++++- piwigo/LoginViewController.m | 17 ++++-- piwigo/Model.h | 1 + piwigo/Model.m | 10 +--- piwigo/PiwigoAlbumData.m | 2 +- piwigo/Reachability.m | 2 +- piwigo/Resources/Localizable.strings | 2 +- piwigo/SessionService.m | 8 +-- piwigo/SettingsViewController.m | 3 +- 10 files changed, 111 insertions(+), 23 deletions(-) diff --git a/piwigo.xcodeproj/project.pbxproj b/piwigo.xcodeproj/project.pbxproj index 3984d6f3c..055154513 100644 --- a/piwigo.xcodeproj/project.pbxproj +++ b/piwigo.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ AD0134641EBE310000F11C3F /* TabBarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AD0134631EBE310000F11C3F /* TabBarViewController.m */; }; AD35CA381E9BF8A600E3B897 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AD35CA361E9BF8A600E3B897 /* Launch Screen.storyboard */; }; AD35CA3A1E9C1EBC00E3B897 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AD35CA391E9C1EBC00E3B897 /* Images.xcassets */; }; + AD6D203C1EDC45C4003B60E8 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = AD6D203B1EDC45C4003B60E8 /* Reachability.m */; }; D8083A4F1A7CB65400A95605 /* UIActionSheet+Blocks.m in Sources */ = {isa = PBXBuildFile; fileRef = D8083A4E1A7CB65400A95605 /* UIActionSheet+Blocks.m */; }; D8083A521A7CB78900A95605 /* UIAlertView+Blocks.m in Sources */ = {isa = PBXBuildFile; fileRef = D8083A511A7CB78900A95605 /* UIAlertView+Blocks.m */; }; D8083A551A7D66CD00A95605 /* ImageService.m in Sources */ = {isa = PBXBuildFile; fileRef = D8083A541A7D66CD00A95605 /* ImageService.m */; }; @@ -123,6 +124,8 @@ AD0134631EBE310000F11C3F /* TabBarViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TabBarViewController.m; sourceTree = ""; }; AD35CA371E9BF8A600E3B897 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = "piwigo/Base.lproj/Launch Screen.storyboard"; sourceTree = ""; }; AD35CA391E9C1EBC00E3B897 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + AD6D203A1EDC45C4003B60E8 /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = ""; }; + AD6D203B1EDC45C4003B60E8 /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = ""; }; B37F5B7464A6A11CDDABA253 /* libPods-piwigoTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-piwigoTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; D8083A4D1A7CB65400A95605 /* UIActionSheet+Blocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIActionSheet+Blocks.h"; sourceTree = ""; }; D8083A4E1A7CB65400A95605 /* UIActionSheet+Blocks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIActionSheet+Blocks.m"; sourceTree = ""; }; @@ -653,6 +656,8 @@ children = ( D82B8CE41A678ED2000E47CA /* NetworkHandler.h */, D82B8CE51A678ED2000E47CA /* NetworkHandler.m */, + AD6D203A1EDC45C4003B60E8 /* Reachability.h */, + AD6D203B1EDC45C4003B60E8 /* Reachability.m */, ); name = Network; sourceTree = ""; @@ -1111,6 +1116,7 @@ D89045B91A946A5B00A306FE /* TagsService.m in Sources */, D8C71A471A8489CF0048BA33 /* ImageUploadViewController.m in Sources */, D82B8CE61A678ED2000E47CA /* NetworkHandler.m in Sources */, + AD6D203C1EDC45C4003B60E8 /* Reachability.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/piwigo/AppDelegate.m b/piwigo/AppDelegate.m index 650d7fd08..f1b5c44aa 100644 --- a/piwigo/AppDelegate.m +++ b/piwigo/AppDelegate.m @@ -15,6 +15,7 @@ #import "Model.h" #import "KeychainAccess.h" #import "AFNetworkActivityIndicatorManager.h" +#import "Reachability.h" #import "PhotosFetch.h" #import "iRate.h" @@ -22,6 +23,7 @@ @interface AppDelegate () @property (nonatomic, strong) LoginViewController *loginVC; +@property (nonatomic, strong) Reachability *internetReachability; @end @@ -40,7 +42,8 @@ + (void)initialize { - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. + + // Override point for customization after application launch. NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:[Model sharedInstance].memoryCache * 1024*1024 diskCapacity:[Model sharedInstance].diskCache * 1024*1024 @@ -70,6 +73,84 @@ -(void)loadNavigation self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:navigation]; [self.loginVC removeFromParentViewController]; self.loginVC = nil; + + // Observe the kNetworkReachabilityChangedNotification. + // When that notification is posted, the method reachabilityChanged will be called. + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil]; + + // Monitor Internet connection reachability + self.internetReachability = [Reachability reachabilityForInternetConnection]; + [self.internetReachability startNotifier]; +} + +// Called by Reachability whenever Internet connection changes. +- (void) reachabilityChanged:(NSNotification *)note +{ + Reachability* curReach = [note object]; + NetworkStatus netStatus = [curReach currentReachabilityStatus]; + + switch (netStatus) + { + case NotReachable: + { + // NSLog(@"Access Not Available"); + break; + } + case ReachableViaWWAN: + { + // Connection changed but now reachable WWAN — Login again? + BOOL hadOpenedSession = [Model sharedInstance].hadOpenedSession; + NSString *server = [Model sharedInstance].serverName; + NSString *user = [KeychainAccess getLoginUser]; + NSString *password = [KeychainAccess getLoginPassword]; + + if(hadOpenedSession && (server.length > 0) && (user.length > 0)) + { + [SessionService performLoginWithUser:user + andPassword:password + onCompletion:^(BOOL result, id response) { + [Model sharedInstance].hadOpenedSession = YES; + } + onFailure:^(NSURLSessionTask *task, NSError *error) { + [Model sharedInstance].hadOpenedSession = NO; + NSLog(@"Error %ld: %@", (long)error.code, error.localizedDescription); + [UIAlertView showWithTitle:NSLocalizedString(@"internetErrorGeneral_title", @"Connection Error") + message:[error localizedDescription] + cancelButtonTitle:NSLocalizedString(@"alertOkButton", @"OK") + otherButtonTitles:nil + tapBlock:nil]; + }]; + } + break; + } + case ReachableViaWiFi: + { + // Connection changed but now reachable WiFi — Login again? + BOOL hadOpenedSession = [Model sharedInstance].hadOpenedSession; + NSString *server = [Model sharedInstance].serverName; + NSString *user = [KeychainAccess getLoginUser]; + NSString *password = [KeychainAccess getLoginPassword]; + + if(hadOpenedSession && (server.length > 0) && (user.length > 0)) + { + [SessionService performLoginWithUser:user + andPassword:password + onCompletion:^(BOOL result, id response) { + [Model sharedInstance].hadOpenedSession = YES; + } + onFailure:^(NSURLSessionTask *task, NSError *error) { + [Model sharedInstance].hadOpenedSession = NO; + NSLog(@"Error %ld: %@", (long)error.code, error.localizedDescription); + [UIAlertView showWithTitle:NSLocalizedString(@"internetErrorGeneral_title", @"Connection Error") + message:[error localizedDescription] + cancelButtonTitle:NSLocalizedString(@"alertOkButton", @"OK") + otherButtonTitles:nil + tapBlock:nil]; + }]; + } + break; + } + } } -(void)loadLoginView diff --git a/piwigo/LoginViewController.m b/piwigo/LoginViewController.m index d82436722..cc55fca90 100644 --- a/piwigo/LoginViewController.m +++ b/piwigo/LoginViewController.m @@ -131,19 +131,23 @@ -(void)performLogin [Model sharedInstance].serverProtocol = [self.serverTextField getProtocolString]; [[Model sharedInstance] saveToDisk]; - if(self.userTextField.text.length > 0) + if(self.userTextField.text.length > 0) // Perform Login if username exists { [SessionService performLoginWithUser:self.userTextField.text andPassword:self.passwordTextField.text onCompletion:^(BOOL result, id response) { if(result) { - [self getSessionStatus]; - [self getSessionPluginsList]; + [Model sharedInstance].hadOpenedSession = YES; + [self getSessionStatus]; + if([Model sharedInstance].hasAdminRights) { + [self getSessionPluginsList]; // To determine if VideoJS is active + } } else { - [self hideLoading]; + [Model sharedInstance].hadOpenedSession = NO; + [self hideLoading]; [self showLoginFail]; } } onFailure:^(NSURLSessionTask *task, NSError *error) { @@ -157,9 +161,10 @@ -(void)performLogin tapBlock:nil]; }]; } - else + else // No username, get only session status { - [self getSessionStatus]; + [Model sharedInstance].hadOpenedSession = NO; + [self getSessionStatus]; [KeychainAccess resetKeychain]; } } diff --git a/piwigo/Model.h b/piwigo/Model.h index f8db2d969..f3e412b5d 100644 --- a/piwigo/Model.h +++ b/piwigo/Model.h @@ -38,6 +38,7 @@ typedef enum { @property (nonatomic, assign) BOOL hasAdminRights; @property (nonatomic, assign) BOOL hasInstalledVideoJS; @property (nonatomic, assign) BOOL hasUploadedImages; +@property (nonatomic, assign) BOOL hadOpenedSession; @property (nonatomic, assign) kPiwigoPrivacy defaultPrivacyLevel; @property (nonatomic, strong) NSString *defaultAuthor; diff --git a/piwigo/Model.m b/piwigo/Model.m index 3395ae5f4..4c86bdff0 100644 --- a/piwigo/Model.m +++ b/piwigo/Model.m @@ -28,8 +28,9 @@ + (Model*)sharedInstance instance.defaultPrivacyLevel = kPiwigoPrivacyEverybody; instance.defaultAuthor = @""; instance.hasAdminRights = NO; + instance.hadOpenedSession = NO; instance.hasUploadedImages = NO; - instance.hasInstalledVideoJS = NO; + instance.hasInstalledVideoJS = YES; // Will be checked if the user has admin rights instance.stripGPSdataOnUpload = NO; instance.photoQuality = 95; instance.photoResize = 100; @@ -125,7 +126,6 @@ - (void)readFromDisk self.resizeImageOnUpload = modelData.resizeImageOnUpload; self.defaultImagePreviewSize = modelData.defaultImagePreviewSize; self.stripGPSdataOnUpload = modelData.stripGPSdataOnUpload; - self.hasInstalledVideoJS = modelData.hasInstalledVideoJS; } } @@ -154,7 +154,6 @@ - (void) encodeWithCoder:(NSCoder *)encoder { [saveObject addObject:[ NSNumber numberWithBool:self.resizeImageOnUpload]]; [saveObject addObject:@(self.defaultImagePreviewSize)]; [saveObject addObject:[NSNumber numberWithBool:self.stripGPSdataOnUpload]]; - [saveObject addObject:[NSNumber numberWithBool:self.hasInstalledVideoJS]]; [encoder encodeObject:saveObject forKey:@"Model"]; } @@ -203,11 +202,6 @@ - (id)initWithCoder:(NSCoder *)decoder { } else { self.stripGPSdataOnUpload = NO; } - if(savedData.count > 13) { - self.hasInstalledVideoJS = [[savedData objectAtIndex:13] boolValue]; - } else { - self.hasInstalledVideoJS = NO; - } return self; } diff --git a/piwigo/PiwigoAlbumData.m b/piwigo/PiwigoAlbumData.m index 006390c75..01176dc46 100644 --- a/piwigo/PiwigoAlbumData.m +++ b/piwigo/PiwigoAlbumData.m @@ -110,7 +110,7 @@ -(void)loadCategoryImageDataChunkWithSort:(NSString*)sort if(error) { [UIAlertView showWithTitle:NSLocalizedString(@"albumPhotoError_title", @"Get Album Photos Error") - message:[NSString stringWithFormat:@"%@\n%@", NSLocalizedString(@"albumPhotoError_message", @"Failed to get album photos (You probably have a corrupt image in your album) Error:"), [error localizedDescription]] + message:[NSString stringWithFormat:@"%@\n%@", NSLocalizedString(@"albumPhotoError_message", @"Failed to get album photos (corrupt image in your album?)"), [error localizedDescription]] cancelButtonTitle:NSLocalizedString(@"alertOkButton", @"OK") otherButtonTitles:nil tapBlock:nil]; diff --git a/piwigo/Reachability.m b/piwigo/Reachability.m index f081a16aa..6e5f3ee0c 100644 --- a/piwigo/Reachability.m +++ b/piwigo/Reachability.m @@ -25,7 +25,7 @@ #pragma mark - Supporting functions -#define kShouldPrintReachabilityFlags 1 +#define kShouldPrintReachabilityFlags 0 static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment) { diff --git a/piwigo/Resources/Localizable.strings b/piwigo/Resources/Localizable.strings index f4e1c4bf7..f4cd4047e 100644 --- a/piwigo/Resources/Localizable.strings +++ b/piwigo/Resources/Localizable.strings @@ -261,7 +261,7 @@ "createAlbumError_message" = "Failed to create a new album"; "albumPhotoError_title" = "Get Album Photos Error"; -"albumPhotoError_message" = "Failed to get album photos (You probably have a corrupt image in your album) Error:"; +"albumPhotoError_message" = "Failed to get album photos (corrupt image in your album?)"; "renameCategoyError_title" = "Rename Fail"; "renameCategoyError_message" = "Failed to rename your album"; diff --git a/piwigo/SessionService.m b/piwigo/SessionService.m index 033a61ce1..238f065a8 100644 --- a/piwigo/SessionService.m +++ b/piwigo/SessionService.m @@ -93,10 +93,8 @@ +(NSURLSessionTask*)getPluginsListOnCompletion:(void (^)(NSDictionary *responseO success:^(NSURLSessionTask *task, id responseObject) { if(completion) { - // By default, the plugin is not installed/active - [Model sharedInstance].hasInstalledVideoJS = NO; - // Did the server answer the request? + // Did the server answer the request? (Yes if Admin) if([[responseObject objectForKey:@"stat"] isEqualToString:@"ok"]) { // Collect the list of plugins @@ -116,8 +114,10 @@ +(NSURLSessionTask*)getPluginsListOnCompletion:(void (^)(NSDictionary *responseO } completion([responseObject objectForKey:@"result"]); } - else + else // Non-admin access => Cannot determine if VideoJS is installed { + // So we assume that VideoJS is installed and active + [Model sharedInstance].hasInstalledVideoJS = YES; completion(nil); } } diff --git a/piwigo/SettingsViewController.m b/piwigo/SettingsViewController.m index 2cd4bbb72..ae629cbcc 100644 --- a/piwigo/SettingsViewController.m +++ b/piwigo/SettingsViewController.m @@ -713,7 +713,8 @@ -(void)logout [SessionService sessionLogoutOnCompletion:^(NSURLSessionTask *task, BOOL sucessfulLogout) { if(sucessfulLogout) { - [ClearCache clearAllCache]; + [Model sharedInstance].hadOpenedSession = NO; + [ClearCache clearAllCache]; AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; [appDelegate loadLoginView]; }