From 8ae952ec8df2a713afeaef5960a88888e050c6fc Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Sun, 15 Oct 2017 23:47:11 +0300 Subject: WIP --- Juick/0.png | Bin 1586 -> 0 bytes Juick/AppDelegate.h | 2 +- Juick/AppDelegate.m | 25 ++- Juick/AttachPlaceholder@2x.png | Bin 15565 -> 0 bytes Juick/CoreDataStack.h | 189 ++++++++++++++++ Juick/CoreDataStack.m | 133 +++++++++++ Juick/Helpers/ColorScheme.h | 1 + Juick/Helpers/ColorScheme.m | 5 +- Juick/Helpers/UIImage+Utils.h | 1 + Juick/Helpers/UIImage+Utils.m | 14 ++ Juick/Main.storyboard | 270 +++++++++++++++-------- Juick/Model/Attachment.h | 18 ++ Juick/Model/Attachment.m | 13 ++ Juick/Model/Message.h | 2 + Juick/Supporting Files/Juick-Prefix.pch | 1 + Juick/ViewControllers/MessagesViewController.m | 49 +--- Juick/ViewControllers/NewPostViewController.h | 3 +- Juick/ViewControllers/NewPostViewController.m | 21 +- Juick/ViewControllers/RootNavigationController.h | 13 -- Juick/ViewControllers/RootNavigationController.m | 24 -- Juick/Views/MessageCell.h | 5 +- Juick/Views/MessageCell.m | 26 ++- Juick/reveal-icon.png | Bin 1118 -> 0 bytes Juick/reveal-icon@2x.png | Bin 1066 -> 0 bytes 24 files changed, 633 insertions(+), 182 deletions(-) delete mode 100644 Juick/0.png delete mode 100644 Juick/AttachPlaceholder@2x.png create mode 100644 Juick/CoreDataStack.h create mode 100644 Juick/CoreDataStack.m create mode 100644 Juick/Model/Attachment.h create mode 100644 Juick/Model/Attachment.m delete mode 100644 Juick/ViewControllers/RootNavigationController.h delete mode 100644 Juick/ViewControllers/RootNavigationController.m delete mode 100644 Juick/reveal-icon.png delete mode 100644 Juick/reveal-icon@2x.png (limited to 'Juick') diff --git a/Juick/0.png b/Juick/0.png deleted file mode 100644 index 7f2f7ac..0000000 Binary files a/Juick/0.png and /dev/null differ diff --git a/Juick/AppDelegate.h b/Juick/AppDelegate.h index 6753fd7..b5954e1 100644 --- a/Juick/AppDelegate.h +++ b/Juick/AppDelegate.h @@ -9,7 +9,7 @@ #import #import "User.h" -@interface AppDelegate : UIResponder +@interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; diff --git a/Juick/AppDelegate.m b/Juick/AppDelegate.m index b5c4e27..7be4424 100644 --- a/Juick/AppDelegate.m +++ b/Juick/AppDelegate.m @@ -20,16 +20,23 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [[UINavigationBar appearance] setTintColor:[ColorScheme linkColor]]; + [[UINavigationBar appearance] setBackgroundColor:[ColorScheme headerBackground]]; [[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName: [ColorScheme linkColor]}]; + [[UIToolbar appearance] setTintColor:[ColorScheme linkColor]]; [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault; return YES; } - --(void) application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { - [[UIApplication sharedApplication] registerForRemoteNotifications]; +- (void)registerForRemoteNotifications { + UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; + center.delegate = self; + [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error){ + if(!error){ + [[UIApplication sharedApplication] registerForRemoteNotifications]; + } + }]; } -(void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { @@ -46,4 +53,16 @@ NSLog(@"Error: %@", [error debugDescription]); } +//Called when a notification is delivered to a foreground app. +-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{ + NSLog(@"User Info : %@",notification.request.content.userInfo); + completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge); +} + +//Called to let your app know which action was selected by the user for a given notification. +-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler{ + NSLog(@"User Info : %@",response.notification.request.content.userInfo); + completionHandler(); +} + @end diff --git a/Juick/AttachPlaceholder@2x.png b/Juick/AttachPlaceholder@2x.png deleted file mode 100644 index 94e8c32..0000000 Binary files a/Juick/AttachPlaceholder@2x.png and /dev/null differ diff --git a/Juick/CoreDataStack.h b/Juick/CoreDataStack.h new file mode 100644 index 0000000..b430654 --- /dev/null +++ b/Juick/CoreDataStack.h @@ -0,0 +1,189 @@ +// +// CoreDataStack.h +// Juick +// +// Created by Vitaly Takmazov on 15/10/2017. +// Copyright © 2017 com.juick. All rights reserved. +// + +@import Foundation; +@import CoreData; + +NS_ASSUME_NONNULL_BEGIN + +API_AVAILABLE(macosx(10.12),ios(10.0),tvos(10.0),watchos(3.0)) +@interface CoreDataStack : NSObject + +/** + The default directory for the persistent stores on the current platform. + @return An `NSURL` for the directory containing the persistent store(s). If the + persistent store does not exist it will be created by default in this location + when loaded. + */ ++ (NSURL *)defaultDirectoryURL; + +///--------------------- +/// @name Properties +///--------------------- + +/** + A read-only flag indicating if the persistent store is loaded. + */ +@property (readonly, assign, getter=isStoreLoaded) BOOL storeLoaded; + +/** + The managed object context associated with the main queue (read-only). To + perform tasks on a private background queue see `performBackgroundTask:` and + `newPrivateContext`. + The context is configured to be generational and to automatically consume save + notifications from other contexts. + */ +@property (readonly, strong) NSManagedObjectContext *viewContext; + +/** + The `URL` of the persistent store for this Core Data Stack. If there are more + than one stores this property returns the first store it finds. The store may + not yet exist. It will be created at this URL by default when first loaded. + + This is a readonly property to create a persistent store in a different + location use `loadStoreAtURL:withCompletionHandler`. To move an existing + persistent store use `replacePersistentStoreAtURL:withPersistentStoreFromURL:`. + */ +@property (readonly, copy) NSURL *storeURL; + +/** + A flag that indicates whether this store is read-only. Set this value to YES + before loading the persistent store if you want a read-only store (for example + if you are loading a store from the application bundle). + + Default is NO. + */ +@property (assign, getter=isReadOnly) BOOL readOnly; + +/** + A flag that indicates whether the store is added asynchronously. Set this + value before loading the persistent store. + + Default is YES. + */ +@property (assign) BOOL shouldAddStoreAsynchronously; + +/** + A flag that indicates whether the store should be migrated + automatically if the store model version does not match the + coordinators model version. + + Set this value before loading the persistent store. + Default is YES. + */ +@property (assign) BOOL shouldMigrateStoreAutomatically; + +/** + A flag that indicates whether a mapping model should be inferred + when migrating a store. + Set this value before loading the persistent store. + + Default is YES. + */ +@property (assign) BOOL shouldInferMappingModelAutomatically; + +///--------------------- +/// @name Initialization +///--------------------- + +- (instancetype)init NS_UNAVAILABLE; + +/** + Creates and returns a `CoreDataController` object. This is the designated + initializer for the class. It creates the managed object model, persistent + store coordinator and main managed object context but does not load the + persistent store. + + @param name The name of the `NSManagedObjectModel` and by default the name used + for the persistent store + @return A `CoreDataController` object initialized with the given name. + */ +- (instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER; + +///--------------------------------- +/// @name Loading a Persistent Store +///--------------------------------- + +/** + Load the persistent store. + @param handler This handler block is executed on the calling thread when the + loading of the persistent store has completed. + + To override the default name and location of the persistent store use + `loadStoreAtURL:withCompletionHandler:`. + */ +- (void)loadStoreWithCompletionHandler:(void(^)(NSError *))handler; + +/** + Load the persistent store. + @param storeURL The URL for the location of the persistent store. It will be created if it does not exist. + @param handler This handler block is executed on the calling thread when the + loading of the persistent store has completed. + */ +- (void)loadStoreAtURL:(NSURL *)storeURL withCompletionHandler:(void(^)(NSError * _Nullable))handler; + +///---------------------------------- +/// @name Managing a Persistent Store +///---------------------------------- + +/** + A flag indicating if the persistent store exists at the specified URL. + @param storeURL An `NSURL` object for the location of the peristent store. + @return YES if a file exists at the specified URL otherwise NO. + @warning This method checks if a file exists at the specified location but + does not verify if it is a valid persistent store. + */ +- (BOOL)persistentStoreExistsAtURL:(NSURL *)storeURL; + +/** + Replace a persistent store. + @param destinationURL An `NSURL` for the persistent store to be replaced. + @param sourceURL An `NSURL` for the source persistent store. + @return A flag indicating if the operation was successful. + */ +- (BOOL)replacePersistentStoreAtURL:(NSURL *)destinationURL withPersistentStoreFromURL:(NSURL *)sourceURL; + +/** + Destroy a persistent store. + @param storeURL An `NSURL` for the persistent store to be destroyed. + @return A flag indicating if the operation was successful. + */ +- (BOOL)destroyPersistentStoreAtURL:(NSURL *)storeURL; + +///---------------------------------- +/// @name Performing Background tasks +///---------------------------------- + +/** + Execute a block on a new private queue context. + @param block A block to execute on a newly created private context. The context + is passed to the block as a paramater. + */ +- (void)performBackgroundTask:(void(^)(NSManagedObjectContext *))block; + +/** + Create and return a new private queue `NSManagedObjectContext`. The new context + is set to consume `NSManagedObjectContextSave` broadcasts automatically. + @return A new private managed object context. + */ +- (NSManagedObjectContext *)newPrivateContext NS_RETURNS_RETAINED; + +///------------------------ +/// @name NSManagedObjectID +///------------------------ + +/** + Return an object ID for the specified URI representation if a matching + store is available. + @param url An `NSURL` containing a URI of a managed object. + @return An `NSManagedObjectID` or `nil`. + */ +- (NSManagedObjectID *)managedObjectIDForURIRepresentation:(NSURL *)url; + +@end +NS_ASSUME_NONNULL_END diff --git a/Juick/CoreDataStack.m b/Juick/CoreDataStack.m new file mode 100644 index 0000000..6122731 --- /dev/null +++ b/Juick/CoreDataStack.m @@ -0,0 +1,133 @@ +// +// CoreDataStack.m +// Juick +// +// Created by Vitaly Takmazov on 15/10/2017. +// Copyright © 2017 com.juick. All rights reserved. +// + +#import "CoreDataStack.h" + +@interface CoreDataStack () +@property (nonatomic, getter=isStoreLoaded) BOOL storeLoaded; +@property (nonatomic, strong) NSPersistentContainer *persistentContainer; +@end + +@implementation CoreDataStack + ++ (NSURL *)defaultDirectoryURL { + return [NSPersistentContainer defaultDirectoryURL]; +} + +- (instancetype)initWithName:(NSString *)name { + + NSManagedObjectModel *mom = [NSManagedObjectModel mergedModelFromBundles:nil]; + if (mom == nil) return nil; + + self = [super init]; + if (self) { + _storeLoaded = NO; + _shouldAddStoreAsynchronously = YES; + _shouldMigrateStoreAutomatically = YES; + _shouldInferMappingModelAutomatically = YES; + _readOnly = NO; + _persistentContainer = [NSPersistentContainer persistentContainerWithName:name managedObjectModel:mom]; + _persistentContainer.viewContext.automaticallyMergesChangesFromParent = YES; + } + return self; +} + +- (void)loadStoreWithCompletionHandler:(void(^)(NSError *))handler { + + [self loadStoreAtURL:self.storeURL withCompletionHandler:handler]; +} + +- (void)loadStoreAtURL:(NSURL *)storeURL withCompletionHandler:(void(^)(NSError *))handler { + + if (!self.persistentContainer) { + NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSNotFound userInfo:nil]; + if (handler) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + } + return; + } + + self.persistentContainer.persistentStoreDescriptions = @[[self storeDescriptionWithURL:storeURL]]; + [self.persistentContainer loadPersistentStoresWithCompletionHandler: + ^(NSPersistentStoreDescription *storeDescription, NSError *error) { + if (error == nil) { + self.storeLoaded = YES; + } + if (handler) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + } + }]; +} + +- (BOOL)persistentStoreExistsAtURL:(NSURL *)storeURL { + + if (storeURL.isFileURL && + [NSFileManager.defaultManager fileExistsAtPath:storeURL.path]) { + return YES; + } + return NO; +} + +- (NSURL *)storeURL { + NSArray *descriptions = self.persistentContainer.persistentStoreDescriptions; + NSPersistentStoreDescription *description = [descriptions firstObject]; + return description.URL; +} + +- (BOOL)destroyPersistentStoreAtURL:(NSURL *)storeURL { + + NSError *error = nil; + BOOL result = [self.persistentContainer.persistentStoreCoordinator destroyPersistentStoreAtURL:storeURL withType:NSSQLiteStoreType options:nil error:&error]; + return result; +} + +- (BOOL)replacePersistentStoreAtURL:(NSURL *)destinationURL withPersistentStoreFromURL:(NSURL *)sourceURL { + + NSError *error = nil; + BOOL result = [self.persistentContainer.persistentStoreCoordinator replacePersistentStoreAtURL:destinationURL destinationOptions:nil withPersistentStoreFromURL:sourceURL sourceOptions:nil storeType:NSSQLiteStoreType error:&error]; + return result; +} + +- (NSManagedObjectContext *)viewContext { + + return self.persistentContainer.viewContext; +} + +- (NSManagedObjectContext *)newPrivateContext { + + return [self.persistentContainer newBackgroundContext]; +} + +- (void)performBackgroundTask:(void(^)(NSManagedObjectContext *))block { + + [self.persistentContainer performBackgroundTask:block]; +} + +- (NSManagedObjectID *)managedObjectIDForURIRepresentation:(NSURL *)url { + return [self.persistentContainer.persistentStoreCoordinator managedObjectIDForURIRepresentation:url]; +} + +#pragma mark - +#pragma mark === Private methods === +#pragma mark - + +- (NSPersistentStoreDescription *)storeDescriptionWithURL:(NSURL *)URL { + + NSPersistentStoreDescription *description = [NSPersistentStoreDescription persistentStoreDescriptionWithURL:URL]; + description.shouldAddStoreAsynchronously = self.shouldAddStoreAsynchronously; + description.shouldMigrateStoreAutomatically = self.shouldMigrateStoreAutomatically; + description.shouldInferMappingModelAutomatically = self.shouldInferMappingModelAutomatically; + description.readOnly = self.isReadOnly; + return description; +} + +@end diff --git a/Juick/Helpers/ColorScheme.h b/Juick/Helpers/ColorScheme.h index de69689..3226f75 100644 --- a/Juick/Helpers/ColorScheme.h +++ b/Juick/Helpers/ColorScheme.h @@ -13,5 +13,6 @@ + (UIColor *)colorWithHex:(UInt32)col; +(UIColor *) mainBackground; ++(UIColor *) headerBackground; +(UIColor *) linkColor; @end diff --git a/Juick/Helpers/ColorScheme.m b/Juick/Helpers/ColorScheme.m index 56684a6..53cca4f 100644 --- a/Juick/Helpers/ColorScheme.m +++ b/Juick/Helpers/ColorScheme.m @@ -24,9 +24,12 @@ return [UIColor colorWithRed:(float)r/255.0f green:(float)g/255.0f blue:(float)b/255.0f alpha:1]; } ++ (UIColor *) headerBackground { + return [self colorWithHex:0xeeeee5]; +} + (UIColor *) mainBackground { - return [self colorWithHex:0xf8f8f8]; + return [self colorWithHex:0xddddd5]; } + (UIColor *) linkColor { diff --git a/Juick/Helpers/UIImage+Utils.h b/Juick/Helpers/UIImage+Utils.h index 8de91bf..d2e8b99 100644 --- a/Juick/Helpers/UIImage+Utils.h +++ b/Juick/Helpers/UIImage+Utils.h @@ -16,4 +16,5 @@ + (UIImage*)imageWithImage:(UIImage *)image fitInsideWidth:(float)width fitInsideHeight:(float)height; + (UIImage*)imageWithImage:(UIImage *)image fitOutsideWidth:(float)width fitOutsideHeight:(float)height; + (UIImage*)imageWithImage:(UIImage *)image cropToWidth:(float)width cropToHeight:(float)height; ++ (UIImage*)placeholderImageWithColor:(UIColor *)color size:(CGSize)size; @end diff --git a/Juick/Helpers/UIImage+Utils.m b/Juick/Helpers/UIImage+Utils.m index 4617c65..c209bcf 100644 --- a/Juick/Helpers/UIImage+Utils.m +++ b/Juick/Helpers/UIImage+Utils.m @@ -66,4 +66,18 @@ return img; } ++(UIImage *) placeholderImageWithColor:(UIColor *)color size:(CGSize)size { + CGRect rect = (CGRect){ + .origin = CGPointZero, + .size = size + }; + UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0f); + [color setFill]; + UIRectFill(rect); + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return [[self alloc] initWithCGImage:[image CGImage]]; +} + @end diff --git a/Juick/Main.storyboard b/Juick/Main.storyboard index ebc1465..5394264 100644 --- a/Juick/Main.storyboard +++ b/Juick/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -10,11 +10,11 @@ - + - - + + @@ -29,72 +29,69 @@ - + - + - + - + - - + + - - + + - + - - + + - - + + - - - + + - - - - - - - + + + + @@ -107,45 +104,50 @@ - - - - + - - - - + + + + + - - - - - - - + + + + + + + + @@ -154,66 +156,162 @@ - - - - + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + + + + + + + + + + + + + + + + + + - Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. - - - + + + + + + + - + - - - - + + + + - + - + + + + + - + - - + + - - + + - + - - + - - - + diff --git a/Juick/Model/Attachment.h b/Juick/Model/Attachment.h new file mode 100644 index 0000000..26fc1c0 --- /dev/null +++ b/Juick/Model/Attachment.h @@ -0,0 +1,18 @@ +// +// Attachment.h +// Juick +// +// Created by Vitaly Takmazov on 15/10/2017. +// Copyright © 2017 com.juick. All rights reserved. +// + +#import + +@interface Attachment : NSObject +@property(nonatomic, strong) NSString *url; +@property(nonatomic, strong) NSNumber *width; +@property(nonatomic, strong) NSNumber *height; +@property(nonatomic, strong) Attachment *small; +@property(nonatomic, strong) Attachment *medium; +@property(nonatomic, strong) Attachment *thumbnail; +@end diff --git a/Juick/Model/Attachment.m b/Juick/Model/Attachment.m new file mode 100644 index 0000000..a54e462 --- /dev/null +++ b/Juick/Model/Attachment.m @@ -0,0 +1,13 @@ +// +// Attachment.m +// Juick +// +// Created by Vitaly Takmazov on 15/10/2017. +// Copyright © 2017 com.juick. All rights reserved. +// + +#import "Attachment.h" + +@implementation Attachment + +@end diff --git a/Juick/Model/Message.h b/Juick/Model/Message.h index 1b41315..5eab279 100644 --- a/Juick/Model/Message.h +++ b/Juick/Model/Message.h @@ -8,6 +8,7 @@ #import #import "User.h" +#import "Attachment.h" @interface Message : NSObject @@ -20,5 +21,6 @@ @property NSString *attach; @property NSString *repliesBy; @property NSNumber *repliesCount; +@property Attachment *attachment; @end diff --git a/Juick/Supporting Files/Juick-Prefix.pch b/Juick/Supporting Files/Juick-Prefix.pch index 1062827..1af6911 100644 --- a/Juick/Supporting Files/Juick-Prefix.pch +++ b/Juick/Supporting Files/Juick-Prefix.pch @@ -15,4 +15,5 @@ #import #import #import + #import #endif diff --git a/Juick/ViewControllers/MessagesViewController.m b/Juick/ViewControllers/MessagesViewController.m index b877cd1..badc4a3 100644 --- a/Juick/ViewControllers/MessagesViewController.m +++ b/Juick/ViewControllers/MessagesViewController.m @@ -7,7 +7,6 @@ // #import "MessagesViewController.h" -@import YYWebImage; #import "MessageCell.h" #import "Message.h" @@ -21,7 +20,7 @@ #import "NSURL+PathParameters.h" -@interface MessagesViewController (); +@interface MessagesViewController () @property(nonatomic, strong) NSMutableArray *messages; @property(nonatomic, assign) Boolean dataLoading; @@ -63,18 +62,16 @@ self.dataLoading = NO; [self.view setBackgroundColor:[ColorScheme mainBackground]]; - self.messages = [NSMutableArray array]; - self.params = [NSMutableDictionary new]; - self.tableView.rowHeight = UITableViewAutomaticDimension; self.tableView.estimatedRowHeight = 500.0f; + self.messages = [NSMutableArray array]; + self.params = [NSMutableDictionary new]; self.refreshControl = [UIRefreshControl new]; [self.refreshControl addTarget:self action:@selector(refreshData) forControlEvents:UIControlEventValueChanged]; if ([User isAuthenticated]) { [User checkIsValid:^(BOOL success) { if (success) { self.path = [APIClient feedUrl]; - [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert|UIUserNotificationTypeSound|UIUserNotificationTypeBadge) categories:nil]]; [self refreshData]; } else { [User throwUnableToLogin]; @@ -85,36 +82,12 @@ self.path = [APIClient messagesUrl]; [self refreshData]; } - self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"profile_icon"] style:UIBarButtonItemStylePlain target:self action:@selector(composePressed)]; - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"settings_icon"] style:UIBarButtonItemStylePlain target:self action:@selector(composePressed)]; } - (void) composePressed { } -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(contentSizeCategoryChanged:) - name:UIContentSizeCategoryDidChangeNotification - object:nil]; -} - -- (void)viewDidDisappear:(BOOL)animated -{ - [super viewDidDisappear:animated]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:UIContentSizeCategoryDidChangeNotification - object:nil]; -} - -- (void)contentSizeCategoryChanged:(NSNotification *)notification -{ - [self.tableView reloadData]; -} - - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } @@ -124,20 +97,10 @@ } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - MessageCell *cell = [tableView dequeueReusableCellWithIdentifier:@"messageCell" forIndexPath:indexPath]; Message *msg = [self.messages objectAtIndex:indexPath.row]; - cell.layer.borderWidth = 6; - cell.layer.borderColor = [ColorScheme mainBackground].CGColor; - [cell setMessage:msg]; - if ([msg.attach length] > 0) { - [cell.attach yy_setImageWithURL:[NSURL URLWithString:msg.attach] placeholder:[UIImage imageNamed:@"AttachPlaceholder"] options:YYWebImageOptionProgressiveBlur | YYWebImageOptionSetImageWithFadeAnimation completion:^(UIImage * _Nullable image, NSURL * _Nonnull url, YYWebImageFromType from, YYWebImageStage stage, NSError * _Nullable error) { - [cell setNeedsUpdateConstraints]; - [cell updateConstraintsIfNeeded]; - }]; - } else { - cell.attach.image = nil; - } - + NSString * cellIdentifier = @"messageCell"; + MessageCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath]; + [cell configureWithMessage:msg]; return cell; } diff --git a/Juick/ViewControllers/NewPostViewController.h b/Juick/ViewControllers/NewPostViewController.h index ceaca49..3d4ba88 100644 --- a/Juick/ViewControllers/NewPostViewController.h +++ b/Juick/ViewControllers/NewPostViewController.h @@ -9,5 +9,6 @@ #import @interface NewPostViewController : UIViewController - +@property (weak, nonatomic) IBOutlet UITextView *textView; +@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomConstraint; @end diff --git a/Juick/ViewControllers/NewPostViewController.m b/Juick/ViewControllers/NewPostViewController.m index 318de4e..9643b78 100644 --- a/Juick/ViewControllers/NewPostViewController.m +++ b/Juick/ViewControllers/NewPostViewController.m @@ -12,6 +12,7 @@ @interface NewPostViewController () @property (nonatomic, assign) BOOL didSetupConstraints; +@property (nonatomic, assign) int paddingValue; @end @@ -21,14 +22,17 @@ { [super viewDidLoad]; self.navigationController.visibleViewController.title = @"Post"; - self.view.backgroundColor = [ColorScheme mainBackground]; self.navigationController.visibleViewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelCompose)]; self.navigationController.visibleViewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd - target:self action:@selector(doneCompose)]; + target:self action:@selector(doneCompose)]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil]; + [self.textView becomeFirstResponder]; } - (void) cancelCompose { + [self.textView resignFirstResponder]; [self.navigationController.visibleViewController.navigationController popViewControllerAnimated:YES]; } @@ -36,4 +40,17 @@ [self.navigationController.visibleViewController.navigationController popToRootViewControllerAnimated:YES]; } +-(void) keyboardDidShow:(NSNotification *)sender { + CGRect frame = [sender.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; + CGRect newFrame = [self.view convertRect:frame fromView:[[UIApplication sharedApplication] delegate].window]; + [self.view layoutIfNeeded]; + [UIView animateWithDuration:[sender.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue] animations:^{ + self.bottomConstraint.constant = newFrame.origin.y - CGRectGetHeight(self.view.frame) + self.paddingValue; + [self.view layoutIfNeeded]; + }]; +} +-(void) keyboardWillHide:(NSNotification *)sender { + self.bottomConstraint.constant = self.paddingValue; + [self.view layoutIfNeeded]; +} @end diff --git a/Juick/ViewControllers/RootNavigationController.h b/Juick/ViewControllers/RootNavigationController.h deleted file mode 100644 index f7f6734..0000000 --- a/Juick/ViewControllers/RootNavigationController.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// RootNavigationController.h -// Juick -// -// Created by Vitaly Takmazov on 24/09/2017. -// Copyright © 2017 com.juick. All rights reserved. -// - -#import - -@interface RootNavigationController : UINavigationController - -@end diff --git a/Juick/ViewControllers/RootNavigationController.m b/Juick/ViewControllers/RootNavigationController.m deleted file mode 100644 index 9be0a5f..0000000 --- a/Juick/ViewControllers/RootNavigationController.m +++ /dev/null @@ -1,24 +0,0 @@ -// -// RootNavigationController.m -// Juick -// -// Created by Vitaly Takmazov on 24/09/2017. -// Copyright © 2017 com.juick. All rights reserved. -// - -#import "RootNavigationController.h" -#import "ColorScheme.h" - -@interface RootNavigationController () - -@end - -@implementation RootNavigationController - -- (void) awakeFromNib { - [super awakeFromNib]; - [self.toolbar setTintColor:[ColorScheme linkColor]]; - [self.visibleViewController setToolbarItems:@[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"nearby_icon"] style:UIBarButtonItemStylePlain target:self action:nil],[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"new_chat_icon"] style:UIBarButtonItemStylePlain target:self action:nil],[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"chats_icon"] style:UIBarButtonItemStylePlain target:self action:nil],[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]] animated:YES]; -} - -@end diff --git a/Juick/Views/MessageCell.h b/Juick/Views/MessageCell.h index 124ed83..92345d6 100644 --- a/Juick/Views/MessageCell.h +++ b/Juick/Views/MessageCell.h @@ -13,13 +13,14 @@ @interface MessageCell : UITableViewCell @property (weak, nonatomic) IBOutlet UIImageView *avatar; -@property (weak, nonatomic) IBOutlet UILabel *timestamp; @property (weak, nonatomic) IBOutlet UILabel *title; +@property (weak, nonatomic) IBOutlet UILabel *timestamp; @property (weak, nonatomic) IBOutlet TagListView *tags; @property (weak, nonatomic) IBOutlet TTTAttributedLabel *text; @property (weak, nonatomic) IBOutlet UIImageView *attach; +@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachmentHeight; @property (weak, nonatomic) IBOutlet UILabel *summary; -@property (strong, nonatomic) Message * message; +- (void) configureWithMessage:(Message *)msg; @end diff --git a/Juick/Views/MessageCell.m b/Juick/Views/MessageCell.m index cc35446..1cfe304 100644 --- a/Juick/Views/MessageCell.m +++ b/Juick/Views/MessageCell.m @@ -6,11 +6,14 @@ // Copyright © 2016 com.juick. All rights reserved. // + #import "MessageCell.h" -@import YYWebImage; +#import "ColorScheme.h" +#import "UIImage+Utils.h" + @import DateTools; @import MWFeedParser; -#import "ColorScheme.h" +@import YYWebImage; @implementation MessageCell @@ -20,11 +23,22 @@ self.text.delegate = self; self.text.linkAttributes = @{ (id)kCTForegroundColorAttributeName: [ColorScheme linkColor], (id)kCTUnderlineStyleAttributeName : [NSNumber numberWithInt:NSUnderlineStyleSingle] }; + self.title.textColor = [ColorScheme linkColor]; + self.timestamp.textColor = [UIColor grayColor]; + self.summary.textColor = [UIColor grayColor]; + self.tags.textFont = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; } -- (void) setMessage:(Message *)msg { - _message = msg; - self.avatar.yy_imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://i.juick.com/a/%d.png", [msg.user.uid intValue]]]; +- (void) configureWithMessage:(Message *)msg { + [self.avatar setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://i.juick.com/a/%d.png", [msg.user.uid intValue]]]]; + if ([msg.attach length] > 0) { + CGFloat imageHeight = [msg.attachment.small.height floatValue] / [[UIScreen mainScreen] scale]; + self.attachmentHeight.constant = imageHeight; + [self.attach yy_setImageWithURL:[NSURL URLWithString:msg.attach] options:YYWebImageOptionProgressiveBlur|YYWebImageOptionSetImageWithFadeAnimation]; + } else { + self.attachmentHeight.constant = 0; + self.attach.image = nil; + } self.title.text = msg.user.uname; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss"; @@ -51,7 +65,7 @@ } -(void)attributedLabel:(TTTAttributedLabel *)label didSelectLinkWithURL:(NSURL *)url { - [[UIApplication sharedApplication] openURL:url]; + [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; } @end diff --git a/Juick/reveal-icon.png b/Juick/reveal-icon.png deleted file mode 100644 index 4a4d467..0000000 Binary files a/Juick/reveal-icon.png and /dev/null differ diff --git a/Juick/reveal-icon@2x.png b/Juick/reveal-icon@2x.png deleted file mode 100644 index 08dc402..0000000 Binary files a/Juick/reveal-icon@2x.png and /dev/null differ -- cgit v1.2.3