From 6da16f4165e93912c5cd264fbb0265ee071dc4f1 Mon Sep 17 00:00:00 2001 From: Martin Fleisz Date: Mon, 8 Apr 2013 13:25:00 +0200 Subject: [PATCH] iOS: Replaced UIViewAlert with custom alert dialog --- client/iOS/Controllers/AboutController.h | 2 +- client/iOS/Controllers/AboutController.m | 24 +- .../Controllers/BookmarkEditorController.h | 2 +- .../Controllers/BookmarkEditorController.m | 22 +- .../iOS/Controllers/BookmarkListController.h | 2 +- .../iOS/Controllers/BookmarkListController.m | 29 +- client/iOS/Controllers/HelpController.m | 23 -- .../Controllers/RDPSessionViewController.h | 2 +- .../Controllers/RDPSessionViewController.m | 23 +- client/iOS/Resources/alert-black-button.png | Bin 0 -> 1591 bytes .../iOS/Resources/alert-black-button@2x.png | Bin 0 -> 2168 bytes client/iOS/Resources/alert-gray-button.png | Bin 0 -> 1622 bytes client/iOS/Resources/alert-gray-button@2x.png | Bin 0 -> 2363 bytes client/iOS/Resources/alert-red-button.png | Bin 0 -> 1512 bytes client/iOS/Resources/alert-red-button@2x.png | Bin 0 -> 2062 bytes client/iOS/Resources/alert-window.png | Bin 0 -> 4886 bytes client/iOS/Resources/alert-window@2x.png | Bin 0 -> 7537 bytes client/iOS/Views/BlockAlertView.h | 28 ++ client/iOS/Views/BlockAlertView.m | 340 ++++++++++++++++++ client/iOS/Views/BlockBackground.h | 24 ++ client/iOS/Views/BlockBackground.m | 160 +++++++++ 21 files changed, 602 insertions(+), 79 deletions(-) create mode 100644 client/iOS/Resources/alert-black-button.png create mode 100644 client/iOS/Resources/alert-black-button@2x.png create mode 100644 client/iOS/Resources/alert-gray-button.png create mode 100644 client/iOS/Resources/alert-gray-button@2x.png create mode 100644 client/iOS/Resources/alert-red-button.png create mode 100644 client/iOS/Resources/alert-red-button@2x.png create mode 100644 client/iOS/Resources/alert-window.png create mode 100644 client/iOS/Resources/alert-window@2x.png create mode 100755 client/iOS/Views/BlockAlertView.h create mode 100755 client/iOS/Views/BlockAlertView.m create mode 100644 client/iOS/Views/BlockBackground.h create mode 100644 client/iOS/Views/BlockBackground.m diff --git a/client/iOS/Controllers/AboutController.h b/client/iOS/Controllers/AboutController.h index 0ace59c13..6d6917a7e 100644 --- a/client/iOS/Controllers/AboutController.h +++ b/client/iOS/Controllers/AboutController.h @@ -10,7 +10,7 @@ #import -@interface AboutController : UIViewController +@interface AboutController : UIViewController { NSString* last_link_clicked; UIWebView* webView; diff --git a/client/iOS/Controllers/AboutController.m b/client/iOS/Controllers/AboutController.m index a30bb40ba..ba3cdb488 100644 --- a/client/iOS/Controllers/AboutController.m +++ b/client/iOS/Controllers/AboutController.m @@ -9,6 +9,7 @@ #import "AboutController.h" #import "Utils.h" +#import "BlockAlertView.h" @implementation AboutController @@ -76,24 +77,19 @@ { [last_link_clicked release]; last_link_clicked = [[[request URL] absoluteString] retain]; - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"External Link", @"External Link Alert Title") - message:[NSString stringWithFormat:NSLocalizedString(@"Open [%@] in Browser?", @"Open link in browser (with link as parameter)"), last_link_clicked] - delegate:self - cancelButtonTitle:NSLocalizedString(@"OK", @"OK Button") - otherButtonTitles:NSLocalizedString(@"No", @"No Button"), nil]; - [alert show]; - [alert release]; + BlockAlertView *alert = [BlockAlertView alertWithTitle:NSLocalizedString(@"External Link", @"External Link Alert Title") + message:[NSString stringWithFormat:NSLocalizedString(@"Open [%@] in Browser?", @"Open link in browser (with link as parameter)"), last_link_clicked]]; + + [alert setCancelButtonWithTitle:NSLocalizedString(@"No", @"No Button") block:nil]; + [alert addButtonWithTitle:NSLocalizedString(@"OK", @"OK Button") block:^{ + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:last_link_clicked]]; + }]; + + [alert show]; return NO; } return YES; } -#pragma mark UIAlertView delegate -- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex -{ - if (buttonIndex == 0) - [[UIApplication sharedApplication] openURL:[NSURL URLWithString:last_link_clicked]]; -} - @end diff --git a/client/iOS/Controllers/BookmarkEditorController.h b/client/iOS/Controllers/BookmarkEditorController.h index 1ca68d3e4..5cdf0c9e0 100644 --- a/client/iOS/Controllers/BookmarkEditorController.h +++ b/client/iOS/Controllers/BookmarkEditorController.h @@ -21,7 +21,7 @@ @end -@interface BookmarkEditorController : EditorBaseController +@interface BookmarkEditorController : EditorBaseController { @private ComputerBookmark* _bookmark; diff --git a/client/iOS/Controllers/BookmarkEditorController.m b/client/iOS/Controllers/BookmarkEditorController.m index dc5714da6..57fa93f39 100644 --- a/client/iOS/Controllers/BookmarkEditorController.m +++ b/client/iOS/Controllers/BookmarkEditorController.m @@ -14,6 +14,7 @@ #import "PerformanceEditorController.h" #import "CredentialsEditorController.h" #import "AdvancedBookmarkEditorController.h" +#import "BlockAlertView.h" @implementation BookmarkEditorController @@ -338,18 +339,6 @@ return YES; } -#pragma mark - UIAlertViewDelegate methods - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - // clicked yes? - if (buttonIndex == 0) - { - // cancel bookmark editing and return to previous view controller - [[self navigationController] popViewControllerAnimated:YES]; - } -} - #pragma mark - #pragma mark Action Handlers @@ -363,8 +352,13 @@ { if ([[_bookmark label] length] == 0 || [[_params StringForKey:@"hostname"] length] == 0 || [_params intForKey:@"port"] == 0) { - UIAlertView* alertView = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Cancel without saving?", @"Incomplete bookmark error title") message:NSLocalizedString(@"Press 'Cancel' to abort!\nPress 'Continue' to specify the required fields!", @"Incomplete bookmark error message") delegate:self cancelButtonTitle:NSLocalizedString(@"Cancel", @"Cancel Button") otherButtonTitles:NSLocalizedString(@"Continue", @"Continue Button"), nil] autorelease]; - [alertView show]; + BlockAlertView* alertView = [BlockAlertView alertWithTitle:NSLocalizedString(@"Cancel without saving?", @"Incomplete bookmark error title") message:NSLocalizedString(@"Press 'Cancel' to abort!\nPress 'Continue' to specify the required fields!", @"Incomplete bookmark error message")]; + [alertView setCancelButtonWithTitle:NSLocalizedString(@"Cancel", @"Cancel Button") block:^{ + // cancel bookmark editing and return to previous view controller + [[self navigationController] popViewControllerAnimated:YES]; + }]; + [alertView addButtonWithTitle:NSLocalizedString(@"Continue", @"Continue Button") block:nil]; + [alertView show]; return; } } diff --git a/client/iOS/Controllers/BookmarkListController.h b/client/iOS/Controllers/BookmarkListController.h index a8a046e94..e57ea9035 100644 --- a/client/iOS/Controllers/BookmarkListController.h +++ b/client/iOS/Controllers/BookmarkListController.h @@ -14,7 +14,7 @@ #import "BookmarkEditorController.h" #import "Reachability.h" -@interface BookmarkListController : UIViewController +@interface BookmarkListController : UIViewController { // custom bookmark and session table cells BookmarkTableCell* _bmTableCell; diff --git a/client/iOS/Controllers/BookmarkListController.m b/client/iOS/Controllers/BookmarkListController.m index a6ff0685a..386917edd 100644 --- a/client/iOS/Controllers/BookmarkListController.m +++ b/client/iOS/Controllers/BookmarkListController.m @@ -14,6 +14,7 @@ #import "Toast+UIView.h" #import "Reachability.h" #import "GlobalDefaults.h" +#import "BlockAlertView.h" #define SECTION_SESSIONS 0 #define SECTION_BOOKMARKS 1 @@ -633,8 +634,17 @@ // ask the user if he wants to save the bookmark NSString* title = NSLocalizedString(@"Save Connection Settings?", @"Save connection settings title"); NSString* message = NSLocalizedString(@"Your Connection Settings have not been saved. Do you want to save them?", @"Save connection settings message"); - UIAlertView* alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self - cancelButtonTitle:NSLocalizedString(@"Yes", @"Yes Button") otherButtonTitles:NSLocalizedString(@"No", @"No Button"), nil]; + BlockAlertView* alert = [BlockAlertView alertWithTitle:title message:message]; + [alert setCancelButtonWithTitle:NSLocalizedString(@"No", @"No Button") block:nil]; + [alert addButtonWithTitle:NSLocalizedString(@"Yes", @"Yes Button") block:^{ + if (_temporary_bookmark) + { + [_manual_bookmarks addObject:_temporary_bookmark]; + [_tableView reloadSections:[NSIndexSet indexSetWithIndex:SECTION_BOOKMARKS] withRowAnimation:UITableViewRowAnimationNone]; + [_temporary_bookmark autorelease]; + _temporary_bookmark = nil; + } + }]; [alert show]; } } @@ -649,21 +659,6 @@ [[self view] makeToast:NSLocalizedString(@"Failed to connect to session!", @"Failed to connect error message") duration:ToastDurationNormal position:@"center"]; } -#pragma mark - UIAlertView delegates - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - // yes clicked? - if (buttonIndex == 0 && _temporary_bookmark) - { - [_manual_bookmarks addObject:_temporary_bookmark]; - [_tableView reloadSections:[NSIndexSet indexSetWithIndex:SECTION_BOOKMARKS] withRowAnimation:UITableViewRowAnimationNone]; - } - - [_temporary_bookmark autorelease]; - _temporary_bookmark = nil; -} - #pragma mark - Reachability notification - (void)reachabilityChanged:(NSNotification*)notification { diff --git a/client/iOS/Controllers/HelpController.m b/client/iOS/Controllers/HelpController.m index 5ed3bc90b..594dfb2ee 100644 --- a/client/iOS/Controllers/HelpController.m +++ b/client/iOS/Controllers/HelpController.m @@ -55,27 +55,4 @@ return YES; } -#pragma mark - -#pragma mark UIWebView callbacks -- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType -{ - if([[request URL] isFileURL]) - return YES; - - if(navigationType == UIWebViewNavigationTypeLinkClicked) - { - NSString* lastClickedLink = [[request URL] absoluteString]; - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"External Link" - message:[NSString stringWithFormat:@"Open [%@] in Browser?", lastClickedLink] - delegate:self - cancelButtonTitle:@"OK" - otherButtonTitles:@"No", nil]; - [alert show]; - [alert release]; - - return NO; - } - return YES; -} - @end diff --git a/client/iOS/Controllers/RDPSessionViewController.h b/client/iOS/Controllers/RDPSessionViewController.h index 52502bf9a..996c2915f 100644 --- a/client/iOS/Controllers/RDPSessionViewController.h +++ b/client/iOS/Controllers/RDPSessionViewController.h @@ -14,7 +14,7 @@ #import "TouchPointerView.h" #import "AdvancedKeyboardView.h" -@interface RDPSessionViewController : UIViewController +@interface RDPSessionViewController : UIViewController { // scrollview that hosts the rdp session view IBOutlet UIScrollView* _session_scrollview; diff --git a/client/iOS/Controllers/RDPSessionViewController.m b/client/iOS/Controllers/RDPSessionViewController.m index 87137548c..c431d8c51 100644 --- a/client/iOS/Controllers/RDPSessionViewController.m +++ b/client/iOS/Controllers/RDPSessionViewController.m @@ -15,6 +15,7 @@ #import "ConnectionParams.h" #import "CredentialsInputController.h" #import "VerifyCertificateController.h" +#import "BlockAlertView.h" #define TOOLBAR_HEIGHT 30 @@ -415,8 +416,12 @@ - (void)showGoProScreen:(RDPSession*)session { - UIAlertView* alertView = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Pro Version", @"Pro version dialog title") - message:NSLocalizedString(@"Do you want to buy Thinstuff RDC Pro and enable the full RDP Experience", @"Pro version dialog message") delegate:self cancelButtonTitle:NSLocalizedString(@"No", @"No Button title") otherButtonTitles:NSLocalizedString(@"Yes", @"Yes button title"), nil] autorelease]; + BlockAlertView* alertView = [BlockAlertView alertWithTitle:NSLocalizedString(@"Unlicensed Client", @"Pro version dialog title") message:NSLocalizedString(@"You are connected to Thinstuff Remote Desktop Host (RDH). Do you want to purchase an access license for this client which allows you to connect to any computer running Thinstuff RDH?", @"Pro version dialog message")]; + + [alertView setCancelButtonWithTitle:NSLocalizedString(@"No", @"No Button title") block:nil]; + [alertView addButtonWithTitle:NSLocalizedString(@"Yes", @"Yes button title") block:^ { + }]; + [alertView show]; } @@ -556,16 +561,20 @@ - (void)onTransactionSuccess:(NSNotification*)notification { - UIAlertView* alertView = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Transaction Succeeded", @"Pro version bought dialog title") - message:NSLocalizedString(@"Thanks for buying Thinstuff RDC Pro. In order for the purchase to take effect please reconnect your current session.", @"Pro version bought dialog message") delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"OK Button title") otherButtonTitles:nil] autorelease]; + BlockAlertView* alertView = [BlockAlertView alertWithTitle:NSLocalizedString(@"Transaction Succeeded", @"Pro version bought dialog title") + message:NSLocalizedString(@"Thanks for buying Thinstuff RDC Pro. In order for the purchase to take effect please reconnect your current session.", @"Pro version bought dialog message")]; + [alertView setCancelButtonWithTitle:NSLocalizedString(@"OK", @"OK Button title") block:nil]; + [alertView show]; } - (void)onTransactionFailed:(NSNotification*)notification { - UIAlertView* alertView = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Transaction Failed", @"Pro version buy failed dialog title") - message:NSLocalizedString(@"The transaction did not complete successfully!", @"Pro version buy failed dialog message") delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"OK Button title") otherButtonTitles:nil] autorelease]; - [alertView show]; + BlockAlertView* alertView = [BlockAlertView alertWithTitle:NSLocalizedString(@"Transaction Failed", @"Pro version buy failed dialog title") + message:NSLocalizedString(@"The transaction did not complete successfully!", @"Pro version buy failed dialog message")]; + [alertView setCancelButtonWithTitle:NSLocalizedString(@"OK", @"OK Button title") block:nil]; + + [alertView show]; } #pragma mark - diff --git a/client/iOS/Resources/alert-black-button.png b/client/iOS/Resources/alert-black-button.png new file mode 100644 index 0000000000000000000000000000000000000000..d06b66df18233a13c822fb93eb10e252d986dbf3 GIT binary patch literal 1591 zcmbVMdr%a09AD`nq68{xG?eR-dLrCD?!9v0aSuJ?=!6T8M$Kh+xx3+Z_u5;y105`U zW#t1w%Y0NbO1>bRabVH_r4&U?Cm|nWiH;(6Iw+y#=t+CPS<^WF(a!Ate&65k`}us| zyV{yHD>~}6C;$MW&9e>J;+iPF$&oLM-=1~DJ{6aE!Dtt9xB|gP@HC*KxO^HkGlYZA zrU|O#{S$O50K8D(ve^Z@B@-t(MoNTqq<+RDq5&W^-R~jDLRtXxX@`r|LOq9?A<#u> zp?L}mV)5u{r)zd8Pv?|o*~rpDQbR%MX<(`!7YP_zAV5FkX1%yy3k~q%;y!c?L*Rgl zP^g6low8f3pq}GtP$5N9NJNQ%N>qx<rD(Z7-%oayF7x6 zW5Ez3kke7FLg`Oc{D5f?}A+VMKK@RB4jyR2dn1gGqxZ!dNrw z6$qB3!**Sw-9fCv^js{i=V?OVcpJyL!yRCCasuadavo5hqW~=g>0(22s62zw8fe~C zOj9PFW59v@;;v`dH>v*gNYL0(3OZZ6az|i(- z>x;tE;h|Y^Vt8>h($2Qb1AqvJ*`TxeFWt7EDQuq^S7x5_pziCDwd_$Q7}H)89M)LU ztxHXggRd=Jzs#Q`>67@K@QVEYh?ls=$S1>B)K5RUa86Hd;9z~;wJ8@Vtm(5~^UjsG zQeBKwAJHDD<$nN4pv8^Mj#?_x*Z;LK2 zPHVY!tKpmRYa16VEb~vb}8y+=x-s=oBsU7cCJXUA7blBKzqgh|b@wiTzeP$IS~G4aU;^9Jg+dz|iJ zD@E6vi_mBqbg~^hcp{J z?o?Rby<_QbShkcIPN+XP0_K{I$!qp@yeUk(GpW5|m_@4(-mROOI~HpwYqQ4e*>Gy- z8}2^CoWKMJNSkOy|Os1Mm9^ZQhA%kyd&Wf zV!HQRMnUdJ+tpc<1IClKRkr=fWASb8wU;)@9gd#nm~v0x@#T|Q6XVHV`(Epqs#U#n ze?vw!SeM7RuU}W33FOU<`>wL`mCVff`eXYJU&&khVnp}-CEw2yB#oOY+{&Ic>3Hg6 rXkB2!=!U4cn=|rbY7@@)k6r{E{Hb?O+X3&9(68KV%rewwEGqvS5XD=- literal 0 HcmV?d00001 diff --git a/client/iOS/Resources/alert-black-button@2x.png b/client/iOS/Resources/alert-black-button@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4caec8ea3433e36d506619f740521d5d65564cab GIT binary patch literal 2168 zcmbVOdsGuw8qZeRVyYG*+K9Fc0W6>-GYRAcK|>}3D1i{7q6KRb1_+Q$NCF8|UBL$l zu(-Td1ziM+^$D$jS|Kg2_(E7zD3P+eR6xp#h*0Ya741aD-LuEjKRV~k-22`8{eIv3 zoH2{TgXa^Si39>+erO0R!B+%-qwU|pzaf)Z7``mg3#0W>SiIgK)1m}^941GBP?anJ zm7ub?jMQsr0D&+kUMY>%M~lL^3QR?n*>tEzl?F!>2mz~%8kr&))dO-gL8<0Z#+$yS z0LnNXWrLpx6lnx#qB0~?i$-OJOBI>P3QinlRUi;xR4)UJsuZ=3YvfU0@N)6J z?U+UZUa07kd6bt(>E)mlJ zf+#;gBvUBWHrZC5m(jwgR+)~*AzDlYyvQ$C`3Cz4`~TwRGhrdf7BUe(h{I+IDX*|` zzb9uj+!>m!IsT_vW{>a=v~6FvJ}$f-9#oA_j20h_=?E}^K(IR+3iGAL@9)QSBrl9~ zsMxA1ZxD5L*Hv}bF@tX+Fj4406N;T^#30K^{|`c1_Q%h6WRjd<2Vterkxvx1E}n=M zHi(m!mivmzmY3hJW%O+;7nL>qb2{rpjt^MuIXE8&-mtT#+F+uZO<)&(T z7vCdF(_WLZl|A4^k&*X|x;P8TqJl`uk;MUi_MEJ9dF-(XQUG=7ubf0(mn_zS%lO{L7|)0qTJ#mY=4RXq~Q`Z|pFUKMI_~<26+-QK{7* zZMI~pNN8_{`;VxPJVi1vQ4O+%Eu$s?gRGI{-bAWEy16QspcztvyLwY$~%IV7pvO9sz2%}g*yrg(i1U^ zwe7DJ5#k5tfhz_FYY1d9jR#hIfFQNmRZm1UD}8GC@8rQ;(cK|!hVjt|lvo!2#ecdE z4iN`ZR`$F*GxKhx_^QCW(e5#=Qc*nUKM<|y3NEDU7aFpzd0Lf+b*aL}BVosYDRWNvhNrd3%}9uGCNRSg11COu=p zbyH&iQpau!4vW1+UKBiKg4iW7yGf-<2Nt%R^V_FMgKwWHyL`=1KXgJ_)?MlT z^wZ$5jLR!V+xJ~>?9-~G%g`9OXRe23SiWXj=pOOVcxtFNMppoxi)r$<))c8l`XP7Z zNoQ{FwB6of+QPv-jpB~KNZj0P}6a|=yp}flqGq6{?bdDN%Ydg_I)QvG|F?8r;pp;%GT3A zyLvVHv@&PMs{%{5V}po?_#9F2LGO)uMe{!Ix;{{pXMFJW62Eo*HR-plR(U6uPD)Wm zmPw#TCHFcjyxLEs!~Y1DsBe2TUp9ohs$IjoTvRH4{U*oA+*`NZBUg3EBQM@7z6d98 zIDFRB7t+>u>e&KTRDa9k)nCs%lflgw+!9F>9c4{C{?ntZgkL;b2q6>V?|)eOsL1v& N5Go9ZYlF6A{|aRxZfpPm literal 0 HcmV?d00001 diff --git a/client/iOS/Resources/alert-gray-button.png b/client/iOS/Resources/alert-gray-button.png new file mode 100644 index 0000000000000000000000000000000000000000..06548df511cbe012e7c59ff4b696baa05a107691 GIT binary patch literal 1622 zcmbVMdrT8|9IuaniVAZtzQ5o1`}usI zw<#@k-jqo*CviBODe7b_gIy!oH+Dh*`|aC4W-GhA!zeQuEoEdJI8AV51}c{T)Ff^q zG6>wTvhXsI$l;7Lnsu2>re=XePmx^Qr^9uUHrATMNlbFuaD4&60J((8Y?Xq2XX`=0 zY>kBm+~8aPzGVAifBDs4`YPin9bdP6ZsTbZzKz8Gg}ngf>HV+lCUyrObW6$T!YylQHg~r z1QEu=LLMv-A&3YTp%^Mxq5>F36!9`Y#+z*UN)?O=Q5fOzcnG3IWGEs~#mj_pxdKy( zVZPs1ZM8GFRZsYN%`7ipsZ{ZJnBqTeB?_9r8H(0Xl*QixX?YYw+4CqHpwRLG4X!s^ zeX_4SucE~W+Ps1=sA!4=M)E5$zky#R`d8dC0j7jSN`Z=xh(!V=IBIM7KRJU~XCPm5 z{G(a?M{EcBwy#^C6NVe)t~LOOfMZQ z3>i13`g~By9i?0r?VNVaJuCydLyMmUAH6X=_qU{wN%Bq0KapQuRqaYU)NaXLaX-r2 zZI62Nxav+Jnt%)3P341dpSRonZc|ukOXaqdXOF5<*0|4Y8?wx;TUduqzJIcFUn4v| z{fKu)Z?Evoo-50a-z2Z~p712A4k7`iV_y6jEJ_^uPN8U1qX zDQQRKF;7lR=zAx+2wl}jzx-O)*u8wMJ7;h4_@@T)N%8g^+v>yyi$Kvmy{Th^w=TGB z71MuWUU*-MEN#s|&)w33vY-V~Z%OkP{XG9r^y#Tt)m0+VbLQf~tL_2SI9yb6J)o)< z7pabQKDe1ZSqq*1pyi=Gx#IfF@Grz+0rT6;X|iU~9QVmDwL$U^f1LL1I<;1lTV8ti z`Pv*^bF+Z%aLo)d?%#DBs7(L9GQHO5I%;&)qMvW(l4T#av_#{r(b?!w#H^5w2s5`U z^!C@SdHRB=(AEX{L8o#mcP!I9zL#Hq%jA-3(&H~OFH$C7`aSXN-X&+2N=xfuSM==i zgX_TG{IdpP$ literal 0 HcmV?d00001 diff --git a/client/iOS/Resources/alert-gray-button@2x.png b/client/iOS/Resources/alert-gray-button@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8333e6cfbeece177ff0d3b685a5d18c008b82793 GIT binary patch literal 2363 zcmbVOc~BEs8jpzJaEY!*&_Q~_h_DFh4o65JFgYbk9OV!cG=`*s2sum|!Zm0BMFC+E z6~TjJM#NFW3@V~58eI?+5Dg3wkY!(iry2z>*P0FD=#FA>@EW_0YMMN$-v!MJ%uOL_co7y*LeP@$ND8>_s51B3z! z&fkdxa-?)POz0UagMDH*`0``J`6L0(!yRyoCZhx*7~uiYq6o2^98JM}7vNNF>q>2Z3ORYS_tR#0W3iPAs>a zWnjQ^zDy`Zgc30@!^jJkL?RR%>glHtL{bjt3$a-KIZ;ge9po;^;fyQ)j20@7KNS)>Q8kWXjFI{CSIsU6zW{=PgoY{V9eN^}|Jg^v@7#TVm%1fD*7|gtIHiPOL-SI4l z8x{yJ_8?v*vYWT&RospgUms=^n-?(!+x*Js=_P9K8^>$(M=#=Ap=0<|>(orm8{A~S zg_S`Pbrbfad)Sg)WCpkT;SFK7Bd4>!r)wZ*A^;J3Qsa^NR zPD~8E#-19Q!`=yeBNCXtifMsb-fpsB9i%Bz)85!V;g&d*aEk`38)>^Pj_~N1iShmv z4sm;a1$dzToT)fBcC7nKt#IP*Wca8u_k}X|SjC@M`>}#k`x!WCf8AWrZQ9hxy-JOuJ)N> zXz%^Pq(bD#apH%hrW+O2$`=D$bcc?ctASeGf^R(%jLIHn@7S`mLS>lI_rqD=#DfPp zrcH|D*nM-Vs@TJ0V?$BQpErryUcS5{9qm})s(!2ntQCFli7hWjnzvwAtQf$wM=co~ zT2{FDq`8#wAiuJ9Ag=_*CuuSx$e%DeN*Coh-rRXv>^Rytoy>VBZOP; z&DHxmn3tCq|B+zauwBVh)s3VcDz&wI1f@xd8}y@OWF;RO($75; zX5I%0t!=i~f+tn3>)Y}Kg2;3WzSpJ<9wCF5nzAT6F1@3_{+Isx#jCkil#*cdsCnet z#phecw;y1~t!jig`IZHzFF3wjr_$D%sH`4k)cISudIsuTj`JK@ASNG1N?U}b)r*I) z#c`*rUaq^Q?!2JxY;V^-ZQab|0A4;vkF=PqYHIeVVDHIFUWBzfw==kI&jb6PFM6-t z!gftxb2zb$^y=w(J3FO&N5rE=lb4>^mGDAj7w{~a28YPWxIUc9R%_oRxdXfuy$d!tWeZ`K$!pNeO$^e?}~C)mS!(=T@BDF?OvXKQ+wS|DC1_OSt;juZJ+_;t%SUohH@6 zkZvtThrQ~oYqEZ_5-&#vmUZ}@^Gm2H^BPF>Y+nNcUh}cb9~(R!AT+MfvGn$6^d2b{ zJM>{E33PSPp!#s@O%?e>Qml6TwhuHG7@n8+9RaR=nZdj|yNU73H%&FSf4|)H zSa#s`2(tV+V@Y4ru-Tc-^wy}#x4!q%6X85g)C26Dcz66tQc^*DjZX!}>iADOA-nU8 zZ}WVf-0M1`WZ)Lw_3}OIyCX(u7SXvhr`YuHctN>Pcc1Rfm_<2hC98+!T&{(`Z3y+m z{$JDfY9M2xeQ8eNKTj%EMb{4$1RXii`$tYz*237{{$~;0al?kouYVsw*!w!;%7uLj zvl~D9kZLC1#ci?}l>rH?ceSP6?(}U&^DE%#_aAhOFbkp|(30H(<7R$m*vt(K6>Uf2 FzX8(H>$U&@ literal 0 HcmV?d00001 diff --git a/client/iOS/Resources/alert-red-button.png b/client/iOS/Resources/alert-red-button.png new file mode 100644 index 0000000000000000000000000000000000000000..896742f9c645c90daf785cff15ad467ba69e4701 GIT binary patch literal 1512 zcmeAS@N?(olHy`uVBq!ia0vp^@<6P^!3HGfIwV^GDajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_cg49sbnArU1JzCKpT`MG+DAT@dwxdlMo3=B5*6$OdO*{LN8 zNvY|XdA3ULckfqH$V{%1*XSQL?vFu&J;D8jzb> zlBiITo0C^;Rbi_HHrEQs1_|pcDS(xfWZNo192Makpx~Tel&WB=XP}#GU}m6TW~gUq zY+`P1uA^XNU}&IkV5Dzoq-$tyWo%?+V4wg6Nh+i#(Mch>H3D2mX;thjEr=FDs+o0^GXscbn}XpVJ5hw7AF^F7L;V>=P7_pOiaoz zEwNPsx)kDt+yY-;xWReF(0~F4nSMoLfxe-hfqrf-$X{U9#U(+h2xnkbT^v$bkg6Y) zTAW{6lnjiIG-a4(VA$ce2&53`8Y};zOkkuW=D6f1m*%GCm3X??DgkBmQZiGl+$_!A z3=Pdq49txT%q$EIEetG-U5uSvjm-=U44q9JVP;^{YwGG|;9_oUVQ6GzWN7GW=xA(c z=4Rq(?&Rd`;$~@J3e)SES6q^qmz)Z-HxpvEej%F^d1{SVn zZl;Eo7G|zWP`xSSgqc3jG5Vmyfs|NaLckOVV#1R?kOR*=sd>O0Qv}Q!#WqKi85o!( zJY5_^DsH`*ao+omgUIpyn`a*>EuEXN^~S9r8+?z3Eq3SCxB&a&q2jxIMh|GJ>#;iNA~VY{wAoxQyHe`)bCEpP8#4|83k~SMvJYJ;>b-!cl4hQ^)wE8VMhZt5leC9>&9W~#^?0*Qx3(f~-h4}6(L(JvdqwrL*4ibA`ggUy^3gx=RiSD1 zq|FKL95T_YHH$u7nmW57+eYu-#eZ|ueN|?BT)#xt@9XN;qid(``1{klfsx_JYX#3@ So#4};ve(nq&t;ucLK6TOojf}L literal 0 HcmV?d00001 diff --git a/client/iOS/Resources/alert-red-button@2x.png b/client/iOS/Resources/alert-red-button@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..852bd3f4b7d48bfa6bbc3b4b660fd3fca21d3790 GIT binary patch literal 2062 zcmbVNc~}!?8czkKAk+da6#AD{lQGtbQTe&4*m-+Mok z;qU8VVzkZ(hr^k8Zs!JIt1I>hKU{^qE8@6%*kXzDglHflL6bx(80Qv^M8SAZxhMt> zfJM>C@$E1RhtreDf`q70;KLLnazLch0W@+YhQ{Go+cZj%I2K0nQE-e*!6r;yY#`ue z(QHD9ivScTIj~f=Jw*ivruYVlQ)0!8Xu>vEJWIpG2;?v-!fWJl3N=&1CcNQgVzTa- zNWi~QL1Wp3w@wKK{&)_eg7Gc@=qv`QAf5^V5Sc=w(VXxk5CVxHi3pLLAsUlRVuB!k z=^|j(RM8S<0GGdH3)`^?QWRA(iNvI&Bp`_lAgUN5#9%OV93+x6rs1qkR-ht{vqHUb znSl$d#VVN+l_3hej!_haB%o{p=IPrIFSC8QMn9AAp{wDZ(F4!Re{pvx zD@|u@(d_r~I$+@i4z_;Y9hP*@ZtKNDfn?#eZ)Zf<5!b}I@hJmsQSRS%9`9NJ9(H`Q z;G~^9UsRFlVMejGo7nI?*L6cpF(l7HPg1<?-v|7 zC#SYH=VluiXia<@x5{d__adPdvx(?n<0Ji)E2c9ZeNAoaZn6f~-nb!RO%1k=QxvBq zcc7}mk`JEE|57!e|Ju%^VYp9YzKPwEZd#U}&sWUsP%%FGzY+8J}O5;3pKD&G9 z@rj6o*DjW}dv^HwG~O6F+9i2H)HrlxH=Jpz^0aNK@lU@nQa$fMe+_yDLV|`QJ7kT@@{EHWXUo8$pC%tkm zm@TM7ckRxoWdGWeZmu7`)~dPVw~NO&NV9$C1)J+*>XRgq7Lq8cWK+2R8vAmg2G0;Ie2yaxyG^q*tprLSCzM7U(=)l8uv<&L%$KE-qP55@U(#xL#}h&Y?}YQ=rR z0B9YS8OpAW(Zo+*9r|X-?2*}{s-kw4BqHm2Z26_X8`ge8b5I2IZ)#f^Hv6b50!CY_pjEZOU-n2GxaHFx+r{hrR<`6wrxjZ)U;GxIHb(d>XyNpVI zo;ZMmsg#8;5cD4bRzq}B&*J%a2l~W-5b~c zwSLY8M`(BYcU|A^OAdW}g(#(a_jcKiIXiEuC^5*9J~<2u{uy?4eW1|ZvtZm}%-T(R z=5qJEBu_gg$vb`j-VaqD)mz=2E!k7zXJtKu+%msRdyz-k;krY6VkQr#hkIi5^ZCEb S{&raRhxX+8a?iO(ru`d(-&KPE literal 0 HcmV?d00001 diff --git a/client/iOS/Resources/alert-window.png b/client/iOS/Resources/alert-window.png new file mode 100644 index 0000000000000000000000000000000000000000..e4907cf53b5f8edc6c2025e8c0a46eb29d5812a9 GIT binary patch literal 4886 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 IM6N<$g6rlaSpWb4 literal 0 HcmV?d00001 diff --git a/client/iOS/Resources/alert-window@2x.png b/client/iOS/Resources/alert-window@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2ecd138557734dc3842f83a66dfc051c22e963d3 GIT binary patch literal 7537 zcmXw7byQT{*S>T&NF!a+3|#_4m&6DtF?5N5ARR*wE!`n0LkbAe9ZG|MG}0lUgf#qy z_gmi|ch0Q6_TJ~&&)w&&=kBN%+A0LNG`Ii&5U8nw^#A}>0Quh*8x#3E(_B%BTyR`f zjokqNkL>Y50kU$a0039VK~eF=3wsw27k7IXS4K5OMMl?mF18MDYyiM}Ay?ndK!5Lv z%*D!?f(9IxqT!-Pfz7C=5CbDmWannWAy$VoeVnJz?IuxDLZ=-nfTP97!(u6PdGMog ze`0Mi6~>1a!K1(5{PHVunr*w-9=-oEC%aR5np;1P)rF0prYfu}0>dv?U?5ow9qb$U zwaNE97?;%*AjYn@W^%t{K>;oUrKO)ScVTq^DBja}*g%(7c9#HMA_jS=J30oeF}fG#|o3qbb+ zphGMy-auF;K(2gZDE;?YHSrENlBvu(>1I|5rQp}tylz;AhI|a1V``Mo$VDwsEwY~T z_4s5`3k8FS)=ozNpdgU~S?%ea_ZVUI*qCU1BcVC(ekbMwv!&(6{nmJe>vI73b$#SU>Enmy`T4EQ&7bOh3a>4` z8wT9l^_X`V-o3dBl)k+lr!IETJ1u!U?ln+D=fpZNhuFrJrW* zQ?qO~;wInFC3TAjXT_chl`uysBysh#O+8qzukzfW$*zh3wT`kVeu=!FOs&xVX>br5 zd33E`0KiGBOZN{>Y&4jC=&y0Fhhw=rl>#;ZW~-Lu1^{MYRz8F8^>TyQ001rs=B|~e zJ?p08>B6Mz##rjcyM>B|DX{kSC=e^)TEpnxLAfeJ6gVSBYw5Y6{6C)4gSvF>Ba&SS z`FbE<31wV~t}U?hx;fi|anR+5u*oc#7T_qB(MBxs*p!*!mrUKN=%g{MjNjnoy387h zBC3LV(FTkVRr(W|cc>DPCdw^|QbT}H$ZbTMieO4`ovzFe{4a{lpTuawlne1DtUUy? z5}p)fPrPfOk%<-kxHC~CaWsEGRr_3QFhx40JoQ$OWsj#k8>C9Z zlKgGK+NlmpB87+X*--dq?q=_%@Fwjh)5&YxT+8Qf#h3c)oO<6K)v33Lw?JE%HW@> zeZp{Rcu!?FeHZP_3!fl@B6JXL$4Q+{g+*mY?L}3Sp;<~j9YZ~6ARs1qkg=0Vl<5L7 z;%?;jr%3#co2s75o=VHjZ%~dXMXVt3Ag7RFgM@N3{eWs^h_L=fInIx?3J4>`;y~lOC`{vC&0ZbFV%>tz<{NDTjCfYm_1-*8P6QPZ?}J79*gucX z`+IV?X57)Y#>gPbKT0SHs|y>}>z$_9%3*C}xLxLWXyfc~mZhHtMz4?`bFFjHmVz{! z1#L{65NYXYMir_Rx)mx1?V{C(Wx1v8O0C8>!G!XI>KrB#i+UY&2tjxzE(%wTz%E@dk|?K{_W0sMCcch1*k=PLL{nDzLqn2Y#h zRMPz-ZZ6XF{DX^sbrnr}pDUJFq*|o^3QKIBlrEZ4j#DOzbr>+&VBK&Ya2_aP$7E+> z*U;M6I?B@1YA)p}mC}^b92^}PEgYTA6v>tmoDy@i=tJr2+t6IxQ%9^#4wJY*w?RsnfHhya?Z=$Z<`iZ$% z-RRsHU}0xTY1h(N)7@LoXbu|q&4eRu}na zOaf&vHWWLws9^cv*Qhs_zWz*|@p6)jHvj7859MPEn&m0v6GEy&wz{jB?1z4TsA9U< z$rwu-|D z5;eT)BHXeFK1b;Vu@+E^+yI}g@yLu(u94as4LS)v?rPDuZ#q_Q4^Jc4bJy`U{3tW{ zhfH04K92RAg_k`k=Og8jOna^g*A`FtBTvlz=}9cx37HpLJg!dB-;f;lM+9;DIl1% zk{j*z?Y3<_hbwKu>+bvC#x(IWq+)$@s{c@lVa$u$s8G6V@QQPe8>`OF#?ZENH0rxV zT1DQo(ZiAY?~5PAa*p#K4oQ1Ree6sH3`2<}#Rz`@eop{b4$zwzo9i|dG7T3L#y z=xXvs%5;jLpPWnHTeOib-#asxQX0xD`kJlBZKrJawpV!bUK6Gv(znwI-xAC(G!U%5 zY&bmsr?kkQKFYb+8rrDXT+}K3waupN+t{d-oI$a{nZdPz=+V^j7mK;ex06S-er^9i zzh@R-w_V)He(P9-pg^={Y-en4)Nbl8AJ@(=y5G8=b3KlP-y zqvv;2$U4bV&eqSmd2RW+MQ22Ia&~{k_f}=`DNznc+So_^)Zm-L!d}R9vfaseY;J09 zKp@}M5_GY!(Qn6UY}Jv-<+z2|@)}HInAe`yTt! z_sP>bgRMEOS=G%ZPR&QY?O*(CFZO8j#KxA-+I{{$d6=EalaN_%KlOFF=)X8$eX<<* zj^l1@xOLu(ENFK2^5(GHYsriLxM-C~XVafCi1Wez>hrn&MA=O;b#n3p zI$Fl*t(7qEB2sTMTB+)30e~+X0Kh^4;OYUn?g7Aiq%hrw0)S)&08qLlnfEIL0BMdI zSl+;U;rFsr0_&XV;NR5;gY);Ev(1OTVk?!oJby7Xpt0fBIL7kw%tWVvmhx37I5D!>uhARgN?H4r(gUJt=P}+2S7~cIcaJgRCje#&j zdH$WNm>Igz(~sUgh4YvtlQa6>2)&box#?2;aZ_o;wJ_wiOX8wt2s+^>8DG>%o>(?a`{Ve+?QQ|m?!RjDn;^2KGYE&dM|LOJcpfb((DnqDtVXK~Y7~q+znkCMntv5QY|}d2{ua;1$g6 z^@&~I9pN#b*Z{j8lHPy1vCi%*3_XH^5)#Of=tkdP9FeR%tSS239A2;v*9lp7q_ghD z7~8J$GP65}jesl-+MO^pV;!qBsQKHO&8~Yb9&|RueNnnN3ORd1#awnNJ6!dPII~`+ zxihTzed6|KPz8g*9>LUBjLZT9jL{<=o&yq*`46{^Z2>o?Zeu82^iIn$MY<>B0O=1E z>+f(k#EK|dY0PzsE;WCsMtX#~m~tK#?B=+$FhS;8>F~S-fbrD3js>?`ks--sW)9(u zp4i*GA<<&zy1y9BAG$dX;sn;(J3PF_uW4Xz8hu8Pd}KoNK8+?glH2b4`#;&tCzbHE zM3uLDNWh$ckyE0L=XOLncjbFdM=j%5*zSr~eMUwyK%}*%7#q zfUTqDNy8X;WR}Hqtm`*>96;AO8^ zamM7;!6c`T1Uw@OA!m;{QWgWF_Gta9co%rg2Bbd?*lar69>oG_>5Cikj_}TPAiJNW zip2ykxzlCh(9`YapWn&$YdH!4OHIf}R_l--S?H(hRp6XuD=o&WwcYH(1u*IGd`O-3 z&eYT!z(Ypo!rcjz)o9v|6HB??uJ}K%Sq@S{G2zQ9j@d70vB%3ea{U>k4bI#1u$2Dy zvp36TUbD^hJCbC$s651unSEI3(Y&zNN1SLE(R=T%)YoUx5a!}lICLukEVZ0}pg}8k z_)?~uX8h^ok`LKR4fF7Cb#Ekdt*exp7Q3rn6YXWY+#5uT`fPoL?crm#^G6Nox0?~= zw+EU|gR1`V=#B8Ku`x3P%(g!xac@5Xp zXfYuf=K=hW2Hu~q%$7zceG9wbL)Pf5^^@jG_l{TAYold5kyIw8QAB`wiY&1Pj$Liq ziuh%ZH`n%fkMMHY)L5#$&xnO4xQ}zw;Rx#ROPOr zBB0jGp+?ldw_g3R`}x8TKO%m%HW)fl6f{yMEuq4G)z-i;x2#AybRMbF8Z)Mv&g{r< z!YO`}`l<`QCJYd(xE&V9j&bQsJ)TP`d@3b6{Lg*5CddpOwC9Wu)*BvkmH#0uQT9W3 z7Rpf8`g0}zPj;?N}Pu%SMIM0xW5I2Y2D zBIG6whyLZ~k?x*uUE(_y&RILrK;}7IlR0#;8#KN>&>JG2&oq2; zp=BLCNgc`=O|v>w@Q5(209eZzF6#I5-YMH-jN_lPL9->nSpc`IY|GT~tV8&b!t~kj;_0VG~6S3=A1PZ&y4LEQ0AVok9R^|I?B9+fLv*X}61p`M?i2F^RAXMY6ZSv-VwwLG;FSJ;hmnpFKlIqXtIHSde=v@$Gy*4MX@PP* zE&q#)gL0LH=D0&@D`nWM9kYYv1@zow=eddpzF}?CM>R2kDxUrwyYc@^*npqqNDwEe zJN$MrmIg_J>417i`z-TIgb0tto3PbJe*#rkdP#TseM9NY4esJu^8N&KL3_uT5Qs%? zIB&cma#Im?EAMS~WNcMM2-{Or2h5mCkvzu3$@|cuBSHpxZG9%;BpE|p zsuUtU^3+K8FA%)9^ljU%ARQIC5%y4cPV1U^UY6*NNU6EWmfw1kATi;W zvU}~)FKl^mob|S~#g=0ip#>eIdG09|mRBDU>MZ;&9#G$^blZ^aJr;O${ zL(cE#Ae$craGK2OvR_9_V6eez;3af9`pM^zt6;aJy=;2k#%0^3Dsq9H$={r#-)5&q zG_4#0^Eh^3?}CnQHzDjlZ`8ckWS9%_3Zw;07@jeh(c-=N9OY0j5TVMq^38KS<{EwR z?1%m$neI%lq@0X0!HdHw(|!UKCpdfz;b>5jbMKIkYFQ}&^`sGzltKT4Q&{Sgi*Oy2 zpPA_?Tf&RBPy~C3Dkwpk1Q0^B&xC_q^!>VaLoWE=&cESvw5_Q(8rq^G4kLJx^PrYx z(OV`&GU=(Hbnvk-@L%Q7yIZHLM$0Ycw=tA=*>);W4<`;qNf%yWKNXi>)p|9x83eRe z#IZjO25Xs^3vCoivX07218vR!*yQpaB+(`}Zd6U2+;wvmYekIqg!dfCD88}z#ujtzzTVtiY+g~X$yS`}qjK(hgV2(^6CUI5{{GGzB9Z#?3 z0RH})BKM5qUDS(7=Qh&mLIz_h0gnYzOx{lU!SK;OOmkD02t;)b>fH}IBb^y}02inQQ`_dlV}EZj|&fGfQ5v*HzBlQn~BeM@}U zyE#|cc<@g61w*tyz50Ei$mq1RnY!?cMl!Bbh495M^}&8jf^T}vjZN>=-ko&04Wbhw zYDv)G&taBl5z_|XGF#!o1tY)0Ps)1n5_Y57s3qs&k$!h3#3pEpGkLmB2N7zr@AQ<_y>a9^YN@RkYZ&Sl>{8sZcDAmX^|~hd zS@2|AM-#Jc9V>9(H=)Gj$87$h>3wPg|d;Y5>H{*(Na?GYp)1G_l3lmpd5zMoUg z1LBJ(9H|5vmWHE8qO$2R<410sYP>DRDCx&LakkDN3?dl=T2xY7)csLM0VyeVLe+)E z(J8kZRR@|h&b8TGxihFXf1m1tHL&n0|4z~HtHnfoIQLkt=JsxQ74~MwBp;psvftyS z&lV{i|Da}QWRZ+PP<3iI3Sd@YHEXytuY0+d;wa%L^q|JaJ3c*qiORH;HsRYTQGtPf z8t!>MICnA*SsootR-*m5Pe8fC-P(7Km8f5}nz;UF%Q?T|?Tcm(%0sheRS|!Nh-rc8 z3zGN{dyO2P) zaSMD{wE7@2q_a2oJ{LD{V4M0vrwm1LGXKhaS@=0_aNp9}9|Xx)(g=Xdge+#U z>19@HI-F@uc(sqpcTV&D*EvQ9us~<{ccnv5jbirmiV@}RKCq{5Vcj9eH`p>9ObJmJpRe3CY|3|G1t;BWO?DUn})Kf zfR`e(r2geIUl-aGBGk!tAGZypRuJm~gYC4xJ``chE~P#y3wwT=|*Z=a5$Z;rZwAWIGekqN-=Nk5F+Wu}V9 zgW5=|U$7wW_+^aP9}6tQl?GK)*i^^oahyqVb(t8~?fdFb;Ji)jF@+cknm(=6=gizj z^(#SrjMyN0fZbt0iT_b3Ii@)4HLCMMlUM`jfhka^`#DLvc)a&9QsPX`ie&dnB!EU8 ztMu@wAi1CRy#Odk+Z*bHR3|N1`=f$d>V1ue&VrlYapPRv=vnqu+O&kW0bNUdnCN5ynWsUs!lv@|S?r^^^pS0)k>kW=j zvIeioT&O@Yfg~#YV7W6E>sEm*(!Fu8tA*k2- z4ze}r`&g(In3agiz{$1UkdA>NwTOR}d%fgbwe87sNg6i(iv5a}XR@;5ImWl7N)akM zNJU;4*RMgInVAse@5;II%;0t#f20fr5(4` z!UocynpBLsR$!k*j;D-tb;w%qs(inSoHm5AsIixi+`s5uu6TsQ>qgg|G4GAE(a~+{ ztIW2z6qg6s>2`fxC*y*Bvrq9~^b5cNj+P`+)HM21#9&O1dkjYmyDbZ37QfpWvv8Y` z3~&IccMw2B9Ix$Lq#9E2-YIE5eO~tUEP5Ck6m+RY;`0RHGhdnhRV(L(QNvxZ-`w=5 zPP?gs;oXH>^+mcu^gg;XhDR&(0TfsBWgPu%XdlY2i>U=nH~rZ9<@-EP@cB$>0+*?L z7=Y`$YO{{EGUr}dBn)uHpOu|q$cYI5A2V}FX}W+acsdA9iPwd=ZlD$rgnjx7Vkzxx zntP~6&K7XHIKb$By&Xq~1Sx*3kFA3+piohb~brwDQ`;{{Y&UA{zhz literal 0 HcmV?d00001 diff --git a/client/iOS/Views/BlockAlertView.h b/client/iOS/Views/BlockAlertView.h new file mode 100755 index 000000000..9a6a4431d --- /dev/null +++ b/client/iOS/Views/BlockAlertView.h @@ -0,0 +1,28 @@ +// +// BlockAlertView.h +// +// + +#import + +@interface BlockAlertView : NSObject { +@private + UIView *_view; + NSMutableArray *_blocks; + CGFloat _height; +} + ++ (BlockAlertView *)alertWithTitle:(NSString *)title message:(NSString *)message; + +- (id)initWithTitle:(NSString *)title message:(NSString *)message; + +- (void)setDestructiveButtonWithTitle:(NSString *)title block:(void (^)())block; +- (void)setCancelButtonWithTitle:(NSString *)title block:(void (^)())block; +- (void)addButtonWithTitle:(NSString *)title block:(void (^)())block; + +- (void)show; +- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated; + +@property (nonatomic, readonly) UIView *view; + +@end diff --git a/client/iOS/Views/BlockAlertView.m b/client/iOS/Views/BlockAlertView.m new file mode 100755 index 000000000..f231d7dc5 --- /dev/null +++ b/client/iOS/Views/BlockAlertView.m @@ -0,0 +1,340 @@ +// +// BlockAlertView.m +// +// + +#import "BlockAlertView.h" +#import "BlockBackground.h" + +@implementation BlockAlertView + +@synthesize view = _view; + +static UIImage *background = nil; +static UIFont *titleFont = nil; +static UIFont *messageFont = nil; +static UIFont *buttonFont = nil; + +#define kBounce 20 +#define kBorder 10 +#define kButtonHeight 44 + +#define kAlertFontColor [UIColor colorWithWhite:244.0/255.0 alpha:1.0] + +#define kAlertViewBackground @"alert-window.png" +#define kAlertViewBackgroundCapHeight 38 + +#pragma mark - init + ++ (void)initialize +{ + if (self == [BlockAlertView class]) + { + background = [UIImage imageNamed:kAlertViewBackground]; + background = [[background stretchableImageWithLeftCapWidth:0 topCapHeight:kAlertViewBackgroundCapHeight] retain]; + titleFont = [[UIFont boldSystemFontOfSize:20] retain]; + messageFont = [[UIFont systemFontOfSize:18] retain]; + buttonFont = [[UIFont boldSystemFontOfSize:18] retain]; + } +} + ++ (BlockAlertView *)alertWithTitle:(NSString *)title message:(NSString *)message +{ + return [[[BlockAlertView alloc] initWithTitle:title message:message] autorelease]; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - NSObject + +- (id)initWithTitle:(NSString *)title message:(NSString *)message +{ + if ((self = [super init])) + { + BlockBackground* blockBackground = [BlockBackground sharedInstance]; + [blockBackground sizeToFill]; + [self setViewTransform:blockBackground forOrientation:blockBackground.orientation]; + + CGRect frame = blockBackground.bounds; + frame.origin.x = (frame.size.width - background.size.width) * 0.5; + frame.size.width = background.size.width; + + _view = [[UIView alloc] initWithFrame:frame]; + _blocks = [[NSMutableArray alloc] init]; + _height = kBorder + 15; + + if (title) + { + CGSize size = [title sizeWithFont:titleFont + constrainedToSize:CGSizeMake(frame.size.width-kBorder*2, 1000) + lineBreakMode:NSLineBreakByWordWrapping]; + + UILabel *labelView = [[UILabel alloc] initWithFrame:CGRectMake(kBorder, _height, frame.size.width-kBorder*2, size.height)]; + labelView.font = titleFont; + labelView.numberOfLines = 0; + labelView.lineBreakMode = NSLineBreakByWordWrapping; + labelView.textColor = kAlertFontColor; + labelView.backgroundColor = [UIColor clearColor]; + labelView.textAlignment = NSTextAlignmentCenter; + labelView.shadowColor = [UIColor blackColor]; + labelView.shadowOffset = CGSizeMake(0, -1); + labelView.text = title; + [_view addSubview:labelView]; + [labelView release]; + + _height += size.height + kBorder; + } + + if (message) + { + CGSize size = [message sizeWithFont:messageFont + constrainedToSize:CGSizeMake(frame.size.width-kBorder*2, 1000) + lineBreakMode:NSLineBreakByWordWrapping]; + + UILabel *labelView = [[UILabel alloc] initWithFrame:CGRectMake(kBorder, _height, frame.size.width-kBorder*2, size.height)]; + labelView.font = messageFont; + labelView.numberOfLines = 0; + labelView.lineBreakMode = NSLineBreakByWordWrapping; + labelView.textColor = kAlertFontColor; + labelView.backgroundColor = [UIColor clearColor]; + labelView.textAlignment = NSTextAlignmentCenter; + labelView.shadowColor = [UIColor blackColor]; + labelView.shadowOffset = CGSizeMake(0, -1); + labelView.text = message; + [_view addSubview:labelView]; + [labelView release]; + + _height += size.height + kBorder; + } + } + + return self; +} + +- (void)dealloc +{ + [_view release]; + [_blocks release]; + [super dealloc]; +} + +- (void)setViewTransform:(UIView*)view forOrientation:(UIInterfaceOrientation)orientation +{ + switch(orientation) + { + case UIInterfaceOrientationPortrait: + view.transform = CGAffineTransformMakeRotation(0); + break; + + case UIInterfaceOrientationPortraitUpsideDown: + view.transform = CGAffineTransformMakeRotation((-2) *M_PI/2); + break; + + case UIInterfaceOrientationLandscapeRight: + view.transform = CGAffineTransformMakeRotation(M_PI/2); + break; + + case UIInterfaceOrientationLandscapeLeft: + view.transform = CGAffineTransformMakeRotation((-1) * M_PI/2); + break; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - Public + +- (void)addButtonWithTitle:(NSString *)title color:(NSString*)color block:(void (^)())block +{ + [_blocks addObject:[NSArray arrayWithObjects: + block ? [[block copy] autorelease] : [NSNull null], + title, + color, + nil]]; +} + +- (void)addButtonWithTitle:(NSString *)title block:(void (^)())block +{ + [self addButtonWithTitle:title color:@"gray" block:block]; +} + +- (void)setCancelButtonWithTitle:(NSString *)title block:(void (^)())block +{ + [self addButtonWithTitle:title color:@"black" block:block]; +} + +- (void)setDestructiveButtonWithTitle:(NSString *)title block:(void (^)())block +{ + [self addButtonWithTitle:title color:@"red" block:block]; +} + +- (void)show +{ + BOOL isSecondButton = NO; + NSUInteger index = 0; + for (NSUInteger i = 0; i < _blocks.count; i++) + { + NSArray *block = [_blocks objectAtIndex:i]; + NSString *title = [block objectAtIndex:1]; + NSString *color = [block objectAtIndex:2]; + + UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"alert-%@-button.png", color]]; + image = [image stretchableImageWithLeftCapWidth:(int)(image.size.width+1)>>1 topCapHeight:0]; + + CGFloat maxHalfWidth = floorf((_view.bounds.size.width-kBorder*3)*0.5); + CGFloat width = _view.bounds.size.width-kBorder*2; + CGFloat xOffset = kBorder; + if (isSecondButton) + { + width = maxHalfWidth; + xOffset = width + kBorder * 2; + isSecondButton = NO; + } + else if (i + 1 < _blocks.count) + { + // In this case there's another button. + // Let's check if they fit on the same line. + CGSize size = [title sizeWithFont:buttonFont + minFontSize:10 + actualFontSize:nil + forWidth:_view.bounds.size.width-kBorder*2 + lineBreakMode:NSLineBreakByClipping]; + + if (size.width < maxHalfWidth - kBorder) + { + // It might fit. Check the next Button + NSArray *block2 = [_blocks objectAtIndex:i+1]; + NSString *title2 = [block2 objectAtIndex:1]; + size = [title2 sizeWithFont:buttonFont + minFontSize:10 + actualFontSize:nil + forWidth:_view.bounds.size.width-kBorder*2 + lineBreakMode:NSLineBreakByClipping]; + + if (size.width < maxHalfWidth - kBorder) + { + // They'll fit! + isSecondButton = YES; // For the next iteration + width = maxHalfWidth; + } + } + } + + UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; + button.frame = CGRectMake(xOffset, _height, width, kButtonHeight); + button.titleLabel.font = buttonFont; + if ([button.titleLabel respondsToSelector:@selector(setMinimumScaleFactor:)]) + button.titleLabel.minimumScaleFactor = 10; + button.titleLabel.textAlignment = NSTextAlignmentCenter; + button.titleLabel.shadowOffset = CGSizeMake(0, -1); + button.backgroundColor = [UIColor clearColor]; + button.tag = i+1; + + [button setBackgroundImage:image forState:UIControlStateNormal]; + [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [button setTitleShadowColor:[UIColor blackColor] forState:UIControlStateNormal]; + [button setTitle:title forState:UIControlStateNormal]; + button.accessibilityLabel = title; + + [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside]; + + [_view addSubview:button]; + + if (!isSecondButton) + _height += kButtonHeight + kBorder; + + index++; + } + + CGRect frame = _view.frame; + frame.origin.y = - _height; + frame.size.height = _height; + _view.frame = frame; + + UIImageView *modalBackground = [[UIImageView alloc] initWithFrame:_view.bounds]; + modalBackground.image = background; + modalBackground.contentMode = UIViewContentModeScaleToFill; + [_view insertSubview:modalBackground atIndex:0]; + [modalBackground release]; + + [[BlockBackground sharedInstance] addToMainWindow:_view]; + + __block CGPoint center = _view.center; + center.y = floorf([BlockBackground sharedInstance].bounds.size.height * 0.5) + kBounce; + + [UIView animateWithDuration:0.4 + delay:0.0 + options:UIViewAnimationOptionCurveEaseOut + animations:^{ + [BlockBackground sharedInstance].alpha = 1.0f; + _view.center = center; + } + completion:^(BOOL finished) { + [UIView animateWithDuration:0.1 + delay:0.0 + options:0 + animations:^{ + center.y -= kBounce; + _view.center = center; + } + completion:nil]; + }]; + + [self retain]; +} + +- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated +{ + if (buttonIndex >= 0 && buttonIndex < [_blocks count]) + { + id obj = [[_blocks objectAtIndex: buttonIndex] objectAtIndex:0]; + if (![obj isEqual:[NSNull null]]) + { + ((void (^)())obj)(); + } + } + + if (animated) + { + [UIView animateWithDuration:0.1 + delay:0.0 + options:0 + animations:^{ + CGPoint center = _view.center; + center.y += 20; + _view.center = center; + } + completion:^(BOOL finished) { + [UIView animateWithDuration:0.4 + delay:0.0 + options:UIViewAnimationOptionCurveEaseIn + animations:^{ + CGRect frame = _view.frame; + frame.origin.y = -frame.size.height; + _view.frame = frame; + [[BlockBackground sharedInstance] reduceAlphaIfEmpty]; + } + completion:^(BOOL finished) { + [[BlockBackground sharedInstance] removeView:_view]; + [_view release]; _view = nil; + [self autorelease]; + }]; + }]; + } + else + { + [[BlockBackground sharedInstance] removeView:_view]; + [_view release]; _view = nil; + [self autorelease]; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - Action + +- (void)buttonClicked:(id)sender +{ + /* Run the button's block */ + int buttonIndex = [sender tag] - 1; + [self dismissWithClickedButtonIndex:buttonIndex animated:YES]; +} + +@end diff --git a/client/iOS/Views/BlockBackground.h b/client/iOS/Views/BlockBackground.h new file mode 100644 index 000000000..c5cfb66c7 --- /dev/null +++ b/client/iOS/Views/BlockBackground.h @@ -0,0 +1,24 @@ +// +// BlockBackground.h +// arrived +// +// Created by Gustavo Ambrozio on 29/11/11. +// Copyright (c) 2011 N/A. All rights reserved. +// + +#import + +@interface BlockBackground : UIWindow + ++ (BlockBackground *) sharedInstance; + +- (void)addToMainWindow:(UIView *)view; +- (void)reduceAlphaIfEmpty; +- (void)removeView:(UIView *)view; + +- (UIInterfaceOrientation)orientation; +- (CGFloat)statusBarHeight; + +- (void)sizeToFill; + +@end diff --git a/client/iOS/Views/BlockBackground.m b/client/iOS/Views/BlockBackground.m new file mode 100644 index 000000000..a4633f9e9 --- /dev/null +++ b/client/iOS/Views/BlockBackground.m @@ -0,0 +1,160 @@ +// +// BlockBackground.m +// arrived +// +// Created by Gustavo Ambrozio on 29/11/11. +// Copyright (c) 2011 N/A. All rights reserved. +// +#import +#import "BlockBackground.h" + +@implementation BlockBackground + +static BlockBackground *_sharedInstance = nil; + ++ (BlockBackground*)sharedInstance +{ + if (_sharedInstance != nil) { + return _sharedInstance; + } + + @synchronized(self) { + if (_sharedInstance == nil) { + [[[self alloc] init] autorelease]; + } + } + + return _sharedInstance; +} + ++ (id)allocWithZone:(NSZone*)zone +{ + @synchronized(self) { + if (_sharedInstance == nil) { + _sharedInstance = [super allocWithZone:zone]; + return _sharedInstance; + } + } + NSAssert(NO, @ "[BlockBackground alloc] explicitly called on singleton class."); + return nil; +} + +- (id)copyWithZone:(NSZone*)zone +{ + return self; +} + +- (id)retain +{ + return self; +} + +- (unsigned)retainCount +{ + return UINT_MAX; +} + +- (oneway void)release +{ +} + +- (id)autorelease +{ + return self; +} + +- (void)sizeToFill +{ + UIInterfaceOrientation o = [self orientation]; + + if(UIInterfaceOrientationIsPortrait(o)) + { + CGRect r = [[UIScreen mainScreen] applicationFrame]; + + CGFloat portraitHeight = [[UIScreen mainScreen] bounds].size.height; + CGFloat portraitWidth = [[UIScreen mainScreen] bounds].size.width; + + CGFloat center_y = (r.size.height / 2) + [self statusBarHeight]; + CGFloat center_x = (r.size.width / 2); + + self.bounds = CGRectMake(0, 0, portraitWidth, portraitHeight); + self.center = CGPointMake(center_x, center_y); + } + else if(UIInterfaceOrientationIsLandscape(o)) + { + CGFloat landscapeHeight = [[UIScreen mainScreen] bounds].size.height; + CGFloat landscapeWidth = [[UIScreen mainScreen] bounds].size.width; + CGFloat center_y = (landscapeHeight/2); + CGFloat center_x = (landscapeWidth / 2); + + self.bounds = CGRectMake(0, 0, landscapeHeight, landscapeWidth); + self.center = CGPointMake(center_x, center_y); + } +} + +- (id)init +{ + self = [super initWithFrame:[[UIScreen mainScreen] applicationFrame]]; + if (self) { + self.windowLevel = UIWindowLevelStatusBar; + self.hidden = YES; + self.userInteractionEnabled = NO; + self.backgroundColor = [UIColor colorWithWhite:0.4 alpha:0.5f]; + } + return self; +} + +- (UIInterfaceOrientation)orientation +{ + return [UIApplication sharedApplication].statusBarOrientation; +} + +- (CGFloat)statusBarHeight +{ + CGSize statusBarSize =[[UIApplication sharedApplication] statusBarFrame].size; + return MIN(statusBarSize.height, statusBarSize.width); +} + +- (void)addToMainWindow:(UIView *)view +{ + if (self.hidden) + { + self.alpha = 0.0f; + self.hidden = NO; + self.userInteractionEnabled = YES; + [self makeKeyAndVisible]; + } + + if (self.subviews.count > 0) + { + ((UIView*)[self.subviews lastObject]).userInteractionEnabled = NO; + } + + [self addSubview:view]; +} + +- (void)reduceAlphaIfEmpty +{ + if (self.subviews.count == 1) + { + self.alpha = 0.0f; +// 20120907JY - disabling this user interaction can cause issues with fast taps when showing alerts - thanks for finding Anagd. +// self.userInteractionEnabled = NO; + } +} + +- (void)removeView:(UIView *)view +{ + [view removeFromSuperview]; + if (self.subviews.count == 0) + { + self.hidden = YES; + [self resignKeyWindow]; + } + else + { + ((UIView*)[self.subviews lastObject]).userInteractionEnabled = YES; + } +} + +@end