Files
keyboard/keyBoard/VC/KBPermissionViewController.m

351 lines
13 KiB
Mathematica
Raw Normal View History

2025-10-27 20:07:37 +08:00
//
// KBPermissionViewController.m
// CustomKeyboard
//
// Created by Mac on 2025/10/27.
//
#import "KBPermissionViewController.h"
2025-11-27 21:39:03 +08:00
#import <AVFoundation/AVFoundation.h>
2025-10-27 20:07:37 +08:00
2025-11-28 13:07:35 +08:00
static void *KBPermPlayerPresentationSizeContext = &KBPermPlayerPresentationSizeContext;
2025-10-27 20:07:37 +08:00
@interface KBPermissionViewController ()
2025-11-03 16:57:24 +08:00
@property (nonatomic, strong) UILabel *titleLabel; //
@property (nonatomic, strong) UILabel *tipsLabel; //
@property (nonatomic, strong) UIButton *openButton; //
2025-11-14 16:34:01 +08:00
@property (nonatomic, strong) UIButton *closeButton; //
2025-11-03 16:57:24 +08:00
@property (nonatomic, strong) UILabel *helpLabel; //
2025-11-14 16:34:01 +08:00
@property (nonatomic, strong) UIImageView *redImageView;
@property (nonatomic, strong) UIImageView *bgImageView;
2025-11-27 21:39:03 +08:00
//
@property (nonatomic, strong) AVPlayer *kb_permPlayer;
@property (nonatomic, strong) AVPlayerLayer *kb_permPlayerLayer;
2025-11-28 13:07:35 +08:00
// KBFit(550)
@property (nonatomic, strong) UIView *videoContainerView;
2025-10-27 20:07:37 +08:00
@end
@implementation KBPermissionViewController
- (void)viewDidLoad {
[super viewDidLoad];
2025-11-14 16:34:01 +08:00
[self.view addSubview:self.bgImageView];
[self.view addSubview:self.redImageView];
2025-10-27 20:07:37 +08:00
2025-11-03 16:57:24 +08:00
// +
2025-11-14 16:34:01 +08:00
[self.view addSubview:self.closeButton];
2025-11-03 16:57:24 +08:00
[self.view addSubview:self.titleLabel];
[self.view addSubview:self.tipsLabel];
2025-11-28 13:07:35 +08:00
[self.view addSubview:self.videoContainerView];
2025-11-03 16:57:24 +08:00
[self.view addSubview:self.openButton];
[self.view addSubview:self.helpLabel];
2025-11-14 16:34:01 +08:00
[self.bgImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
2025-11-03 16:57:24 +08:00
// Masonry
2025-11-14 16:34:01 +08:00
[self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) {
2025-11-03 16:57:24 +08:00
make.left.equalTo(self.view).offset(16);
2025-11-14 16:34:01 +08:00
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(20);
make.width.mas_equalTo(26);
make.height.mas_equalTo(26);
}];
[self.redImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.closeButton.mas_centerY);
make.right.equalTo(self.view).offset(20);
make.width.mas_equalTo(143);
make.height.mas_equalTo(132);
2025-11-03 16:57:24 +08:00
}];
2025-11-14 16:34:01 +08:00
2025-11-03 16:57:24 +08:00
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
2025-11-14 16:34:01 +08:00
make.top.equalTo(self.closeButton.mas_bottom).offset(13);
make.left.equalTo(self.view).offset(22);
make.height.mas_equalTo(24);
2025-11-03 16:57:24 +08:00
}];
[self.tipsLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.titleLabel.mas_bottom).offset(8);
2025-11-14 16:34:01 +08:00
make.left.equalTo(self.titleLabel);
2025-11-03 16:57:24 +08:00
}];
2025-11-28 13:07:35 +08:00
// 25 tipsLabel 32 KBFit(550)
[self.videoContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
2025-11-28 13:20:50 +08:00
make.top.equalTo(self.tipsLabel.mas_bottom).offset(KB_DEVICE_HAS_NOTCH ? 32 : 0);
2025-11-28 13:07:35 +08:00
make.left.equalTo(self.view).offset(25);
make.right.equalTo(self.view).offset(-25);
2025-11-28 13:20:50 +08:00
make.height.mas_equalTo(KB_DEVICE_HAS_NOTCH ? KBFit(550) : KBFit(500));
2025-11-28 13:07:35 +08:00
}];
2025-11-03 16:57:24 +08:00
[self.openButton mas_makeConstraints:^(MASConstraintMaker *make) {
2025-11-14 16:34:01 +08:00
make.bottom.equalTo(self.view).offset(-KB_SAFE_BOTTOM-20);
make.left.equalTo(self.view).offset(47);
make.right.equalTo(self.view).offset(-47);
make.height.mas_equalTo(60);
2025-11-03 16:57:24 +08:00
}];
2025-11-14 16:34:01 +08:00
// [self.helpLabel mas_makeConstraints:^(MASConstraintMaker *make) {
// make.top.equalTo(self.openButton.mas_bottom).offset(12);
// make.left.equalTo(self.view).offset(24);
// make.right.equalTo(self.view).offset(-24);
// }];
2025-10-27 20:07:37 +08:00
}
2025-11-27 21:39:03 +08:00
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//
[self kb_setupPermissionVideoPlayer];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
//
[self.kb_permPlayer pause];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if (!self.kb_permPlayerLayer) { return; }
2025-11-28 13:07:35 +08:00
// videoContainerView
// KBFit(550)
CGSize videoSize = self.kb_permPlayer.currentItem.presentationSize;
if (videoSize.width <= 0) { return; } //
CGFloat aspect = videoSize.height / videoSize.width;
CGRect containerBounds = self.videoContainerView.bounds;
if (CGRectIsEmpty(containerBounds)) { return; }
CGFloat width = CGRectGetWidth(containerBounds); //
CGFloat height = width * aspect; //
// y = 0 height >
self.kb_permPlayerLayer.frame = CGRectMake(0, 0, width, height);
2025-11-27 21:39:03 +08:00
}
- (void)dealloc {
//
[[NSNotificationCenter defaultCenter] removeObserver:self];
2025-11-28 13:07:35 +08:00
@try {
[self.kb_permPlayer.currentItem removeObserver:self
forKeyPath:@"presentationSize"
context:KBPermPlayerPresentationSizeContext];
} @catch (__unused NSException *e) {
// ignore if observer not set
}
2025-11-27 21:39:03 +08:00
}
2025-11-03 16:57:24 +08:00
#pragma mark - Actions
- (void)onBack {
2025-11-03 18:45:06 +08:00
//
// 1) presentingViewController VC pop
// 2) pop dismiss
UIViewController *presenter = self.presentingViewController;
if (!presenter) {
if (self.backHandler) self.backHandler();
return;
}
UINavigationController *nav = nil;
if ([presenter isKindOfClass:UINavigationController.class]) {
nav = (UINavigationController *)presenter;
} else if (presenter.navigationController) {
nav = presenter.navigationController;
}
if (nav) {
[nav popViewControllerAnimated:NO];
[nav dismissViewControllerAnimated:YES completion:^{ if (self.backHandler) self.backHandler(); }];
} else {
[self dismissViewControllerAnimated:YES completion:^{ if (self.backHandler) self.backHandler(); }];
}
2025-10-27 20:07:37 +08:00
}
- (void)openSettings {
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
UIApplication *app = [UIApplication sharedApplication];
if ([app canOpenURL:url]) {
if (@available(iOS 10.0, *)) {
[app openURL:url options:@{} completionHandler:nil];
} else {
[app openURL:url];
}
}
}
2025-11-14 16:34:01 +08:00
- (void)closeButtonAction{
[self.navigationController popViewControllerAnimated:true];
}
2025-11-27 21:39:03 +08:00
#pragma mark - Video Player
// cardView
- (void)kb_setupPermissionVideoPlayer {
//
if (self.kb_permPlayer) {
[self.kb_permPlayer play];
return;
}
NSURL *videoURL = [[NSBundle mainBundle] URLForResource:@"permiss_video" withExtension:@"mp4"];
if (!videoURL) {
return;
}
AVPlayerItem *item = [AVPlayerItem playerItemWithURL:videoURL];
self.kb_permPlayer = [AVPlayer playerWithPlayerItem:item];
self.kb_permPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
self.kb_permPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.kb_permPlayer];
// 使 frame
2025-11-28 13:07:35 +08:00
self.kb_permPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
2025-11-27 21:39:03 +08:00
self.kb_permPlayerLayer.cornerRadius = 20;
self.kb_permPlayerLayer.masksToBounds = true;
2025-11-28 13:07:35 +08:00
//
[self.videoContainerView.layer addSublayer:self.kb_permPlayerLayer];
// presentationSize {0,0}
[item addObserver:self
forKeyPath:@"presentationSize"
options:NSKeyValueObservingOptionNew
context:KBPermPlayerPresentationSizeContext];
2025-11-27 21:39:03 +08:00
//
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(kb_playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:item];
[self.kb_permPlayer play];
}
- (void)kb_playerItemDidReachEnd:(NSNotification *)note {
AVPlayerItem *item = (AVPlayerItem *)note.object;
if (!item) return;
__weak typeof(self) weakSelf = self;
[item seekToTime:kCMTimeZero completionHandler:^(BOOL finished) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf.kb_permPlayer play];
}];
}
2025-11-28 13:07:35 +08:00
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary<NSKeyValueChangeKey,id> *)change
context:(void *)context {
if (context == KBPermPlayerPresentationSizeContext) {
// presentationSize {0,0}
dispatch_async(dispatch_get_main_queue(), ^{
[self.view setNeedsLayout];
});
return;
}
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
2025-11-03 16:57:24 +08:00
#pragma mark - Lazy Subviews
- (UIButton *)backButton {
if (!_backButton) {
_backButton = [UIButton buttonWithType:UIButtonTypeSystem];
[_backButton setTitle:KBLocalized(@"common_back") forState:UIControlStateNormal];
_backButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium];
[_backButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal];
[_backButton addTarget:self action:@selector(onBack) forControlEvents:UIControlEventTouchUpInside];
}
return _backButton;
}
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [UILabel new];
2025-11-14 16:34:01 +08:00
_titleLabel.text = (@"key of love keyboard");
_titleLabel.font = [UIFont systemFontOfSize:20 weight:UIFontWeightSemibold];
2025-11-03 16:57:24 +08:00
_titleLabel.textColor = [UIColor blackColor];
_titleLabel.textAlignment = NSTextAlignmentCenter;
}
return _titleLabel;
}
- (UILabel *)tipsLabel {
if (!_tipsLabel) {
_tipsLabel = [UILabel new];
2025-11-14 16:34:01 +08:00
_tipsLabel.text = (@"One-click to find a partner");
2025-11-03 16:57:24 +08:00
_tipsLabel.font = [UIFont systemFontOfSize:14];
_tipsLabel.textColor = [UIColor darkGrayColor];
_tipsLabel.textAlignment = NSTextAlignmentCenter;
}
return _tipsLabel;
}
- (UIButton *)openButton {
if (!_openButton) {
2025-11-14 16:34:01 +08:00
_openButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_openButton setTitle:@"Turn on the keyboard" forState:UIControlStateNormal];
_openButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold];
2025-11-03 16:57:24 +08:00
[_openButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
2025-11-14 16:34:01 +08:00
_openButton.backgroundColor = [UIColor colorWithHex:KBBlackValue];
_openButton.layer.cornerRadius = 30;
2025-11-03 16:57:24 +08:00
[_openButton addTarget:self action:@selector(openSettings) forControlEvents:UIControlEventTouchUpInside];
}
return _openButton;
}
2025-11-14 16:34:01 +08:00
- (UIButton *)closeButton {
if (!_closeButton) {
_closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_closeButton setImage:[UIImage imageNamed:@"close_icon"] forState:UIControlStateNormal];
[_closeButton addTarget:self action:@selector(closeButtonAction) forControlEvents:UIControlEventTouchUpInside];
}
return _closeButton;
}
2025-11-03 16:57:24 +08:00
- (UILabel *)helpLabel {
if (!_helpLabel) {
_helpLabel = [UILabel new];
_helpLabel.text = KBLocalized(@"perm_help");
_helpLabel.font = [UIFont systemFontOfSize:12];
_helpLabel.textColor = [UIColor grayColor];
_helpLabel.textAlignment = NSTextAlignmentCenter;
_helpLabel.numberOfLines = 2;
}
return _helpLabel;
}
2025-11-14 16:34:01 +08:00
- (UIImageView *)bgImageView{
if (!_bgImageView) {
_bgImageView = [[UIImageView alloc] init];
_bgImageView.image = [UIImage imageNamed:@"qx_bg_icon"];
}
return _bgImageView;
}
2025-11-28 13:07:35 +08:00
2025-11-14 16:34:01 +08:00
- (UIImageView *)redImageView{
if (!_redImageView) {
_redImageView = [[UIImageView alloc] init];
_redImageView.image = [UIImage imageNamed:@"qx_ax_icon"];
}
return _redImageView;
}
2025-11-28 13:07:35 +08:00
- (UIView *)videoContainerView {
if (!_videoContainerView) {
_videoContainerView = [UIView new];
_videoContainerView.backgroundColor = [UIColor clearColor];
_videoContainerView.layer.cornerRadius = 20.0;
_videoContainerView.clipsToBounds = YES; //
}
return _videoContainerView;
}
2025-10-27 20:07:37 +08:00
@end