Brion VIBBER has submitted this change and it was merged. Change subject: Anonymous editing killswitch. ......................................................................
Anonymous editing killswitch. Syncs with config/ios.json at most once a day. Adjusts saving interface to hide anon saving option if ios.json has flag for disabling anon editing. The periodic sync code is done in generic fashion to make future sync between server and bundled app json files painless. Note: will need to amend copyBundledFolderToAppDataDocuments to copy files and folders which don't exist in documents directory after initial install. Right now it won't copy if it sees the Json folder has already been copied from the bundle to the writable documents dir. Will also need to rename all of the "bundled" things from this commit as they're not really bundled now that they've been moved to the documents directory. Change-Id: Ia64c060806c14cbf08cacb3168af8f471c8de048 --- M Wikipedia.xcodeproj/project.pbxproj M wikipedia/AppDelegate.m A wikipedia/BundledJson/BundledJson.h A wikipedia/BundledJson/BundledJson.m A wikipedia/BundledJson/BundledJsonEnum.h A wikipedia/BundledPaths/BundledPaths.h A wikipedia/BundledPaths/BundledPaths.m A wikipedia/BundledPaths/BundledPathsEnum.h A wikipedia/Data/Operations/ConfigFileSyncOp.h A wikipedia/Data/Operations/ConfigFileSyncOp.m M wikipedia/Data/Operations/DownloadLangLinksOp.h M wikipedia/Data/Operations/DownloadLangLinksOp.m R wikipedia/Json/Languages/languages.json R wikipedia/Json/Languages/mainpages.json A wikipedia/Json/config/ios.json M wikipedia/Queues/QueuesSingleton.h M wikipedia/Queues/QueuesSingleton.m M wikipedia/Session/SessionSingleton.h M wikipedia/Session/SessionSingleton.m M wikipedia/View Controllers/Languages/LanguagesTableVC.m M wikipedia/View Controllers/Preview/PreviewChoicesMenuView.m M wikipedia/View Controllers/Preview/PreviewChoicesMenuView.xib M wikipedia/View Controllers/TopNav/NavController.m M wikipedia/View Controllers/WebView/WebViewController.m 24 files changed, 414 insertions(+), 49 deletions(-) Approvals: Brion VIBBER: Verified; Looks good to me, approved diff --git a/Wikipedia.xcodeproj/project.pbxproj b/Wikipedia.xcodeproj/project.pbxproj index 262a856..cc69069 100644 --- a/Wikipedia.xcodeproj/project.pbxproj +++ b/Wikipedia.xcodeproj/project.pbxproj @@ -43,6 +43,10 @@ 043DAC4B1901C3EE001CD17C /* CreditsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 043DAC4A1901C3EE001CD17C /* CreditsViewController.m */; }; 043F18E118D9691D00D8489A /* TopActionSheetLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 043F18DC18D9691D00D8489A /* TopActionSheetLabel.m */; }; 043F18E518D9691D00D8489A /* UINavigationController+TopActionSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = 043F18E018D9691D00D8489A /* UINavigationController+TopActionSheet.m */; }; + 044213C8191C3C2A006C03BF /* ConfigFileSyncOp.m in Sources */ = {isa = PBXBuildFile; fileRef = 044213C7191C3C2A006C03BF /* ConfigFileSyncOp.m */; }; + 044213D0191D6F43006C03BF /* BundledPaths.m in Sources */ = {isa = PBXBuildFile; fileRef = 044213CF191D6F43006C03BF /* BundledPaths.m */; }; + 044213D4191D70E9006C03BF /* BundledJson.m in Sources */ = {isa = PBXBuildFile; fileRef = 044213D3191D70E9006C03BF /* BundledJson.m */; }; + 044213D8191D99FB006C03BF /* Json in Resources */ = {isa = PBXBuildFile; fileRef = 044213D7191D99FB006C03BF /* Json */; }; 0442F57B19006DCC00F55DF9 /* PageHistoryLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0442F57A19006DCC00F55DF9 /* PageHistoryLabel.m */; }; 0442F57E190071A100F55DF9 /* WikiFont.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0442F57D190071A100F55DF9 /* WikiFont.ttf */; }; 0447862F185145090050563B /* HistoryResultCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04478621185145090050563B /* HistoryResultCell.m */; }; @@ -107,7 +111,6 @@ 04C695CE18ED08D900D9F2DA /* UIView+SearchSubviews.m in Sources */ = {isa = PBXBuildFile; fileRef = 04C695CD18ED08D900D9F2DA /* UIView+SearchSubviews.m */; }; 04C695D218ED213000D9F2DA /* UIScrollView+NoHorizontalScrolling.m in Sources */ = {isa = PBXBuildFile; fileRef = 04C695D118ED213000D9F2DA /* UIScrollView+NoHorizontalScrolling.m */; }; 04C8781018F4A42700FA3B99 /* AccountCreationTokenOp.m in Sources */ = {isa = PBXBuildFile; fileRef = 04C8780F18F4A42700FA3B99 /* AccountCreationTokenOp.m */; }; - 04CF1CB6187C8F4400E9516F /* Languages in Resources */ = {isa = PBXBuildFile; fileRef = 04CF1CB5187C8F4400E9516F /* Languages */; }; 04D122321899B8AC006B9A30 /* AlertWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04D122311899B8AC006B9A30 /* AlertWebView.m */; }; 04D149DD18877343006B4104 /* AlertLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 04D149DA18877343006B4104 /* AlertLabel.m */; }; 04D149DF18877343006B4104 /* UIViewController+Alert.m in Sources */ = {isa = PBXBuildFile; fileRef = 04D149DC18877343006B4104 /* UIViewController+Alert.m */; }; @@ -230,6 +233,15 @@ 043F18DF18D9691D00D8489A /* UINavigationController+TopActionSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UINavigationController+TopActionSheet.h"; sourceTree = "<group>"; }; 043F18E018D9691D00D8489A /* UINavigationController+TopActionSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UINavigationController+TopActionSheet.m"; sourceTree = "<group>"; }; 043F18F118DCDD3A00D8489A /* WMF_Colors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMF_Colors.h; sourceTree = "<group>"; }; + 044213C6191C3C2A006C03BF /* ConfigFileSyncOp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConfigFileSyncOp.h; sourceTree = "<group>"; }; + 044213C7191C3C2A006C03BF /* ConfigFileSyncOp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConfigFileSyncOp.m; sourceTree = "<group>"; }; + 044213CE191D6F43006C03BF /* BundledPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BundledPaths.h; sourceTree = "<group>"; }; + 044213CF191D6F43006C03BF /* BundledPaths.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BundledPaths.m; sourceTree = "<group>"; }; + 044213D2191D70E9006C03BF /* BundledJson.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BundledJson.h; sourceTree = "<group>"; }; + 044213D3191D70E9006C03BF /* BundledJson.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BundledJson.m; sourceTree = "<group>"; }; + 044213D5191D7FEA006C03BF /* BundledJsonEnum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BundledJsonEnum.h; sourceTree = "<group>"; }; + 044213D6191D7FFC006C03BF /* BundledPathsEnum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BundledPathsEnum.h; sourceTree = "<group>"; }; + 044213D7191D99FB006C03BF /* Json */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Json; sourceTree = "<group>"; }; 0442F57919006DCC00F55DF9 /* PageHistoryLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageHistoryLabel.h; sourceTree = "<group>"; }; 0442F57A19006DCC00F55DF9 /* PageHistoryLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PageHistoryLabel.m; sourceTree = "<group>"; }; 0442F57D190071A100F55DF9 /* WikiFont.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = WikiFont.ttf; sourceTree = "<group>"; }; @@ -353,7 +365,6 @@ 04C695D118ED213000D9F2DA /* UIScrollView+NoHorizontalScrolling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+NoHorizontalScrolling.m"; sourceTree = "<group>"; }; 04C8780E18F4A42700FA3B99 /* AccountCreationTokenOp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccountCreationTokenOp.h; sourceTree = "<group>"; }; 04C8780F18F4A42700FA3B99 /* AccountCreationTokenOp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AccountCreationTokenOp.m; sourceTree = "<group>"; }; - 04CF1CB5187C8F4400E9516F /* Languages */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Languages; sourceTree = "<group>"; }; 04D122301899B8AC006B9A30 /* AlertWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlertWebView.h; sourceTree = "<group>"; }; 04D122311899B8AC006B9A30 /* AlertWebView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AlertWebView.m; sourceTree = "<group>"; }; 04D149D918877343006B4104 /* AlertLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlertLabel.h; sourceTree = "<group>"; }; @@ -708,6 +719,26 @@ path = TopActionSheet; sourceTree = "<group>"; }; + 044213CD191D6F43006C03BF /* BundledPaths */ = { + isa = PBXGroup; + children = ( + 044213D6191D7FFC006C03BF /* BundledPathsEnum.h */, + 044213CE191D6F43006C03BF /* BundledPaths.h */, + 044213CF191D6F43006C03BF /* BundledPaths.m */, + ); + path = BundledPaths; + sourceTree = "<group>"; + }; + 044213D1191D70BC006C03BF /* BundledJson */ = { + isa = PBXGroup; + children = ( + 044213D5191D7FEA006C03BF /* BundledJsonEnum.h */, + 044213D2191D70E9006C03BF /* BundledJson.h */, + 044213D3191D70E9006C03BF /* BundledJson.m */, + ); + path = BundledJson; + sourceTree = "<group>"; + }; 0442F57C1900718600F55DF9 /* Fonts */ = { isa = PBXGroup; children = ( @@ -999,6 +1030,8 @@ 04D149E5188889CA006B4104 /* Operations */ = { isa = PBXGroup; children = ( + 044213C6191C3C2A006C03BF /* ConfigFileSyncOp.h */, + 044213C7191C3C2A006C03BF /* ConfigFileSyncOp.m */, 04F27B7918FE19B700EDD838 /* PageHistoryOp.h */, 04F27B7A18FE19B700EDD838 /* PageHistoryOp.m */, 0406CEF418F8C390007EE43E /* LogEventOp.h */, @@ -1197,14 +1230,16 @@ D469889318B52DA200DBE014 /* Main_iPhone.strings */, D46CD8C218A1AC4F0042959E /* Localizable.strings */, 045A9F0C18F6090E0057EA85 /* assets */, + 044213D1191D70BC006C03BF /* BundledJson */, + 044213CD191D6F43006C03BF /* BundledPaths */, 04C43AB7183442FC006C643B /* Categories */, 040E5C50184673F2007AFE6F /* Data */, 04292FFB185FC026002A13FC /* Defines */, 0442F57C1900718600F55DF9 /* Fonts */, 04D34DA31863D2D600610A87 /* HTML Parsing */, 0466F44C183A30CC00EA1FD7 /* Images */, + 044213D7191D99FB006C03BF /* Json */, 0463639518A844380049EE4F /* Keychain */, - 04CF1CB5187C8F4400E9516F /* Languages */, 048A26741906268100395F53 /* PaddedLabel */, 04292FFD185FC2C7002A13FC /* Queues */, 0447866C1852B5010050563B /* Session */, @@ -1398,7 +1433,6 @@ buildActionMask = 2147483647; files = ( D469889518B52DA200DBE014 /* Main_iPhone.strings in Resources */, - 04CF1CB6187C8F4400E9516F /* Languages in Resources */, 0466F44F183A30CC00EA1FD7 /* logo-search-placeholder.png in Resources */, D46CD8C418A1AC4F0042959E /* InfoPlist.strings in Resources */, D4991454181D51DE00E6073C /* Images.xcassets in Resources */, @@ -1418,6 +1452,7 @@ 04B91AAE18E4056D00FFAA1C /* MainMenuRowView.xib in Resources */, 04090A33187F53E400577EDF /* clear.png in Resources */, 0412362E189C29EA00E0CF8E /* abuse-filter-disallowed.png in Resources */, + 044213D8191D99FB006C03BF /* Json in Resources */, 0442F57E190071A100F55DF9 /* WikiFont.ttf in Resources */, 04082B5518ADA25A00FAF3D6 /* text_field_x_circle_g...@2x.png in Resources */, 0466F450183A30CC00EA1FD7 /* logo-search-placehol...@2x.png in Resources */, @@ -1457,6 +1492,7 @@ 044BD6B618849AD000FFE4BE /* SectionEditorViewController.m in Sources */, 04D34DAB1863D2D600610A87 /* TFHpple.m in Sources */, 0429301018604898002A13FC /* SavedPagesViewController.m in Sources */, + 044213D4191D70E9006C03BF /* BundledJson.m in Sources */, 04D149DF18877343006B4104 /* UIViewController+Alert.m in Sources */, 04FD6C7A184EBFCD002CA02F /* ArticleData.xcdatamodeld in Sources */, 048A26771906268100395F53 /* PaddedLabel.m in Sources */, @@ -1492,6 +1528,7 @@ 040E533C1885FB4E00AFBFE9 /* ImageData.m in Sources */, 04DB0BE618BC2E1E00B4BCF3 /* CaptchaResetOp.m in Sources */, 0415581C18ADFA5D00B81A59 /* UIImage+ColorMask.m in Sources */, + 044213C8191C3C2A006C03BF /* ConfigFileSyncOp.m in Sources */, 04A70FD7185BB6C300E24515 /* URLCache.m in Sources */, 04992BC018B687AF00A6C22B /* SearchOp.m in Sources */, 041A3B5E18E11ED90079FF1C /* LanguagesCell.m in Sources */, @@ -1552,6 +1589,7 @@ 0442F57B19006DCC00F55DF9 /* PageHistoryLabel.m in Sources */, 0447862F185145090050563B /* HistoryResultCell.m in Sources */, 04B0EA45190AFDD8007458AF /* ArticleImporter.m in Sources */, + 044213D0191D6F43006C03BF /* BundledPaths.m in Sources */, 0406CEF618F8C390007EE43E /* LogEventOp.m in Sources */, 0476967C18BBFC9400071963 /* AccountCreationOp.m in Sources */, ); diff --git a/wikipedia/AppDelegate.m b/wikipedia/AppDelegate.m index fe9868d..4f372f7 100644 --- a/wikipedia/AppDelegate.m +++ b/wikipedia/AppDelegate.m @@ -20,6 +20,12 @@ [self registerStandardUserDefaults]; [self systemWideStyleOverrides]; + // We may need to overwrite these json files form the server, so they need to be + // placed in the "AppData/Documents/" folder and access and update them there. + // This method copies bundled "Json" folder over to "AppData/Documents/" if it's + // not already there. + [self copyBundledFolderToAppDataDocuments:@"Json"]; + // Enables Alignment Rect highlighting for debugging //[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"UIViewShowAlignmentRects"]; //[[NSUserDefaults standardUserDefaults] synchronize]; @@ -29,6 +35,23 @@ return YES; } +-(void)copyBundledFolderToAppDataDocuments:(NSString *)folderName +{ + +//TODO: modify so if new app release has new bundled files or folders these +// get copied too. Presently if folderName is seen to already exist in the +// AppData/Documents/ directory no copying occurs. + + NSFileManager *fileManager = [[NSFileManager defaultManager] init]; + NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:folderName]; + if (![fileManager fileExistsAtPath:documentsPath]){ + NSString *bundledPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:folderName]; + //[fileManager createDirectoryAtPath: documentDBFolderPath attributes:nil]; + [fileManager copyItemAtPath:bundledPath toPath:documentsPath error:nil]; + } +} + -(void)registerStandardUserDefaults { // Register default default values. diff --git a/wikipedia/BundledJson/BundledJson.h b/wikipedia/BundledJson/BundledJson.h new file mode 100644 index 0000000..bcf2bc1 --- /dev/null +++ b/wikipedia/BundledJson/BundledJson.h @@ -0,0 +1,15 @@ +// Created by Monte Hurd on 5/9/14. +// Copyright (c) 2013 Wikimedia Foundation. Provided under MIT-style license; please copy and modify! + +#import "BundledPathsEnum.h" +#import "BundledJsonEnum.h" + +@interface BundledJson : NSObject + ++ (NSDictionary *)dictionaryFromBundledJsonFile:(BundledJsonFile)file; + ++ (NSArray *)arrayFromBundledJsonFile:(BundledJsonFile)file; + ++ (BOOL)isRefreshNeededForBundledJsonFile:(BundledJsonFile)file maxAge:(CGFloat)maxAge; + +@end diff --git a/wikipedia/BundledJson/BundledJson.m b/wikipedia/BundledJson/BundledJson.m new file mode 100644 index 0000000..7a58086 --- /dev/null +++ b/wikipedia/BundledJson/BundledJson.m @@ -0,0 +1,58 @@ +// Created by Monte Hurd on 5/9/14. +// Copyright (c) 2013 Wikimedia Foundation. Provided under MIT-style license; please copy and modify! + +#import "BundledJson.h" +#import "BundledPaths.h" + +@implementation BundledJson + ++ (NSDictionary *)dictionaryFromBundledJsonFile:(BundledJsonFile)file +{ + NSError *error = nil; + NSData *fileData = [NSData dataWithContentsOfFile:[BundledPaths bundledJsonFilePath:file] options:0 error:&error]; + if (error) return @{}; + error = nil; + NSMutableDictionary *result = [NSJSONSerialization JSONObjectWithData:fileData options:0 error:&error]; + return (error) ? @{}: result; +} + ++ (NSArray *)arrayFromBundledJsonFile:(BundledJsonFile)file +{ + NSError *error = nil; + NSData *fileData = [NSData dataWithContentsOfFile:[BundledPaths bundledJsonFilePath:file] options:0 error:&error]; + if (error) return @[]; + error = nil; + NSArray *result = [NSJSONSerialization JSONObjectWithData:fileData options:0 error:&error]; + return (error) ? @[]: result; +} + +// Returns YES if the local version of the config file doesn't exist or is older than maxAge. ++ (BOOL)isRefreshNeededForBundledJsonFile:(BundledJsonFile)file maxAge:(CGFloat)maxAge +{ + NSString *path = [BundledPaths bundledJsonFilePath:file]; + + BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:NO]; + if (!fileExists){ + NSLog(@"REFRESH NEEDED"); + return YES; + } + + NSDate *lastModified = nil; + NSError *error = nil; + NSURL *url = [NSURL fileURLWithPath:path]; + [url getResourceValue: &lastModified + forKey: NSURLContentModificationDateKey + error: &error]; + if (!error){ + NSTimeInterval currentAge = [[NSDate date] timeIntervalSinceDate:lastModified]; + NSLog(@"currentAge = %f maxAge = %f", currentAge, maxAge); + if (currentAge > maxAge){ + NSLog(@"REFRESH NEEDED"); + return YES; + } + } + NSLog(@"NO REFRESH NEEDED"); + return NO; +} + +@end diff --git a/wikipedia/BundledJson/BundledJsonEnum.h b/wikipedia/BundledJson/BundledJsonEnum.h new file mode 100644 index 0000000..e301b98 --- /dev/null +++ b/wikipedia/BundledJson/BundledJsonEnum.h @@ -0,0 +1,7 @@ + +typedef NS_ENUM(NSUInteger, BundledJsonFile) { + BUNDLED_JSON_UNDEFINED = 0, + BUNDLED_JSON_CONFIG = 1, + BUNDLED_JSON_LANGUAGES = 2, + BUNDLED_JSON_MAINPAGES = 3 +}; diff --git a/wikipedia/BundledPaths/BundledPaths.h b/wikipedia/BundledPaths/BundledPaths.h new file mode 100644 index 0000000..7601df1 --- /dev/null +++ b/wikipedia/BundledPaths/BundledPaths.h @@ -0,0 +1,12 @@ +// Created by Monte Hurd on 5/9/14. +// Copyright (c) 2013 Wikimedia Foundation. Provided under MIT-style license; please copy and modify! + +#import "BundledPathsEnum.h" +#import "BundledJsonEnum.h" + +@interface BundledPaths : NSObject + ++ (NSString *)bundledJsonFilePath:(BundledJsonFile)file; ++ (NSURL *)bundledJsonFileRemoteUrl:(BundledJsonFile)file; + +@end diff --git a/wikipedia/BundledPaths/BundledPaths.m b/wikipedia/BundledPaths/BundledPaths.m new file mode 100644 index 0000000..d115f70 --- /dev/null +++ b/wikipedia/BundledPaths/BundledPaths.m @@ -0,0 +1,96 @@ +// Created by Monte Hurd on 5/9/14. +// Copyright (c) 2013 Wikimedia Foundation. Provided under MIT-style license; please copy and modify! + +#import "BundledPaths.h" +#import "BundledJson.h" + +@implementation BundledPaths + ++ (NSString *)nameForFile:(BundledJsonFile)bundledJsonFile +{ + switch (bundledJsonFile) { + case BUNDLED_JSON_CONFIG: + return @"ios.json"; + break; + case BUNDLED_JSON_LANGUAGES: + return @"languages.json"; + break; + case BUNDLED_JSON_MAINPAGES: + return @"mainpages.json"; + break; + default: + return BUNDLED_JSON_UNDEFINED; + break; + } +} + ++ (NSString *)nameForPath:(BundledPath)bundledPath +{ + switch (bundledPath) { + case BUNDLED_PATH_CONFIG: + return @"config"; + break; + case BUNDLED_PATH_LANGUAGES: + case BUNDLED_PATH_MAINPAGES: + return @"Languages"; + break; + default: + return BUNDLED_PATH_UNDEFINED; + break; + } +} + ++ (BundledPath)bundledPathForFile:(BundledJsonFile)file +{ + switch (file) { + case BUNDLED_JSON_CONFIG: + return BUNDLED_PATH_CONFIG; + break; + case BUNDLED_JSON_LANGUAGES: + return BUNDLED_PATH_LANGUAGES; + break; + case BUNDLED_JSON_MAINPAGES: + return BUNDLED_PATH_MAINPAGES; + break; + default: + return BUNDLED_PATH_UNDEFINED; + break; + } +} + ++ (NSString *)remoteUrlForFile:(BundledJsonFile)bundledJsonFile +{ + // For now only the config file is remote synced. + switch (bundledJsonFile) { + case BUNDLED_JSON_CONFIG: + return @"https://bits.wikimedia.org/static-current/extensions/MobileApp/config/ios.json"; + break; + default: + return @""; + break; + } +} + ++(NSString *)pathForFolder:(BundledPath)folder file:(BundledJsonFile)file +{ + NSString *folderName = [self nameForPath:folder]; + NSString *fileName = [self nameForFile:file]; + NSArray *documentsPath = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES); + NSString *jsonPath = [[documentsPath objectAtIndex:0] stringByAppendingPathComponent:@"Json"]; + NSString *folderPath = [jsonPath stringByAppendingPathComponent:folderName]; + NSString *filePath = [folderPath stringByAppendingPathComponent:fileName]; + return filePath; +} + ++ (NSString *)bundledJsonFilePath:(BundledJsonFile)file +{ + BundledPath bundledPath = [self bundledPathForFile:file]; + return [self pathForFolder:bundledPath file:file]; +} + ++ (NSURL *)bundledJsonFileRemoteUrl:(BundledJsonFile)file +{ + return [NSURL URLWithString:[self remoteUrlForFile:file]]; +} + +@end diff --git a/wikipedia/BundledPaths/BundledPathsEnum.h b/wikipedia/BundledPaths/BundledPathsEnum.h new file mode 100644 index 0000000..189a518 --- /dev/null +++ b/wikipedia/BundledPaths/BundledPathsEnum.h @@ -0,0 +1,7 @@ + +typedef NS_ENUM(NSUInteger, BundledPath) { + BUNDLED_PATH_UNDEFINED = 0, + BUNDLED_PATH_CONFIG = 1, + BUNDLED_PATH_LANGUAGES = 2, + BUNDLED_PATH_MAINPAGES = 3 +}; diff --git a/wikipedia/Data/Operations/ConfigFileSyncOp.h b/wikipedia/Data/Operations/ConfigFileSyncOp.h new file mode 100644 index 0000000..a27fc90 --- /dev/null +++ b/wikipedia/Data/Operations/ConfigFileSyncOp.h @@ -0,0 +1,22 @@ +// Created by Monte Hurd on 5/8/14. +// Copyright (c) 2013 Wikimedia Foundation. Provided under MIT-style license; please copy and modify! + +#import "MWNetworkOp.h" + +#import "BundledJsonEnum.h" + +@interface ConfigFileSyncOp : MWNetworkOp + +// Syncs any bundled app json file with a remote file. + +// Only does so if age of app file exceeds maxAge or if the file isn't found in app. + +// Nice because we can sync any bundled files with any periodicity +// required just by firing these operations off occasionally. + +// They self-cancel if maxAge has not been exceeded, so fire away. + +- (id)initForBundledJsonFile: (BundledJsonFile)file + maxAge: (CGFloat)maxAge; + +@end diff --git a/wikipedia/Data/Operations/ConfigFileSyncOp.m b/wikipedia/Data/Operations/ConfigFileSyncOp.m new file mode 100644 index 0000000..87fc1c2 --- /dev/null +++ b/wikipedia/Data/Operations/ConfigFileSyncOp.m @@ -0,0 +1,63 @@ +// Created by Monte Hurd on 5/8/14. +// Copyright (c) 2013 Wikimedia Foundation. Provided under MIT-style license; please copy and modify! + +#import "ConfigFileSyncOp.h" +#import "MWNetworkActivityIndicatorManager.h" +#import "NSURLRequest+DictionaryRequest.h" + +#import "BundledJson.h" +#import "BundledPaths.h" + +@implementation ConfigFileSyncOp + +- (id)initForBundledJsonFile: (BundledJsonFile)file + maxAge: (CGFloat)maxAge +{ + self = [super init]; + if (self) { + + self.request = [NSURLRequest getRequestWithURL: [BundledPaths bundledJsonFileRemoteUrl:file] + parameters: nil]; + + __weak ConfigFileSyncOp *weakSelf = self; + self.aboutToStart = ^{ + + // Cancel the operation if the existing file hasn't aged enough. + BOOL shouldRefresh = [BundledJson isRefreshNeededForBundledJsonFile:file maxAge:maxAge]; + + if (!shouldRefresh) { + [weakSelf cancel]; + return; + } + + [[MWNetworkActivityIndicatorManager sharedManager] push]; + }; + self.completionBlock = ^(){ + [[MWNetworkActivityIndicatorManager sharedManager] pop]; + + if(weakSelf.isCancelled){ + return; + } + + if (weakSelf.error) { + return; + } + + // If it got this far, then a refresh was needed and has completed. + if (weakSelf.dataRetrieved) { + NSString *jsonString = [[NSString alloc] initWithData:weakSelf.dataRetrieved encoding:NSUTF8StringEncoding]; + //NSLog(@"jsonString = %@", jsonString); + if (!jsonString) return; + NSString *filePath = [BundledPaths bundledJsonFilePath:file]; + NSError *error = nil; + [jsonString writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error]; + if (error) { + NSLog(@"%@", error.localizedDescription); + } + } + }; + } + return self; +} + +@end diff --git a/wikipedia/Data/Operations/DownloadLangLinksOp.h b/wikipedia/Data/Operations/DownloadLangLinksOp.h index 7c60b9b..68fbe47 100644 --- a/wikipedia/Data/Operations/DownloadLangLinksOp.h +++ b/wikipedia/Data/Operations/DownloadLangLinksOp.h @@ -7,7 +7,7 @@ - (id)initForPageTitle: (NSString *)title domain: (NSString *)domain - allLanguages: (NSMutableArray *)allLanguages + allLanguages: (NSArray *)allLanguages completionBlock: (void (^)(NSArray *))completionBlock cancelledBlock: (void (^)(NSError *))cancelledBlock errorBlock: (void (^)(NSError *))errorBlock diff --git a/wikipedia/Data/Operations/DownloadLangLinksOp.m b/wikipedia/Data/Operations/DownloadLangLinksOp.m index 0d44e4b..e290721 100644 --- a/wikipedia/Data/Operations/DownloadLangLinksOp.m +++ b/wikipedia/Data/Operations/DownloadLangLinksOp.m @@ -10,7 +10,7 @@ - (id)initForPageTitle: (NSString *)title domain: (NSString *)domain - allLanguages: (NSMutableArray *)allLanguages + allLanguages: (NSArray *)allLanguages completionBlock: (void (^)(NSArray *))completionBlock cancelledBlock: (void (^)(NSError *))cancelledBlock errorBlock: (void (^)(NSError *))errorBlock diff --git a/wikipedia/Languages/languages.json b/wikipedia/Json/Languages/languages.json similarity index 100% rename from wikipedia/Languages/languages.json rename to wikipedia/Json/Languages/languages.json diff --git a/wikipedia/Languages/mainpages.json b/wikipedia/Json/Languages/mainpages.json similarity index 100% rename from wikipedia/Languages/mainpages.json rename to wikipedia/Json/Languages/mainpages.json diff --git a/wikipedia/Json/config/ios.json b/wikipedia/Json/config/ios.json new file mode 100644 index 0000000..75b5c8d --- /dev/null +++ b/wikipedia/Json/config/ios.json @@ -0,0 +1,3 @@ +{ + "disableAnonEditing": false +} diff --git a/wikipedia/Queues/QueuesSingleton.h b/wikipedia/Queues/QueuesSingleton.h index 1607054..9618d2c 100644 --- a/wikipedia/Queues/QueuesSingleton.h +++ b/wikipedia/Queues/QueuesSingleton.h @@ -22,6 +22,8 @@ @property (strong, nonatomic) NSOperationQueue *eventLoggingQ; @property (strong, nonatomic) NSOperationQueue *pageHistoryQ; +@property (strong, nonatomic) NSOperationQueue *bundledFileSyncQ; + + (QueuesSingleton *)sharedInstance; @end diff --git a/wikipedia/Queues/QueuesSingleton.m b/wikipedia/Queues/QueuesSingleton.m index 6289a5a..bbf87c2 100644 --- a/wikipedia/Queues/QueuesSingleton.m +++ b/wikipedia/Queues/QueuesSingleton.m @@ -32,6 +32,7 @@ self.randomArticleQ = [[NSOperationQueue alloc] init]; self.eventLoggingQ = [[NSOperationQueue alloc] init]; self.pageHistoryQ = [[NSOperationQueue alloc] init]; + self.bundledFileSyncQ = [[NSOperationQueue alloc] init]; //[self setupQMonitorLogging]; } return self; diff --git a/wikipedia/Session/SessionSingleton.h b/wikipedia/Session/SessionSingleton.h index 55c03be..33e7897 100644 --- a/wikipedia/Session/SessionSingleton.h +++ b/wikipedia/Session/SessionSingleton.h @@ -28,7 +28,6 @@ @property (strong, atomic) NSArray *unsupportedCharactersLanguageIds; -(NSURL *)urlForDomain:(NSString *)domain; --(NSMutableArray *)getBundledLanguagesJson; -(NSString *)domainNameForCode:(NSString *)code; -(NSString *)mainArticleTitleForCode:(NSString *)code; diff --git a/wikipedia/Session/SessionSingleton.m b/wikipedia/Session/SessionSingleton.m index d10fe95..545791e 100644 --- a/wikipedia/Session/SessionSingleton.m +++ b/wikipedia/Session/SessionSingleton.m @@ -2,6 +2,8 @@ // Copyright (c) 2013 Wikimedia Foundation. Provided under MIT-style license; please copy and modify! #import "SessionSingleton.h" +#import "BundledPaths.h" +#import "BundledJson.h" @implementation SessionSingleton @@ -117,12 +119,8 @@ -(NSString *)domainNameForCode:(NSString *)code { - NSError *error = nil; - NSData *fileData = [NSData dataWithContentsOfFile:[self bundledLanguagesJsonPath] options:0 error:&error]; - if (error) return nil; - error = nil; - NSArray *result = [NSJSONSerialization JSONObjectWithData:fileData options:0 error:&error]; - if (!error) { + NSArray *result = [BundledJson arrayFromBundledJsonFile:BUNDLED_JSON_LANGUAGES]; + if (result.count > 0) { for (NSDictionary *d in result) { if ([d[@"code"] isEqualToString:code]) { return d[@"name"]; @@ -134,39 +132,9 @@ } } -- (NSString *)bundledLanguagesJsonPath -{ - return [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Languages/languages.json"]; -} - --(NSMutableArray *)getBundledLanguagesJson -{ - NSError *error = nil; - NSData *fileData = [NSData dataWithContentsOfFile:[[SessionSingleton sharedInstance] bundledLanguagesJsonPath] options:0 error:&error]; - if (error) return [@[] mutableCopy]; - error = nil; - NSArray *result = [NSJSONSerialization JSONObjectWithData:fileData options:0 error:&error]; - return (error) ? [@[] mutableCopy]: [result mutableCopy]; -} - -- (NSString *)bundledMainArticleTitlesJsonPath -{ - return [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Languages/mainpages.json"]; -} - --(NSMutableDictionary *)getBundledMainArticleTitlesJson -{ - NSError *error = nil; - NSData *fileData = [NSData dataWithContentsOfFile:[[SessionSingleton sharedInstance] bundledMainArticleTitlesJsonPath] options:0 error:&error]; - if (error) return @{}.mutableCopy; - error = nil; - NSDictionary *result = [NSJSONSerialization JSONObjectWithData:fileData options:0 error:&error]; - return (error) ? @{}.mutableCopy: [result mutableCopy]; -} - -(NSString *)mainArticleTitleForCode:(NSString *)code { - NSMutableDictionary *mainPageNames = [self getBundledMainArticleTitlesJson]; + NSDictionary *mainPageNames = [BundledJson dictionaryFromBundledJsonFile:BUNDLED_JSON_MAINPAGES]; return mainPageNames[code]; } diff --git a/wikipedia/View Controllers/Languages/LanguagesTableVC.m b/wikipedia/View Controllers/Languages/LanguagesTableVC.m index 1f31fa4..a6cadea 100644 --- a/wikipedia/View Controllers/Languages/LanguagesTableVC.m +++ b/wikipedia/View Controllers/Languages/LanguagesTableVC.m @@ -10,6 +10,7 @@ #import "LanguagesSectionHeadingLabel.h" #import "NavController.h" #import "Defines.h" +#import "BundledJson.h" #import "UIViewController+Alert.h" @@ -70,7 +71,7 @@ if(self.downloadLanguagesForCurrentArticle){ [self downloadLangLinkData]; }else{ - self.languagesData = [[SessionSingleton sharedInstance] getBundledLanguagesJson]; + self.languagesData = [BundledJson arrayFromBundledJsonFile:BUNDLED_JSON_LANGUAGES]; self.headerView.hidden = NO; [self reloadTableDataFiltered]; } @@ -292,7 +293,7 @@ DownloadLangLinksOp *langLinksOp = [[DownloadLangLinksOp alloc] initForPageTitle: [SessionSingleton sharedInstance].currentArticleTitle domain: [SessionSingleton sharedInstance].currentArticleDomain - allLanguages: [[SessionSingleton sharedInstance] getBundledLanguagesJson] + allLanguages: [BundledJson arrayFromBundledJsonFile:BUNDLED_JSON_LANGUAGES] completionBlock: ^(NSArray *result){ [[NSOperationQueue mainQueue] addOperationWithBlock: ^ { diff --git a/wikipedia/View Controllers/Preview/PreviewChoicesMenuView.m b/wikipedia/View Controllers/Preview/PreviewChoicesMenuView.m index ae0b7f9..770ffbe 100644 --- a/wikipedia/View Controllers/Preview/PreviewChoicesMenuView.m +++ b/wikipedia/View Controllers/Preview/PreviewChoicesMenuView.m @@ -5,6 +5,7 @@ #import "PaddedLabel.h" #import "WikipediaAppUtils.h" #import "NSString+FormattedAttributedString.h" +#import "BundledJson.h" #define PREVIEW_BLUE_COLOR [UIColor colorWithRed:0.13 green:0.42 blue:0.68 alpha:1.0] @@ -14,6 +15,8 @@ @interface PreviewChoicesMenuView(){ } + +@property (weak, nonatomic) IBOutlet UIView *topRowContainer; @end @@ -52,7 +55,6 @@ self.signInView.backgroundColor = PREVIEW_BLUE_COLOR; [self underlineLabelText: self.signInTitleLabel]; - [self underlineLabelText: self.saveAnonTitleLabel]; /* self.signInTitleLabel.text = [@" abc " randomlyRepeatMaxTimes:100]; @@ -61,6 +63,21 @@ self.saveAnonSubTitleLabel.text = [@" abc " randomlyRepeatMaxTimes:100]; [self randomlyColorSubviews]; */ + + if ([self isAnonymousEditingDisabled]) { + [self.saveAnonView removeFromSuperview]; + // The right side of the signInView had been constrained to the left side of the + // saveAnonView, but now that the saveAnonView is gone the right side of the + // signInView needs to be constrained to the right side of the topRowContainer. + [self.topRowContainer addConstraints: + [NSLayoutConstraint constraintsWithVisualFormat: @"H:[signInView]|" + options: 0 + metrics: nil + views: @{@"signInView" : self.signInView}] + ]; + }else{ + [self underlineLabelText: self.saveAnonTitleLabel]; + } } -(void)underlineLabelText:(UILabel *)label @@ -79,4 +96,14 @@ label.attributedText = aString; } +-(BOOL)isAnonymousEditingDisabled +{ + NSDictionary *iosConfigJson = [BundledJson dictionaryFromBundledJsonFile:BUNDLED_JSON_CONFIG]; + NSNumber *disableAnonEditing = iosConfigJson[@"disableAnonEditing"]; + if (disableAnonEditing && (disableAnonEditing.boolValue == YES)) { + return YES; + } + return NO; +} + @end diff --git a/wikipedia/View Controllers/Preview/PreviewChoicesMenuView.xib b/wikipedia/View Controllers/Preview/PreviewChoicesMenuView.xib index 2ad687f..57d3cd9 100644 --- a/wikipedia/View Controllers/Preview/PreviewChoicesMenuView.xib +++ b/wikipedia/View Controllers/Preview/PreviewChoicesMenuView.xib @@ -102,6 +102,7 @@ <outlet property="signInSubTitleLabel" destination="dVR-8O-7eG" id="hus-QR-GXZ"/> <outlet property="signInTitleLabel" destination="PPh-Eu-usA" id="LO3-x5-pCZ"/> <outlet property="signInView" destination="JYT-4n-1ej" id="k1q-zU-i4A"/> + <outlet property="topRowContainer" destination="2HE-pz-gbX" id="8XN-KB-zcG"/> </connections> </view> </objects> diff --git a/wikipedia/View Controllers/TopNav/NavController.m b/wikipedia/View Controllers/TopNav/NavController.m index f6b3b0b..4eaa78f 100644 --- a/wikipedia/View Controllers/TopNav/NavController.m +++ b/wikipedia/View Controllers/TopNav/NavController.m @@ -473,7 +473,7 @@ case NAVBAR_MODE_EDIT_WIKITEXT_LOGIN_OR_SAVE_ANONYMOUSLY: self.label.text = @""; self.navBarSubViewsHorizontalVFLString = - @"H:|[NAVBAR_BUTTON_PENCIL(50)][NAVBAR_VERTICAL_LINE_1(singlePixel)]-(10)-[NAVBAR_LABEL]-(10)-[NAVBAR_VERTICAL_LINE_2(singlePixel)][NAVBAR_BUTTON_CHECK(50)]|"; + @"H:|[NAVBAR_BUTTON_PENCIL(50)][NAVBAR_VERTICAL_LINE_1(singlePixel)]-(10)-[NAVBAR_LABEL]|"; break; case NAVBAR_MODE_EDIT_WIKITEXT_SAVE: self.label.text = MWLocalizedString(@"navbar-title-mode-edit-wikitext-save", nil); diff --git a/wikipedia/View Controllers/WebView/WebViewController.m b/wikipedia/View Controllers/WebView/WebViewController.m index 4e299a7..86598ba 100644 --- a/wikipedia/View Controllers/WebView/WebViewController.m +++ b/wikipedia/View Controllers/WebView/WebViewController.m @@ -39,6 +39,8 @@ #import "DataMigrator.h" #import "ArticleImporter.h" +#import "ConfigFileSyncOp.h" + #define TOC_TOGGLE_ANIMATION_DURATION 0.3f #define NAV ((NavController *)self.navigationController) @@ -174,7 +176,12 @@ -(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; - + + // Don't move this to viewDidLoad - this is because viewDidLoad may only get + // called very occasionally as app suspend/resume probably doesn't cause + // viewDidLoad to fire. + [self sycnConfigIosJsonIfNecessary]; + //[self.view randomlyColorSubviews]; } @@ -191,6 +198,21 @@ [super viewWillDisappear:animated]; } +#pragma mark Sync bundled config/ios.json if necessary + +-(void)sycnConfigIosJsonIfNecessary +{ + // Sync config/ios.json at most once per day. + CGFloat maxAge = 60 * 60 * 24; + + ConfigFileSyncOp *configSyncOp = + [[ConfigFileSyncOp alloc] initForBundledJsonFile: BUNDLED_JSON_CONFIG + maxAge: maxAge]; + + [[QueuesSingleton sharedInstance].bundledFileSyncQ cancelAllOperations]; + [[QueuesSingleton sharedInstance].bundledFileSyncQ addOperation:configSyncOp]; +} + #pragma mark Edit section -(void)showSectionEditor -- To view, visit https://gerrit.wikimedia.org/r/132587 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ia64c060806c14cbf08cacb3168af8f471c8de048 Gerrit-PatchSet: 2 Gerrit-Project: apps/ios/wikipedia Gerrit-Branch: master Gerrit-Owner: Mhurd <mh...@wikimedia.org> Gerrit-Reviewer: Brion VIBBER <br...@wikimedia.org> Gerrit-Reviewer: Dr0ptp4kt <ab...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits