JKLLockScreenPincodeView.m 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // This file is based on third party code, see below for the original author
  2. // and original license.
  3. // Modifications are (c) by Threema GmbH and licensed under the AGPLv3.
  4. // See Resources/License.html for original license
  5. #import "JKLLockScreenPincodeView.h"
  6. #import "KKKeychain.h"
  7. static const NSUInteger LSPMaxPincodeLength = 6;
  8. @interface JKLLockScreenPincodeView() {
  9. NSUInteger _wasCompleted;
  10. }
  11. @property (nonatomic, strong) NSString * pincode;
  12. @end
  13. @implementation JKLLockScreenPincodeView
  14. - (instancetype)init {
  15. if (self = [super init]) {
  16. [self lsp_initialize];
  17. }
  18. return self;
  19. }
  20. - (instancetype)initWithCoder:(NSCoder *)aDecoder {
  21. if (self = [super initWithCoder:aDecoder]) {
  22. [self lsp_initialize];
  23. }
  24. return self;
  25. }
  26. - (instancetype)initWithFrame:(CGRect)frame {
  27. if (self = [super initWithFrame:frame]) {
  28. [self lsp_initialize];
  29. }
  30. return self;
  31. }
  32. - (void)lsp_initialize {
  33. _maxPincodeLength = LSPMaxPincodeLength;
  34. self.enabled = YES;
  35. [self initPincode];
  36. }
  37. - (void)initPincode {
  38. self.pincode = @"";
  39. }
  40. /**
  41. 핀코드를 설정하는 프로퍼티 메소드
  42. @param NSString PIN code
  43. */
  44. - (void)setPincode:(NSString *)pincode {
  45. if (_pincode != pincode) {
  46. _pincode = pincode;
  47. [self setNeedsDisplay];
  48. BOOL length = ([pincode length] == _maxPincodeLength);
  49. if (length && [_delegate respondsToSelector:@selector(lockScreenPincodeView:pincode:)]) {
  50. //------------------ Threema edit begin ---------------------------
  51. [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(checkPinCode:) userInfo:pincode repeats:NO];
  52. //------------------ Threema edit end ---------------------------
  53. }
  54. }
  55. }
  56. //------------------ Threema edit begin ---------------------------
  57. - (void)checkPinCode:(NSTimer*)timer {
  58. [_delegate lockScreenPincodeView:self pincode:timer.userInfo];
  59. }
  60. //------------------ Threema edit end ---------------------------
  61. /**
  62. 핀코드를 추가하는 메소드
  63. @param NSString PIN code
  64. */
  65. - (void)appendingPincode:(NSString *)pincode {
  66. if (!_enabled) return;
  67. NSString * appended = [_pincode stringByAppendingString:pincode];
  68. // 최대 자릿수를 넘는다면 최대 자릿수만큼만 설정
  69. NSUInteger length = MIN([appended length], _maxPincodeLength);
  70. self.pincode = [appended substringToIndex:length];
  71. }
  72. /**
  73. 마지막 핀코드를 제거하는 메소드
  74. */
  75. - (void)removeLastPincode {
  76. if (!_enabled) return;
  77. NSUInteger index = ([_pincode length] - 1);
  78. if ([_pincode length] > index) {
  79. self.pincode = [_pincode substringToIndex:index];
  80. }
  81. }
  82. - (void)wasCompleted {
  83. for (NSUInteger idx = 0; idx < _maxPincodeLength; idx++) {
  84. dispatch_time_t delayInSeconds = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(idx * 0.01f * NSEC_PER_SEC));
  85. dispatch_after(delayInSeconds, dispatch_get_main_queue(), ^(void){
  86. _wasCompleted++;
  87. [self setNeedsDisplay];
  88. });
  89. }
  90. }
  91. // Only override drawRect: if you perform custom drawing.
  92. // An empty implementation adversely affects performance during animation.
  93. - (void)drawRect:(CGRect)rect {
  94. // Drawing code
  95. [super drawRect:rect];
  96. [_pincodeColor setFill];
  97. // 1 character box size
  98. CGSize boxSize = CGSizeMake(CGRectGetWidth(rect) / _maxPincodeLength, CGRectGetHeight(rect));
  99. CGSize charSize = CGSizeMake(self.frame.size.height/1.8, self.frame.size.height/1.8);
  100. CGFloat y = rect.origin.y;
  101. NSUInteger completed = MAX([_pincode length], _wasCompleted);
  102. // draw a circle : '.'
  103. NSInteger str = MIN(completed, _maxPincodeLength);
  104. for (NSUInteger idx = 0; idx < str; idx++) {
  105. CGFloat x = boxSize.width * idx;
  106. CGRect rounded = CGRectMake(x + floorf((boxSize.width - charSize.width) / 2),
  107. y + floorf((boxSize.height - charSize.width) / 2),
  108. charSize.width,
  109. charSize.height);
  110. CGContextRef context = UIGraphicsGetCurrentContext();
  111. CGContextSetFillColorWithColor(context, _pincodeColor.CGColor);
  112. CGContextSetLineWidth(context, 1.0);
  113. CGContextFillEllipseInRect(context, rounded);
  114. CGContextFillPath(context);
  115. }
  116. // draw a dash : '-'
  117. for (NSUInteger idx = str; idx < _maxPincodeLength; idx++) {
  118. CGFloat x = boxSize.width * idx;
  119. CGRect rounded = CGRectMake(x + floorf((boxSize.width - charSize.width) / 2),
  120. y + floorf((boxSize.height - charSize.height) / 2),
  121. charSize.width,
  122. charSize.height);
  123. CGContextRef context = UIGraphicsGetCurrentContext();
  124. CGContextSetStrokeColorWithColor(context, _pincodeColor.CGColor);
  125. CGContextSetLineWidth(context, 1.0);
  126. CGContextAddEllipseInRect(context, rounded);
  127. CGContextStrokePath(context);
  128. }
  129. }
  130. @end