From e4700dab9b73265604cc6c775841aa020e8205d5 Mon Sep 17 00:00:00 2001 From: moritz haarmann Date: Wed, 30 Apr 2014 16:53:20 +0200 Subject: [PATCH] + Refactored Preview of Attachments. --- Classes/BITAttachmentGalleryViewController.h | 19 -- Classes/BITAttachmentGalleryViewController.m | 247 ------------------ Classes/BITFeedbackListViewCell.m | 41 +-- Classes/BITFeedbackListViewController.h | 3 +- Classes/BITFeedbackListViewController.m | 47 +++- Classes/BITFeedbackManager.m | 3 +- Classes/BITFeedbackMessage.m | 2 + ...TFeedbackMessageAttachment+QLPreviewItem.h | 16 ++ ...TFeedbackMessageAttachment+QLPreviewItem.m | 21 ++ Classes/BITFeedbackMessageAttachment.h | 6 +- Classes/BITFeedbackMessageAttachment.m | 121 ++++++--- Classes/View.xib | 31 +++ Support/HockeySDK.xcodeproj/project.pbxproj | 30 +-- 13 files changed, 234 insertions(+), 353 deletions(-) delete mode 100644 Classes/BITAttachmentGalleryViewController.h delete mode 100644 Classes/BITAttachmentGalleryViewController.m create mode 100644 Classes/BITFeedbackMessageAttachment+QLPreviewItem.h create mode 100644 Classes/BITFeedbackMessageAttachment+QLPreviewItem.m create mode 100644 Classes/View.xib diff --git a/Classes/BITAttachmentGalleryViewController.h b/Classes/BITAttachmentGalleryViewController.h deleted file mode 100644 index a745b6dde0..0000000000 --- a/Classes/BITAttachmentGalleryViewController.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// BITAttachmentGalleryViewController.h -// HockeySDK -// -// Created by Moritz Haarmann on 06.03.14. -// -// - -#import - -@class BITFeedbackMessageAttachment; - -@interface BITAttachmentGalleryViewController : UIViewController - -@property (nonatomic, strong) NSArray *messages; - -@property (nonatomic, strong) BITFeedbackMessageAttachment *preselectedAttachment; - -@end diff --git a/Classes/BITAttachmentGalleryViewController.m b/Classes/BITAttachmentGalleryViewController.m deleted file mode 100644 index f3d1fc94d4..0000000000 --- a/Classes/BITAttachmentGalleryViewController.m +++ /dev/null @@ -1,247 +0,0 @@ -// -// BITAttachmentGalleryViewController.m -// HockeySDK -// -// Created by Moritz Haarmann on 06.03.14. -// -// - -#import "BITAttachmentGalleryViewController.h" - -#import "BITFeedbackMessage.h" -#import "BITFeedbackMessageAttachment.h" - -@interface BITAttachmentGalleryViewController () - -@property (nonatomic, strong) UIScrollView *scrollView; -@property (nonatomic, strong) NSArray *imageViews; -@property (nonatomic, strong) NSArray *extractedAttachments; -@property (nonatomic) NSInteger currentIndex; -@property (nonatomic) NSInteger loadedImageIndex; -@property (nonatomic, strong) UITapGestureRecognizer *tapognizer; -@property (nonatomic, strong) NSMutableDictionary *images; - -@end - -@implementation BITAttachmentGalleryViewController - -#pragma mark - UIViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - self.navigationController.navigationBar.translucent = YES; - self.navigationController.navigationBar.opaque = NO; -#if __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_6_1 - self.automaticallyAdjustsScrollViewInsets = NO; - self.edgesForExtendedLayout = YES; - self.extendedLayoutIncludesOpaqueBars = YES; -#endif - self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(close:)]; - - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(share:)]; - - - self.currentIndex = 0; - - [self extractUsableAttachments]; - [self setupScrollView]; - - self.view.frame = UIScreen.mainScreen.applicationFrame; - - - - self.tapognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)]; - [self.view addGestureRecognizer:self.tapognizer]; -} - --(void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - // Hide the navigation bar and stuff initially. - [self tapped:nil]; - - if (self.preselectedAttachment){ - NSInteger indexOfSelectedAttachment = [self.extractedAttachments indexOfObject:self.preselectedAttachment]; - if (indexOfSelectedAttachment != NSNotFound){ - self.currentIndex = indexOfSelectedAttachment; - self.scrollView.contentOffset = CGPointMake(self.scrollView.frame.size.width * self.currentIndex, 0); - } - } - - self.images = [NSMutableDictionary new]; - [self layoutViews]; -} - -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; -} - --(void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; - [self.images removeAllObjects]; -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - [self.images removeAllObjects]; -} - -- (BOOL)prefersStatusBarHidden { - return self.navigationController.navigationBarHidden; -} - -#pragma mark - Scroll View Content/Layout - -- (void)setupScrollView { - self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; - CGRect frame = self.scrollView.frame; - - frame.origin.y = self.scrollView.frame.size.height - [[UIScreen mainScreen] bounds].size.height; - - self.scrollView.frame = frame; - self.view.autoresizesSubviews = NO; - [self.view addSubview:self.scrollView]; - self.scrollView.delegate = self; - self.scrollView.pagingEnabled = YES; - self.scrollView.backgroundColor = [UIColor groupTableViewBackgroundColor]; - self.scrollView.bounces = NO; - - - NSMutableArray *imageviews = [NSMutableArray new]; - - for (int i = 0; i<3; i++){ - UIImageView *newImageView = [[UIImageView alloc] initWithFrame:CGRectZero]; - [imageviews addObject:newImageView]; - newImageView.contentMode = UIViewContentModeScaleAspectFit; - [self.scrollView addSubview:newImageView]; - } - - self.imageViews = imageviews; - -} - -- (void)extractUsableAttachments { - NSMutableArray *extractedOnes = [NSMutableArray new]; - - for (BITFeedbackMessage *message in self.messages){ - for (BITFeedbackMessageAttachment *attachment in message.attachments){ - if ([attachment imageRepresentation]){ - [extractedOnes addObject:attachment]; - } - } - } - - self.extractedAttachments = extractedOnes; -} - - -- (void)layoutViews { - CGPoint savedOffset = self.scrollView.contentOffset; - - self.scrollView.delegate = nil; - self.scrollView.frame = self.view.bounds; - self.scrollView.contentSize = CGSizeMake( [[UIScreen mainScreen] bounds].size.width * self.extractedAttachments.count, [[UIScreen mainScreen] bounds].size.height); - self.scrollView.delegate = self; - self.scrollView.contentInset = UIEdgeInsetsZero; - self.scrollView.autoresizesSubviews = NO; - self.scrollView.contentOffset = savedOffset; - - - NSInteger baseIndex = MAX(0,self.currentIndex-1); - NSInteger z = baseIndex; - for ( NSInteger i = baseIndex; i < MIN(baseIndex+2, self.extractedAttachments.count);i++ ){ - UIImageView *imageView = self.imageViews[z%self.imageViews.count]; - BITFeedbackMessageAttachment *attachment = self.extractedAttachments[i]; - imageView.image = [self imageForAttachment:attachment]; - imageView.frame = [self frameForItemAtIndex:i]; - z++; - } - - CGRect frame = self.scrollView.frame; - - frame.origin.y = self.scrollView.frame.size.height - [[UIScreen mainScreen] bounds].size.height; - - self.scrollView.frame = frame; - -} - -#pragma mark - UIScrollViewDelegate - -- (void)scrollViewDidScroll:(UIScrollView *)scrollView { - NSInteger newIndex = self.scrollView.contentOffset.x / self.scrollView.frame.size.width; - if (newIndex!=self.currentIndex){ - self.currentIndex = newIndex; - [self layoutViews]; - } -} - -#pragma mark - IBActions - -- (void)close:(id)sender { - [self dismissViewControllerAnimated:YES completion:nil]; -} - -- (void)share:(id)sender { - BITFeedbackMessageAttachment *attachment = self.extractedAttachments[self.currentIndex]; - - UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:[NSArray arrayWithObjects:attachment.originalFilename, attachment.imageRepresentation , nil] applicationActivities:nil]; - [self presentViewController:activityVC animated:YES completion:nil]; -} - -#pragma mark - UIGestureRecognizer - -- (void)tapped:(UITapGestureRecognizer *)tapRecognizer { - if (self.navigationController.navigationBar.alpha == 0 || self.navigationController.navigationBarHidden ){ - - [UIView animateWithDuration:0.35f animations:^{ - - if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { - [self.navigationController setNavigationBarHidden:NO animated:NO]; - } else { - self.navigationController.navigationBar.alpha = 1.0; - } - - [[UIApplication sharedApplication] setStatusBarHidden:NO]; - - } completion:^(BOOL finished){ - [self layoutViews]; - }]; - } else { - [UIView animateWithDuration:0.35f animations:^{ - - if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { - [self.navigationController setNavigationBarHidden:YES animated:NO]; - } else { - self.navigationController.navigationBar.alpha = 0.0; - } - - [[UIApplication sharedApplication] setStatusBarHidden:YES]; - - } completion:^(BOOL finished){ - [self layoutViews]; - }]; - } - - -} - -#pragma mark - Layout Helpers - -- (CGRect)frameForItemAtIndex:(NSInteger)index { - return CGRectMake(index * [[UIScreen mainScreen] bounds].size.width, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height); -} - -- (UIImage *)imageForAttachment:(BITFeedbackMessageAttachment *)attachment { - UIImage *cachedObject = self.images[@([self.extractedAttachments indexOfObject:attachment])]; - - if (!cachedObject){ - cachedObject = [attachment imageRepresentation]; - self.images[@([self.extractedAttachments indexOfObject:attachment])] = cachedObject; - } - - return cachedObject; -} - -@end diff --git a/Classes/BITFeedbackListViewCell.m b/Classes/BITFeedbackListViewCell.m index 9998a07648..e10afbb82a 100644 --- a/Classes/BITFeedbackListViewCell.m +++ b/Classes/BITFeedbackListViewCell.m @@ -87,15 +87,15 @@ self.dateFormatter = [[NSDateFormatter alloc] init]; [self.dateFormatter setTimeStyle:NSDateFormatterNoStyle]; [self.dateFormatter setDateStyle:NSDateFormatterMediumStyle]; - [self.dateFormatter setLocale:[NSLocale currentLocale]]; + [self.dateFormatter setLocale:[NSLocale currentLocale]]; [self.dateFormatter setDoesRelativeDateFormatting:YES]; - + self.timeFormatter = [[NSDateFormatter alloc] init]; [self.timeFormatter setTimeStyle:NSDateFormatterShortStyle]; [self.timeFormatter setDateStyle:NSDateFormatterNoStyle]; [self.timeFormatter setLocale:[NSLocale currentLocale]]; [self.timeFormatter setDoesRelativeDateFormatting:YES]; - + self.labelTitle = [[UILabel alloc] init]; self.labelTitle.font = [UIFont systemFontOfSize:TITLE_FONTSIZE]; @@ -171,7 +171,7 @@ // added to make space for the images. - + } else { #endif #pragma clang diagnostic push @@ -179,7 +179,7 @@ calculatedHeight = [message.text sizeWithFont:[UIFont systemFontOfSize:TEXT_FONTSIZE] constrainedToSize:CGSizeMake(width - (2 * FRAME_SIDE_BORDER), CGFLOAT_MAX) ].height + FRAME_TOP_BORDER + LABEL_TEXT_Y + FRAME_BOTTOM_BORDER; - + #pragma clang diagnostic pop #if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1 } @@ -190,7 +190,7 @@ - (void)setAttachments:(NSArray *)attachments { for (UIView *view in self.attachmentViews){ - [view removeFromSuperview]; + [view removeFromSuperview]; } [self.attachmentViews removeAllObjects]; @@ -198,9 +198,14 @@ for (BITFeedbackMessageAttachment *attachment in attachments){ UIButton *imageView = [UIButton buttonWithType:UIButtonTypeCustom]; [imageView setImage:[attachment thumbnailWithSize:CGSizeMake(ATTACHMENT_SIZE, ATTACHMENT_SIZE)] forState:UIControlStateNormal]; + [imageView setTitle:attachment.originalFilename forState:UIControlStateNormal]; + [imageView setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter]; + [imageView setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter]; [imageView addTarget:self action:@selector(imageButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; + imageView.contentMode = UIViewContentModeScaleAspectFill; + [self.attachmentViews addObject:imageView]; } } @@ -208,12 +213,12 @@ - (void)layoutSubviews { if (!self.accessoryBackgroundView){ - self.accessoryBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 2, self.frame.size.width * 2, self.frame.size.height - 2)]; - self.accessoryBackgroundView.autoresizingMask = UIViewAutoresizingFlexibleHeight; - self.accessoryBackgroundView.clipsToBounds = YES; - - // colors - self.accessoryBackgroundView.backgroundColor = [self backgroundColor]; + self.accessoryBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 2, self.frame.size.width * 2, self.frame.size.height - 2)]; + self.accessoryBackgroundView.autoresizingMask = UIViewAutoresizingFlexibleHeight; + self.accessoryBackgroundView.clipsToBounds = YES; + + // colors + self.accessoryBackgroundView.backgroundColor = [self backgroundColor]; } if (self.style == BITFeedbackListViewCellPresentatationStyleDefault) { @@ -231,9 +236,9 @@ } else { [self.labelText setTextColor:TEXTCOLOR_DEFAULT]; } - + // background for deletion accessory view - + // header NSString *dateString = @""; @@ -248,7 +253,7 @@ } [self.labelTitle setText:dateString]; [self.labelTitle setFrame:CGRectMake(FRAME_SIDE_BORDER, FRAME_TOP_BORDER + LABEL_TITLE_Y, self.frame.size.width - (2 * FRAME_SIDE_BORDER), LABEL_TITLE_HEIGHT)]; - + if (_message.userMessage) { self.labelTitle.textAlignment = kBITTextLabelAlignmentRight; self.labelText.textAlignment = kBITTextLabelAlignmentRight; @@ -256,13 +261,13 @@ self.labelTitle.textAlignment = kBITTextLabelAlignmentLeft; self.labelText.textAlignment = kBITTextLabelAlignmentLeft; } - + [self addSubview:self.labelTitle]; - + // text [self.labelText setText:_message.text]; CGSize sizeForTextLabel = CGSizeMake(self.frame.size.width - (2 * FRAME_SIDE_BORDER), - [[self class] heightForTextInRowWithMessage:_message tableViewWidth:self.frame.size.width] - LABEL_TEXT_Y - FRAME_BOTTOM_BORDER); + [[self class] heightForTextInRowWithMessage:_message tableViewWidth:self.frame.size.width] - LABEL_TEXT_Y - FRAME_BOTTOM_BORDER); [self.labelText setFrame:CGRectMake(FRAME_SIDE_BORDER, LABEL_TEXT_Y, sizeForTextLabel.width, sizeForTextLabel.height)]; diff --git a/Classes/BITFeedbackListViewController.h b/Classes/BITFeedbackListViewController.h index 0a513904cf..8ee2b064d9 100644 --- a/Classes/BITFeedbackListViewController.h +++ b/Classes/BITFeedbackListViewController.h @@ -28,6 +28,7 @@ #import +#import #import "BITHockeyBaseViewController.h" @@ -54,7 +55,7 @@ This ensures that the presentation on iOS 6 and iOS 7 will use the corret design on each OS Version. */ -@interface BITFeedbackListViewController : BITHockeyBaseViewController { +@interface BITFeedbackListViewController : BITHockeyBaseViewController { } @end diff --git a/Classes/BITFeedbackListViewController.m b/Classes/BITFeedbackListViewController.m index 70f58a1f8a..88b92d2ef6 100644 --- a/Classes/BITFeedbackListViewController.m +++ b/Classes/BITFeedbackListViewController.m @@ -39,13 +39,15 @@ #import "BITFeedbackComposeViewController.h" #import "BITFeedbackUserDataViewController.h" #import "BITFeedbackMessage.h" +#import "BITFeedbackMessageAttachment.h" +#import "BITFeedbackMessageAttachment+QLPreviewItem.h" #import "BITAttributedLabel.h" -#import "BITAttachmentGalleryViewController.h" #import "BITHockeyBaseManagerPrivate.h" #import "BITHockeyHelper.h" #import +#import #define DEFAULT_BACKGROUNDCOLOR BIT_RGBCOLOR(245, 245, 245) @@ -70,6 +72,7 @@ @property (nonatomic, weak) BITFeedbackManager *manager; @property (nonatomic, strong) NSDateFormatter *lastUpdateDateFormatter; @property (nonatomic) BOOL userDataComposeFlow; +@property (nonatomic, strong) NSArray *cachedPreviewItems; @end @@ -330,6 +333,7 @@ -(void)userDataUpdateFinished { [self.manager saveMessages]; + [self refreshPreviewItems]; if (self.userDataComposeFlow) { if ([self.manager showFirstRequiredPresentationModal]) { @@ -771,19 +775,46 @@ } } +#pragma mark - ListViewCellDelegate + - (void)listCell:(id)cell didSelectAttachment:(BITFeedbackMessageAttachment *)attachment { - BITAttachmentGalleryViewController *galleryController = [BITAttachmentGalleryViewController new]; - UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:galleryController]; + QLPreviewController *previewController = [[QLPreviewController alloc] init]; + previewController.dataSource = self; + + [self presentViewController:previewController animated:YES completion:nil]; + + [previewController setCurrentPreviewItemIndex:[self.cachedPreviewItems indexOfObject:attachment]]; - NSMutableArray *collectedMessages = [NSMutableArray new]; +} +- (void)refreshPreviewItems { + self.cachedPreviewItems = nil; + NSMutableArray *collectedAttachments = [NSMutableArray new]; for (int i = 0; i) previewController: (QLPreviewController *) controller previewItemAtIndex: (NSInteger) index { + if (index>=0){ + return self.cachedPreviewItems[index];} + return nil; } @end diff --git a/Classes/BITFeedbackManager.m b/Classes/BITFeedbackManager.m index 5cd2091d1f..c2cf0facc5 100644 --- a/Classes/BITFeedbackManager.m +++ b/Classes/BITFeedbackManager.m @@ -739,7 +739,7 @@ newAttachment.originalFilename = attachmentData[@"file_name"]; newAttachment.id = attachmentData[@"id"]; newAttachment.sourceURL = attachmentData[@"url"]; - newAttachment.contentType = @"image/jpg"; + newAttachment.contentType = attachmentData[@"content_type"]; [message addAttachmentsObject:newAttachment]; } @@ -1048,7 +1048,6 @@ completionHandler:^(NSError *err){ if (err) { [self markSendInProgressMessagesAsPending]; - [self saveMessages]; } diff --git a/Classes/BITFeedbackMessage.m b/Classes/BITFeedbackMessage.m index 446fb0da3c..6d2ab49c11 100644 --- a/Classes/BITFeedbackMessage.m +++ b/Classes/BITFeedbackMessage.m @@ -96,4 +96,6 @@ } self.attachments = [self.attachments arrayByAddingObject:object]; } + + @end diff --git a/Classes/BITFeedbackMessageAttachment+QLPreviewItem.h b/Classes/BITFeedbackMessageAttachment+QLPreviewItem.h new file mode 100644 index 0000000000..5c05718ae1 --- /dev/null +++ b/Classes/BITFeedbackMessageAttachment+QLPreviewItem.h @@ -0,0 +1,16 @@ +// +// BITFeedbackMessageAttachment+QLPreviewItem.h +// HockeySDK +// +// Created by Moritz Haarmann on 30.04.14. +// +// + +#import "BITFeedbackMessageAttachment.h" +#import + +@interface BITFeedbackMessageAttachment (QLPreviewItem) + + + +@end diff --git a/Classes/BITFeedbackMessageAttachment+QLPreviewItem.m b/Classes/BITFeedbackMessageAttachment+QLPreviewItem.m new file mode 100644 index 0000000000..da5424ebeb --- /dev/null +++ b/Classes/BITFeedbackMessageAttachment+QLPreviewItem.m @@ -0,0 +1,21 @@ +// +// BITFeedbackMessageAttachment+QLPreviewItem.m +// HockeySDK +// +// Created by Moritz Haarmann on 30.04.14. +// +// + +#import "BITFeedbackMessageAttachment+QLPreviewItem.h" + +@implementation BITFeedbackMessageAttachment (QLPreviewItem) + +- (NSString *)previewItemTitle { + return self.originalFilename; +} + +- (NSURL *)previewItemURL { + return self.localURL; +} + +@end diff --git a/Classes/BITFeedbackMessageAttachment.h b/Classes/BITFeedbackMessageAttachment.h index 1d05641971..a76b995e68 100644 --- a/Classes/BITFeedbackMessageAttachment.h +++ b/Classes/BITFeedbackMessageAttachment.h @@ -49,6 +49,10 @@ - (void)deleteContents; --(BOOL)needsLoadingFromURL; +- (BOOL)needsLoadingFromURL; + +- (BOOL)isImage; + +- (NSURL *)localURL; @end diff --git a/Classes/BITFeedbackMessageAttachment.m b/Classes/BITFeedbackMessageAttachment.m index 3350b96d24..541d25fd53 100644 --- a/Classes/BITFeedbackMessageAttachment.m +++ b/Classes/BITFeedbackMessageAttachment.m @@ -30,6 +30,7 @@ #import "BITFeedbackMessageAttachment.h" #import "BITHockeyHelper.h" #import "HockeySDKPrivate.h" +#import #define kCacheFolderName @"hockey_attachments" @@ -52,7 +53,7 @@ formatter = [NSDateFormatter new]; formatter.dateStyle = NSDateFormatterShortStyle; formatter.timeStyle = NSDateFormatterShortStyle; - + } BITFeedbackMessageAttachment *newAttachment = [BITFeedbackMessageAttachment new]; @@ -97,6 +98,17 @@ return (self.sourceURL); } +- (BOOL)isImage { + return ([self.contentType rangeOfString:@"image"].location != NSNotFound); +} + +- (NSURL *)localURL { + if (self.filename){ + return [NSURL fileURLWithPath:self.filename]; + } else + { return nil;} +} + #pragma mark NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder { @@ -104,8 +116,8 @@ [aCoder encodeObject:self.filename forKey:@"filename"]; [aCoder encodeObject:self.originalFilename forKey:@"originalFilename"]; [aCoder encodeObject:self.sourceURL forKey:@"url"]; - - + + } - (id)initWithCoder:(NSCoder *)aDecoder { @@ -117,7 +129,7 @@ self.thumbnailRepresentations = [NSMutableDictionary new]; self.originalFilename = [aDecoder decodeObjectForKey:@"originalFilename"]; self.sourceURL = [aDecoder decodeObjectForKey:@"sourceURL"]; - + } return self; @@ -126,10 +138,14 @@ #pragma mark - Thubmnails / Image Representation - (UIImage *)imageRepresentation { - if ([self.contentType rangeOfString:@"image"].location != NSNotFound || [self.sourceURL rangeOfString:@"jpeg"].location != NSNotFound){ + if ([self.contentType rangeOfString:@"image"].location != NSNotFound ){ return [UIImage imageWithData:self.data]; } else { - return bit_imageNamed(@"feedbackActiviy.png", BITHOCKEYSDK_BUNDLE); // TODO add another placeholder. + // Create a Icon .. + UIDocumentInteractionController* docController = [[UIDocumentInteractionController alloc] init]; + docController.name = self.originalFilename; + NSArray* icons = docController.icons; + return icons[0]; } } @@ -139,46 +155,69 @@ if (!self.thumbnailRepresentations[cacheKey]){ UIImage *image = self.imageRepresentation; // consider the scale. + if (!image) + return nil; CGFloat scale = [UIScreen mainScreen].scale; - CGSize scaledSize = CGSizeApplyAffineTransform(size, CGAffineTransformMakeScale(scale, scale)); - UIImage *thumbnail = bit_imageToFitSize(image, scaledSize, NO) ; + if (scale != image.scale){ + + CGSize scaledSize = CGSizeApplyAffineTransform(size, CGAffineTransformMakeScale(scale, scale)); + UIImage *thumbnail = bit_imageToFitSize(image, scaledSize, YES) ; + + UIImage *scaledTumbnail = [UIImage imageWithCGImage:thumbnail.CGImage scale:scale orientation:thumbnail.imageOrientation]; + if (thumbnail){ + [self.thumbnailRepresentations setObject:scaledTumbnail forKey:cacheKey]; + } + + } else { + UIImage *thumbnail = bit_imageToFitSize(image, size, YES) ; + + [self.thumbnailRepresentations setObject:thumbnail forKey:cacheKey]; + + } - UIImage *scaledTumbnail = [UIImage imageWithCGImage:thumbnail.CGImage scale:scale orientation:thumbnail.imageOrientation]; - if (thumbnail){ - [self.thumbnailRepresentations setObject:scaledTumbnail forKey:cacheKey]; + } + + return self.thumbnailRepresentations[cacheKey]; + } + +#pragma mark - Persistence Helpers + + - (NSString *)createFilename { + NSArray* cachePathArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + NSString* cachePath = [cachePathArray lastObject]; + cachePath = [cachePath stringByAppendingPathComponent:kCacheFolderName]; + + BOOL isDirectory; + + if (![[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&isDirectory]){ + [[NSFileManager defaultManager] createDirectoryAtPath:cachePath withIntermediateDirectories:YES attributes:nil error:nil]; + } + + NSString *uniqueString = bit_UUID(); + cachePath = [cachePath stringByAppendingPathComponent:uniqueString]; + + // File extension that suits the Content type. + + CFStringRef mimeType = (__bridge CFStringRef)self.contentType; + CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL); + CFStringRef extension = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension); + + cachePath = [cachePath stringByAppendingPathExtension:(__bridge NSString *)(extension)]; + + CFRelease(uti); + CFRelease(extension); + + return cachePath; + } + + - (void)deleteContents { + if (self.filename){ + [[NSFileManager defaultManager] removeItemAtPath:self.filename error:nil]; + self.filename = nil; } } - return self.thumbnailRepresentations[cacheKey]; -} - -#pragma mark - Persistence Helpers - -- (NSString *)createFilename { - NSArray* cachePathArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); - NSString* cachePath = [cachePathArray lastObject]; - cachePath = [cachePath stringByAppendingPathComponent:kCacheFolderName]; - BOOL isDirectory; - - if (![[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&isDirectory]){ - [[NSFileManager defaultManager] createDirectoryAtPath:cachePath withIntermediateDirectories:YES attributes:nil error:nil]; - } - - NSString *uniqueString = bit_UUID(); - cachePath = [cachePath stringByAppendingPathComponent:uniqueString]; - - return cachePath; -} - -- (void)deleteContents { - if (self.filename){ - [[NSFileManager defaultManager] removeItemAtPath:self.filename error:nil]; - self.filename = nil; - } -} - - -@end + @end diff --git a/Classes/View.xib b/Classes/View.xib new file mode 100644 index 0000000000..8cd84946d0 --- /dev/null +++ b/Classes/View.xib @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Support/HockeySDK.xcodeproj/project.pbxproj b/Support/HockeySDK.xcodeproj/project.pbxproj index 993fffc7ea..3d5d956fde 100644 --- a/Support/HockeySDK.xcodeproj/project.pbxproj +++ b/Support/HockeySDK.xcodeproj/project.pbxproj @@ -140,8 +140,6 @@ 973EC8BC18BDE29800DBFFBB /* BITArrowImageAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 973EC8BA18BDE29800DBFFBB /* BITArrowImageAnnotation.m */; }; 973EC8BF18BE2B5B00DBFFBB /* BITBlurImageAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = 973EC8BD18BE2B5B00DBFFBB /* BITBlurImageAnnotation.h */; }; 973EC8C018BE2B5B00DBFFBB /* BITBlurImageAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 973EC8BE18BE2B5B00DBFFBB /* BITBlurImageAnnotation.m */; }; - 973EC91818C87E7300DBFFBB /* BITAttachmentGalleryViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 973EC91618C87E7300DBFFBB /* BITAttachmentGalleryViewController.h */; }; - 973EC91918C87E7300DBFFBB /* BITAttachmentGalleryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 973EC91718C87E7300DBFFBB /* BITAttachmentGalleryViewController.m */; }; 9760F6C418BB4D2D00959B93 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9760F6C318BB4D2D00959B93 /* AssetsLibrary.framework */; }; 9760F6CF18BB685600959B93 /* BITImageAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = 9760F6CD18BB685600959B93 /* BITImageAnnotation.h */; }; 9760F6D018BB685600959B93 /* BITImageAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 9760F6CE18BB685600959B93 /* BITImageAnnotation.m */; }; @@ -155,6 +153,9 @@ 9782023918F81BFC00A98D8B /* Ok@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9782022F18F81BFC00A98D8B /* Ok@2x.png */; }; 9782023A18F81BFC00A98D8B /* Rectangle.png in Resources */ = {isa = PBXBuildFile; fileRef = 9782023018F81BFC00A98D8B /* Rectangle.png */; }; 9782023B18F81BFC00A98D8B /* Rectangle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9782023118F81BFC00A98D8B /* Rectangle@2x.png */; }; + 97BD9BD21911085A0043FD59 /* BITFeedbackMessageAttachment+QLPreviewItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 97BD9BD01911085A0043FD59 /* BITFeedbackMessageAttachment+QLPreviewItem.h */; }; + 97BD9BD31911085A0043FD59 /* BITFeedbackMessageAttachment+QLPreviewItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 97BD9BD11911085A0043FD59 /* BITFeedbackMessageAttachment+QLPreviewItem.m */; }; + 97BD9BD5191109730043FD59 /* QuickLook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 97BD9BD4191109730043FD59 /* QuickLook.framework */; }; 97F0F9FD18ABAECD00EF50AA /* iconCamera.png in Resources */ = {isa = PBXBuildFile; fileRef = 97F0F9FB18ABAECD00EF50AA /* iconCamera.png */; }; 97F0F9FE18ABAECD00EF50AA /* iconCamera@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 97F0F9FC18ABAECD00EF50AA /* iconCamera@2x.png */; }; 97F0FA0518B2294D00EF50AA /* BITFeedbackMessageAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = 97F0FA0318AE5AED00EF50AA /* BITFeedbackMessageAttachment.m */; }; @@ -324,8 +325,6 @@ 973EC8BA18BDE29800DBFFBB /* BITArrowImageAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITArrowImageAnnotation.m; sourceTree = ""; }; 973EC8BD18BE2B5B00DBFFBB /* BITBlurImageAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITBlurImageAnnotation.h; sourceTree = ""; }; 973EC8BE18BE2B5B00DBFFBB /* BITBlurImageAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITBlurImageAnnotation.m; sourceTree = ""; }; - 973EC91618C87E7300DBFFBB /* BITAttachmentGalleryViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITAttachmentGalleryViewController.h; sourceTree = ""; }; - 973EC91718C87E7300DBFFBB /* BITAttachmentGalleryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITAttachmentGalleryViewController.m; sourceTree = ""; }; 9760F6C318BB4D2D00959B93 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; 9760F6CD18BB685600959B93 /* BITImageAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITImageAnnotation.h; sourceTree = ""; }; 9760F6CE18BB685600959B93 /* BITImageAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITImageAnnotation.m; sourceTree = ""; }; @@ -339,6 +338,10 @@ 9782022F18F81BFC00A98D8B /* Ok@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Ok@2x.png"; sourceTree = ""; }; 9782023018F81BFC00A98D8B /* Rectangle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Rectangle.png; sourceTree = ""; }; 9782023118F81BFC00A98D8B /* Rectangle@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Rectangle@2x.png"; sourceTree = ""; }; + 97BD9BD01911085A0043FD59 /* BITFeedbackMessageAttachment+QLPreviewItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "BITFeedbackMessageAttachment+QLPreviewItem.h"; sourceTree = ""; }; + 97BD9BD11911085A0043FD59 /* BITFeedbackMessageAttachment+QLPreviewItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "BITFeedbackMessageAttachment+QLPreviewItem.m"; sourceTree = ""; }; + 97BD9BD4191109730043FD59 /* QuickLook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLook.framework; path = System/Library/Frameworks/QuickLook.framework; sourceTree = SDKROOT; }; + 97BD9BDF19113F9B0043FD59 /* View.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = View.xib; sourceTree = ""; }; 97F0F9FB18ABAECD00EF50AA /* iconCamera.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = iconCamera.png; sourceTree = ""; }; 97F0F9FC18ABAECD00EF50AA /* iconCamera@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iconCamera@2x.png"; sourceTree = ""; }; 97F0F9FF18AE375E00EF50AA /* BITImageAnnotationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITImageAnnotationViewController.h; sourceTree = ""; }; @@ -370,6 +373,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 97BD9BD5191109730043FD59 /* QuickLook.framework in Frameworks */, 9760F6C418BB4D2D00959B93 /* AssetsLibrary.framework in Frameworks */, 1E5954DC15B6F24A00A03429 /* Foundation.framework in Frameworks */, 1E5954DD15B6F24A00A03429 /* CrashReporter.framework in Frameworks */, @@ -505,7 +509,6 @@ 1E754E461621FA9A0070AB92 /* Feedback */ = { isa = PBXGroup; children = ( - 973EC91518C87E5A00DBFFBB /* Image Viewer */, 9760F6CC18BB684200959B93 /* Image Editor */, 1E49A4361612223B00463151 /* BITFeedbackMessage.h */, 1E49A4371612223B00463151 /* BITFeedbackMessage.m */, @@ -518,6 +521,7 @@ 1E49A4391612223B00463151 /* BITFeedbackUserDataViewController.m */, 1E49A42F1612223B00463151 /* BITFeedbackListViewCell.h */, 1E49A4301612223B00463151 /* BITFeedbackListViewCell.m */, + 97BD9BDF19113F9B0043FD59 /* View.xib */, 1E49A4311612223B00463151 /* BITFeedbackListViewController.h */, 1E49A4321612223B00463151 /* BITFeedbackListViewController.m */, 1EF95CA4162CB036000AE3AD /* BITFeedbackActivity.h */, @@ -526,6 +530,8 @@ 1E49A4341612223B00463151 /* BITFeedbackManager.m */, E405266117A2AD300096359C /* BITFeedbackManagerDelegate.h */, 1E49A4351612223B00463151 /* BITFeedbackManagerPrivate.h */, + 97BD9BD01911085A0043FD59 /* BITFeedbackMessageAttachment+QLPreviewItem.h */, + 97BD9BD11911085A0043FD59 /* BITFeedbackMessageAttachment+QLPreviewItem.m */, ); name = Feedback; sourceTree = ""; @@ -604,15 +610,6 @@ name = Private; sourceTree = ""; }; - 973EC91518C87E5A00DBFFBB /* Image Viewer */ = { - isa = PBXGroup; - children = ( - 973EC91618C87E7300DBFFBB /* BITAttachmentGalleryViewController.h */, - 973EC91718C87E7300DBFFBB /* BITAttachmentGalleryViewController.m */, - ); - name = "Image Viewer"; - sourceTree = ""; - }; 9760F6CC18BB684200959B93 /* Image Editor */ = { isa = PBXGroup; children = ( @@ -658,6 +655,7 @@ E400561C148D79B500EB22B9 /* Frameworks */ = { isa = PBXGroup; children = ( + 97BD9BD4191109730043FD59 /* QuickLook.framework */, 9760F6C318BB4D2D00959B93 /* AssetsLibrary.framework */, E41EB48B148D7C4E0015DEDC /* CrashReporter.framework */, E400561D148D79B500EB22B9 /* Foundation.framework */, @@ -735,6 +733,7 @@ 1E59559A15B6FDA500A03429 /* BITHockeyManager.h in Headers */, 1E5955FD15B7877B00A03429 /* BITHockeyManagerDelegate.h in Headers */, 1E754E5C1621FBB70070AB92 /* BITCrashManager.h in Headers */, + 97BD9BD21911085A0043FD59 /* BITFeedbackMessageAttachment+QLPreviewItem.h in Headers */, 1E754E5E1621FBB70070AB92 /* BITCrashManagerDelegate.h in Headers */, 1E49A4731612226D00463151 /* BITUpdateManager.h in Headers */, 1E49A4791612226D00463151 /* BITUpdateManagerDelegate.h in Headers */, @@ -760,7 +759,6 @@ 1E49A47C1612226D00463151 /* BITUpdateManagerPrivate.h in Headers */, 1E49A4851612226D00463151 /* BITUpdateViewControllerPrivate.h in Headers */, 1E49A4B5161222B900463151 /* BITHockeyBaseManagerPrivate.h in Headers */, - 973EC91818C87E7300DBFFBB /* BITAttachmentGalleryViewController.h in Headers */, E4933E8017B66CDA00B11ACC /* BITHTTPOperation.h in Headers */, 1E49A4BE161222B900463151 /* BITHockeyHelper.h in Headers */, 973EC8BB18BDE29800DBFFBB /* BITArrowImageAnnotation.h in Headers */, @@ -989,7 +987,7 @@ files = ( 1E5954D315B6F24A00A03429 /* BITHockeyManager.m in Sources */, 1E49A43F1612223B00463151 /* BITFeedbackComposeViewController.m in Sources */, - 973EC91918C87E7300DBFFBB /* BITAttachmentGalleryViewController.m in Sources */, + 97BD9BD31911085A0043FD59 /* BITFeedbackMessageAttachment+QLPreviewItem.m in Sources */, E40E0B0D17DA1AFF005E38C1 /* BITHockeyAppClient.m in Sources */, 1E49A4451612223B00463151 /* BITFeedbackListViewCell.m in Sources */, 973EC8B818BCA8A200DBFFBB /* BITRectangleImageAnnotation.m in Sources */,