Attachements: Fixing UI issues

pull/1/head
dtsbourg 11 years ago committed by Frederic Jacobs
parent db74e17564
commit f8db90014d

@ -522,6 +522,7 @@
FCB626B51A3B067900FDB504 /* ArrowBottom@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCB626B11A3B067900FDB504 /* ArrowBottom@2x.png */; };
FCB626B61A3B067900FDB504 /* ArrowBottom@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCB626B21A3B067900FDB504 /* ArrowBottom@3x.png */; };
FCB626B71A3B067900FDB504 /* ArrowTop@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCB626B31A3B067900FDB504 /* ArrowTop@3x.png */; };
FCC81A981A44558300DFEC7D /* UIDevice+TSHardwareVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = FCC81A971A44558300DFEC7D /* UIDevice+TSHardwareVersion.m */; };
FCF72A081A01A765006BC849 /* ContactsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCF72A071A01A765006BC849 /* ContactsTableViewController.m */; };
FCF72A131A02D27F006BC849 /* ContactDetailTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCF72A111A02D27F006BC849 /* ContactDetailTableViewController.m */; };
FCFA64B41A24F3880007FB87 /* UIColor+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFA64B31A24F3880007FB87 /* UIColor+OWS.m */; };
@ -1220,6 +1221,8 @@
FCB626B11A3B067900FDB504 /* ArrowBottom@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "ArrowBottom@2x.png"; sourceTree = "<group>"; };
FCB626B21A3B067900FDB504 /* ArrowBottom@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "ArrowBottom@3x.png"; sourceTree = "<group>"; };
FCB626B31A3B067900FDB504 /* ArrowTop@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "ArrowTop@3x.png"; sourceTree = "<group>"; };
FCC81A961A44558300DFEC7D /* UIDevice+TSHardwareVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIDevice+TSHardwareVersion.h"; sourceTree = "<group>"; };
FCC81A971A44558300DFEC7D /* UIDevice+TSHardwareVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIDevice+TSHardwareVersion.m"; sourceTree = "<group>"; };
FCF72A061A01A765006BC849 /* ContactsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsTableViewController.h; sourceTree = "<group>"; };
FCF72A071A01A765006BC849 /* ContactsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactsTableViewController.m; sourceTree = "<group>"; };
FCF72A111A02D27F006BC849 /* ContactDetailTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactDetailTableViewController.m; sourceTree = "<group>"; };
@ -1806,6 +1809,8 @@
76EB04FB18170B33006006FC /* Util.h */,
76EB04FC18170B33006006FC /* Zid.h */,
76EB04FD18170B33006006FC /* Zid.m */,
FCC81A961A44558300DFEC7D /* UIDevice+TSHardwareVersion.h */,
FCC81A971A44558300DFEC7D /* UIDevice+TSHardwareVersion.m */,
);
path = util;
sourceTree = "<group>";
@ -3259,6 +3264,7 @@
FCFD256F1A151BCB00F4C644 /* NewGroupViewController.m in Sources */,
76EB059E18170B33006006FC /* HttpSocket.m in Sources */,
E197B60E18BBEC1A00F073E5 /* CallAudioManager.m in Sources */,
FCC81A981A44558300DFEC7D /* UIDevice+TSHardwareVersion.m in Sources */,
76EB054018170B33006006FC /* AppDelegate.m in Sources */,
76EB05D018170B33006006FC /* ZrtpHandshakeSocket.m in Sources */,
B63761EF19E1FBE8005735D1 /* HttpResponse.m in Sources */,

@ -119,7 +119,6 @@
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
<connections>
<segue destination="m2q-RS-sTo" kind="presentation" identifier="fullImage" id="vI3-mk-n1C"/>
<segue destination="urv-62-RsD" kind="presentation" identifier="fingerprintSegue" modalPresentationStyle="overCurrentContext" animates="NO" id="Zjl-QX-tHE"/>
</connections>
</viewController>
@ -2532,177 +2531,6 @@ A0 09 9A FF A8 8A 09 99</string>
</objects>
<point key="canvasLocation" x="3154.5" y="392.25"/>
</scene>
<!--Full Image View Controller-->
<scene sceneID="Awx-pS-RDJ">
<objects>
<viewController id="m2q-RS-sTo" customClass="FullImageViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="t0J-yq-Mbh"/>
<viewControllerLayoutGuide type="bottom" id="LH9-C1-m9I"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="WfW-cb-tK6">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Nm6-V1-1DQ">
<rect key="frame" x="0.0" y="0.0" width="240" height="128"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Neb-cr-TuQ">
<rect key="frame" x="0.0" y="0.0" width="240" height="128"/>
</imageView>
</subviews>
<constraints>
<constraint firstItem="Neb-cr-TuQ" firstAttribute="leading" secondItem="Nm6-V1-1DQ" secondAttribute="leading" id="9te-80-0Kb"/>
<constraint firstItem="Neb-cr-TuQ" firstAttribute="top" secondItem="Nm6-V1-1DQ" secondAttribute="top" id="JpP-5v-dCV"/>
<constraint firstAttribute="trailing" secondItem="Neb-cr-TuQ" secondAttribute="trailing" constant="400" id="MIF-Ph-3aX">
<variation key="heightClass=regular-widthClass=compact" constant="0.0"/>
</constraint>
<constraint firstAttribute="centerX" secondItem="Neb-cr-TuQ" secondAttribute="centerX" constant="200" id="OgJ-gl-OHy">
<variation key="heightClass=regular-widthClass=compact" constant="0.0"/>
</constraint>
<constraint firstAttribute="centerY" secondItem="Neb-cr-TuQ" secondAttribute="centerY" constant="400" id="pHe-78-0g9">
<variation key="heightClass=regular-widthClass=compact" constant="0.0"/>
</constraint>
<constraint firstAttribute="bottom" secondItem="Neb-cr-TuQ" secondAttribute="bottom" constant="800" id="wCF-r0-Mcy">
<variation key="heightClass=regular-widthClass=compact" constant="0.0"/>
</constraint>
</constraints>
<variation key="default">
<mask key="subviews">
<exclude reference="Neb-cr-TuQ"/>
</mask>
<mask key="constraints">
<exclude reference="9te-80-0Kb"/>
<exclude reference="JpP-5v-dCV"/>
<exclude reference="MIF-Ph-3aX"/>
<exclude reference="OgJ-gl-OHy"/>
<exclude reference="pHe-78-0g9"/>
<exclude reference="wCF-r0-Mcy"/>
</mask>
</variation>
<variation key="heightClass=regular-widthClass=compact">
<mask key="subviews">
<include reference="Neb-cr-TuQ"/>
</mask>
<mask key="constraints">
<include reference="9te-80-0Kb"/>
<include reference="JpP-5v-dCV"/>
<include reference="MIF-Ph-3aX"/>
<include reference="OgJ-gl-OHy"/>
<include reference="pHe-78-0g9"/>
<include reference="wCF-r0-Mcy"/>
</mask>
</variation>
</scrollView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2yV-c9-cpf">
<rect key="frame" x="-23" y="-15" width="46" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="g8h-b7-vpN"/>
<constraint firstAttribute="width" constant="50" id="r8b-pK-z62"/>
</constraints>
<state key="normal" image="quit.png">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<variation key="default">
<mask key="constraints">
<exclude reference="g8h-b7-vpN"/>
<exclude reference="r8b-pK-z62"/>
</mask>
</variation>
<variation key="heightClass=regular-widthClass=compact">
<mask key="constraints">
<include reference="g8h-b7-vpN"/>
<include reference="r8b-pK-z62"/>
</mask>
</variation>
<connections>
<action selector="close:" destination="m2q-RS-sTo" eventType="touchUpInside" id="xN6-p0-Brk"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wrt-Gs-Awk">
<rect key="frame" x="-23" y="-15" width="46" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="8e9-NC-H21"/>
<constraint firstAttribute="width" constant="50" id="LMa-lp-yS7"/>
</constraints>
<state key="normal" image="savephoto.png">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<variation key="default">
<mask key="constraints">
<exclude reference="8e9-NC-H21"/>
<exclude reference="LMa-lp-yS7"/>
</mask>
</variation>
<variation key="heightClass=regular-widthClass=compact">
<mask key="constraints">
<include reference="8e9-NC-H21"/>
<include reference="LMa-lp-yS7"/>
</mask>
</variation>
<connections>
<action selector="more:" destination="m2q-RS-sTo" eventType="touchUpInside" id="jeq-kT-wEb"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" cocoaTouchSystemColor="darkTextColor"/>
<constraints>
<constraint firstItem="LH9-C1-m9I" firstAttribute="top" secondItem="wrt-Gs-Awk" secondAttribute="bottom" constant="20" id="3F7-s6-l2J"/>
<constraint firstItem="LH9-C1-m9I" firstAttribute="top" secondItem="Nm6-V1-1DQ" secondAttribute="bottom" id="Ept-m4-iN0"/>
<constraint firstItem="Nm6-V1-1DQ" firstAttribute="top" secondItem="t0J-yq-Mbh" secondAttribute="bottom" id="Roc-JQ-f9y"/>
<constraint firstItem="2yV-c9-cpf" firstAttribute="leading" secondItem="WfW-cb-tK6" secondAttribute="leadingMargin" id="YbI-cl-hOB"/>
<constraint firstItem="Nm6-V1-1DQ" firstAttribute="leading" secondItem="WfW-cb-tK6" secondAttribute="leadingMargin" constant="-16" id="ZDj-at-031"/>
<constraint firstItem="LH9-C1-m9I" firstAttribute="top" secondItem="2yV-c9-cpf" secondAttribute="bottom" constant="20" id="lve-Jx-YbD"/>
<constraint firstItem="wrt-Gs-Awk" firstAttribute="leading" secondItem="2yV-c9-cpf" secondAttribute="trailing" constant="20" id="qxF-m3-YlM"/>
<constraint firstAttribute="trailingMargin" secondItem="Nm6-V1-1DQ" secondAttribute="trailing" constant="-16" id="rPg-Hq-Xxk"/>
</constraints>
<variation key="default">
<mask key="subviews">
<exclude reference="Nm6-V1-1DQ"/>
<exclude reference="2yV-c9-cpf"/>
<exclude reference="wrt-Gs-Awk"/>
</mask>
<mask key="constraints">
<exclude reference="3F7-s6-l2J"/>
<exclude reference="Ept-m4-iN0"/>
<exclude reference="lve-Jx-YbD"/>
<exclude reference="YbI-cl-hOB"/>
<exclude reference="qxF-m3-YlM"/>
<exclude reference="Roc-JQ-f9y"/>
<exclude reference="ZDj-at-031"/>
<exclude reference="rPg-Hq-Xxk"/>
</mask>
</variation>
<variation key="heightClass=regular-widthClass=compact">
<mask key="subviews">
<include reference="Nm6-V1-1DQ"/>
<include reference="2yV-c9-cpf"/>
<include reference="wrt-Gs-Awk"/>
</mask>
<mask key="constraints">
<include reference="3F7-s6-l2J"/>
<include reference="Ept-m4-iN0"/>
<include reference="lve-Jx-YbD"/>
<include reference="YbI-cl-hOB"/>
<include reference="qxF-m3-YlM"/>
<include reference="Roc-JQ-f9y"/>
<include reference="ZDj-at-031"/>
<include reference="rPg-Hq-Xxk"/>
</mask>
</variation>
</view>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="lightContent"/>
<connections>
<outlet property="closeButton" destination="2yV-c9-cpf" id="0LC-MN-kUI"/>
<outlet property="fullImageView" destination="Neb-cr-TuQ" id="oFA-rD-2T5"/>
<outlet property="pinchView" destination="Nm6-V1-1DQ" id="yXB-Op-QkS"/>
<outlet property="saveButton" destination="wrt-Gs-Awk" id="69f-4L-Igh"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="a5y-ji-0eO" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="4000.5" y="392.25"/>
</scene>
<!--Signals Navigation Controller-->
<scene sceneID="miN-Ma-3eR">
<objects>
@ -3824,7 +3652,6 @@ Licensed under the GPLv3</string>
<image name="qr.png" width="100" height="100"/>
<image name="qr_scan_fingerprint.png" width="100" height="100"/>
<image name="quit.png" width="50" height="50"/>
<image name="savephoto.png" width="50" height="50"/>
<image name="settings_tab.png" width="24" height="24"/>
<image name="shred.png" width="200" height="200"/>
<image name="signal.png" width="50" height="50"/>

@ -0,0 +1,48 @@
//
// UIDevice+TSHardwareVersion.h
// Signal
//
// Created by Dylan Bourgeois on 19/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
// Original Source :
// Erica Sadun, http://ericasadun.com
// iPhone Developer's Cookbook, 6.x Edition
// BSD License, Use at your own risk
//
//
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSUInteger, UIDeviceFamily) {
UIDeviceFamilyiPhone,
UIDeviceFamilyiPod,
UIDeviceFamilyiPad,
UIDeviceFamilyAppleTV,
UIDeviceFamilyUnknown,
};
@interface UIDevice (TSHardwareVersion)
/**
Returns a machine-readable model name in the format of "iPhone4,1"
*/
- (NSString *)modelIdentifier;
/**
Returns a human-readable model name in the format of "iPhone 4S". Fallback of the the `modelIdentifier` value.
*/
- (NSString *)modelName;
/**
Returns the device family as a `UIDeviceFamily`
*/
- (UIDeviceFamily)deviceFamily;
/*
* Returns true if device is iPhone 6 or 6+
*/
- (BOOL)isiPhoneVersionSixOrMore;
@end

@ -0,0 +1,125 @@
//
// UIDevice+TSHardwareVersion.m
// Signal
//
// Created by Dylan Bourgeois on 19/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
// Original Source :
// Erica Sadun, http://ericasadun.com
// iPhone Developer's Cookbook, 6.x Edition
// BSD License, Use at your own risk
//
//
#import "UIDevice+TSHardwareVersion.h"
#include <sys/sysctl.h>
@implementation UIDevice (TSHardwareVersion)
- (NSString *)getSysInfoByName:(char *)typeSpecifier
{
size_t size;
sysctlbyname(typeSpecifier, NULL, &size, NULL, 0);
char *answer = malloc(size);
sysctlbyname(typeSpecifier, answer, &size, NULL, 0);
NSString *results = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding];
free(answer);
return results;
}
- (NSString *)modelIdentifier
{
return [self getSysInfoByName:"hw.machine"];
}
- (NSString *)modelName
{
return [self modelNameForModelIdentifier:[self modelIdentifier]];
}
- (NSString *)modelNameForModelIdentifier:(NSString *)modelIdentifier
{
// iPhone http://theiphonewiki.com/wiki/IPhone
if ([modelIdentifier isEqualToString:@"iPhone1,1"]) return @"iPhone 1G";
if ([modelIdentifier isEqualToString:@"iPhone1,2"]) return @"iPhone 3G";
if ([modelIdentifier isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS";
if ([modelIdentifier isEqualToString:@"iPhone3,1"]) return @"iPhone 4 (GSM)";
if ([modelIdentifier isEqualToString:@"iPhone3,2"]) return @"iPhone 4 (GSM Rev A)";
if ([modelIdentifier isEqualToString:@"iPhone3,3"]) return @"iPhone 4 (CDMA)";
if ([modelIdentifier isEqualToString:@"iPhone4,1"]) return @"iPhone 4S";
if ([modelIdentifier isEqualToString:@"iPhone5,1"]) return @"iPhone 5 (GSM)";
if ([modelIdentifier isEqualToString:@"iPhone5,2"]) return @"iPhone 5 (Global)";
if ([modelIdentifier isEqualToString:@"iPhone5,3"]) return @"iPhone 5c (GSM)";
if ([modelIdentifier isEqualToString:@"iPhone5,4"]) return @"iPhone 5c (Global)";
if ([modelIdentifier isEqualToString:@"iPhone6,1"]) return @"iPhone 5s (GSM)";
if ([modelIdentifier isEqualToString:@"iPhone6,2"]) return @"iPhone 5s (Global)";
if ([modelIdentifier isEqualToString:@"iPhone7,1"]) return @"iPhone 6 Plus";
if ([modelIdentifier isEqualToString:@"iPhone7,2"]) return @"iPhone 6";
// iPad http://theiphonewiki.com/wiki/IPad
if ([modelIdentifier isEqualToString:@"iPad1,1"]) return @"iPad 1G";
if ([modelIdentifier isEqualToString:@"iPad2,1"]) return @"iPad 2 (Wi-Fi)";
if ([modelIdentifier isEqualToString:@"iPad2,2"]) return @"iPad 2 (GSM)";
if ([modelIdentifier isEqualToString:@"iPad2,3"]) return @"iPad 2 (CDMA)";
if ([modelIdentifier isEqualToString:@"iPad2,4"]) return @"iPad 2 (Rev A)";
if ([modelIdentifier isEqualToString:@"iPad3,1"]) return @"iPad 3 (Wi-Fi)";
if ([modelIdentifier isEqualToString:@"iPad3,2"]) return @"iPad 3 (GSM)";
if ([modelIdentifier isEqualToString:@"iPad3,3"]) return @"iPad 3 (Global)";
if ([modelIdentifier isEqualToString:@"iPad3,4"]) return @"iPad 4 (Wi-Fi)";
if ([modelIdentifier isEqualToString:@"iPad3,5"]) return @"iPad 4 (GSM)";
if ([modelIdentifier isEqualToString:@"iPad3,6"]) return @"iPad 4 (Global)";
if ([modelIdentifier isEqualToString:@"iPad4,1"]) return @"iPad Air (Wi-Fi)";
if ([modelIdentifier isEqualToString:@"iPad4,2"]) return @"iPad Air (Cellular)";
if ([modelIdentifier isEqualToString:@"iPad5,3"]) return @"iPad Air 2 (Wi-Fi)";
if ([modelIdentifier isEqualToString:@"iPad5,4"]) return @"iPad Air 2 (Cellular)";
// iPad Mini http://theiphonewiki.com/wiki/IPad_mini
if ([modelIdentifier isEqualToString:@"iPad2,5"]) return @"iPad mini 1G (Wi-Fi)";
if ([modelIdentifier isEqualToString:@"iPad2,6"]) return @"iPad mini 1G (GSM)";
if ([modelIdentifier isEqualToString:@"iPad2,7"]) return @"iPad mini 1G (Global)";
if ([modelIdentifier isEqualToString:@"iPad4,4"]) return @"iPad mini 2G (Wi-Fi)";
if ([modelIdentifier isEqualToString:@"iPad4,5"]) return @"iPad mini 2G (Cellular)";
if ([modelIdentifier isEqualToString:@"iPad4,7"]) return @"iPad mini 3G (Wi-Fi)";
if ([modelIdentifier isEqualToString:@"iPad4,8"]) return @"iPad mini 3G (Cellular)";
if ([modelIdentifier isEqualToString:@"iPad4,9"]) return @"iPad mini 3G (Cellular)";
// iPod http://theiphonewiki.com/wiki/IPod
if ([modelIdentifier isEqualToString:@"iPod1,1"]) return @"iPod touch 1G";
if ([modelIdentifier isEqualToString:@"iPod2,1"]) return @"iPod touch 2G";
if ([modelIdentifier isEqualToString:@"iPod3,1"]) return @"iPod touch 3G";
if ([modelIdentifier isEqualToString:@"iPod4,1"]) return @"iPod touch 4G";
if ([modelIdentifier isEqualToString:@"iPod5,1"]) return @"iPod touch 5G";
// Simulator
if ([modelIdentifier hasSuffix:@"86"] || [modelIdentifier isEqual:@"x86_64"])
{
BOOL smallerScreen = ([[UIScreen mainScreen] bounds].size.width < 768.0);
return (smallerScreen ? @"iPhone Simulator" : @"iPad Simulator");
}
return modelIdentifier;
}
- (UIDeviceFamily) deviceFamily
{
NSString *modelIdentifier = [self modelIdentifier];
if ([modelIdentifier hasPrefix:@"iPhone"]) return UIDeviceFamilyiPhone;
if ([modelIdentifier hasPrefix:@"iPod"]) return UIDeviceFamilyiPod;
if ([modelIdentifier hasPrefix:@"iPad"]) return UIDeviceFamilyiPad;
return UIDeviceFamilyUnknown;
}
-(BOOL)isiPhoneVersionSixOrMore
{
return [[self modelIdentifier] isEqualToString:@"iPhone7,1"] || [[self modelIdentifier] isEqualToString:@"iPhone7,2"];
}
@end

@ -10,12 +10,8 @@
@interface FullImageViewController : UIViewController
@property(nonatomic, strong) IBOutlet UIImageView* fullImageView;
@property(nonatomic, strong) IBOutlet UIButton* saveButton;
@property(nonatomic, strong) IBOutlet UIButton* closeButton;
@property(nonatomic, strong) IBOutlet UIScrollView* pinchView;
@property(nonatomic, strong) UIImage* image;
- (instancetype)initWithImage:(UIImage*)image fromRect:(CGRect)rect;
-(void)presentFromViewController:(UIViewController*)viewController;
@end

@ -9,130 +9,379 @@
#import "FullImageViewController.h"
#import "DJWActionSheet.h"
@interface FullImageViewController () <UIScrollViewDelegate>
#define kImageViewCornerRadius 5.0f
#define kMinZoomScale 1.0f
#define kMaxZoomScale 8.0f
#define kTargetDoubleTapZoom 3.0f
#define kBackgroundAlpha 0.6f
@interface FullImageViewController () <UIScrollViewDelegate, UIGestureRecognizerDelegate>
@property (nonatomic, strong) UIView *backgroundView;
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIImage* image;
@property (nonatomic, strong) UITapGestureRecognizer *singleTap;
@property (nonatomic, strong) UITapGestureRecognizer *doubleTap;
@property (nonatomic, strong) UIButton *shareButton;
@property CGRect originRect;
@property BOOL isPresenting;
@end
@implementation FullImageViewController
- (instancetype)initWithImage:(UIImage*)image fromRect:(CGRect)rect {
self = [super initWithNibName:nil bundle:nil];
if (self) {
self.image = image;
self.imageView.image = image;
self.originRect = rect;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
_fullImageView.image = _image;
[self initializeBackground];
[self initializeScrollView];
[self initializeImageView];
[self initializeGestureRecognizers];
[self populateImageView:self.image];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Initializer
-(void)initializeScrollView
#pragma mark - Initializers
- (void)initializeBackground
{
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
[_pinchView addGestureRecognizer:doubleTap];
self.imageView.backgroundColor = [UIColor colorWithWhite:0 alpha:kBackgroundAlpha];
self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:kBackgroundAlpha];
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.backgroundView = [[UIView alloc] initWithFrame:CGRectInset(self.view.bounds, -512, -512)];
self.backgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:kBackgroundAlpha];
_pinchView.delegate = self;
_pinchView.minimumZoomScale=0.9f;
_pinchView.maximumZoomScale=3.0f;
_pinchView.showsVerticalScrollIndicator = NO;
_pinchView.showsHorizontalScrollIndicator = NO;
_pinchView.contentSize=CGSizeMake(CGRectGetWidth(_fullImageView.frame), CGRectGetHeight(_fullImageView.frame));
[self.view addSubview:self.backgroundView];
}
#pragma mark - IBAction
- (void)initializeScrollView
{
self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
self.scrollView.delegate = self;
self.scrollView.zoomScale = 1.0f;
self.scrollView.maximumZoomScale = kMaxZoomScale;
self.scrollView.scrollEnabled = NO;
[self.view addSubview:self.scrollView];
}
-(IBAction)close:(id)sender
- (void)initializeImageView
{
[self dismissViewControllerAnimated:YES completion:nil];
self.imageView = [[UIImageView alloc]initWithFrame:self.originRect];
self.imageView.layer.cornerRadius = kImageViewCornerRadius;
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
self.imageView.userInteractionEnabled = YES;
self.imageView.clipsToBounds = YES;
self.imageView.layer.allowsEdgeAntialiasing = YES;
[self.scrollView addSubview:self.imageView];
}
-(IBAction)more:(id)sender
- (void)populateImageView:(UIImage*)image
{
[DJWActionSheet showInView:self.view
withTitle:@"Options"
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@[@"Save to Camera Roll", @"Delete"]
tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) {
if (tappedButtonIndex == actionSheet.cancelButtonIndex) {
NSLog(@"User Cancelled");
if (image) {
self.imageView.image = image;
}
}
} else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) {
NSLog(@"Destructive button tapped");
}else {
NSLog(@"The user tapped button at index: %li", (long)tappedButtonIndex);
- (void)initializeGestureRecognizers
{
self.doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(imageDoubleTapped:)];
self.doubleTap.numberOfTapsRequired = 2;
self.singleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(imageSingleTapped:)];
[self.singleTap requireGestureRecognizerToFail:self.doubleTap];
self.singleTap.delegate = self;
self.doubleTap.delegate = self;
[self.view addGestureRecognizer:self.singleTap];
[self.view addGestureRecognizer:self.doubleTap];
}
- (void) initializeShareButton
{
CGFloat buttonRadius = 50.0f;
CGFloat x = 14.0f;
CGFloat y = self.view.bounds.size.height - buttonRadius - 10.0f;
self.shareButton = [[UIButton alloc]initWithFrame:CGRectMake(x, y, buttonRadius, buttonRadius)];
[self.shareButton addTarget:self action:@selector(shareButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
[self.shareButton setImage:[UIImage imageNamed:@"savephoto"] forState:UIControlStateNormal];
[self.view addSubview:self.shareButton];
}
#pragma mark - Gesture Recognizers
- (void)imageDoubleTapped:(UITapGestureRecognizer*)doubleTap
{
CGPoint tap = [doubleTap locationInView:doubleTap.view];
CGPoint convertCoord = [self.scrollView convertPoint:tap fromView:doubleTap.view];
CGRect targetZoomRect;
UIEdgeInsets targetInsets;
CGSize zoom ;
if (self.scrollView.zoomScale == 1.0f) {
zoom = CGSizeMake(self.view.bounds.size.width / kTargetDoubleTapZoom, self.view.bounds.size.height / kTargetDoubleTapZoom);
targetZoomRect = CGRectMake(convertCoord.x - (zoom.width/2.0f), convertCoord.y - (zoom.height/2.0f), zoom.width, zoom.height);
targetInsets = [self contentInsetForScrollView:kTargetDoubleTapZoom];
} else {
zoom = CGSizeMake(self.view.bounds.size.width * self.scrollView.zoomScale, self.view.bounds.size.height * self.scrollView.zoomScale);
targetZoomRect = CGRectMake(convertCoord.x - (zoom.width/2.0f), convertCoord.y - (zoom.height/2.0f), zoom.width, zoom.height);
targetInsets = [self contentInsetForScrollView:1.0f];
}
self.view.userInteractionEnabled = NO;
[CATransaction begin];
[CATransaction setCompletionBlock:^{
self.scrollView.contentInset = targetInsets;
self.view.userInteractionEnabled = YES;
}];
[self.scrollView zoomToRect:targetZoomRect animated:YES];
[CATransaction commit];
}
- (void)imageSingleTapped:(UITapGestureRecognizer*)singleTap
{
[self dismiss];
}
#pragma mark - Presentation
-(void)presentFromViewController:(UIViewController*)viewController
{
_isPresenting = YES;
self.view.userInteractionEnabled = NO;
[self.view addSubview:self.imageView];
self.modalPresentationStyle = UIModalPresentationOverCurrentContext;
self.view.alpha = 0;
[viewController presentViewController:self animated:NO completion:^{
[UIView animateWithDuration:0.4f
delay:0
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut
animations:^(){
self.view.alpha = 1.0f;
self.imageView.frame = [self resizedFrameForImageView:self.image.size];
self.imageView.center = CGPointMake(self.view.bounds.size.width/2.0f, self.view.bounds.size.height/2.0f);
} completion:^(BOOL completed){
self.scrollView.frame = self.view.bounds;
[self.scrollView addSubview:self.imageView];
[self updateLayouts];
[self initializeShareButton];
self.view.userInteractionEnabled = YES;
_isPresenting = NO;
}];
}];
}
- (void)dismiss
{
self.view.userInteractionEnabled = NO;
[UIView animateWithDuration:0.4f
delay:0
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut
animations:^(){
self.backgroundView.backgroundColor = [UIColor clearColor];
self.scrollView.alpha = 0;
self.view.alpha = 0;
} completion:^(BOOL completed){
[self.presentingViewController dismissViewControllerAnimated:NO completion:nil];
}];
}
#pragma mark - Scroll View
#pragma mark - Update Layout
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
- (void)viewDidLayoutSubviews
{
return _fullImageView;
[self updateLayouts];
}
- (IBAction)handleDoubleTap:(id)sender {
CGFloat desiredScale = [self doubleTapDestinationZoomScale];
CGPoint center = [(UITapGestureRecognizer*)sender locationInView:_fullImageView];
CGRect zoomRect = [self zoomRectForScale:desiredScale withCenter:center];
- (void) updateLayouts
{
if (_isPresenting) {
return;
}
[_pinchView zoomToRect:zoomRect animated:YES];
[_pinchView setZoomScale:desiredScale animated:YES];
self.scrollView.frame = self.view.bounds;
self.imageView.frame = [self resizedFrameForImageView:self.image.size];
self.scrollView.contentSize = self.imageView.frame.size;
self.scrollView.contentInset = [self contentInsetForScrollView:self.scrollView.zoomScale];
}
- (CGRect)zoomRectForScale:(CGFloat)scale withCenter:(CGPoint)center {
CGRect zoomRect;
#pragma mark - Resizing
zoomRect.size.height = CGRectGetHeight(_pinchView.frame) / scale;
zoomRect.size.width = CGRectGetWidth(_pinchView.frame) / scale;
- (CGRect)resizedFrameForImageView:(CGSize)imageSize {
CGRect frame = self.view.bounds;
CGSize screenSize = CGSizeMake(frame.size.width * self.scrollView.zoomScale, frame.size.height * self.scrollView.zoomScale);
CGSize targetSize = screenSize;
zoomRect.origin.x = center.x - ((CGRectGetWidth(zoomRect) / 2.0f));
zoomRect.origin.y = center.y - ((CGRectGetHeight(zoomRect) / 2.0f));
if ([self isImagePortrait]) {
if ([self getAspectRatioForCGSize:screenSize] < [self getAspectRatioForCGSize:imageSize]) {
targetSize.width = screenSize.height / [self getAspectRatioForCGSize:imageSize];
} else {
targetSize.height = screenSize.width * [self getAspectRatioForCGSize:imageSize];
}
} else {
if ([self getAspectRatioForCGSize:screenSize] > [self getAspectRatioForCGSize:imageSize]) {
targetSize.height = screenSize.width * [self getAspectRatioForCGSize:imageSize];
} else {
targetSize.width = screenSize.height / [self getAspectRatioForCGSize:imageSize];
}
}
return zoomRect;
frame.size = targetSize;
frame.origin = CGPointMake(0, 0);
return frame;
}
- (CGFloat)doubleTapDestinationZoomScale
{
BOOL cond = _pinchView.zoomScale == _pinchView.maximumZoomScale;
- (UIEdgeInsets)contentInsetForScrollView:(CGFloat)targetZoomScale {
UIEdgeInsets inset = UIEdgeInsetsZero;
CGSize boundsSize = self.scrollView.bounds.size;
CGSize contentSize = self.image.size;
CGSize minSize;
if ([self isImagePortrait]) {
if ([self getAspectRatioForCGSize:boundsSize] < [self getAspectRatioForCGSize:contentSize]) {
minSize.height = boundsSize.height;
minSize.width = minSize.height / [self getAspectRatioForCGSize:contentSize];
} else {
minSize.width = boundsSize.width;
minSize.height = minSize.width * [self getAspectRatioForCGSize:contentSize];
}
} else {
if ([self getAspectRatioForCGSize:boundsSize] > [self getAspectRatioForCGSize:contentSize]) {
minSize.width = boundsSize.width;
minSize.height = minSize.width * [self getAspectRatioForCGSize:contentSize];
} else {
minSize.height = boundsSize.height;
minSize.width = minSize.height / [self getAspectRatioForCGSize:contentSize];
}
}
CGSize finalSize = self.view.bounds.size;
minSize.width *= targetZoomScale;
minSize.height *= targetZoomScale;
if (minSize.height > finalSize.height && minSize.width > finalSize.width) {
inset = UIEdgeInsetsZero;
} else {
CGFloat dy = boundsSize.height - minSize.height;
CGFloat dx = boundsSize.width - minSize.width;
dy = (dy > 0) ? dy : 0;
dx = (dx > 0) ? dx : 0;
inset.top = dy/2.0f;
inset.bottom = dy/2.0f;
inset.left = dx/2.0f;
inset.right = dx/2.0f;
}
return inset;
}
#pragma mark - UIScrollViewDelegate
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.imageView;
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
return cond ? _pinchView.minimumZoomScale : _pinchView.maximumZoomScale;
scrollView.contentInset = [self contentInsetForScrollView:scrollView.zoomScale];
if (self.scrollView.scrollEnabled == NO) {
self.scrollView.scrollEnabled = YES;
}
}
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
self.scrollView.scrollEnabled = (scale > 1);
self.scrollView.contentInset = [self contentInsetForScrollView:scale];
}
#pragma mark - Layout
#pragma mark - Utility
- (BOOL)isImagePortrait
{
return ([self getAspectRatioForCGSize:self.image.size] > 1.0f);
}
-(void)centerInSuperview
- (CGFloat)getAspectRatioForCGSize:(CGSize)size
{
CGRect frame = _fullImageView.frame;
CGRect superviewFrame = self.view.frame;
return size.height / size.width;
}
CGFloat dy = (CGRectGetHeight(superviewFrame) - CGRectGetHeight(frame)) / 2.0f;
frame.origin.y = dy;
#pragma mark - Actions
CGFloat dx = (CGRectGetWidth(superviewFrame) - CGRectGetWidth(frame)) / 2.0f;
frame.origin.x = dx;
-(void)shareButtonTapped:(UIButton*)sender
{
[DJWActionSheet showInView:self.view withTitle:nil cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Delete" otherButtonTitles:@[@"Save to Camera Roll", @"Copy"] tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) {
if (tappedButtonIndex == actionSheet.cancelButtonIndex) {
_fullImageView.frame = frame;
} else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) {
#warning Unimplemented deleting attachments from FullImageView
NSLog(@"Destructive button tapped");
}else {
switch (tappedButtonIndex) {
case 0:
UIImageWriteToSavedPhotosAlbum(self.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
break;
case 1:
[[UIPasteboard generalPasteboard] setImage:self.image];
break;
default:
DDLogWarn(@"Illegal Action sheet field #%ld <%s>",tappedButtonIndex, __PRETTY_FUNCTION__);
break;
}
}
}];
}
/*
#pragma mark - Navigation
#pragma mark - Saving images to Camera Roll
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error
contextInfo:(void *)contextInfo
{
if (error)
{
DDLogWarn(@"There was a problem saving <%@> to camera roll from %s ", error.localizedDescription ,__PRETTY_FUNCTION__);
}
}
*/
@end

@ -322,7 +322,6 @@ typedef enum : NSUInteger {
}
return cell;
}
-(JSQCallCollectionViewCell*)loadCallCellForCall:(id<JSQMessageData>)call atIndexPath:(NSIndexPath*)indexPath
@ -473,7 +472,9 @@ typedef enum : NSUInteger {
if ([messageMedia isImage]) {
//is a photo
tappedImage = ((UIImageView*)[messageMedia mediaView]).image ;
[self performSegueWithIdentifier:@"fullImage" sender:self];
CGRect convertedRect = [self.collectionView convertRect:[collectionView cellForItemAtIndexPath:indexPath].frame toView:nil];
FullImageViewController * vc = [[FullImageViewController alloc]initWithImage:tappedImage fromRect:convertedRect];
[vc presentFromViewController:self];
} else {
DDLogWarn(@"Currently unsupported");
@ -544,12 +545,8 @@ typedef enum : NSUInteger {
#pragma mark - Navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"fullImage"])
{
FullImageViewController* dest = [segue destinationViewController];
dest.image = tappedImage;
} else if ([segue.identifier isEqualToString:@"fingerprintSegue"]){
if ([segue.identifier isEqualToString:@"fingerprintSegue"]){
FingerprintViewController *vc = [segue destinationViewController];
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[vc configWithThread:self.thread];

@ -8,6 +8,7 @@
#import "TSAttachementAdapter.h"
#import "UIDevice+TSHardwareVersion.h"
#import "JSQMessagesMediaViewBubbleImageMasker.h"
@interface TSAttachementAdapter ()
@ -15,7 +16,6 @@
@property UIImage *image;
@property (strong, nonatomic) UIImageView *cachedImageView;
@property (assign, nonatomic, readonly) BOOL isImageAttachment;
@end
@ -66,9 +66,59 @@
return self.cachedImageView;
}
- (CGSize)mediaViewDisplaySize
{
return [self getBubbleSizeForImage:_image];
}
-(BOOL)isImage
{
return _isImageAttachment;
}
#pragma mark - Utility
-(CGSize)getBubbleSizeForImage:(UIImage*)image
{
CGFloat aspectRatio = image.size.height / image.size.width ;
if ([[UIDevice currentDevice] isiPhoneVersionSixOrMore])
{
return [self getLargeSizeForAspectRatio:aspectRatio];
} else {
return [self getSmallSizeForAspectRatio:aspectRatio];
}
}
-(CGSize)getLargeSizeForAspectRatio:(CGFloat)ratio
{
return ratio > 1.0f ? [self largePortraitSize] : [self largeLandscapeSize];
}
-(CGSize)getSmallSizeForAspectRatio:(CGFloat)ratio
{
return ratio > 1.0f ? [self smallPortraitSize] : [self smallLandscapeSize];
}
- (CGSize)largePortraitSize
{
return CGSizeMake(220.0f, 310.0f);
}
- (CGSize)smallPortraitSize
{
return CGSizeMake(150.0f, 210.0f);
}
- (CGSize)largeLandscapeSize
{
return CGSizeMake(310.0f, 220.0f);
}
- (CGSize)smallLandscapeSize
{
return CGSizeMake(210.0f, 150.0f);
}
@end

Loading…
Cancel
Save