turbo-native-initializer 0.0.15 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (22) hide show
  1. checksums.yaml +4 -4
  2. data/lib/turbo_native_initializer/generator.rb +1 -0
  3. data/lib/turbo_native_initializer/templates/android_stack/base/app/src/main/assets/json/configuration.json +2 -2
  4. data/lib/turbo_native_initializer/templates/android_tabs/base/app/src/main/assets/json/configuration.json +2 -2
  5. data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Configuration/path-configuration.json +3 -3
  6. data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Controllers/TurboNavigationController.swift +22 -6
  7. data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Controllers/TurboWebViewController.swift +9 -2
  8. data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Delegates/{SceneDelegate.swift.tt → SceneDelegate.swift} +4 -3
  9. data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/{Controllers → Extensions}/UIViewController+Toast.swift +9 -18
  10. data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/{TurboNativeProject.swift.tt → TurboNativeProject.swift} +1 -1
  11. data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject.xcodeproj/project.pbxproj.tt +15 -5
  12. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Configuration/path-configuration.json +3 -3
  13. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Controllers/TurboNavigationController.swift +22 -6
  14. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Controllers/TurboWebViewController.swift +9 -2
  15. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Delegates/{SceneDelegate.swift.tt → SceneDelegate.swift} +7 -6
  16. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/{Controllers → Extensions}/UIViewController+Toast.swift +9 -18
  17. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/{TurboNativeProject.swift.tt → TurboNativeProject.swift} +1 -1
  18. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject.xcodeproj/project.pbxproj.tt +12 -4
  19. data/lib/turbo_native_initializer/version.rb +1 -1
  20. metadata +11 -11
  21. /data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/{Controllers → Extensions}/WKWebViewConfiguration+App.swift +0 -0
  22. /data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/{Controllers → Extensions}/WKWebViewConfiguration+App.swift +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d5b3658efa201b5340d0e5ecdc401395f6659c235a5177c1e7a6b908b69a2f09
4
- data.tar.gz: 7327665391ec9be569354ad811f9565a6164da08aea90c3e8bfe04f65e03cf5a
3
+ metadata.gz: 3b5ef5d8b7a0d8f95f129356baa6f612368985f84ddec474db83057174b438ac
4
+ data.tar.gz: e99f39bff9585a3b391d4ab6bf6f5516355e646eb79490704b172470ed83449a
5
5
  SHA512:
6
- metadata.gz: 1dcedc375f6de7437ff80b816424e599b7b266713c94417a6752bf16104e8ac719f0cbbed03b500efe891a3590f84c000a16f254d25e8fac5c6546883a4b8a30
7
- data.tar.gz: b5e35c0791bf2a6b3fdc6eeaec4c45b5b14388b796c9d51f3539d2547fd93f106c01d483ec6a90d7cb6d73359cdfb2d76501226dab9fd070535f082922c6ef1c
6
+ metadata.gz: 12a257749999a07cfdd00f3738b383e6f608ac0433d8026ca2139a929b39ad503cf9998774765c03db9d1b9d1103f7e14933c73a9af8ad1183ad9e9b47047495
7
+ data.tar.gz: 176211b7e460001de9b829a30fb3eec2d5dd8f960b829dd1b422dd45a23e0d4fe164ef3e42a2d419a5ef9d5fb030d9075a50438c8ce991062f3c5c3d35f2d254
@@ -22,6 +22,7 @@ module TurboNativeInitializer
22
22
  directory "#{project}/TurboNativeProject/Configuration", "#{name}/#{name}/Configuration"
23
23
  directory "#{project}/TurboNativeProject/Controllers", "#{name}/#{name}/Controllers"
24
24
  directory "#{project}/TurboNativeProject/Delegates", "#{name}/#{name}/Delegates"
25
+ directory "#{project}/TurboNativeProject/Extensions", "#{name}/#{name}/Extensions"
25
26
  directory "#{project}/TurboNativeProject/Resources", "#{name}/#{name}/Resources"
26
27
  directory "#{project}/TurboNativeProject/Strada", "#{name}/#{name}/Strada"
27
28
  directory "#{project}/TurboNativeProject.xcodeproj", "#{name}/#{name}.xcodeproj"
@@ -2,11 +2,11 @@
2
2
  "settings": {},
3
3
  "rules": [
4
4
  { "patterns": [".*"], "properties": { "uri": "turbo://fragment/web", "pull_to_refresh_enabled": true } },
5
- { "patterns": ["/refresh_historical_location"], "properties": { "presentation": "refresh" } },
6
5
  { "patterns": ["/recede_historical_location"], "properties": { "presentation": "pop" } },
7
6
  { "patterns": ["/resume_historical_location"], "properties": { "presentation": "none" } },
8
- { "patterns": ["^/$"], "properties": { "uri": "turbo://fragment/web/home", "presentation": "replace_all" } },
7
+ { "patterns": ["/refresh_historical_location"], "properties": { "presentation": "refresh" } },
9
8
  { "patterns": ["/new$", "/edit$", "/signin$", "/strada-form$"], "properties": { "context": "modal", "uri": "turbo://fragment/web/modal", "pull_to_refresh_enabled": false } },
9
+ { "patterns": ["^/$"], "properties": { "uri": "turbo://fragment/web/home", "presentation": "replace_all" } },
10
10
  { "patterns": ["/numbers$"], "properties": { "uri": "turbo://fragment/numbers", "title": "Numbers" } }
11
11
  ]
12
12
  }
@@ -2,11 +2,11 @@
2
2
  "settings": {},
3
3
  "rules": [
4
4
  { "patterns": [".*"], "properties": { "uri": "turbo://fragment/web", "pull_to_refresh_enabled": true } },
5
- { "patterns": ["/refresh_historical_location"], "properties": { "presentation": "refresh" } },
6
5
  { "patterns": ["/recede_historical_location"], "properties": { "presentation": "pop" } },
7
6
  { "patterns": ["/resume_historical_location"], "properties": { "presentation": "none" } },
8
- { "patterns": ["^/$"], "properties": { "uri": "turbo://fragment/web/home", "presentation": "replace_all" } },
7
+ { "patterns": ["/refresh_historical_location"], "properties": { "presentation": "refresh" } },
9
8
  { "patterns": ["/new$", "/edit$", "/signin$", "/strada-form$"], "properties": { "context": "modal", "uri": "turbo://fragment/web/modal", "pull_to_refresh_enabled": false } },
9
+ { "patterns": ["^/$"], "properties": { "uri": "turbo://fragment/web/home", "presentation": "replace_all" } },
10
10
  { "patterns": ["/numbers$"], "properties": { "uri": "turbo://fragment/numbers", "title": "Numbers" } }
11
11
  ]
12
12
  }
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "settings": {},
3
3
  "rules": [
4
- { "patterns": ["/refresh_historical_location"], "properties": { "presentation": "refresh", "visitable": false } },
5
- { "patterns": ["/recede_historical_location"], "properties": { "presentation": "pop", "visitable": false } },
4
+ { "patterns": ["/recede_historical_location"], "properties": { "presentation": "back", "visitable": false } },
6
5
  { "patterns": ["/resume_historical_location"], "properties": { "presentation": "none", "visitable": false } },
6
+ { "patterns": ["/refresh_historical_location"], "properties": { "presentation": "refresh", "visitable": false } },
7
+ { "patterns": ["/new$", "/edit$", "/signin$", "/strada-form$"], "properties": { "presentation": "modal", "pull-to-refresh-enabled": false } },
7
8
  { "patterns": ["^/$"], "properties": { "presentation": "replace-all" } },
8
- { "patterns": ["/new$", "/edit$", "/signin$", "/strada-form$"], "properties": { "presentation": "modal" } },
9
9
  { "patterns": ["/numbers$"], "properties": { "view-controller": "numbers" } }
10
10
  ]
11
11
  }
@@ -22,9 +22,14 @@ class TurboNavigationController : UINavigationController {
22
22
  }
23
23
 
24
24
  // - Create view controller appropriate for url/properties
25
- // - Navigate to that with the correct presentation
26
25
  let viewController = makeViewController(for: url, properties: properties)
27
- navigate(to: viewController, action: options.action, properties: properties)
26
+
27
+ // - Navigate to that with the correct presentation
28
+ if session.topmostVisitable?.visitableURL == url {
29
+ navigate(to: viewController, action: .replace, properties: properties)
30
+ } else {
31
+ navigate(to: viewController, action: options.action, properties: properties)
32
+ }
28
33
 
29
34
  // Initiate the visit with Turbo
30
35
  if isVisitable(properties) {
@@ -43,8 +48,8 @@ extension TurboNavigationController {
43
48
  return properties["presentation"] as? String == "modal"
44
49
  }
45
50
 
46
- private func isPop(_ properties: PathProperties) -> Bool {
47
- return properties["presentation"] as? String == "pop"
51
+ private func isBack(_ properties: PathProperties) -> Bool {
52
+ return properties["presentation"] as? String == "back"
48
53
  }
49
54
 
50
55
  private func isRefresh(_ properties: PathProperties) -> Bool {
@@ -71,6 +76,14 @@ extension TurboNavigationController {
71
76
  return properties["visitable"] as? Bool ?? true
72
77
  }
73
78
 
79
+ private func isPullToRefreshEnabled(_ properties: PathProperties) -> Bool {
80
+ return properties["pull-to-refresh-enabled"] as? Bool ?? true
81
+ }
82
+
83
+ private func title(from properties: PathProperties) -> String? {
84
+ return properties["title"] as? String
85
+ }
86
+
74
87
  private func noticeMessage(from url: URL) -> String? {
75
88
  URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.first(where: { $0.name == "notice" })?.value
76
89
  }
@@ -90,13 +103,16 @@ extension TurboNavigationController {
90
103
  }
91
104
  }
92
105
 
93
- return TurboWebViewController(url: url)
106
+ let viewController = TurboWebViewController(url: url)
107
+ viewController.pullToRefreshEnabled = isPullToRefreshEnabled(properties)
108
+ viewController.title = title(from: properties)
109
+ return viewController
94
110
  }
95
111
 
96
112
  private func navigate(to viewController: UIViewController, action: VisitAction, properties: PathProperties = [:]) {
97
113
  if isModal(properties) {
98
114
  present(UINavigationController(rootViewController: viewController), animated: true)
99
- } else if isPop(properties) {
115
+ } else if isBack(properties) {
100
116
  popViewController(animated: true)
101
117
  } else if isRefresh(properties) {
102
118
  session.reload()
@@ -5,6 +5,8 @@ import WebKit
5
5
 
6
6
  final class TurboWebViewController: VisitableViewController, ErrorPresenter, BridgeDestination {
7
7
 
8
+ var pullToRefreshEnabled = true
9
+
8
10
  private lazy var bridgeDelegate: BridgeDelegate = {
9
11
  BridgeDelegate(location: visitableURL.absoluteString, destination: self, componentTypes: BridgeComponent.allTypes)
10
12
  }()
@@ -17,14 +19,15 @@ final class TurboWebViewController: VisitableViewController, ErrorPresenter, Bri
17
19
 
18
20
  override func viewDidLoad() {
19
21
  super.viewDidLoad()
22
+ bridgeDelegate.onViewDidLoad()
20
23
 
21
24
  navigationItem.backButtonTitle = "Back"
22
25
 
26
+ visitableView.allowsPullToRefresh = pullToRefreshEnabled
27
+
23
28
  if presentingViewController != nil {
24
29
  navigationItem.leftBarButtonItem = dismissModalButton
25
30
  }
26
-
27
- bridgeDelegate.onViewDidLoad()
28
31
  }
29
32
 
30
33
  override func viewWillAppear(_ animated: Bool) {
@@ -49,6 +52,10 @@ final class TurboWebViewController: VisitableViewController, ErrorPresenter, Bri
49
52
 
50
53
  // MARK: Visitable
51
54
 
55
+ override func visitableDidRender() {
56
+ title = title ?? visitableView.webView?.title
57
+ }
58
+
52
59
  override func visitableDidActivateWebView(_ webView: WKWebView) {
53
60
  bridgeDelegate.webViewDidBecomeActive(webView)
54
61
  }
@@ -5,16 +5,16 @@ import Turbo
5
5
  import Strada
6
6
 
7
7
  final class SceneDelegate: UIResponder {
8
- private static var sharedProcessPool = WKProcessPool()
9
8
 
10
9
  var window: UIWindow?
11
- private let rootURL = <%= name %>.homeURL
10
+ private let rootURL = TurboNativeProject.homeURL
12
11
  private var navigationController: TurboNavigationController!
13
12
 
14
13
  // MARK: - Setup
15
14
 
16
15
  private func configureRootViewController() {
17
16
  navigationController = window!.rootViewController as? TurboNavigationController
17
+ navigationController.navigationBar.scrollEdgeAppearance = .init()
18
18
  navigationController.session = session
19
19
  navigationController.modalSession = modalSession
20
20
  }
@@ -22,7 +22,7 @@ final class SceneDelegate: UIResponder {
22
22
  // MARK: - Authentication
23
23
 
24
24
  private func promptForAuthentication() {
25
- let authURL = <%= name %>.signInURL
25
+ let authURL = TurboNativeProject.signInURL
26
26
  let properties = pathConfiguration.properties(for: authURL)
27
27
  navigationController.route(url: authURL, options: VisitOptions(), properties: properties)
28
28
  }
@@ -42,6 +42,7 @@ final class SceneDelegate: UIResponder {
42
42
  let session = Session(webView: webView)
43
43
  session.delegate = self
44
44
  session.pathConfiguration = pathConfiguration
45
+
45
46
  return session
46
47
  }
47
48
 
@@ -2,33 +2,24 @@ import SwiftUI
2
2
 
3
3
  public extension UIViewController {
4
4
  func presentToast(_ message: String) {
5
- guard let root = view.window?.rootViewController else { return }
5
+ guard let window = view.window else { return }
6
6
 
7
- removeToastViews(from: root)
7
+ removeToastViews(from: window)
8
8
 
9
9
  let toastView = ToastView(message: message)
10
10
  toastView.translatesAutoresizingMaskIntoConstraints = false
11
11
 
12
- root.view.addSubview(toastView)
12
+ window.addSubview(toastView)
13
13
 
14
14
  NSLayoutConstraint.activate([
15
- toastView.topAnchor.constraint(equalTo: root.view.safeAreaLayoutGuide.topAnchor),
16
- toastView.centerXAnchor.constraint(equalTo: root.view.centerXAnchor)
17
- ])
18
-
19
- let widthConstraint = toastView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -10)
20
- widthConstraint.priority = .defaultHigh
21
-
22
- let maxWidthConstraint = toastView.widthAnchor.constraint(lessThanOrEqualToConstant: 600)
23
- maxWidthConstraint.priority = .required
24
-
25
- NSLayoutConstraint.activate([
26
- widthConstraint, maxWidthConstraint
15
+ toastView.centerXAnchor.constraint(equalTo: window.centerXAnchor),
16
+ toastView.topAnchor.constraint(equalTo: window.safeAreaLayoutGuide.topAnchor, constant: 2),
17
+ toastView.widthAnchor.constraint(equalTo: window.safeAreaLayoutGuide.widthAnchor, constant: -10)
27
18
  ])
28
19
  }
29
20
 
30
- fileprivate func removeToastViews(from root: UIViewController) {
31
- root.view.subviews.filter({ $0 is ToastView }).forEach({ toast in
21
+ fileprivate func removeToastViews(from window: UIWindow) {
22
+ window.subviews.filter({ $0 is ToastView }).forEach({ toast in
32
23
  toast.removeFromSuperview()
33
24
  })
34
25
  }
@@ -36,7 +27,7 @@ public extension UIViewController {
36
27
 
37
28
  public class ToastView: UIView {
38
29
 
39
- private var duration = 2.5
30
+ private var duration = 2.0
40
31
 
41
32
  convenience init(message: String) {
42
33
  self.init(frame: .zero)
@@ -1,6 +1,6 @@
1
1
  import Foundation
2
2
 
3
- struct <%= name %> {
3
+ struct TurboNativeProject {
4
4
  private static let developmentURL = URL(string: "http://localhost:3000")!
5
5
  private static let productionURL = URL(string: "https://turbo-native-demo.glitch.me")!
6
6
 
@@ -86,6 +86,15 @@
86
86
  path = Configuration;
87
87
  sourceTree = "<group>";
88
88
  };
89
+ 5DAD248F2AD6533E0082D23D /* Extensions */ = {
90
+ isa = PBXGroup;
91
+ children = (
92
+ 5DAF71B62AC3FB53002D04FE /* UIViewController+Toast.swift */,
93
+ 5D281BB02ABC0C3D001CE599 /* WKWebViewConfiguration+App.swift */,
94
+ );
95
+ path = Extensions;
96
+ sourceTree = "<group>";
97
+ };
89
98
  5DCC50C72A959DF800B529A0 = {
90
99
  isa = PBXGroup;
91
100
  children = (
@@ -105,11 +114,12 @@
105
114
  5DCC50D22A959DF900B529A0 /* <%= name %> */ = {
106
115
  isa = PBXGroup;
107
116
  children = (
117
+ 5DAD248F2AD6533E0082D23D /* Extensions */,
108
118
  5D281BB22ABC0C8F001CE599 /* Strada */,
109
- 5D2FA5CD2A9DB1AB001AF2F1 /* Configuration */,
110
119
  5DCC50F42A95AC4E00B529A0 /* Controllers */,
111
120
  5DCC50FB2A95B55200B529A0 /* Delegates */,
112
121
  5DCC51072A95CCEE00B529A0 /* Resources */,
122
+ 5D2FA5CD2A9DB1AB001AF2F1 /* Configuration */,
113
123
  5DCC50F22A95A7E600B529A0 /* <%= name %>.swift */,
114
124
  );
115
125
  path = <%= name %>;
@@ -118,10 +128,8 @@
118
128
  5DCC50F42A95AC4E00B529A0 /* Controllers */ = {
119
129
  isa = PBXGroup;
120
130
  children = (
121
- 5DCC50ED2A95A27600B529A0 /* ErrorPresenter.swift */,
122
- 5DAF71B62AC3FB53002D04FE /* UIViewController+Toast.swift */,
123
- 5D281BB02ABC0C3D001CE599 /* WKWebViewConfiguration+App.swift */,
124
131
  5DCC50E72A95A0D900B529A0 /* TurboNavigationController.swift */,
132
+ 5DCC50ED2A95A27600B529A0 /* ErrorPresenter.swift */,
125
133
  5DCC50D72A959DF900B529A0 /* TurboWebViewController.swift */,
126
134
  5DDD58802AA9A8BE00FAC961 /* NumbersViewController.swift */,
127
135
  );
@@ -179,7 +187,7 @@
179
187
  attributes = {
180
188
  BuildIndependentTargetsInParallel = 1;
181
189
  LastSwiftUpdateCheck = 1430;
182
- LastUpgradeCheck = 1430;
190
+ LastUpgradeCheck = 1500;
183
191
  TargetAttributes = {
184
192
  5DCC50CF2A959DF900B529A0 = {
185
193
  CreatedOnToolsVersion = 14.3.1;
@@ -302,6 +310,7 @@
302
310
  DEBUG_INFORMATION_FORMAT = dwarf;
303
311
  ENABLE_STRICT_OBJC_MSGSEND = YES;
304
312
  ENABLE_TESTABILITY = YES;
313
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
305
314
  GCC_C_LANGUAGE_STANDARD = gnu11;
306
315
  GCC_DYNAMIC_NO_PIC = NO;
307
316
  GCC_NO_COMMON_BLOCKS = YES;
@@ -362,6 +371,7 @@
362
371
  DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
363
372
  ENABLE_NS_ASSERTIONS = NO;
364
373
  ENABLE_STRICT_OBJC_MSGSEND = YES;
374
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
365
375
  GCC_C_LANGUAGE_STANDARD = gnu11;
366
376
  GCC_NO_COMMON_BLOCKS = YES;
367
377
  GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "settings": {},
3
3
  "rules": [
4
- { "patterns": ["/refresh_historical_location"], "properties": { "presentation": "refresh", "visitable": false } },
5
- { "patterns": ["/recede_historical_location"], "properties": { "presentation": "pop", "visitable": false } },
4
+ { "patterns": ["/recede_historical_location"], "properties": { "presentation": "back", "visitable": false } },
6
5
  { "patterns": ["/resume_historical_location"], "properties": { "presentation": "none", "visitable": false } },
6
+ { "patterns": ["/refresh_historical_location"], "properties": { "presentation": "refresh", "visitable": false } },
7
+ { "patterns": ["/new$", "/edit$", "/signin$", "/strada-form$"], "properties": { "presentation": "modal", "pull-to-refresh-enabled": false } },
7
8
  { "patterns": ["^/$"], "properties": { "presentation": "replace-all" } },
8
- { "patterns": ["/new$", "/edit$", "/signin$", "/strada-form$"], "properties": { "presentation": "modal" } },
9
9
  { "patterns": ["/numbers$"], "properties": { "view-controller": "numbers" } }
10
10
  ]
11
11
  }
@@ -22,9 +22,14 @@ class TurboNavigationController : UINavigationController {
22
22
  }
23
23
 
24
24
  // - Create view controller appropriate for url/properties
25
- // - Navigate to that with the correct presentation
26
25
  let viewController = makeViewController(for: url, properties: properties)
27
- navigate(to: viewController, action: options.action, properties: properties)
26
+
27
+ // - Navigate to that with the correct presentation
28
+ if session.topmostVisitable?.visitableURL == url {
29
+ navigate(to: viewController, action: .replace, properties: properties)
30
+ } else {
31
+ navigate(to: viewController, action: options.action, properties: properties)
32
+ }
28
33
 
29
34
  // Initiate the visit with Turbo
30
35
  if isVisitable(properties) {
@@ -43,8 +48,8 @@ extension TurboNavigationController {
43
48
  return properties["presentation"] as? String == "modal"
44
49
  }
45
50
 
46
- private func isPop(_ properties: PathProperties) -> Bool {
47
- return properties["presentation"] as? String == "pop"
51
+ private func isBack(_ properties: PathProperties) -> Bool {
52
+ return properties["presentation"] as? String == "back"
48
53
  }
49
54
 
50
55
  private func isRefresh(_ properties: PathProperties) -> Bool {
@@ -71,6 +76,14 @@ extension TurboNavigationController {
71
76
  return properties["visitable"] as? Bool ?? true
72
77
  }
73
78
 
79
+ private func isPullToRefreshEnabled(_ properties: PathProperties) -> Bool {
80
+ return properties["pull-to-refresh-enabled"] as? Bool ?? true
81
+ }
82
+
83
+ private func title(from properties: PathProperties) -> String? {
84
+ return properties["title"] as? String
85
+ }
86
+
74
87
  private func noticeMessage(from url: URL) -> String? {
75
88
  URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.first(where: { $0.name == "notice" })?.value
76
89
  }
@@ -90,13 +103,16 @@ extension TurboNavigationController {
90
103
  }
91
104
  }
92
105
 
93
- return TurboWebViewController(url: url)
106
+ let viewController = TurboWebViewController(url: url)
107
+ viewController.pullToRefreshEnabled = isPullToRefreshEnabled(properties)
108
+ viewController.title = title(from: properties)
109
+ return viewController
94
110
  }
95
111
 
96
112
  private func navigate(to viewController: UIViewController, action: VisitAction, properties: PathProperties = [:]) {
97
113
  if isModal(properties) {
98
114
  present(UINavigationController(rootViewController: viewController), animated: true)
99
- } else if isPop(properties) {
115
+ } else if isBack(properties) {
100
116
  popViewController(animated: true)
101
117
  } else if isRefresh(properties) {
102
118
  session.reload()
@@ -5,6 +5,8 @@ import WebKit
5
5
 
6
6
  final class TurboWebViewController: VisitableViewController, ErrorPresenter, BridgeDestination {
7
7
 
8
+ var pullToRefreshEnabled = true
9
+
8
10
  private lazy var bridgeDelegate: BridgeDelegate = {
9
11
  BridgeDelegate(location: visitableURL.absoluteString, destination: self, componentTypes: BridgeComponent.allTypes)
10
12
  }()
@@ -17,14 +19,15 @@ final class TurboWebViewController: VisitableViewController, ErrorPresenter, Bri
17
19
 
18
20
  override func viewDidLoad() {
19
21
  super.viewDidLoad()
22
+ bridgeDelegate.onViewDidLoad()
20
23
 
21
24
  navigationItem.backButtonTitle = "Back"
22
25
 
26
+ visitableView.allowsPullToRefresh = pullToRefreshEnabled
27
+
23
28
  if presentingViewController != nil {
24
29
  navigationItem.leftBarButtonItem = dismissModalButton
25
30
  }
26
-
27
- bridgeDelegate.onViewDidLoad()
28
31
  }
29
32
 
30
33
  override func viewWillAppear(_ animated: Bool) {
@@ -49,6 +52,10 @@ final class TurboWebViewController: VisitableViewController, ErrorPresenter, Bri
49
52
 
50
53
  // MARK: Visitable
51
54
 
55
+ override func visitableDidRender() {
56
+ title = title ?? visitableView.webView?.title
57
+ }
58
+
52
59
  override func visitableDidActivateWebView(_ webView: WKWebView) {
53
60
  bridgeDelegate.webViewDidBecomeActive(webView)
54
61
  }
@@ -5,13 +5,11 @@ import Turbo
5
5
  import Strada
6
6
 
7
7
  final class SceneDelegate: UIResponder {
8
- private static var sharedProcessPool = WKProcessPool()
9
-
10
8
  var window: UIWindow?
11
9
 
12
- private let baseURL = <%= name %>.baseURL
13
- private let rootURL1 = <%= name %>.homeURL1
14
- private let rootURL2 = <%= name %>.homeURL2
10
+ private let baseURL = TurboNativeProject.baseURL
11
+ private let rootURL1 = TurboNativeProject.homeURL1
12
+ private let rootURL2 = TurboNativeProject.homeURL2
15
13
 
16
14
  private var tabBarController: UITabBarController!
17
15
  private var navigationController1: TurboNavigationController!
@@ -25,12 +23,15 @@ final class SceneDelegate: UIResponder {
25
23
 
26
24
  private func configureRootViewController() {
27
25
  tabBarController = window!.rootViewController as? UITabBarController
26
+ tabBarController.tabBar.scrollEdgeAppearance = .init()
28
27
 
29
28
  navigationController1 = tabBarController.viewControllers![0] as? TurboNavigationController
29
+ navigationController1.navigationBar.scrollEdgeAppearance = .init()
30
30
  navigationController1.session = session1
31
31
  navigationController1.modalSession = modalSession
32
32
 
33
33
  navigationController2 = tabBarController.viewControllers![1] as? TurboNavigationController
34
+ navigationController2.navigationBar.scrollEdgeAppearance = .init()
34
35
  navigationController2.session = session2
35
36
  navigationController2.modalSession = modalSession
36
37
  }
@@ -113,7 +114,7 @@ extension SceneDelegate: WKUIDelegate {
113
114
  func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
114
115
  let confirm = UIAlertController(title: nil, message: message, preferredStyle: .alert)
115
116
  confirm.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in completionHandler(false) })
116
- confirm.addAction(UIAlertAction(title: "OK", style: .default) { _ in completionHandler(true) })
117
+ confirm.addAction(UIAlertAction(title: "OK", style: .default) { _ in completionHandler(true) })
117
118
  navigationController().present(confirm, animated: true)
118
119
  }
119
120
  }
@@ -2,33 +2,24 @@ import SwiftUI
2
2
 
3
3
  public extension UIViewController {
4
4
  func presentToast(_ message: String) {
5
- guard let root = view.window?.rootViewController else { return }
5
+ guard let window = view.window else { return }
6
6
 
7
- removeToastViews(from: root)
7
+ removeToastViews(from: window)
8
8
 
9
9
  let toastView = ToastView(message: message)
10
10
  toastView.translatesAutoresizingMaskIntoConstraints = false
11
11
 
12
- root.view.addSubview(toastView)
12
+ window.addSubview(toastView)
13
13
 
14
14
  NSLayoutConstraint.activate([
15
- toastView.topAnchor.constraint(equalTo: root.view.safeAreaLayoutGuide.topAnchor),
16
- toastView.centerXAnchor.constraint(equalTo: root.view.centerXAnchor)
17
- ])
18
-
19
- let widthConstraint = toastView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -10)
20
- widthConstraint.priority = .defaultHigh
21
-
22
- let maxWidthConstraint = toastView.widthAnchor.constraint(lessThanOrEqualToConstant: 600)
23
- maxWidthConstraint.priority = .required
24
-
25
- NSLayoutConstraint.activate([
26
- widthConstraint, maxWidthConstraint
15
+ toastView.centerXAnchor.constraint(equalTo: window.centerXAnchor),
16
+ toastView.topAnchor.constraint(equalTo: window.safeAreaLayoutGuide.topAnchor, constant: 2),
17
+ toastView.widthAnchor.constraint(equalTo: window.safeAreaLayoutGuide.widthAnchor, constant: -10)
27
18
  ])
28
19
  }
29
20
 
30
- fileprivate func removeToastViews(from root: UIViewController) {
31
- root.view.subviews.filter({ $0 is ToastView }).forEach({ toast in
21
+ fileprivate func removeToastViews(from window: UIWindow) {
22
+ window.subviews.filter({ $0 is ToastView }).forEach({ toast in
32
23
  toast.removeFromSuperview()
33
24
  })
34
25
  }
@@ -36,7 +27,7 @@ public extension UIViewController {
36
27
 
37
28
  public class ToastView: UIView {
38
29
 
39
- private var duration = 2.5
30
+ private var duration = 2.0
40
31
 
41
32
  convenience init(message: String) {
42
33
  self.init(frame: .zero)
@@ -1,6 +1,6 @@
1
1
  import Foundation
2
2
 
3
- struct <%= name %> {
3
+ struct TurboNativeProject {
4
4
  private static let developmentURL = URL(string: "http://localhost:3000")!
5
5
  private static let productionURL = URL(string: "https://turbo-native-demo.glitch.me")!
6
6
 
@@ -105,11 +105,12 @@
105
105
  5DCC50D22A959DF900B529A0 /* <%= name %> */ = {
106
106
  isa = PBXGroup;
107
107
  children = (
108
+ 5DD38FFC2AD659BC00EA0059 /* Extensions */,
108
109
  5D8AB2F82ABC117400C6A82F /* Strada */,
109
- 5D2FA5CD2A9DB1AB001AF2F1 /* Configuration */,
110
110
  5DCC50F42A95AC4E00B529A0 /* Controllers */,
111
111
  5DCC50FB2A95B55200B529A0 /* Delegates */,
112
112
  5DCC51072A95CCEE00B529A0 /* Resources */,
113
+ 5D2FA5CD2A9DB1AB001AF2F1 /* Configuration */,
113
114
  5DCC50F22A95A7E600B529A0 /* <%= name %>.swift */,
114
115
  );
115
116
  path = <%= name %>;
@@ -118,10 +119,8 @@
118
119
  5DCC50F42A95AC4E00B529A0 /* Controllers */ = {
119
120
  isa = PBXGroup;
120
121
  children = (
121
- 5D8AB2FD2ABC119900C6A82F /* WKWebViewConfiguration+App.swift */,
122
- 5D0735D32AC514F800AC547A /* UIViewController+Toast.swift */,
123
- 5DCC50ED2A95A27600B529A0 /* ErrorPresenter.swift */,
124
122
  5DCC50E72A95A0D900B529A0 /* TurboNavigationController.swift */,
123
+ 5DCC50ED2A95A27600B529A0 /* ErrorPresenter.swift */,
125
124
  5DCC50D72A959DF900B529A0 /* TurboWebViewController.swift */,
126
125
  5DDD58802AA9A8BE00FAC961 /* NumbersViewController.swift */,
127
126
  );
@@ -147,6 +146,15 @@
147
146
  path = Resources;
148
147
  sourceTree = "<group>";
149
148
  };
149
+ 5DD38FFC2AD659BC00EA0059 /* Extensions */ = {
150
+ isa = PBXGroup;
151
+ children = (
152
+ 5D0735D32AC514F800AC547A /* UIViewController+Toast.swift */,
153
+ 5D8AB2FD2ABC119900C6A82F /* WKWebViewConfiguration+App.swift */,
154
+ );
155
+ path = Extensions;
156
+ sourceTree = "<group>";
157
+ };
150
158
  /* End PBXGroup section */
151
159
 
152
160
  /* Begin PBXNativeTarget section */
@@ -1,3 +1,3 @@
1
1
  module TurboNativeInitializer
2
- VERSION = "0.0.15"
2
+ VERSION = "0.0.17"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: turbo-native-initializer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nixon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-04 00:00:00.000000000 Z
11
+ date: 2023-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -166,10 +166,10 @@ files:
166
166
  - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Controllers/NumbersViewController.swift
167
167
  - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Controllers/TurboNavigationController.swift
168
168
  - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Controllers/TurboWebViewController.swift
169
- - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Controllers/UIViewController+Toast.swift
170
- - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Controllers/WKWebViewConfiguration+App.swift
171
169
  - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Delegates/AppDelegate.swift
172
- - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Delegates/SceneDelegate.swift.tt
170
+ - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Delegates/SceneDelegate.swift
171
+ - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Extensions/UIViewController+Toast.swift
172
+ - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Extensions/WKWebViewConfiguration+App.swift
173
173
  - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Resources/Assets.xcassets/AccentColor.colorset/Contents.json
174
174
  - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
175
175
  - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Resources/Assets.xcassets/AppIcon.appiconset/turbo.png
@@ -183,7 +183,7 @@ files:
183
183
  - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Strada/FormComponent.swift
184
184
  - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Strada/MenuComponent.swift
185
185
  - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Strada/NavButtonComponent.swift
186
- - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/TurboNativeProject.swift.tt
186
+ - lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/TurboNativeProject.swift
187
187
  - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject.xcodeproj/project.pbxproj.tt
188
188
  - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject.xcodeproj/project.xcworkspace/contents.xcworkspacedata
189
189
  - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -194,10 +194,10 @@ files:
194
194
  - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Controllers/NumbersViewController.swift
195
195
  - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Controllers/TurboNavigationController.swift
196
196
  - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Controllers/TurboWebViewController.swift
197
- - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Controllers/UIViewController+Toast.swift
198
- - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Controllers/WKWebViewConfiguration+App.swift
199
197
  - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Delegates/AppDelegate.swift
200
- - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Delegates/SceneDelegate.swift.tt
198
+ - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Delegates/SceneDelegate.swift
199
+ - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Extensions/UIViewController+Toast.swift
200
+ - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Extensions/WKWebViewConfiguration+App.swift
201
201
  - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Resources/Assets.xcassets/AccentColor.colorset/Contents.json
202
202
  - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
203
203
  - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Resources/Assets.xcassets/AppIcon.appiconset/turbo.png
@@ -211,7 +211,7 @@ files:
211
211
  - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Strada/FormComponent.swift
212
212
  - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Strada/MenuComponent.swift
213
213
  - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Strada/NavButtonComponent.swift
214
- - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/TurboNativeProject.swift.tt
214
+ - lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/TurboNativeProject.swift
215
215
  - lib/turbo_native_initializer/version.rb
216
216
  homepage: https://github.com/lazaronixon/turbo-native-initializer
217
217
  licenses:
@@ -235,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
235
235
  - !ruby/object:Gem::Version
236
236
  version: '0'
237
237
  requirements: []
238
- rubygems_version: 3.4.19
238
+ rubygems_version: 3.4.20
239
239
  signing_key:
240
240
  specification_version: 4
241
241
  summary: A turbo native project generator