Files
keyboard/keyBoard/Class/WebView/KBWebViewViewController.m

280 lines
9.4 KiB
Mathematica
Raw Normal View History

2025-11-10 16:09:47 +08:00
//
// KBWebViewViewController.m
// keyBoard
//
// Created by on 2025/11/10.
//
#import "KBWebViewViewController.h"
#import <WebKit/WebKit.h>
2026-03-08 21:29:10 +08:00
#import "KBConfig.h"
#import "Masonry.h"
2025-11-10 16:09:47 +08:00
@interface KBWebViewViewController () <WKNavigationDelegate, WKScriptMessageHandler>
@property(nonatomic, strong) WKWebView * webView;
// 🟢
@property(nonatomic, strong) UIProgressView *progressView;
@property(nonatomic, assign) BOOL observingProgress;
@end
@implementation KBWebViewViewController
2026-03-08 21:29:10 +08:00
+ (instancetype)legalViewControllerWithType:(KBLegalDocumentType)type {
KBWebViewViewController *vc = [[KBWebViewViewController alloc] init];
NSString *remoteURL = [self kb_remoteURLForLegalDocumentType:type];
if (remoteURL.length > 0) {
vc.url = remoteURL;
} else {
2026-03-09 17:34:08 +08:00
// vc.htmlString = [self kb_htmlForLegalDocumentType:type];
2026-03-08 21:29:10 +08:00
}
return vc;
}
+ (void)presentLegalDocumentType:(KBLegalDocumentType)type fromViewController:(UIViewController *)viewController {
if (![viewController isKindOfClass:UIViewController.class]) { return; }
KBWebViewViewController *vc = [self legalViewControllerWithType:type];
UINavigationController *nav = viewController.navigationController;
if (nav) {
[nav pushViewController:vc animated:YES];
return;
}
[viewController presentViewController:vc animated:YES completion:nil];
}
+ (nullable NSNumber *)legalDocumentTypeNumberFromQueryValue:(NSString *)queryValue {
NSString *value = queryValue.lowercaseString ?: @"";
if ([value isEqualToString:@"privacy"]) {
return @(KBLegalDocumentTypePrivacyPolicy);
}
if ([value isEqualToString:@"membership"]) {
return @(KBLegalDocumentTypeMembershipAgreement);
}
if ([value isEqualToString:@"terms"]) {
return @(KBLegalDocumentTypeTermsOfService);
}
return nil;
}
+ (NSString *)queryValueForLegalDocumentType:(KBLegalDocumentType)type {
switch (type) {
case KBLegalDocumentTypePrivacyPolicy:
return @"privacy";
case KBLegalDocumentTypeMembershipAgreement:
return @"membership";
case KBLegalDocumentTypeTermsOfService:
default:
return @"terms";
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
2025-11-10 16:09:47 +08:00
- (void)viewDidLoad {
[super viewDidLoad];
2026-03-08 21:29:10 +08:00
self.view.backgroundColor = UIColor.whiteColor;
2025-11-10 16:09:47 +08:00
[self configUI];
2026-03-10 11:25:10 +08:00
self.kb_titleLabel.hidden = true;
2025-11-10 16:09:47 +08:00
}
- (void)configUI {
// 1. JS
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
WKUserContentController *userContentController = [[WKUserContentController alloc] init];
[userContentController addScriptMessageHandler:self name:@"keyBoard"];
config.userContentController = userContentController;
// 2. webView
self.webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
self.webView.navigationDelegate = self;
self.webView.backgroundColor = UIColor.clearColor;
[self.view addSubview:self.webView];
2026-03-08 21:29:10 +08:00
[self.webView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.kb_navView.mas_bottom);
make.left.right.bottom.equalTo(self.view);
}];
2025-11-10 16:09:47 +08:00
// 🟢 3. 2
self.progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
self.progressView.trackTintColor = [UIColor clearColor]; //
self.progressView.progressTintColor = [UIColor greenColor];
self.progressView.progress = 0.0f;
self.progressView.hidden = YES; //
[self.view addSubview:self.progressView];
// 2
2026-03-08 21:29:10 +08:00
[self.progressView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.kb_navView.mas_bottom);
make.left.right.equalTo(self.view);
make.height.mas_equalTo(2.0);
}];
2025-11-10 16:09:47 +08:00
// 🟢 4. WKWebView estimatedProgress
[self.webView addObserver:self
forKeyPath:@"estimatedProgress"
options:NSKeyValueObservingOptionNew
context:nil];
self.observingProgress = YES;
2026-03-08 21:29:10 +08:00
// 5.
if (self.htmlString.length > 0) {
[self.webView loadHTMLString:self.htmlString baseURL:nil];
return;
}
NSURL *URL = [NSURL URLWithString:self.url ?: @""];
if (!URL) {
[self.webView loadHTMLString:[self.class kb_fallbackErrorHTML]
baseURL:nil];
return;
}
NSURLRequest * req = [NSURLRequest requestWithURL:URL];
2025-11-10 16:09:47 +08:00
[self.webView loadRequest:req];
2026-03-08 21:29:10 +08:00
[self.view bringSubviewToFront:self.kb_navView];
[self.view bringSubviewToFront:self.progressView];
2025-11-10 16:09:47 +08:00
}
#pragma mark - KVO: estimatedProgress 🟢
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary<NSKeyValueChangeKey,id> *)change
context:(void *)context {
if (object == self.webView && [keyPath isEqualToString:@"estimatedProgress"]) {
CGFloat progress = self.webView.estimatedProgress;
// 0 ~ 1
self.progressView.hidden = NO;
[self.progressView setProgress:progress animated:YES];
if (progress >= 1.0f) {
//
[UIView animateWithDuration:0.25
delay:0.25
options:UIViewAnimationOptionCurveEaseOut
animations:^{
self.progressView.alpha = 0.0;
} completion:^(BOOL finished) {
self.progressView.progress = 0.0;
self.progressView.hidden = YES;
self.progressView.alpha = 1.0;
}];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
#pragma mark - WKNavigationDelegate
//
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
NSLog(@"开始加载url");
//
self.progressView.hidden = NO;
self.progressView.progress = 0.0;
}
//
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
NSLog(@"页面加载成功");
2026-03-10 11:25:10 +08:00
if (webView.title.length > 0) {
2026-03-08 21:29:10 +08:00
self.title = webView.title;
}
2025-11-10 16:09:47 +08:00
}
//
- (void)webView:(WKWebView *)webView
didFailProvisionalNavigation:(WKNavigation *)navigation
withError:(NSError *)error {
NSLog(@"webView load error: %@", error);
//
self.progressView.hidden = YES;
self.progressView.progress = 0.0;
}
#pragma mark - WKScriptMessageHandler JS
- (void)userContentController:(WKUserContentController *)userContentController
didReceiveScriptMessage:(WKScriptMessage *)message {
if (![message.body isKindOfClass:NSDictionary.class]) {
NSLog(@"Body参数不合法");
return;
}
[self handleJSMethodWithParams:message.body];
}
- (void)handleJSMethodWithParams:(NSDictionary *)params {
NSDictionary * body = [params copy];
NSLog(@"收到 JS 消息: %@", body);
NSString * type = body[@"type"];
//
if ([type isEqual:@"ONE_METHOD"]) {
NSLog(@"come on baby js 调用你的方法了");
}
// title
if ([type isEqual:@"changeTiele"]) {
NSLog(@"%@", body);
NSString * newTiele = body[@"payload"][@"data"];
self.title = newTiele;
}
}
2026-03-08 21:29:10 +08:00
#pragma mark - Legal Content
+ (NSString *)kb_titleForLegalDocumentType:(KBLegalDocumentType)type {
switch (type) {
case KBLegalDocumentTypePrivacyPolicy:
return KBLocalized(@"Privacy Policy");
case KBLegalDocumentTypeMembershipAgreement:
return KBLocalized(@"Membership Agreement");
case KBLegalDocumentTypeTermsOfService:
default:
return KBLocalized(@"Agreement");
}
}
+ (NSString *)kb_remoteURLForLegalDocumentType:(KBLegalDocumentType)type {
switch (type) {
case KBLegalDocumentTypePrivacyPolicy:
return KB_PRIVACY_POLICY_URL;
case KBLegalDocumentTypeMembershipAgreement:
return KB_MEMBERSHIP_AGREEMENT_URL;
case KBLegalDocumentTypeTermsOfService:
default:
return KB_TERMS_OF_SERVICE_URL;
}
}
+ (NSString *)kb_fallbackErrorHTML {
return @"<!doctype html><html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><style>body{font-family:-apple-system,BlinkMacSystemFont,'Helvetica Neue',sans-serif;padding:32px;color:#1f2937;}h1{font-size:22px;margin:0 0 12px;}p{font-size:15px;line-height:1.6;color:#4b5563;}</style></head><body><h1>Page unavailable</h1><p>The requested document could not be loaded.</p></body></html>";
}
2025-11-10 16:09:47 +08:00
#pragma mark - Clean up 🟢
- (void)dealloc {
if (self.observingProgress) {
@try {
[self.webView removeObserver:self forKeyPath:@"estimatedProgress"];
} @catch (NSException *exception) {
NSLog(@"removeObserver estimatedProgress exception: %@", exception);
}
}
// 便 JS
[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"keyBoard"];
}
@end