From 943c378206bcb50e8fae176be995923c1fdee043 Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Sat, 10 May 2014 21:42:11 -0400 Subject: [PATCH] Delete site WIP. --- MasterPassword/ObjC/iOS/MPPasswordLargeCell.m | 5 +- .../ObjC/iOS/MPPasswordLargeDeleteCell.h | 24 +++ .../ObjC/iOS/MPPasswordLargeDeleteCell.m | 33 ++++ MasterPassword/ObjC/iOS/MPPasswordTypesCell.h | 1 + MasterPassword/ObjC/iOS/MPPasswordTypesCell.m | 166 ++++++++++++----- .../ObjC/iOS/MPPasswordsViewController.m | 87 +-------- .../project.pbxproj | 6 + MasterPassword/ObjC/iOS/Storyboard.storyboard | 173 ++++++++++++------ 8 files changed, 310 insertions(+), 185 deletions(-) create mode 100644 MasterPassword/ObjC/iOS/MPPasswordLargeDeleteCell.h create mode 100644 MasterPassword/ObjC/iOS/MPPasswordLargeDeleteCell.m diff --git a/MasterPassword/ObjC/iOS/MPPasswordLargeCell.m b/MasterPassword/ObjC/iOS/MPPasswordLargeCell.m index d3cafa12..a21cc458 100644 --- a/MasterPassword/ObjC/iOS/MPPasswordLargeCell.m +++ b/MasterPassword/ObjC/iOS/MPPasswordLargeCell.m @@ -22,6 +22,7 @@ #import "MPPasswordLargeGeneratedCell.h" #import "MPPasswordLargeStoredCell.h" #import "MPPasswordTypesCell.h" +#import "MPPasswordLargeDeleteCell.h" @implementation MPPasswordLargeCell @@ -31,7 +32,9 @@ atIndexPath:(NSIndexPath *)indexPath { NSString *reuseIdentifier; - if (type & MPElementTypeClassGenerated) + if (indexPath.item == 0) + reuseIdentifier = NSStringFromClass( [MPPasswordLargeDeleteCell class] ); + else if (type & MPElementTypeClassGenerated) reuseIdentifier = NSStringFromClass( [MPPasswordLargeGeneratedCell class] ); else if (type & MPElementTypeClassStored) reuseIdentifier = NSStringFromClass( [MPPasswordLargeStoredCell class] ); diff --git a/MasterPassword/ObjC/iOS/MPPasswordLargeDeleteCell.h b/MasterPassword/ObjC/iOS/MPPasswordLargeDeleteCell.h new file mode 100644 index 00000000..03add62f --- /dev/null +++ b/MasterPassword/ObjC/iOS/MPPasswordLargeDeleteCell.h @@ -0,0 +1,24 @@ +/** + * Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) + * + * See the enclosed file LICENSE for license information (LGPLv3). If you did + * not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt + * + * @author Maarten Billemont + * @license http://www.gnu.org/licenses/lgpl-3.0.txt + */ + +// +// MPPasswordLargeDeleteCell.h +// MPPasswordLargeDeleteCell +// +// Created by lhunath on 2014-03-19. +// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. +// + +#import +#import "MPPasswordLargeCell.h" + +@interface MPPasswordLargeDeleteCell : MPPasswordLargeCell + +@end diff --git a/MasterPassword/ObjC/iOS/MPPasswordLargeDeleteCell.m b/MasterPassword/ObjC/iOS/MPPasswordLargeDeleteCell.m new file mode 100644 index 00000000..12f37947 --- /dev/null +++ b/MasterPassword/ObjC/iOS/MPPasswordLargeDeleteCell.m @@ -0,0 +1,33 @@ +/** + * Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) + * + * See the enclosed file LICENSE for license information (LGPLv3). If you did + * not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt + * + * @author Maarten Billemont + * @license http://www.gnu.org/licenses/lgpl-3.0.txt + */ + +// +// MPPasswordLargeDeleteCell.h +// MPPasswordLargeDeleteCell +// +// Created by lhunath on 2014-03-19. +// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. +// + +#import "MPPasswordLargeDeleteCell.h" +#import "MPiOSAppDelegate.h" +#import "MPAppDelegate_Store.h" +#import "MPPasswordElementCell.h" + +@implementation MPPasswordLargeDeleteCell + +#pragma mark - Lifecycle + +- (MPElementEntity *)saveContentTypeWithElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context { + + return element; +} + +@end diff --git a/MasterPassword/ObjC/iOS/MPPasswordTypesCell.h b/MasterPassword/ObjC/iOS/MPPasswordTypesCell.h index f948a307..2a0ff63a 100644 --- a/MasterPassword/ObjC/iOS/MPPasswordTypesCell.h +++ b/MasterPassword/ObjC/iOS/MPPasswordTypesCell.h @@ -26,6 +26,7 @@ @property(nonatomic, strong) IBOutlet UICollectionView *contentCollectionView; @property(nonatomic, strong) id algorithm; +@property(nonatomic) MPElementType activeType; + (instancetype)dequeueCellForElement:(MPElementEntity *)element fromCollectionView:(UICollectionView *)collectionView atIndexPath:(NSIndexPath *)indexPath; + (instancetype)dequeueCellForTransientSite:(NSString *)siteName diff --git a/MasterPassword/ObjC/iOS/MPPasswordTypesCell.m b/MasterPassword/ObjC/iOS/MPPasswordTypesCell.m index bc4931e6..03e45553 100644 --- a/MasterPassword/ObjC/iOS/MPPasswordTypesCell.m +++ b/MasterPassword/ObjC/iOS/MPPasswordTypesCell.m @@ -1,12 +1,12 @@ /** - * Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) - * - * See the enclosed file LICENSE for license information (LGPLv3). If you did - * not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt - * - * @author Maarten Billemont - * @license http://www.gnu.org/licenses/lgpl-3.0.txt - */ +* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) +* +* See the enclosed file LICENSE for license information (LGPLv3). If you did +* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt +* +* @author Maarten Billemont +* @license http://www.gnu.org/licenses/lgpl-3.0.txt +*/ // // MPPasswordTypesCell.h @@ -57,6 +57,7 @@ - (void)prepareForReuse { + _activeType = 0; _algorithm = MPAlgorithmDefault; [super prepareForReuse]; @@ -66,10 +67,10 @@ [super applyLayoutAttributes:layoutAttributes]; - NSIndexPath *visibleIndexPath = [self.contentCollectionView.indexPathsForVisibleItems firstObject]; [self.contentCollectionView.collectionViewLayout invalidateLayout]; - [self.contentCollectionView scrollToItemAtIndexPath:visibleIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally - animated:YES]; + if (self.activeType) + [self.contentCollectionView scrollToItemAtIndexPath:[self contentIndexPathForType:self.activeType] + atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO]; } - (void)reloadWithTransientSite:(NSString *)siteName { @@ -77,22 +78,17 @@ [super reloadWithTransientSite:siteName]; [self.contentCollectionView reloadData]; - NSIndexPath *visibleIndexPath = [self contentIndexPathForType: - IfElse([[MPiOSAppDelegate get] activeUserForMainThread].defaultType, MPElementTypeGeneratedLong)]; - [self.contentCollectionView scrollToItemAtIndexPath:visibleIndexPath - atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO]; + self.activeType = IfElse( [[MPiOSAppDelegate get] activeUserForMainThread].defaultType, MPElementTypeGeneratedLong ); } - (void)reloadWithElement:(MPElementEntity *)mainElement { [super reloadWithElement:mainElement]; - self.algorithm = IfNotNilElse([self mainElement].algorithm, MPAlgorithmDefault); + self.algorithm = IfNotNilElse( [self mainElement].algorithm, MPAlgorithmDefault ); [self.contentCollectionView reloadData]; - NSIndexPath *visibleIndexPath = [self contentIndexPathForType:mainElement.type]; - [self.contentCollectionView scrollToItemAtIndexPath:visibleIndexPath - atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO]; + self.activeType = mainElement.type; } #pragma mark - UICollectionViewDataSource @@ -106,15 +102,9 @@ - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { if (!self.algorithm) - dbg_return_tr(0, @, @(section)); + dbg_return_tr( 0, @, @(section) ); - NSInteger types = 1; - - MPElementType type = [self typeForContentIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]; - for (MPElementType nextType = type; type != (nextType = [self.algorithm nextType:nextType]);) - ++types; - - dbg_return_tr(types, @, @(section)); + dbg_return_tr( [[self.algorithm allTypes] count] + 1, @, @(section) ); } - (MPPasswordLargeCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { @@ -126,15 +116,96 @@ else [cell reloadWithElement:self.mainElement]; - dbg_return(cell, indexPath); + dbg_return( cell, indexPath ); } #pragma mark - UICollectionViewDelegateFlowLayout - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { - UICollectionView *passwordCollectionView = [UICollectionView findAsSuperviewOf:self]; - [passwordCollectionView.delegate collectionView:passwordCollectionView didSelectItemAtIndexPath:[passwordCollectionView indexPathForCell:self]]; + NSString *newSiteName = self.transientSite; + if (newSiteName) { + [PearlAlert showAlertWithTitle:@"Create Site" + message:strf( @"Do you want to create a new site named:\n%@", newSiteName ) + viewStyle:UIAlertViewStyleDefault + initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { + if (buttonIndex == [alert cancelButtonIndex]) { + // Cancel +// NSIndexPath *indexPath_ = [collectionView indexPathForCell:cell]; +// [collectionView selectItemAtIndexPath:indexPath animated:NO +// scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; +// [collectionView deselectItemAtIndexPath:indexPath animated:YES]; + for (NSIndexPath *selectedIndexPath in [collectionView indexPathsForSelectedItems]) + [collectionView deselectItemAtIndexPath:selectedIndexPath animated:YES]; + return; + } + + // Create + [[MPiOSAppDelegate get] addElementNamed:newSiteName completion:^(MPElementEntity *element) { + PearlMainQueue( ^{ + [PearlOverlay showTemporaryOverlayWithTitle:strf( @"Added %@", newSiteName ) dismissAfter:2]; + PearlMainQueueAfter( 0.2f, ^{ +// NSIndexPath *indexPath_ = [collectionView indexPathForCell:cell]; +// [collectionView selectItemAtIndexPath:indexPath animated:NO +// scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; +// [collectionView deselectItemAtIndexPath:indexPath animated:YES]; + for (NSIndexPath *selectedIndexPath in [collectionView indexPathsForSelectedItems]) + [collectionView deselectItemAtIndexPath:selectedIndexPath animated:YES]; + } ); + } ); + }]; + } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonYes, nil]; + return; + } + + MPElementEntity *element = [self mainElement]; + if (!element) { +// [collectionView selectItemAtIndexPath:indexPath animated:NO +// scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; +// [collectionView deselectItemAtIndexPath:indexPath animated:YES]; + for (NSIndexPath *selectedIndexPath in [collectionView indexPathsForSelectedItems]) + [collectionView deselectItemAtIndexPath:selectedIndexPath animated:YES]; + return; + } + + inf( @"Copying password for: %@", element.name ); + MPCheckpoint( MPCheckpointCopyToPasteboard, @{ + @"type" : NilToNSNull( element.typeName ), + @"version" : @(element.version), + @"emergency" : @NO + } ); + + [element resolveContentUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) { + if (![result length]) { + PearlMainQueue( ^{ +// NSIndexPath *indexPath_ = [collectionView indexPathForCell:cell]; +// [collectionView selectItemAtIndexPath:indexPath animated:NO +// scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; +// [collectionView deselectItemAtIndexPath:indexPath animated:YES]; + for (NSIndexPath *selectedIndexPath in [collectionView indexPathsForSelectedItems]) + [collectionView deselectItemAtIndexPath:selectedIndexPath animated:YES]; + } ); + return; + } + + [UIPasteboard generalPasteboard].string = result; + PearlMainQueue( ^{ + [PearlOverlay showTemporaryOverlayWithTitle:@"Password Copied" dismissAfter:2]; + PearlMainQueueAfter( 0.2f, ^{ +// NSIndexPath *indexPath_ = [collectionView indexPathForCell:cell]; +// [collectionView selectItemAtIndexPath:indexPath animated:NO +// scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; +// [collectionView deselectItemAtIndexPath:indexPath animated:YES]; + for (NSIndexPath *selectedIndexPath in [collectionView indexPathsForSelectedItems]) + [collectionView deselectItemAtIndexPath:selectedIndexPath animated:YES]; + + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { + [[self elementInContext:context] use]; + [context saveToStore]; + }]; + } ); + } ); + }]; } #pragma mark - UIScrollViewDelegate @@ -166,24 +237,20 @@ - (MPElementType)typeForContentIndexPath:(NSIndexPath *)indexPath { - MPElementType type = MPElementTypeGeneratedPIN; + if (indexPath.item == 0) + return (MPElementType)NSNotFound; - for (NSUInteger i = 0; i < indexPath.item; ++i) - type = [self.algorithm nextType:type]; - - return type; + return [[self.algorithm allTypesStartingWith:MPElementTypeGeneratedPIN][indexPath.item - 1] unsignedIntegerValue]; } - (NSIndexPath *)contentIndexPathForType:(MPElementType)type { - NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; - while ([self typeForContentIndexPath:indexPath] != type) { - indexPath = [NSIndexPath indexPathForItem:indexPath.item + 1 inSection:indexPath.section]; - NSAssert1(indexPath.item < [self.contentCollectionView numberOfItemsInSection:0], - @"No item found for type: %@", [self.algorithm nameOfType:type]); - } + NSArray *types = [self.algorithm allTypesStartingWith:MPElementTypeGeneratedPIN]; + for (NSInteger t = 0; t < [types count]; ++t) + if ([types[t] unsignedIntegerValue] == type) + return [NSIndexPath indexPathForItem:t + 1 inSection:0]; - return indexPath; + Throw(@"Unsupported type: %d", type); } - (void)saveContentType { @@ -193,24 +260,33 @@ CGPoint centerPoint = CGPointFromCGRectCenter( self.contentCollectionView.bounds ); NSIndexPath *centerIndexPath = [self.contentCollectionView indexPathForItemAtPoint:centerPoint]; + self.activeType = [self typeForContentIndexPath:centerIndexPath]; [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { MPPasswordLargeCell *cell = (MPPasswordLargeCell *)[self.contentCollectionView cellForItemAtIndexPath:centerIndexPath]; if (!cell) { - err(@"Couldn't find cell to change type: centerIndexPath=%@", centerIndexPath); + err( @"Couldn't find cell to change type: centerIndexPath=%@", centerIndexPath ); return; } MPElementEntity *element = [self elementInContext:context]; if (element.type == cell.type) - // Nothing changed. + // Nothing changed. return; self.element = [cell saveContentTypeWithElement:element saveInContext:context]; }]; } -#pragma mark - Properties +#pragma mark - State + +- (void)setActiveType:(MPElementType)activeType { + + _activeType = activeType; + + [self.contentCollectionView scrollToItemAtIndexPath:[self contentIndexPathForType:activeType] + atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO]; +} - (void)setSelected:(BOOL)selected { diff --git a/MasterPassword/ObjC/iOS/MPPasswordsViewController.m b/MasterPassword/ObjC/iOS/MPPasswordsViewController.m index 7826fa58..d656f038 100644 --- a/MasterPassword/ObjC/iOS/MPPasswordsViewController.m +++ b/MasterPassword/ObjC/iOS/MPPasswordsViewController.m @@ -58,7 +58,6 @@ _coachmark = [MPCoachmark coachmarkForClass:[self class] version:0]; self.view.backgroundColor = [UIColor clearColor]; - self.passwordCollectionView.contentInset = UIEdgeInsetsMake( 108, 0, 0, 0 ); [self.passwordCollectionView automaticallyAdjustInsetsForKeyboard]; } @@ -107,6 +106,12 @@ #pragma mark - UICollectionViewDelegateFlowLayout +- (CGSize) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout +referenceSizeForHeaderInSection:(NSInteger)section { + + return CGSizeMake( collectionView.bounds.size.width, CGPointFromCGRectBottom( self.passwordsSearchBar.frame ).y ); +} + - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { @@ -160,90 +165,12 @@ cell = [MPPasswordTypesCell dequeueCellForTransientSite:self.query fromCollectionView:collectionView atIndexPath:indexPath]; [UIView setAnimationsEnabled:YES]; - return cell; + dbg_return(cell, indexPath); } Throw(@"Unexpected collection view: %@", collectionView); } -- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { - - MPPasswordElementCell *cell = (MPPasswordElementCell *)[collectionView cellForItemAtIndexPath:indexPath]; - NSString *newSiteName = cell.transientSite; - if (newSiteName) { - [PearlAlert showAlertWithTitle:@"Create Site" - message:strf( @"Do you want to create a new site named:\n%@", newSiteName ) - viewStyle:UIAlertViewStyleDefault - initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - if (buttonIndex == [alert cancelButtonIndex]) { - // Cancel - NSIndexPath *indexPath_ = [collectionView indexPathForCell:cell]; - [collectionView selectItemAtIndexPath:indexPath_ animated:NO - scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; - [collectionView deselectItemAtIndexPath:indexPath_ animated:YES]; - return; - } - - // Create - [[MPiOSAppDelegate get] addElementNamed:newSiteName completion:^(MPElementEntity *element) { - PearlMainQueue( ^{ - [PearlOverlay showTemporaryOverlayWithTitle:strf( @"Added %@", newSiteName ) dismissAfter:2]; - PearlMainQueueAfter( 0.2f, ^{ - NSIndexPath *indexPath_ = [collectionView indexPathForCell:cell]; - [collectionView selectItemAtIndexPath:indexPath_ animated:NO - scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; - [collectionView deselectItemAtIndexPath:indexPath_ animated:YES]; - } ); - } ); - }]; - } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonYes, nil]; - return; - } - - MPElementEntity *element = [cell mainElement]; - if (!element) { - [collectionView selectItemAtIndexPath:indexPath animated:NO - scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; - [collectionView deselectItemAtIndexPath:indexPath animated:YES]; - return; - } - - inf(@"Copying password for: %@", element.name); - MPCheckpoint( MPCheckpointCopyToPasteboard, @{ - @"type" : NilToNSNull(element.typeName), - @"version" : @(element.version), - @"emergency" : @NO - } ); - - [element resolveContentUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) { - if (![result length]) { - PearlMainQueue( ^{ - NSIndexPath *indexPath_ = [collectionView indexPathForCell:cell]; - [collectionView selectItemAtIndexPath:indexPath_ animated:NO - scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; - [collectionView deselectItemAtIndexPath:indexPath_ animated:YES]; - } ); - return; - } - - [UIPasteboard generalPasteboard].string = result; - PearlMainQueue( ^{ - [PearlOverlay showTemporaryOverlayWithTitle:@"Password Copied" dismissAfter:2]; - PearlMainQueueAfter( 0.2f, ^{ - NSIndexPath *indexPath_ = [collectionView indexPathForCell:cell]; - [collectionView selectItemAtIndexPath:indexPath_ animated:NO - scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; - [collectionView deselectItemAtIndexPath:indexPath_ animated:YES]; - - [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { - [[cell elementInContext:context] use]; - [context saveToStore]; - }]; - } ); - } ); - }]; -} - #pragma mark - NSFetchedResultsControllerDelegate - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { diff --git a/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj b/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj index fe6bd77b..75382895 100644 --- a/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj +++ b/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj @@ -33,6 +33,7 @@ 93D396D8B67DA6522CDBA142 /* MPCoachmarkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */; }; 93D397952F5635C793C24DF1 /* NSError+PearlFullDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */; }; 93D3980046016EFD05B35BC5 /* PearlUICollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39B1D8177A86C5B9EDDE3 /* PearlUICollectionView.h */; }; + 93D398BD8B83FEE8BE4EFFFC /* MPPasswordLargeDeleteCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39EFBC4D6BA3C8581865F /* MPPasswordLargeDeleteCell.m */; }; 93D398ECD7D1A0DEDDADF516 /* MPEmergencyViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39ACBA9F4878B6A1CC33B /* MPEmergencyViewController.m */; }; 93D399246DC90F50913A1287 /* UIResponder+PearlFirstResponder.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A1DDFA09AE2E14D26DC /* UIResponder+PearlFirstResponder.m */; }; 93D399278165FD6D950F0025 /* MPPasswordTypesCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39097C0AAE62C1C321BFC /* MPPasswordTypesCell.m */; }; @@ -548,6 +549,7 @@ 93D3952CC60991B97D69F26A /* MPPasswordSmallCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordSmallCell.m; sourceTree = ""; }; 93D3956915634581E737B38C /* PearlNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlNavigationController.m; sourceTree = ""; }; 93D395BA6B2CFF5F49A4D25F /* MPPasswordLargeStoredCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordLargeStoredCell.h; sourceTree = ""; }; + 93D3966B527CA47A0A661CE2 /* MPPasswordLargeDeleteCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordLargeDeleteCell.h; sourceTree = ""; }; 93D396D04E57792A54D437AC /* NSArray+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Indexing.h"; sourceTree = ""; }; 93D3971FE104BB4052484151 /* MPUsersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUsersViewController.h; sourceTree = ""; }; 93D39730673227EFF6DEFF19 /* MPSetupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSetupViewController.h; sourceTree = ""; }; @@ -593,6 +595,7 @@ 93D39DEA995041A13DC9CAF7 /* MPPasswordCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordCell.m; sourceTree = ""; }; 93D39E02F69CACAB61C056F8 /* MPPasswordLargeCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordLargeCell.h; sourceTree = ""; }; 93D39E7A12CC352B2825AA66 /* MPPasswordsSegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordsSegue.m; sourceTree = ""; }; + 93D39EFBC4D6BA3C8581865F /* MPPasswordLargeDeleteCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordLargeDeleteCell.m; sourceTree = ""; }; 93D39F556F2F142740A65E59 /* MPWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPWebViewController.h; sourceTree = ""; }; 93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlEMail.h; sourceTree = ""; }; 93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+PearlFullDescription.m"; sourceTree = ""; }; @@ -1708,6 +1711,8 @@ DACA22121705DDC5002C6C22 /* External */, DA5BFA47147E415C00F98B1E /* Frameworks */, DA5BFA45147E415C00F98B1E /* Products */, + 93D3966B527CA47A0A661CE2 /* MPPasswordLargeDeleteCell.h */, + 93D39EFBC4D6BA3C8581865F /* MPPasswordLargeDeleteCell.m */, ); sourceTree = ""; }; @@ -3868,6 +3873,7 @@ 93D391C07818F4C2DC1B6956 /* MPPasswordsCoachmarkViewController.m in Sources */, 93D39EAA4D064193074D3021 /* MPFixable.m in Sources */, 93D394982CBD25D46692DD7C /* MPWebViewController.m in Sources */, + 93D398BD8B83FEE8BE4EFFFC /* MPPasswordLargeDeleteCell.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MasterPassword/ObjC/iOS/Storyboard.storyboard b/MasterPassword/ObjC/iOS/Storyboard.storyboard index dd37896a..7d890ad5 100644 --- a/MasterPassword/ObjC/iOS/Storyboard.storyboard +++ b/MasterPassword/ObjC/iOS/Storyboard.storyboard @@ -882,13 +882,13 @@ - + - + @@ -905,31 +905,28 @@ - + - - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - + + + + + + - + @@ -1190,7 +1241,7 @@ - + @@ -1223,7 +1274,7 @@ - + @@ -1256,6 +1307,10 @@ + + + + @@ -2097,15 +2152,15 @@ However, it means that anyone who finds your device unlocked can do the same. - + - + - + @@ -2334,7 +2389,7 @@ However, it means that anyone who finds your device unlocked can do the same. - + @@ -2369,12 +2424,12 @@ However, it means that anyone who finds your device unlocked can do the same. - + - + @@ -2382,7 +2437,7 @@ However, it means that anyone who finds your device unlocked can do the same. - + @@ -2407,7 +2462,7 @@ However, it means that anyone who finds your device unlocked can do the same. -