ruby_everywhere 0.3.0 → 0.4.0

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.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +255 -0
  3. data/bridge/everywhere/bridge.js +60 -3
  4. data/lib/everywhere/android_resources.rb +217 -0
  5. data/lib/everywhere/android_sdk.rb +330 -0
  6. data/lib/everywhere/asset_catalog.rb +185 -0
  7. data/lib/everywhere/auth_handoff.rb +398 -0
  8. data/lib/everywhere/auth_token.rb +118 -0
  9. data/lib/everywhere/builders/android.rb +844 -0
  10. data/lib/everywhere/builders/ios.rb +40 -3
  11. data/lib/everywhere/commands/build.rb +51 -9
  12. data/lib/everywhere/commands/clean.rb +10 -5
  13. data/lib/everywhere/commands/dev.rb +46 -8
  14. data/lib/everywhere/commands/doctor.rb +89 -3
  15. data/lib/everywhere/commands/install.rb +1 -1
  16. data/lib/everywhere/commands/logs.rb +117 -8
  17. data/lib/everywhere/config.rb +409 -13
  18. data/lib/everywhere/emulator.rb +405 -0
  19. data/lib/everywhere/engine.rb +12 -0
  20. data/lib/everywhere/icon.rb +196 -0
  21. data/lib/everywhere/log_filter.rb +74 -0
  22. data/lib/everywhere/native_helper.rb +2 -5
  23. data/lib/everywhere/omniauth.rb +88 -0
  24. data/lib/everywhere/paths.rb +47 -0
  25. data/lib/everywhere/version.rb +1 -1
  26. data/support/mobile/android/README.md +217 -0
  27. data/support/mobile/android/app/build.gradle.kts +156 -0
  28. data/support/mobile/android/app/everywhere.properties +8 -0
  29. data/support/mobile/android/app/native-packages.gradle.kts +16 -0
  30. data/support/mobile/android/app/proguard-rules.pro +21 -0
  31. data/support/mobile/android/app/src/debug/res/xml/network_security_config.xml +30 -0
  32. data/support/mobile/android/app/src/main/AndroidManifest.xml +42 -0
  33. data/support/mobile/android/app/src/main/assets/everywhere.json +9 -0
  34. data/support/mobile/android/app/src/main/assets/fonts/MaterialIcons-Regular.codepoints +2235 -0
  35. data/support/mobile/android/app/src/main/assets/fonts/MaterialIcons-Regular.ttf +0 -0
  36. data/support/mobile/android/app/src/main/assets/json/path-configuration.json +19 -0
  37. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/AuthFlow.kt +268 -0
  38. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/EverywhereApplication.kt +178 -0
  39. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/EverywhereConfig.kt +409 -0
  40. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/EverywhereEvents.kt +68 -0
  41. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/EverywhereHost.kt +101 -0
  42. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/IconFont.kt +211 -0
  43. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/MainActivity.kt +975 -0
  44. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/MainTabs.kt +201 -0
  45. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/WebBottomSheetFragment.kt +13 -0
  46. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/WebFragment.kt +36 -0
  47. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/BiometricsComponent.kt +535 -0
  48. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/HapticsComponent.kt +141 -0
  49. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/MenuComponent.kt +361 -0
  50. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/NotificationComponent.kt +151 -0
  51. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/PermissionsComponent.kt +271 -0
  52. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/StorageComponent.kt +101 -0
  53. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/WebControlChannel.kt +204 -0
  54. data/support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/extensions/EverywhereExtensions.kt +51 -0
  55. data/support/mobile/android/app/src/main/res/color/bottom_navigation_active_indicator.xml +4 -0
  56. data/support/mobile/android/app/src/main/res/color/bottom_navigation_item.xml +11 -0
  57. data/support/mobile/android/app/src/main/res/drawable/ic_launcher_foreground.xml +26 -0
  58. data/support/mobile/android/app/src/main/res/drawable/ic_tab_placeholder.xml +28 -0
  59. data/support/mobile/android/app/src/main/res/layout/activity_main.xml +116 -0
  60. data/support/mobile/android/app/src/main/res/layout/bridge_menu_sheet.xml +83 -0
  61. data/support/mobile/android/app/src/main/res/layout/bridge_menu_sheet_item.xml +35 -0
  62. data/support/mobile/android/app/src/main/res/layout/tab_more_sheet.xml +48 -0
  63. data/support/mobile/android/app/src/main/res/layout/tab_more_sheet_item.xml +35 -0
  64. data/support/mobile/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +12 -0
  65. data/support/mobile/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +6 -0
  66. data/support/mobile/android/app/src/main/res/values/colors.xml +21 -0
  67. data/support/mobile/android/app/src/main/res/values/ic_launcher_background.xml +5 -0
  68. data/support/mobile/android/app/src/main/res/values/strings.xml +18 -0
  69. data/support/mobile/android/app/src/main/res/values/styles.xml +32 -0
  70. data/support/mobile/android/app/src/main/res/values/themes.xml +53 -0
  71. data/support/mobile/android/app/src/main/res/values-night/colors.xml +11 -0
  72. data/support/mobile/android/app/src/main/res/values-night/themes.xml +33 -0
  73. data/support/mobile/android/app/src/main/res/xml/network_security_config.xml +12 -0
  74. data/support/mobile/android/app/src/stamped/AndroidManifest.xml +34 -0
  75. data/support/mobile/android/build.gradle.kts +8 -0
  76. data/support/mobile/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  77. data/support/mobile/android/gradle/wrapper/gradle-wrapper.properties +10 -0
  78. data/support/mobile/android/gradle.properties +14 -0
  79. data/support/mobile/android/gradlew +251 -0
  80. data/support/mobile/android/gradlew.bat +94 -0
  81. data/support/mobile/android/settings.gradle.kts +28 -0
  82. data/support/mobile/ios/App/AppDelegate.swift +5 -0
  83. data/support/mobile/ios/App/AuthFlow.swift +101 -0
  84. data/support/mobile/ios/App/EverywhereConfig.swift +84 -0
  85. data/support/mobile/ios/App/SceneDelegate.swift +103 -0
  86. data/support/mobile/ios/App.xcodeproj/project.pbxproj +4 -0
  87. data/support/mobile/ios/README.md +4 -1
  88. metadata +67 -1
@@ -1,3 +1,4 @@
1
+ import AuthenticationServices
1
2
  import HotwireNative
2
3
  import UIKit
3
4
  import WebKit
@@ -43,6 +44,18 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
43
44
  /// until the first navigator/tab bar is built, then routed.
44
45
  private var pendingUniversalLinkURL: URL?
45
46
 
47
+ /// Third-party sign-in, run in the system browser (everywhere.yml `auth:`).
48
+ /// Held for the scene's lifetime — the session inside it must outlive the
49
+ /// call that started it.
50
+ private lazy var authFlow = AuthFlow { [weak self] in
51
+ self?.window ?? ASPresentationAnchor()
52
+ }
53
+
54
+ /// Set while the web view is spending a handoff token. The visit that
55
+ /// follows carries the Set-Cookie headers that sign the app in, so the
56
+ /// auth-gated tab bar can only be fetched once it has finished.
57
+ private var awaitingAuthHandoff = false
58
+
46
59
  func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
47
60
  guard let windowScene = scene as? UIWindowScene else { return }
48
61
 
@@ -75,6 +88,9 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
75
88
  NotificationCenter.default.addObserver(
76
89
  self, selector: #selector(handleNativeVisit(_:)),
77
90
  name: .everywhereNativeVisit, object: nil)
91
+ NotificationCenter.default.addObserver(
92
+ self, selector: #selector(handleAuthFlow(_:)),
93
+ name: .everywhereAuthFlow, object: nil)
78
94
 
79
95
  // Cookie hydration BEFORE the first visit: after a force-kill relaunch
80
96
  // (iOS kills the app when a Settings permission changes) the first
@@ -182,6 +198,10 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
182
198
  /// 3. refresh the auth-aware server config, which rebuilds the tab bar
183
199
  /// back in if (and only if) the user is now signed in.
184
200
  private func resetApp(to target: URL) {
201
+ // A sign-in sheet still up is answering a question the app no longer
202
+ // has — the reset is re-rooting or re-authing underneath it.
203
+ authFlow.cancel()
204
+ awaitingAuthHandoff = false
185
205
  clearWebContentCache()
186
206
  rebuildRoot(entries: [], routeTo: target)
187
207
  loadedTabsFingerprint = "" // matches the empty tab set we just built
@@ -203,6 +223,75 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
203
223
  activeNavigator.route(url)
204
224
  }
205
225
 
226
+ // MARK: Third-party sign-in
227
+
228
+ /// `{action: "authFlow", to: "/auth/github"}` from the gem's
229
+ /// /everywhere/auth/native page — the fallback for visits the proposal
230
+ /// handler never sees (a `data-turbo="false"` link, or OmniAuth 2's POST).
231
+ @objc private func handleAuthFlow(_ note: Notification) {
232
+ guard let to = note.userInfo?["to"] as? String, to.hasPrefix("/"), !to.hasPrefix("//") else { return }
233
+ startAuthFlow(to: to)
234
+ }
235
+
236
+ /// Open a provider sign-in in the system browser. Nothing is loaded in the
237
+ /// web view: the whole point is that this URL never touches it.
238
+ private func startAuthFlow(to: String) {
239
+ guard let scheme = config.authScheme,
240
+ let start = config.authStartURL(to: to, returnTo: currentPath)
241
+ else { return }
242
+
243
+ #if DEBUG
244
+ NSLog("authFlow: %@", start.absoluteString)
245
+ #endif
246
+
247
+ authFlow.start(url: start, scheme: scheme) { [weak self] result in
248
+ guard let self else { return }
249
+ switch result {
250
+ case .success(let token):
251
+ self.finishAuthFlow(token: token)
252
+ case .failure(.canceled):
253
+ break // they closed the sheet; they're still on the page they started from
254
+ case .failure(let error):
255
+ self.presentAuthFailure(error)
256
+ }
257
+ }
258
+ }
259
+
260
+ /// Spend the handoff token in the web view and rebuild around whatever it
261
+ /// signs the app in as. Deliberately the reset sequence, in order:
262
+ /// 1. drop cached web content — the pre-auth pages are all stale now,
263
+ /// 2. drop to a single navigator aimed at the handoff, which sets the
264
+ /// session cookie in the WEB VIEW's jar (the browser's jar, where the
265
+ /// flow actually happened, is unreachable from here) and redirects on
266
+ /// to the app's post-sign-in page,
267
+ /// 3. once that request has finished — and only then, or the fetch races
268
+ /// the cookie — re-read the auth-gated config, which brings the tab
269
+ /// bar back for the user who just signed in.
270
+ private func finishAuthFlow(token: String) {
271
+ guard let handoff = config.authHandoffURL(token: token) else { return }
272
+
273
+ clearWebContentCache()
274
+ rebuildRoot(entries: [], routeTo: handoff)
275
+ loadedTabsFingerprint = "" // matches the empty tab set we just built
276
+ awaitingAuthHandoff = true
277
+ }
278
+
279
+ private func presentAuthFailure(_ error: AuthFlow.Failure) {
280
+ NSLog("authFlow failed: %@", String(describing: error))
281
+
282
+ let alert = UIAlertController(title: "Sign-in didn't finish",
283
+ message: "Something went wrong on the way back to the app. Please try again.",
284
+ preferredStyle: .alert)
285
+ alert.addAction(UIAlertAction(title: "OK", style: .default))
286
+ activeNavigator.activeNavigationController.present(alert, animated: true)
287
+ }
288
+
289
+ /// The path the user is currently on, for the flow to come back to when the
290
+ /// app's own sign-in doesn't name a destination.
291
+ private var currentPath: String? {
292
+ activeNavigator.currentVisitableURL.map { config.pathAndQuery(of: $0) }
293
+ }
294
+
206
295
  // MARK: Instance switching (multi-instance apps)
207
296
 
208
297
  /// `Everywhere.instance.set(url)`: persist the picked instance as the
@@ -444,6 +533,13 @@ extension SceneDelegate: NavigatorDelegate {
444
533
  resetApp(to: resetTarget(from: proposal.url))
445
534
  return .reject
446
535
  }
536
+ // A provider sign-in: hand it to the system browser instead of loading
537
+ // it here. Rejecting leaves the user on the page they tapped from, which
538
+ // is where they belong if they close the sheet.
539
+ if let target = config.authTarget(for: proposal.url) {
540
+ startAuthFlow(to: target)
541
+ return .reject
542
+ }
447
543
  // App-provided native screens: a path rule's `view_controller`
448
544
  // identifier resolves through the extension registry (everywhere.yml
449
545
  // native.ios.screens). Unknown identifiers fall through to the web.
@@ -460,6 +556,13 @@ extension SceneDelegate: NavigatorDelegate {
460
556
 
461
557
  func requestDidFinish(at url: URL) {
462
558
  dismissSplash()
559
+
560
+ // The handoff has landed, so its cookies are in the web view's jar:
561
+ // now the tab bar can be fetched as the signed-in user.
562
+ if awaitingAuthHandoff {
563
+ awaitingAuthHandoff = false
564
+ loadPathConfiguration(serverOnly: true)
565
+ }
463
566
  }
464
567
 
465
568
  func visitableDidFailRequest(_ visitable: any Visitable, error: HotwireNativeError, retryHandler: RetryBlock?) {
@@ -18,6 +18,7 @@
18
18
  EBE000000000000000000060 /* StorageComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE000000000000000000059 /* StorageComponent.swift */; };
19
19
  EBE000000000000000000068 /* MenuComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE000000000000000000067 /* MenuComponent.swift */; };
20
20
  EBE000000000000000000063 /* EverywhereHost.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE000000000000000000062 /* EverywhereHost.swift */; };
21
+ EBE000000000000000000070 /* AuthFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE000000000000000000069 /* AuthFlow.swift */; };
21
22
  EBE000000000000000000036 /* everywhere.json in Resources */ = {isa = PBXBuildFile; fileRef = EBE000000000000000000018 /* everywhere.json */; };
22
23
  EBE000000000000000000037 /* path-configuration.json in Resources */ = {isa = PBXBuildFile; fileRef = EBE000000000000000000019 /* path-configuration.json */; };
23
24
  EBE000000000000000000038 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EBE000000000000000000020 /* Assets.xcassets */; };
@@ -45,6 +46,7 @@
45
46
  EBE000000000000000000020 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
46
47
  EBE000000000000000000021 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
47
48
  EBE000000000000000000062 /* EverywhereHost.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EverywhereHost.swift; sourceTree = "<group>"; };
49
+ EBE000000000000000000069 /* AuthFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthFlow.swift; sourceTree = "<group>"; };
48
50
  /* End PBXFileReference section */
49
51
 
50
52
  /* Begin PBXFileSystemSynchronizedRootGroup section */
@@ -89,6 +91,7 @@
89
91
  EBE000000000000000000015 /* EverywhereConfig.swift */,
90
92
  EBE000000000000000000016 /* ErrorViewController.swift */,
91
93
  EBE000000000000000000062 /* EverywhereHost.swift */,
94
+ EBE000000000000000000069 /* AuthFlow.swift */,
92
95
  EBE000000000000000000005 /* Bridge */,
93
96
  EBE000000000000000000061 /* Extensions */,
94
97
  EBE000000000000000000023 /* Resources */,
@@ -215,6 +218,7 @@
215
218
  EBE000000000000000000060 /* StorageComponent.swift in Sources */,
216
219
  EBE000000000000000000068 /* MenuComponent.swift in Sources */,
217
220
  EBE000000000000000000063 /* EverywhereHost.swift in Sources */,
221
+ EBE000000000000000000070 /* AuthFlow.swift in Sources */,
218
222
  );
219
223
  runOnlyForDeploymentPostprocessing = 0;
220
224
  };
@@ -19,7 +19,10 @@ this template, it overwrites **exactly** these files and nothing else:
19
19
  4. `App/Assets.xcassets/AppIcon.appiconset/AppIcon.png` — the app icon (1024×1024 opaque PNG)
20
20
  5. *(optionally)* `App/Assets.xcassets/AccentColor.colorset/Contents.json` and
21
21
  `App/Assets.xcassets/LaunchBackground.colorset/Contents.json` — brand colors
22
- 6. *(optionally)* `App/App.entitlements` — the Associated Domains entitlement,
22
+ 6. *(optionally)* `App/Info.plist`'s `CFBundleURLTypes` — the sign-in callback
23
+ scheme, written **only** when `auth:` is set in `everywhere.yml` (alongside
24
+ the permission usage strings, which are stamped the same way)
25
+ 7. *(optionally)* `App/App.entitlements` — the Associated Domains entitlement,
23
26
  written **only** when `deep_linking:` is set in `everywhere.yml`. The matching
24
27
  `CODE_SIGN_ENTITLEMENTS` is added to the xcconfig in the same case, so the
25
28
  default build stays entitlement-free and the frozen template still compiles
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_everywhere
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrea Fomera
@@ -76,6 +76,7 @@ extensions: []
76
76
  extra_rdoc_files: []
77
77
  files:
78
78
  - LICENSE.txt
79
+ - README.md
79
80
  - bridge/LICENSE
80
81
  - bridge/README.md
81
82
  - bridge/everywhere/bridge.js
@@ -85,8 +86,14 @@ files:
85
86
  - exe/every
86
87
  - exe/rbe
87
88
  - lib/everywhere.rb
89
+ - lib/everywhere/android_resources.rb
90
+ - lib/everywhere/android_sdk.rb
91
+ - lib/everywhere/asset_catalog.rb
92
+ - lib/everywhere/auth_handoff.rb
93
+ - lib/everywhere/auth_token.rb
88
94
  - lib/everywhere/blake2b.rb
89
95
  - lib/everywhere/boot.rb
96
+ - lib/everywhere/builders/android.rb
90
97
  - lib/everywhere/builders/ios.rb
91
98
  - lib/everywhere/cli.rb
92
99
  - lib/everywhere/commands/build.rb
@@ -107,6 +114,7 @@ files:
107
114
  - lib/everywhere/commands/updates_keygen.rb
108
115
  - lib/everywhere/config.rb
109
116
  - lib/everywhere/database.rb
117
+ - lib/everywhere/emulator.rb
110
118
  - lib/everywhere/engine.rb
111
119
  - lib/everywhere/framework.rb
112
120
  - lib/everywhere/icon.rb
@@ -116,6 +124,7 @@ files:
116
124
  - lib/everywhere/mobile_config_endpoint.rb
117
125
  - lib/everywhere/mobile_configs_controller.rb
118
126
  - lib/everywhere/native_helper.rb
127
+ - lib/everywhere/omniauth.rb
119
128
  - lib/everywhere/paths.rb
120
129
  - lib/everywhere/platform/client.rb
121
130
  - lib/everywhere/platform/credentials.rb
@@ -133,6 +142,62 @@ files:
133
142
  - support/github/build.yml
134
143
  - support/macos/entitlements.plist
135
144
  - support/macos/notarize.sh
145
+ - support/mobile/android/README.md
146
+ - support/mobile/android/app/build.gradle.kts
147
+ - support/mobile/android/app/everywhere.properties
148
+ - support/mobile/android/app/native-packages.gradle.kts
149
+ - support/mobile/android/app/proguard-rules.pro
150
+ - support/mobile/android/app/src/debug/res/xml/network_security_config.xml
151
+ - support/mobile/android/app/src/main/AndroidManifest.xml
152
+ - support/mobile/android/app/src/main/assets/everywhere.json
153
+ - support/mobile/android/app/src/main/assets/fonts/MaterialIcons-Regular.codepoints
154
+ - support/mobile/android/app/src/main/assets/fonts/MaterialIcons-Regular.ttf
155
+ - support/mobile/android/app/src/main/assets/json/path-configuration.json
156
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/AuthFlow.kt
157
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/EverywhereApplication.kt
158
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/EverywhereConfig.kt
159
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/EverywhereEvents.kt
160
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/EverywhereHost.kt
161
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/IconFont.kt
162
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/MainActivity.kt
163
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/MainTabs.kt
164
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/WebBottomSheetFragment.kt
165
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/WebFragment.kt
166
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/BiometricsComponent.kt
167
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/HapticsComponent.kt
168
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/MenuComponent.kt
169
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/NotificationComponent.kt
170
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/PermissionsComponent.kt
171
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/StorageComponent.kt
172
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/bridge/WebControlChannel.kt
173
+ - support/mobile/android/app/src/main/java/com/rubyeverywhere/shell/extensions/EverywhereExtensions.kt
174
+ - support/mobile/android/app/src/main/res/color/bottom_navigation_active_indicator.xml
175
+ - support/mobile/android/app/src/main/res/color/bottom_navigation_item.xml
176
+ - support/mobile/android/app/src/main/res/drawable/ic_launcher_foreground.xml
177
+ - support/mobile/android/app/src/main/res/drawable/ic_tab_placeholder.xml
178
+ - support/mobile/android/app/src/main/res/layout/activity_main.xml
179
+ - support/mobile/android/app/src/main/res/layout/bridge_menu_sheet.xml
180
+ - support/mobile/android/app/src/main/res/layout/bridge_menu_sheet_item.xml
181
+ - support/mobile/android/app/src/main/res/layout/tab_more_sheet.xml
182
+ - support/mobile/android/app/src/main/res/layout/tab_more_sheet_item.xml
183
+ - support/mobile/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
184
+ - support/mobile/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
185
+ - support/mobile/android/app/src/main/res/values-night/colors.xml
186
+ - support/mobile/android/app/src/main/res/values-night/themes.xml
187
+ - support/mobile/android/app/src/main/res/values/colors.xml
188
+ - support/mobile/android/app/src/main/res/values/ic_launcher_background.xml
189
+ - support/mobile/android/app/src/main/res/values/strings.xml
190
+ - support/mobile/android/app/src/main/res/values/styles.xml
191
+ - support/mobile/android/app/src/main/res/values/themes.xml
192
+ - support/mobile/android/app/src/main/res/xml/network_security_config.xml
193
+ - support/mobile/android/app/src/stamped/AndroidManifest.xml
194
+ - support/mobile/android/build.gradle.kts
195
+ - support/mobile/android/gradle.properties
196
+ - support/mobile/android/gradle/wrapper/gradle-wrapper.jar
197
+ - support/mobile/android/gradle/wrapper/gradle-wrapper.properties
198
+ - support/mobile/android/gradlew
199
+ - support/mobile/android/gradlew.bat
200
+ - support/mobile/android/settings.gradle.kts
136
201
  - support/mobile/ios/App.xcodeproj/project.pbxproj
137
202
  - support/mobile/ios/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata
138
203
  - support/mobile/ios/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -144,6 +209,7 @@ files:
144
209
  - support/mobile/ios/App/Assets.xcassets/AppIcon.appiconset/Contents.json
145
210
  - support/mobile/ios/App/Assets.xcassets/Contents.json
146
211
  - support/mobile/ios/App/Assets.xcassets/LaunchBackground.colorset/Contents.json
212
+ - support/mobile/ios/App/AuthFlow.swift
147
213
  - support/mobile/ios/App/Base.lproj/LaunchScreen.storyboard
148
214
  - support/mobile/ios/App/Bridge/BiometricsComponent.swift
149
215
  - support/mobile/ios/App/Bridge/HapticsComponent.swift