mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 14:45:21 +00:00
Cleanup and bugfixes
- Remove not used code - Fixed some code style - use a subdirectory in the SDK caches folder, instead of creating another folder directly under caches - Height of feedback cells only considers attachments that actually can be previewed. - If an attachment has no source URL and no local URL, don't show it, not even a loading placeholder, don't consider to reserve space in the cell for it - refresh attachment cache when new data is loaded or one or all message(s) with attachments have been deleted locally - `feedbackObservationMode` is a property instead of a method
This commit is contained in:
@@ -1,10 +1,28 @@
|
|||||||
//
|
/*
|
||||||
// BITActivityIndicatorButton.h
|
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
|
||||||
// HockeySDK
|
* All rights reserved.
|
||||||
//
|
*
|
||||||
// Created by Moritz Haarmann on 21.05.14.
|
* Permission is hereby granted, free of charge, to any person
|
||||||
//
|
* obtaining a copy of this software and associated documentation
|
||||||
//
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following
|
||||||
|
* conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,28 @@
|
|||||||
//
|
/*
|
||||||
// BITActivityIndicatorButton.m
|
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
|
||||||
// HockeySDK
|
* All rights reserved.
|
||||||
//
|
*
|
||||||
// Created by Moritz Haarmann on 21.05.14.
|
* Permission is hereby granted, free of charge, to any person
|
||||||
//
|
* obtaining a copy of this software and associated documentation
|
||||||
//
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following
|
||||||
|
* conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
#import "BITActivityIndicatorButton.h"
|
#import "BITActivityIndicatorButton.h"
|
||||||
|
|
||||||
|
|||||||
@@ -602,20 +602,22 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
|
|||||||
if (_crashManagerStatus == BITCrashManagerStatusDisabled) return NO;
|
if (_crashManagerStatus == BITCrashManagerStatusDisabled) return NO;
|
||||||
|
|
||||||
if ([self.fileManager fileExistsAtPath:_crashesDir]) {
|
if ([self.fileManager fileExistsAtPath:_crashesDir]) {
|
||||||
NSString *file = nil;
|
|
||||||
NSError *error = NULL;
|
NSError *error = NULL;
|
||||||
|
|
||||||
NSDirectoryEnumerator *dirEnum = [self.fileManager enumeratorAtPath: _crashesDir];
|
NSArray *dirArray = [self.fileManager contentsOfDirectoryAtPath:_crashesDir error:&error];
|
||||||
|
|
||||||
while ((file = [dirEnum nextObject])) {
|
for (NSString *file in dirArray) {
|
||||||
NSDictionary *fileAttributes = [self.fileManager attributesOfItemAtPath:[_crashesDir stringByAppendingPathComponent:file] error:&error];
|
NSString *filePath = [_crashesDir stringByAppendingPathComponent:file];
|
||||||
if ([[fileAttributes objectForKey:NSFileSize] intValue] > 0 &&
|
|
||||||
|
NSDictionary *fileAttributes = [self.fileManager attributesOfItemAtPath:filePath error:&error];
|
||||||
|
if ([[fileAttributes objectForKey:NSFileType] isEqualToString:NSFileTypeRegular] &&
|
||||||
|
[[fileAttributes objectForKey:NSFileSize] intValue] > 0 &&
|
||||||
![file hasSuffix:@".DS_Store"] &&
|
![file hasSuffix:@".DS_Store"] &&
|
||||||
![file hasSuffix:@".analyzer"] &&
|
![file hasSuffix:@".analyzer"] &&
|
||||||
![file hasSuffix:@".plist"] &&
|
![file hasSuffix:@".plist"] &&
|
||||||
![file hasSuffix:@".data"] &&
|
![file hasSuffix:@".data"] &&
|
||||||
![file hasSuffix:@".meta"]) {
|
![file hasSuffix:@".meta"]) {
|
||||||
[_crashFiles addObject:[_crashesDir stringByAppendingPathComponent: file]];
|
[_crashFiles addObject:filePath];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cell style depending on the iOS version
|
* Cell style depending on the iOS version
|
||||||
*/
|
*/
|
||||||
@@ -67,6 +68,7 @@ typedef NS_ENUM(NSUInteger, BITFeedbackListViewCellBackgroundStyle) {
|
|||||||
BITFeedbackListViewCellBackgroundStyleAlternate = 1
|
BITFeedbackListViewCellBackgroundStyleAlternate = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@interface BITFeedbackListViewCell : UITableViewCell
|
@interface BITFeedbackListViewCell : UITableViewCell
|
||||||
|
|
||||||
@property (nonatomic, strong) BITFeedbackMessage *message;
|
@property (nonatomic, strong) BITFeedbackMessage *message;
|
||||||
|
|||||||
@@ -152,7 +152,7 @@
|
|||||||
|
|
||||||
CGFloat attachmentsPerRow = floorf(width / (FRAME_SIDE_BORDER + ATTACHMENT_SIZE));
|
CGFloat attachmentsPerRow = floorf(width / (FRAME_SIDE_BORDER + ATTACHMENT_SIZE));
|
||||||
|
|
||||||
CGFloat calculatedHeight = baseHeight + (FRAME_TOP_BORDER + ATTACHMENT_SIZE) * ceil(message.attachments.count/attachmentsPerRow);
|
CGFloat calculatedHeight = baseHeight + (FRAME_TOP_BORDER + ATTACHMENT_SIZE) * ceil([message previewableAttachments].count / attachmentsPerRow);
|
||||||
|
|
||||||
return ceil(calculatedHeight);
|
return ceil(calculatedHeight);
|
||||||
}
|
}
|
||||||
@@ -197,6 +197,7 @@
|
|||||||
[self.attachmentViews removeAllObjects];
|
[self.attachmentViews removeAllObjects];
|
||||||
|
|
||||||
for (BITFeedbackMessageAttachment *attachment in attachments){
|
for (BITFeedbackMessageAttachment *attachment in attachments){
|
||||||
|
if (attachment.localURL || attachment.sourceURL) {
|
||||||
BITActivityIndicatorButton *imageView = [BITActivityIndicatorButton buttonWithType:UIButtonTypeCustom];
|
BITActivityIndicatorButton *imageView = [BITActivityIndicatorButton buttonWithType:UIButtonTypeCustom];
|
||||||
|
|
||||||
if (attachment.localURL){
|
if (attachment.localURL){
|
||||||
@@ -210,9 +211,7 @@
|
|||||||
[imageView addTarget:self action:@selector(imageButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
|
[imageView addTarget:self action:@selector(imageButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
|
||||||
[self.attachmentViews addObject:imageView];
|
[self.attachmentViews addObject:imageView];
|
||||||
//[self addSubview:imageView];
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,18 +285,18 @@
|
|||||||
|
|
||||||
CGFloat attachmentsPerRow = floorf(self.frame.size.width / (FRAME_SIDE_BORDER + ATTACHMENT_SIZE));
|
CGFloat attachmentsPerRow = floorf(self.frame.size.width / (FRAME_SIDE_BORDER + ATTACHMENT_SIZE));
|
||||||
|
|
||||||
for ( BITActivityIndicatorButton *imageButton in self.attachmentViews){
|
for (BITActivityIndicatorButton *imageButton in self.attachmentViews) {
|
||||||
imageButton.contentMode = UIViewContentModeScaleAspectFit;
|
imageButton.contentMode = UIViewContentModeScaleAspectFit;
|
||||||
imageButton.imageView.contentMode = UIViewContentModeScaleAspectFill;
|
imageButton.imageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||||
|
|
||||||
if ( !_message.userMessage){
|
if (!_message.userMessage) {
|
||||||
imageButton.frame = CGRectMake(FRAME_SIDE_BORDER + (FRAME_SIDE_BORDER + ATTACHMENT_SIZE) * (i%(int)attachmentsPerRow) , floor(i/attachmentsPerRow)*(FRAME_SIDE_BORDER + ATTACHMENT_SIZE) + baseOffsetOfText , ATTACHMENT_SIZE, ATTACHMENT_SIZE);
|
imageButton.frame = CGRectMake(FRAME_SIDE_BORDER + (FRAME_SIDE_BORDER + ATTACHMENT_SIZE) * (i%(int)attachmentsPerRow) , floor(i/attachmentsPerRow)*(FRAME_SIDE_BORDER + ATTACHMENT_SIZE) + baseOffsetOfText , ATTACHMENT_SIZE, ATTACHMENT_SIZE);
|
||||||
} else {
|
} else {
|
||||||
imageButton.frame = CGRectMake(self.frame.size.width - FRAME_SIDE_BORDER - ATTACHMENT_SIZE - ((FRAME_SIDE_BORDER + ATTACHMENT_SIZE) * (i%(int)attachmentsPerRow) ), floor(i/attachmentsPerRow)*(FRAME_SIDE_BORDER + ATTACHMENT_SIZE) + baseOffsetOfText , ATTACHMENT_SIZE, ATTACHMENT_SIZE);
|
imageButton.frame = CGRectMake(self.frame.size.width - FRAME_SIDE_BORDER - ATTACHMENT_SIZE - ((FRAME_SIDE_BORDER + ATTACHMENT_SIZE) * (i%(int)attachmentsPerRow) ), floor(i/attachmentsPerRow)*(FRAME_SIDE_BORDER + ATTACHMENT_SIZE) + baseOffsetOfText , ATTACHMENT_SIZE, ATTACHMENT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!imageButton.superview){
|
if (!imageButton.superview) {
|
||||||
if (self.accessoryBackgroundView.superview){
|
if (self.accessoryBackgroundView.superview) {
|
||||||
[self insertSubview:imageButton aboveSubview:self.accessoryBackgroundView];
|
[self insertSubview:imageButton aboveSubview:self.accessoryBackgroundView];
|
||||||
} else {
|
} else {
|
||||||
[self addSubview:imageButton];
|
[self addSubview:imageButton];
|
||||||
@@ -311,10 +310,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)imageButtonPressed:(id)sender {
|
- (void)imageButtonPressed:(id)sender {
|
||||||
if ([self.delegate respondsToSelector:@selector(listCell:didSelectAttachment:)]){
|
if ([self.delegate respondsToSelector:@selector(listCell:didSelectAttachment:)]) {
|
||||||
NSInteger index = [self.attachmentViews indexOfObject:sender];
|
NSInteger index = [self.attachmentViews indexOfObject:sender];
|
||||||
if (index != NSNotFound){
|
if (index != NSNotFound && [self.message previewableAttachments].count > index) {
|
||||||
BITFeedbackMessageAttachment *attachment = self.message.attachments[index];
|
BITFeedbackMessageAttachment *attachment = [self.message previewableAttachments][index];
|
||||||
[self.delegate listCell:self didSelectAttachment:attachment];
|
[self.delegate listCell:self didSelectAttachment:attachment];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,13 +135,13 @@
|
|||||||
[self.tableView setBackgroundColor:[UIColor colorWithRed:0.82 green:0.84 blue:0.84 alpha:1]];
|
[self.tableView setBackgroundColor:[UIColor colorWithRed:0.82 green:0.84 blue:0.84 alpha:1]];
|
||||||
[self.tableView setSeparatorColor:[UIColor colorWithRed:0.79 green:0.79 blue:0.79 alpha:1]];
|
[self.tableView setSeparatorColor:[UIColor colorWithRed:0.79 green:0.79 blue:0.79 alpha:1]];
|
||||||
} else {
|
} else {
|
||||||
// [self.tableView setBackgroundColor:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1]];
|
// [self.tableView setBackgroundColor:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([self.manager isPreiOS7Environment]) {
|
if ([self.manager isPreiOS7Environment]) {
|
||||||
self.view.backgroundColor = DEFAULT_BACKGROUNDCOLOR;
|
self.view.backgroundColor = DEFAULT_BACKGROUNDCOLOR;
|
||||||
} else {
|
} else {
|
||||||
// self.view.backgroundColor = DEFAULT_BACKGROUNDCOLOR_OS7;
|
// self.view.backgroundColor = DEFAULT_BACKGROUNDCOLOR_OS7;
|
||||||
}
|
}
|
||||||
|
|
||||||
id refreshClass = NSClassFromString(@"UIRefreshControl");
|
id refreshClass = NSClassFromString(@"UIRefreshControl");
|
||||||
@@ -191,7 +191,9 @@
|
|||||||
CGSize contentSize = self.tableView.contentSize;
|
CGSize contentSize = self.tableView.contentSize;
|
||||||
CGPoint contentOffset = self.tableView.contentOffset;
|
CGPoint contentOffset = self.tableView.contentOffset;
|
||||||
|
|
||||||
|
[self refreshPreviewItems];
|
||||||
[self.tableView reloadData];
|
[self.tableView reloadData];
|
||||||
|
|
||||||
if (contentSize.height > 0 &&
|
if (contentSize.height > 0 &&
|
||||||
self.tableView.contentSize.height > self.tableView.frame.size.height &&
|
self.tableView.contentSize.height > self.tableView.frame.size.height &&
|
||||||
self.tableView.contentSize.height > contentSize.height &&
|
self.tableView.contentSize.height > contentSize.height &&
|
||||||
@@ -272,6 +274,8 @@
|
|||||||
|
|
||||||
- (void)deleteAllMessages {
|
- (void)deleteAllMessages {
|
||||||
[_manager deleteAllMessages];
|
[_manager deleteAllMessages];
|
||||||
|
[self refreshPreviewItems];
|
||||||
|
|
||||||
[self.tableView reloadData];
|
[self.tableView reloadData];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,11 +648,12 @@
|
|||||||
attachment.isLoading = YES;
|
attachment.isLoading = YES;
|
||||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:attachment.sourceURL]];
|
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:attachment.sourceURL]];
|
||||||
[NSURLConnection sendAsynchronousRequest:request queue:self.thumbnailQueue completionHandler:^(NSURLResponse *response, NSData *responseData, NSError *err) {
|
[NSURLConnection sendAsynchronousRequest:request queue:self.thumbnailQueue completionHandler:^(NSURLResponse *response, NSData *responseData, NSError *err) {
|
||||||
if (responseData.length){
|
if (responseData.length) {
|
||||||
[attachment replaceData:responseData];
|
[attachment replaceData:responseData];
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[self.tableView reloadData];
|
[self.tableView reloadData];
|
||||||
});
|
});
|
||||||
|
|
||||||
[[BITHockeyManager sharedHockeyManager].feedbackManager saveMessages];
|
[[BITHockeyManager sharedHockeyManager].feedbackManager saveMessages];
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
@@ -679,12 +684,19 @@
|
|||||||
|
|
||||||
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
|
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
if (editingStyle == UITableViewCellEditingStyleDelete) {
|
if (editingStyle == UITableViewCellEditingStyleDelete) {
|
||||||
|
BITFeedbackMessage *message = [self.manager messageAtIndex:indexPath.row];
|
||||||
|
BOOL messageHasAttachments = ([message attachments].count > 0);
|
||||||
|
|
||||||
if ([_manager deleteMessageAtIndex:indexPath.row]) {
|
if ([_manager deleteMessageAtIndex:indexPath.row]) {
|
||||||
if ([_manager numberOfMessages] > 0) {
|
if ([_manager numberOfMessages] > 0) {
|
||||||
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
|
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||||
} else {
|
} else {
|
||||||
[tableView reloadData];
|
[tableView reloadData];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (messageHasAttachments) {
|
||||||
|
[self refreshPreviewItems];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -794,6 +806,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - ListViewCellDelegate
|
#pragma mark - ListViewCellDelegate
|
||||||
|
|
||||||
- (void)listCell:(id)cell didSelectAttachment:(BITFeedbackMessageAttachment *)attachment {
|
- (void)listCell:(id)cell didSelectAttachment:(BITFeedbackMessageAttachment *)attachment {
|
||||||
@@ -801,16 +814,17 @@
|
|||||||
previewController.dataSource = self;
|
previewController.dataSource = self;
|
||||||
|
|
||||||
[self presentViewController:previewController animated:YES completion:nil];
|
[self presentViewController:previewController animated:YES completion:nil];
|
||||||
if (self.cachedPreviewItems.count > [self.cachedPreviewItems indexOfObject:attachment]){
|
|
||||||
|
if (self.cachedPreviewItems.count > [self.cachedPreviewItems indexOfObject:attachment]) {
|
||||||
[previewController setCurrentPreviewItemIndex:[self.cachedPreviewItems indexOfObject:attachment]];
|
[previewController setCurrentPreviewItemIndex:[self.cachedPreviewItems indexOfObject:attachment]];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)refreshPreviewItems {
|
- (void)refreshPreviewItems {
|
||||||
self.cachedPreviewItems = nil;
|
self.cachedPreviewItems = nil;
|
||||||
NSMutableArray *collectedAttachments = [NSMutableArray new];
|
NSMutableArray *collectedAttachments = [NSMutableArray new];
|
||||||
|
|
||||||
for (int i = 0; i<self.manager.numberOfMessages;i++){
|
for (int i = 0; i < self.manager.numberOfMessages; i++) {
|
||||||
BITFeedbackMessage *message = [self.manager messageAtIndex:i];
|
BITFeedbackMessage *message = [self.manager messageAtIndex:i];
|
||||||
[collectedAttachments addObjectsFromArray:message.previewableAttachments];
|
[collectedAttachments addObjectsFromArray:message.previewableAttachments];
|
||||||
}
|
}
|
||||||
@@ -818,23 +832,25 @@
|
|||||||
self.cachedPreviewItems = collectedAttachments;
|
self.cachedPreviewItems = collectedAttachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSInteger) numberOfPreviewItemsInPreviewController: (QLPreviewController *) controller {
|
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller {
|
||||||
if (!self.cachedPreviewItems){
|
if (!self.cachedPreviewItems){
|
||||||
[self refreshPreviewItems];
|
[self refreshPreviewItems];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.cachedPreviewItems.count;
|
return self.cachedPreviewItems.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id <QLPreviewItem>) previewController: (QLPreviewController *) controller previewItemAtIndex: (NSInteger) index {
|
- (id <QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index {
|
||||||
if (index>=0){
|
if (index >= 0) {
|
||||||
__weak QLPreviewController* blockController = controller;
|
__weak QLPreviewController* blockController = controller;
|
||||||
BITFeedbackMessageAttachment *attachment = self.cachedPreviewItems[index];
|
BITFeedbackMessageAttachment *attachment = self.cachedPreviewItems[index];
|
||||||
if (attachment.needsLoadingFromURL && !attachment.isLoading){
|
|
||||||
|
if (attachment.needsLoadingFromURL && !attachment.isLoading) {
|
||||||
attachment.isLoading = YES;
|
attachment.isLoading = YES;
|
||||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:attachment.sourceURL]];
|
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:attachment.sourceURL]];
|
||||||
[NSURLConnection sendAsynchronousRequest:request queue:self.thumbnailQueue completionHandler:^(NSURLResponse *response, NSData *responseData, NSError *err) {
|
[NSURLConnection sendAsynchronousRequest:request queue:self.thumbnailQueue completionHandler:^(NSURLResponse *response, NSData *responseData, NSError *err) {
|
||||||
attachment.isLoading = NO;
|
attachment.isLoading = NO;
|
||||||
if (responseData.length){
|
if (responseData.length) {
|
||||||
[attachment replaceData:responseData];
|
[attachment replaceData:responseData];
|
||||||
[blockController reloadData];
|
[blockController reloadData];
|
||||||
|
|
||||||
@@ -843,11 +859,13 @@
|
|||||||
[blockController reloadData];
|
[blockController reloadData];
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
return attachment;
|
return attachment;
|
||||||
} else {
|
} else {
|
||||||
return self.cachedPreviewItems[index];
|
return self.cachedPreviewItems[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,20 +61,19 @@ typedef NS_ENUM(NSInteger, BITFeedbackUserDataElement) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Available modes for collecting automated feedback.
|
* Available modes for opening the feedback compose interface with a screenshot attached
|
||||||
*/
|
*/
|
||||||
typedef NS_ENUM(NSInteger, BITFeedbackObservationMode) {
|
typedef NS_ENUM(NSInteger, BITFeedbackObservationMode) {
|
||||||
/**
|
/**
|
||||||
* No automatic feedback gathering.
|
* No SDK provided trigger is active.
|
||||||
*/
|
*/
|
||||||
BITFeedbackObservationNone = 0,
|
BITFeedbackObservationNone = 0,
|
||||||
/**
|
/**
|
||||||
* Feedback compose form will open once a screenshot is taken.
|
* Triggeres when the user takes a screenshot. Requires iOS 7 or later!
|
||||||
*/
|
*/
|
||||||
BITFeedbackObservationModeOnScreenshot = 1,
|
BITFeedbackObservationModeOnScreenshot = 1,
|
||||||
/**
|
/**
|
||||||
* Feedback compose will open with a generated screenshot if the screen is tapped
|
* Triggers when the user tapps with three fingers for three seconds on the screen.
|
||||||
* three fingers for three seconds.
|
|
||||||
*/
|
*/
|
||||||
BITFeedbackObservationModeThreeFingerTap = 2
|
BITFeedbackObservationModeThreeFingerTap = 2
|
||||||
};
|
};
|
||||||
@@ -212,6 +211,26 @@ typedef NS_ENUM(NSInteger, BITFeedbackObservationMode) {
|
|||||||
@property (nonatomic, readwrite) BOOL showAlertOnIncomingMessages;
|
@property (nonatomic, readwrite) BOOL showAlertOnIncomingMessages;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Define the trigger that opens the feedback composer and attaches a screenshot
|
||||||
|
|
||||||
|
The following modes are available:
|
||||||
|
|
||||||
|
- `BITFeedbackObservationNone`: No SDK based trigger is active. You can implement your
|
||||||
|
own trigger and then call `[[BITHockeyManager sharedHockeyManager].feedbackManager showFeedbackComposeViewWithGeneratedScreenshot];` to handle your custom events
|
||||||
|
that should trigger this.
|
||||||
|
- `BITFeedbackObservationModeOnScreenshot`: Triggeres when the user takes a screenshot.
|
||||||
|
Requires iOS 7 or later!
|
||||||
|
- `BITFeedbackObservationModeThreeFingerTap`: Triggers when the user tapps with three fingers
|
||||||
|
for three seconds on the screen.
|
||||||
|
|
||||||
|
Default is `BITFeedbackObservationNone`
|
||||||
|
|
||||||
|
@see showFeedbackComposeViewWithGeneratedScreenshot
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readwrite) BITFeedbackObservationMode feedbackObservationMode;
|
||||||
|
|
||||||
|
|
||||||
///-----------------------------------------------------------------------------
|
///-----------------------------------------------------------------------------
|
||||||
/// @name User Interface
|
/// @name User Interface
|
||||||
///-----------------------------------------------------------------------------
|
///-----------------------------------------------------------------------------
|
||||||
@@ -269,8 +288,13 @@ typedef NS_ENUM(NSInteger, BITFeedbackObservationMode) {
|
|||||||
- (void)showFeedbackComposeViewWithPreparedItems:(NSArray *)items;
|
- (void)showFeedbackComposeViewWithPreparedItems:(NSArray *)items;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Present the modal feedback compose message user interface with a screenshot that is taken
|
Presents a modal feedback compose interface with a screenshot attached which is taken at the time of calling this method.
|
||||||
at the time of calling this method.
|
|
||||||
|
This should be used when your own trigger fires. The following code should be used:
|
||||||
|
|
||||||
|
[[BITHockeyManager sharedHockeyManager].feedbackManager showFeedbackComposeViewWithGeneratedScreenshot];
|
||||||
|
|
||||||
|
@see feedbackObservationMode
|
||||||
*/
|
*/
|
||||||
- (void)showFeedbackComposeViewWithGeneratedScreenshot;
|
- (void)showFeedbackComposeViewWithGeneratedScreenshot;
|
||||||
|
|
||||||
@@ -295,14 +319,5 @@ typedef NS_ENUM(NSInteger, BITFeedbackObservationMode) {
|
|||||||
*/
|
*/
|
||||||
- (BITFeedbackComposeViewController *)feedbackComposeViewController;
|
- (BITFeedbackComposeViewController *)feedbackComposeViewController;
|
||||||
|
|
||||||
/**
|
|
||||||
Set the so-called feedback observation mode. Depending on the chosen mode,
|
|
||||||
the feedback manager will automatically launch once the event has been detected.
|
|
||||||
|
|
||||||
You can choose from the modes in BITFeedbackObservationMode. The default mode is
|
|
||||||
BITFeedbackObservationNone.
|
|
||||||
*/
|
|
||||||
- (void)setFeedbackObservationMode:(BITFeedbackObservationMode)mode;
|
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -740,7 +740,7 @@
|
|||||||
message.id = [(NSDictionary *)objMessage objectForKey:@"id"];
|
message.id = [(NSDictionary *)objMessage objectForKey:@"id"];
|
||||||
message.status = BITFeedbackMessageStatusUnread;
|
message.status = BITFeedbackMessageStatusUnread;
|
||||||
|
|
||||||
for (NSDictionary *attachmentData in objMessage[@"attachments"]){
|
for (NSDictionary *attachmentData in objMessage[@"attachments"]) {
|
||||||
BITFeedbackMessageAttachment *newAttachment = [BITFeedbackMessageAttachment new];
|
BITFeedbackMessageAttachment *newAttachment = [BITFeedbackMessageAttachment new];
|
||||||
newAttachment.originalFilename = attachmentData[@"file_name"];
|
newAttachment.originalFilename = attachmentData[@"file_name"];
|
||||||
newAttachment.id = attachmentData[@"id"];
|
newAttachment.id = attachmentData[@"id"];
|
||||||
@@ -805,45 +805,11 @@
|
|||||||
[self markSendInProgressMessagesAsPending];
|
[self markSendInProgressMessagesAsPending];
|
||||||
}
|
}
|
||||||
|
|
||||||
// we'll load the images on demand.
|
|
||||||
//[self synchronizeMissingAttachments];
|
|
||||||
|
|
||||||
[self saveMessages];
|
[self saveMessages];
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Load all attachments without any local data to have them available.
|
|
||||||
*/
|
|
||||||
-(BOOL)synchronizeMissingAttachments {
|
|
||||||
// Extract all Attachments.
|
|
||||||
NSMutableArray *allAttachments = [NSMutableArray new];
|
|
||||||
for (int i = 0; i < [self numberOfMessages]; i++){
|
|
||||||
BITFeedbackMessage *message = [self messageAtIndex:i];
|
|
||||||
for (BITFeedbackMessageAttachment *attachment in message.attachments){
|
|
||||||
if (attachment.needsLoadingFromURL){
|
|
||||||
[allAttachments addObject:attachment];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BITFeedbackMessageAttachment *attachment in allAttachments){
|
|
||||||
// we will just update the objects here and perform a save after each successful load operation.
|
|
||||||
|
|
||||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:attachment.sourceURL]];
|
|
||||||
__weak BITFeedbackManager *weakSelf = self;
|
|
||||||
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *responseData, NSError *err) {
|
|
||||||
if (responseData.length){
|
|
||||||
[attachment replaceData:responseData];
|
|
||||||
[weakSelf saveMessages];
|
|
||||||
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)sendNetworkRequestWithHTTPMethod:(NSString *)httpMethod withMessage:(BITFeedbackMessage *)message completionHandler:(void (^)(NSError *err))completionHandler {
|
- (void)sendNetworkRequestWithHTTPMethod:(NSString *)httpMethod withMessage:(BITFeedbackMessage *)message completionHandler:(void (^)(NSError *err))completionHandler {
|
||||||
NSString *boundary = @"----FOO";
|
NSString *boundary = @"----FOO";
|
||||||
@@ -1092,12 +1058,15 @@
|
|||||||
|
|
||||||
#pragma mark - Observation Handling
|
#pragma mark - Observation Handling
|
||||||
|
|
||||||
-(void)setFeedbackObservationMode:(BITFeedbackObservationMode)mode {
|
- (void)setFeedbackObservationMode:(BITFeedbackObservationMode)feedbackObservationMode {
|
||||||
if (mode == BITFeedbackObservationModeOnScreenshot){
|
if (feedbackObservationMode != _feedbackObservationMode) {
|
||||||
|
_feedbackObservationMode = feedbackObservationMode;
|
||||||
|
|
||||||
|
if (feedbackObservationMode == BITFeedbackObservationModeOnScreenshot){
|
||||||
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1){
|
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1){
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(screenshotNotificationReceived:) name:UIApplicationUserDidTakeScreenshotNotification object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(screenshotNotificationReceived:) name:UIApplicationUserDidTakeScreenshotNotification object:nil];
|
||||||
} else {
|
} else {
|
||||||
BITHockeyLog("Not enabling Screenshot notifications: iOS6.1 and lower is not supported.");
|
BITHockeyLog("WARNING: BITFeedbackObservationModeOnScreenshot requires iOS 7 or later.");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.screenshotNotificationEnabled = YES;
|
self.screenshotNotificationEnabled = YES;
|
||||||
@@ -1108,7 +1077,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == BITFeedbackObservationModeThreeFingerTap){
|
if (feedbackObservationMode == BITFeedbackObservationModeThreeFingerTap){
|
||||||
if (!self.tapRecognizer){
|
if (!self.tapRecognizer){
|
||||||
self.tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(screenshotTripleTap:)];
|
self.tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(screenshotTripleTap:)];
|
||||||
self.tapRecognizer.numberOfTouchesRequired = 3;
|
self.tapRecognizer.numberOfTouchesRequired = 3;
|
||||||
@@ -1126,6 +1095,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)screenshotNotificationReceived:(NSNotification *)notification {
|
-(void)screenshotNotificationReceived:(NSNotification *)notification {
|
||||||
|
|||||||
@@ -76,18 +76,24 @@ typedef NS_ENUM(NSInteger, BITFeedbackMessageStatus) {
|
|||||||
@property (nonatomic) BOOL userMessage;
|
@property (nonatomic) BOOL userMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method must be called before a feedback message is deleted. It handles the
|
Delete local cached attachment data
|
||||||
* deletion of any data stored on the device in association with the feedback message.
|
|
||||||
*/
|
|
||||||
-(void)deleteContents;
|
|
||||||
|
|
||||||
|
@warning This method must be called before a feedback message is deleted.
|
||||||
|
*/
|
||||||
|
- (void)deleteContents;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Add an attachment to a message
|
||||||
|
|
||||||
|
@param object BITFeedbackMessageAttachment instance representing the attachment that should be added
|
||||||
|
*/
|
||||||
-(void)addAttachmentsObject:(BITFeedbackMessageAttachment *)object;
|
-(void)addAttachmentsObject:(BITFeedbackMessageAttachment *)object;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of attachment objects that may be previewed on this device.
|
Return the attachments that can be viewed
|
||||||
|
|
||||||
|
@return NSArray containing the attachment objects that can be previewed
|
||||||
*/
|
*/
|
||||||
- (NSArray *)previewableAttachments;
|
- (NSArray *)previewableAttachments;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
#pragma mark - NSObject
|
#pragma mark - NSObject
|
||||||
|
|
||||||
- (id) init {
|
- (instancetype) init {
|
||||||
if ((self = [super init])) {
|
if ((self = [super init])) {
|
||||||
_text = nil;
|
_text = nil;
|
||||||
_userID = nil;
|
_userID = nil;
|
||||||
@@ -67,8 +67,8 @@
|
|||||||
[encoder encodeObject:self.token forKey:@"token"];
|
[encoder encodeObject:self.token forKey:@"token"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithCoder:(NSCoder *)decoder {
|
- (instancetype)initWithCoder:(NSCoder *)decoder {
|
||||||
if ((self = [super init])) {
|
if ((self = [self init])) {
|
||||||
self.text = [decoder decodeObjectForKey:@"text"];
|
self.text = [decoder decodeObjectForKey:@"text"];
|
||||||
self.userID = [decoder decodeObjectForKey:@"userID"];
|
self.userID = [decoder decodeObjectForKey:@"userID"];
|
||||||
self.name = [decoder decodeObjectForKey:@"name"];
|
self.name = [decoder decodeObjectForKey:@"name"];
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
* Author: Moritz Haarmann <post@moritzhaarmann.de>
|
* Author: Moritz Haarmann <post@moritzhaarmann.de>
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
|
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
|
||||||
* Copyright (c) 2011 Andreas Linde & Kent Sutherland.
|
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
#import "HockeySDKPrivate.h"
|
#import "HockeySDKPrivate.h"
|
||||||
#import <MobileCoreServices/MobileCoreServices.h>
|
#import <MobileCoreServices/MobileCoreServices.h>
|
||||||
|
|
||||||
#define kCacheFolderName @"hockey_attachments"
|
#define kCacheFolderName @"attachments"
|
||||||
|
|
||||||
@interface BITFeedbackMessageAttachment()
|
@interface BITFeedbackMessageAttachment()
|
||||||
|
|
||||||
@@ -43,47 +43,63 @@
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation BITFeedbackMessageAttachment
|
@implementation BITFeedbackMessageAttachment {
|
||||||
|
NSString *_tempFilename;
|
||||||
|
|
||||||
|
NSString *_cachePath;
|
||||||
|
|
||||||
|
NSFileManager *_fm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+ (BITFeedbackMessageAttachment *)attachmentWithData:(NSData *)data contentType:(NSString *)contentType {
|
+ (BITFeedbackMessageAttachment *)attachmentWithData:(NSData *)data contentType:(NSString *)contentType {
|
||||||
|
|
||||||
static NSDateFormatter *formatter;
|
static NSDateFormatter *formatter;
|
||||||
|
|
||||||
if(!formatter){
|
if(!formatter) {
|
||||||
formatter = [NSDateFormatter new];
|
formatter = [NSDateFormatter new];
|
||||||
formatter.dateStyle = NSDateFormatterShortStyle;
|
formatter.dateStyle = NSDateFormatterShortStyle;
|
||||||
formatter.timeStyle = NSDateFormatterShortStyle;
|
formatter.timeStyle = NSDateFormatterShortStyle;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BITFeedbackMessageAttachment *newAttachment = [BITFeedbackMessageAttachment new];
|
BITFeedbackMessageAttachment *newAttachment = [BITFeedbackMessageAttachment new];
|
||||||
newAttachment.contentType = contentType;
|
newAttachment.contentType = contentType;
|
||||||
newAttachment.data = data;
|
newAttachment.data = data;
|
||||||
newAttachment.originalFilename = [NSString stringWithFormat:@"Attachment: %@", [formatter stringFromDate:[NSDate date]]];
|
newAttachment.originalFilename = [NSString stringWithFormat:@"Attachment: %@", [formatter stringFromDate:[NSDate date]]];
|
||||||
|
|
||||||
return newAttachment;
|
return newAttachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(id)init {
|
- (instancetype)init {
|
||||||
self = [super init];
|
if ((self = [super init])) {
|
||||||
if (self){
|
|
||||||
self.isLoading = NO;
|
self.isLoading = NO;
|
||||||
self.thumbnailRepresentations = [NSMutableDictionary new];
|
self.thumbnailRepresentations = [NSMutableDictionary new];
|
||||||
|
|
||||||
|
_fm = [[NSFileManager alloc] init];
|
||||||
|
_cachePath = [bit_settingsDir() stringByAppendingPathComponent:kCacheFolderName];
|
||||||
|
|
||||||
|
BOOL isDirectory;
|
||||||
|
|
||||||
|
if (![_fm fileExistsAtPath:_cachePath isDirectory:&isDirectory]){
|
||||||
|
[_fm createDirectoryAtPath:_cachePath withIntermediateDirectories:YES attributes:nil error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)setData:(NSData *)data {
|
- (void)setData:(NSData *)data {
|
||||||
self->_internalData = data;
|
self->_internalData = data;
|
||||||
self.filename = [self possibleFilename];
|
self.filename = [self possibleFilename];
|
||||||
[self->_internalData writeToFile:self.filename atomically:NO];
|
[self->_internalData writeToFile:self.filename atomically:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(NSData *)data {
|
- (NSData *)data {
|
||||||
if (!self->_internalData && self.filename){
|
if (!self->_internalData && self.filename) {
|
||||||
self.internalData = [NSData dataWithContentsOfFile:self.filename];
|
self.internalData = [NSData dataWithContentsOfFile:self.filename];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.internalData){
|
if (self.internalData) {
|
||||||
return self.internalData;
|
return self.internalData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,8 +111,8 @@
|
|||||||
self.thumbnailRepresentations = [NSMutableDictionary new];
|
self.thumbnailRepresentations = [NSMutableDictionary new];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(BOOL)needsLoadingFromURL {
|
- (BOOL)needsLoadingFromURL {
|
||||||
return (self.sourceURL && ![[NSFileManager defaultManager] fileExistsAtPath:self.localURL.absoluteString]);
|
return (self.sourceURL && ![_fm fileExistsAtPath:[self.localURL path]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isImage {
|
- (BOOL)isImage {
|
||||||
@@ -104,12 +120,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (NSURL *)localURL {
|
- (NSURL *)localURL {
|
||||||
if (self.filename){
|
if (self.filename && [_fm fileExistsAtPath:self.filename]) {
|
||||||
return [NSURL fileURLWithPath:self.filename];
|
return [NSURL fileURLWithPath:self.filename];
|
||||||
} else
|
}
|
||||||
{ return nil;}
|
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark NSCoding
|
#pragma mark NSCoding
|
||||||
|
|
||||||
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||||
@@ -117,29 +135,25 @@
|
|||||||
[aCoder encodeObject:self.filename forKey:@"filename"];
|
[aCoder encodeObject:self.filename forKey:@"filename"];
|
||||||
[aCoder encodeObject:self.originalFilename forKey:@"originalFilename"];
|
[aCoder encodeObject:self.originalFilename forKey:@"originalFilename"];
|
||||||
[aCoder encodeObject:self.sourceURL forKey:@"url"];
|
[aCoder encodeObject:self.sourceURL forKey:@"url"];
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithCoder:(NSCoder *)aDecoder {
|
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
|
||||||
self = [super init];
|
if ((self = [self init])) {
|
||||||
|
|
||||||
if (self){
|
|
||||||
self.contentType = [aDecoder decodeObjectForKey:@"contentType"];
|
self.contentType = [aDecoder decodeObjectForKey:@"contentType"];
|
||||||
self.filename = [aDecoder decodeObjectForKey:@"filename"];
|
self.filename = [aDecoder decodeObjectForKey:@"filename"];
|
||||||
self.thumbnailRepresentations = [NSMutableDictionary new];
|
self.thumbnailRepresentations = [NSMutableDictionary new];
|
||||||
self.originalFilename = [aDecoder decodeObjectForKey:@"originalFilename"];
|
self.originalFilename = [aDecoder decodeObjectForKey:@"originalFilename"];
|
||||||
self.sourceURL = [aDecoder decodeObjectForKey:@"url"];
|
self.sourceURL = [aDecoder decodeObjectForKey:@"url"];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Thubmnails / Image Representation
|
#pragma mark - Thubmnails / Image Representation
|
||||||
|
|
||||||
- (UIImage *)imageRepresentation {
|
- (UIImage *)imageRepresentation {
|
||||||
if ([self.contentType rangeOfString:@"image"].location != NSNotFound && self.filename ){
|
if ([self.contentType rangeOfString:@"image"].location != NSNotFound && self.filename ) {
|
||||||
return [UIImage imageWithData:self.data];
|
return [UIImage imageWithData:self.data];
|
||||||
} else {
|
} else {
|
||||||
// Create a Icon ..
|
// Create a Icon ..
|
||||||
@@ -157,21 +171,22 @@
|
|||||||
- (UIImage *)thumbnailWithSize:(CGSize)size {
|
- (UIImage *)thumbnailWithSize:(CGSize)size {
|
||||||
id<NSCopying> cacheKey = [NSValue valueWithCGSize:size];
|
id<NSCopying> cacheKey = [NSValue valueWithCGSize:size];
|
||||||
|
|
||||||
if (!self.thumbnailRepresentations[cacheKey]){
|
if (!self.thumbnailRepresentations[cacheKey]) {
|
||||||
UIImage *image = self.imageRepresentation;
|
UIImage *image = self.imageRepresentation;
|
||||||
// consider the scale.
|
// consider the scale.
|
||||||
if (!image)
|
if (!image) {
|
||||||
return nil;
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
CGFloat scale = [UIScreen mainScreen].scale;
|
CGFloat scale = [UIScreen mainScreen].scale;
|
||||||
|
|
||||||
if (scale != image.scale){
|
if (scale != image.scale) {
|
||||||
|
|
||||||
CGSize scaledSize = CGSizeApplyAffineTransform(size, CGAffineTransformMakeScale(scale, scale));
|
CGSize scaledSize = CGSizeApplyAffineTransform(size, CGAffineTransformMakeScale(scale, scale));
|
||||||
UIImage *thumbnail = bit_imageToFitSize(image, scaledSize, YES) ;
|
UIImage *thumbnail = bit_imageToFitSize(image, scaledSize, YES) ;
|
||||||
|
|
||||||
UIImage *scaledTumbnail = [UIImage imageWithCGImage:thumbnail.CGImage scale:scale orientation:thumbnail.imageOrientation];
|
UIImage *scaledTumbnail = [UIImage imageWithCGImage:thumbnail.CGImage scale:scale orientation:thumbnail.imageOrientation];
|
||||||
if (thumbnail){
|
if (thumbnail) {
|
||||||
[self.thumbnailRepresentations setObject:scaledTumbnail forKey:cacheKey];
|
[self.thumbnailRepresentations setObject:scaledTumbnail forKey:cacheKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,42 +206,36 @@
|
|||||||
#pragma mark - Persistence Helpers
|
#pragma mark - Persistence Helpers
|
||||||
|
|
||||||
- (NSString *)possibleFilename {
|
- (NSString *)possibleFilename {
|
||||||
NSArray* cachePathArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
if (_tempFilename) {
|
||||||
NSString* cachePath = [cachePathArray lastObject];
|
return _tempFilename;
|
||||||
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();
|
NSString *uniqueString = bit_UUID();
|
||||||
cachePath = [cachePath stringByAppendingPathComponent:uniqueString];
|
_tempFilename = [_cachePath stringByAppendingPathComponent:uniqueString];
|
||||||
|
|
||||||
// File extension that suits the Content type.
|
// File extension that suits the Content type.
|
||||||
|
|
||||||
CFStringRef mimeType = (__bridge CFStringRef)self.contentType;
|
CFStringRef mimeType = (__bridge CFStringRef)self.contentType;
|
||||||
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
|
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
|
||||||
CFStringRef extension = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension);
|
CFStringRef extension = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension);
|
||||||
if (extension){
|
if (extension) {
|
||||||
cachePath = [cachePath stringByAppendingPathExtension:(__bridge NSString *)(extension)];
|
_tempFilename = [_tempFilename stringByAppendingPathExtension:(__bridge NSString *)(extension)];
|
||||||
CFRelease(extension);
|
CFRelease(extension);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CFRelease(uti);
|
CFRelease(uti);
|
||||||
|
|
||||||
return cachePath;
|
return _tempFilename;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)deleteContents {
|
- (void)deleteContents {
|
||||||
if (self.filename){
|
if (self.filename) {
|
||||||
[[NSFileManager defaultManager] removeItemAtPath:self.filename error:nil];
|
[_fm removeItemAtPath:self.filename error:nil];
|
||||||
self.filename = nil;
|
self.filename = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - QLPreviewItem
|
#pragma mark - QLPreviewItem
|
||||||
|
|
||||||
- (NSString *)previewItemTitle {
|
- (NSString *)previewItemTitle {
|
||||||
@@ -236,9 +245,14 @@
|
|||||||
- (NSURL *)previewItemURL {
|
- (NSURL *)previewItemURL {
|
||||||
if (self.localURL){
|
if (self.localURL){
|
||||||
return self.localURL;
|
return self.localURL;
|
||||||
} else {
|
} else if (self.sourceURL) {
|
||||||
return [NSURL fileURLWithPath:self.possibleFilename];
|
NSString *filename = self.possibleFilename;
|
||||||
|
if (filename) {
|
||||||
|
return [NSURL fileURLWithPath:filename];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
Reference in New Issue
Block a user