@blotch/angular-lynx-native 22.2.4 → 22.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,95 @@
1
+ import AuthenticationServices
2
+ import Lynx
3
+ import UIKit
4
+
5
+ /// The native module behind the runtime's `LynxWebAuthSession`, which calls it
6
+ /// as `NativeModules.AngularLynxWebAuth` (from the background thread, where
7
+ /// NativeModules lives).
8
+ ///
9
+ /// Lynx has no popups or redirects, so a sign-in page can't run inside the
10
+ /// app. ASWebAuthenticationSession opens it in Safari's sign-in sheet instead,
11
+ /// asking the person first, and ends when the page redirects to the callback
12
+ /// scheme. The scheme needn't be registered in Info.plist: the session catches
13
+ /// the redirect itself, so no other app can.
14
+ final class WebAuthModule: NSObject, LynxModule, ASWebAuthenticationPresentationContextProviding {
15
+ static var name: String { "AngularLynxWebAuth" }
16
+
17
+ static var methodLookup: [String: String] {
18
+ ["start": NSStringFromSelector(#selector(start(_:callback:)))]
19
+ }
20
+
21
+ /// The open session. Held until it ends: ASWebAuthenticationSession closes
22
+ /// its sheet when released.
23
+ private var session: ASWebAuthenticationSession?
24
+
25
+ override init() {
26
+ super.init()
27
+ }
28
+
29
+ // Swift can't import an optional initializer as optional, so Lynx's
30
+ // initWithParam: is required here. Registered without a param, the module
31
+ // ignores it.
32
+ init(param: Any) {
33
+ super.init()
34
+ }
35
+
36
+ /// Opens `request.url` and calls back once with `{ url }`, the URL the page
37
+ /// redirected to, or `{ error, message }`, where `error` is `canceled` or
38
+ /// `failed`.
39
+ @objc func start(_ request: [String: Any], callback: @escaping LynxCallbackBlock) {
40
+ // Lynx calls modules off the main thread, and the session presents UI.
41
+ DispatchQueue.main.async {
42
+ self.open(request, callback)
43
+ }
44
+ }
45
+
46
+ private func open(_ request: [String: Any], _ callback: @escaping LynxCallbackBlock) {
47
+ let fail = { (message: String) in callback(["error": "failed", "message": message]) }
48
+ guard session == nil else {
49
+ fail("A sign-in is already open.")
50
+ return
51
+ }
52
+ guard let address = request["url"] as? String, let url = URL(string: address),
53
+ let scheme = request["callbackScheme"] as? String, !scheme.isEmpty
54
+ else {
55
+ fail("The sign-in needs a URL and a callback scheme.")
56
+ return
57
+ }
58
+
59
+ let completion: ASWebAuthenticationSession.CompletionHandler = { [weak self] url, error in
60
+ self?.session = nil
61
+ if let url {
62
+ callback(["url": url.absoluteString])
63
+ } else if let error = error as? ASWebAuthenticationSessionError,
64
+ error.code == .canceledLogin
65
+ {
66
+ callback(["error": "canceled", "message": "The sign-in was canceled."])
67
+ } else {
68
+ fail(error?.localizedDescription ?? "The sign-in page could not be opened.")
69
+ }
70
+ }
71
+ let session: ASWebAuthenticationSession
72
+ if #available(iOS 17.4, *) {
73
+ session = ASWebAuthenticationSession(
74
+ url: url, callback: .customScheme(scheme), completionHandler: completion)
75
+ } else {
76
+ session = ASWebAuthenticationSession(
77
+ url: url, callbackURLScheme: scheme, completionHandler: completion)
78
+ }
79
+ session.presentationContextProvider = self
80
+ session.prefersEphemeralWebBrowserSession = (request["ephemeral"] as? Bool) ?? false
81
+ self.session = session
82
+ if !session.start() {
83
+ self.session = nil
84
+ fail("The sign-in page could not be opened.")
85
+ }
86
+ }
87
+
88
+ /// The sheet opens over the app's window.
89
+ func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
90
+ UIApplication.shared.connectedScenes
91
+ .compactMap { $0 as? UIWindowScene }
92
+ .flatMap(\.windows)
93
+ .first(where: \.isKeyWindow) ?? ASPresentationAnchor()
94
+ }
95
+ }
@@ -11,7 +11,8 @@ import XElement
11
11
  /// support, so the frameworks build leaves it out
12
12
  /// (scripts/build-lynx-ios-frameworks.sh) and the shell registers the same
13
13
  /// classes under the same names here, before the first LynxConfig or LynxView
14
- /// exists.
14
+ /// exists. `<blur-view>` is XElement's with UIKit's blur materials and glass
15
+ /// transitions added (BlurView).
15
16
  enum XElementRegistry {
16
17
  static func register() {
17
18
  let elements: [(String, AnyClass)] = [
@@ -19,7 +20,7 @@ enum XElementRegistry {
19
20
  ("textarea", LynxUITextArea.self),
20
21
  ("overlay", LynxUIOverlay.self),
21
22
  ("svg", LynxUISVG.self),
22
- ("blur-view", LynxUIBlurView.self),
23
+ ("blur-view", BlurView.self),
23
24
  ("viewpager", LynxUIViewPager.self),
24
25
  ("viewpager-item", LynxUIViewPagerItem.self),
25
26
  ("refresh", LynxUIRefresh.self),