montana/Русский/Сайт/junona-app/ios-native/ViewController.swift

135 lines
4.7 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import UIKit
import WebKit
import Contacts
class ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler {
var webView: WKWebView!
let serverURL = "http://72.56.102.240"
override func viewDidLoad() {
super.viewDidLoad()
// Конфигурация WebView
let config = WKWebViewConfiguration()
let contentController = WKUserContentController()
// JavaScript мост для нативных функций
contentController.add(self, name: "montana")
config.userContentController = contentController
// Разрешаем inline media
config.allowsInlineMediaPlayback = true
config.mediaTypesRequiringUserActionForPlayback = []
// Создаём WebView
webView = WKWebView(frame: view.bounds, configuration: config)
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
webView.navigationDelegate = self
webView.backgroundColor = UIColor(red: 15/255, green: 15/255, blue: 26/255, alpha: 1)
webView.isOpaque = false
webView.scrollView.bounces = false
// Safe area
if #available(iOS 11.0, *) {
webView.scrollView.contentInsetAdjustmentBehavior = .never
}
view.addSubview(webView)
// Загружаем сайт
if let url = URL(string: serverURL) {
webView.load(URLRequest(url: url))
}
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
// MARK: - WKScriptMessageHandler
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
guard let body = message.body as? [String: Any],
let action = body["action"] as? String else { return }
switch action {
case "getContacts":
requestContacts()
case "haptic":
let style = body["style"] as? String ?? "medium"
triggerHaptic(style: style)
default:
break
}
}
// MARK: - Native Functions
func requestContacts() {
let store = CNContactStore()
store.requestAccess(for: .contacts) { granted, error in
guard granted else {
self.sendToJS("contactsResult", data: ["error": "Access denied"])
return
}
let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey] as [CNKeyDescriptor]
let request = CNContactFetchRequest(keysToFetch: keys)
var contacts: [[String: String]] = []
do {
try store.enumerateContacts(with: request) { contact, _ in
let name = "\(contact.givenName) \(contact.familyName)".trimmingCharacters(in: .whitespaces)
if let phone = contact.phoneNumbers.first?.value.stringValue {
contacts.append(["name": name, "phone": phone])
}
}
self.sendToJS("contactsResult", data: ["contacts": contacts])
} catch {
self.sendToJS("contactsResult", data: ["error": error.localizedDescription])
}
}
}
func triggerHaptic(style: String) {
switch style {
case "light":
UIImpactFeedbackGenerator(style: .light).impactOccurred()
case "heavy":
UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
case "success":
UINotificationFeedbackGenerator().notificationOccurred(.success)
case "error":
UINotificationFeedbackGenerator().notificationOccurred(.error)
default:
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
}
}
func sendToJS(_ event: String, data: [String: Any]) {
if let jsonData = try? JSONSerialization.data(withJSONObject: data),
let json = String(data: jsonData, encoding: .utf8) {
DispatchQueue.main.async {
self.webView.evaluateJavaScript("window.dispatchEvent(new CustomEvent('\(event)', {detail: \(json)}))")
}
}
}
// MARK: - WKNavigationDelegate
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if let url = navigationAction.request.url {
// Открываем внешние ссылки в Safari
if url.scheme == "tel" || url.scheme == "mailto" || url.host == "t.me" {
UIApplication.shared.open(url)
decisionHandler(.cancel)
return
}
}
decisionHandler(.allow)
}
}