ruby_everywhere 0.5.0 → 0.7.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.
- checksums.yaml +4 -4
- data/README.md +13 -1
- data/exe/every +12 -1
- data/exe/rbe +12 -1
- data/lib/everywhere/agents_guide.rb +59 -0
- data/lib/everywhere/blake2b.rb +17 -1
- data/lib/everywhere/boot.rb +21 -4
- data/lib/everywhere/builders/android.rb +144 -30
- data/lib/everywhere/builders/desktop.rb +25 -17
- data/lib/everywhere/builders/ios.rb +244 -9
- data/lib/everywhere/cli.rb +2 -0
- data/lib/everywhere/commands/build.rb +113 -58
- data/lib/everywhere/commands/clean.rb +8 -3
- data/lib/everywhere/commands/dev.rb +85 -11
- data/lib/everywhere/commands/doctor.rb +138 -21
- data/lib/everywhere/commands/install.rb +121 -9
- data/lib/everywhere/commands/platform/build.rb +136 -27
- data/lib/everywhere/commands/platform/login.rb +16 -2
- data/lib/everywhere/commands/platform/runner.rb +113 -23
- data/lib/everywhere/commands/preview.rb +359 -0
- data/lib/everywhere/commands/publish.rb +20 -2
- data/lib/everywhere/commands/release.rb +145 -28
- data/lib/everywhere/commands/shell_dir.rb +2 -2
- data/lib/everywhere/config.rb +88 -3
- data/lib/everywhere/console.rb +2 -1
- data/lib/everywhere/engine.rb +24 -0
- data/lib/everywhere/framework.rb +21 -4
- data/lib/everywhere/ignore.rb +3 -1
- data/lib/everywhere/jump.rb +121 -0
- data/lib/everywhere/mobile_config_endpoint.rb +47 -0
- data/lib/everywhere/mobile_configs_controller.rb +46 -0
- data/lib/everywhere/paths.rb +13 -6
- data/lib/everywhere/platform/client.rb +27 -6
- data/lib/everywhere/platform/credentials.rb +18 -8
- data/lib/everywhere/platform/snapshot.rb +10 -0
- data/lib/everywhere/receipt.rb +55 -10
- data/lib/everywhere/shellout.rb +19 -0
- data/lib/everywhere/simulator.rb +12 -1
- data/lib/everywhere/version.rb +1 -1
- data/support/agents/AGENTS.md +90 -0
- data/support/agents/frameworks/hanami-views.md +26 -0
- data/support/agents/frameworks/hanami.md +10 -0
- data/support/agents/frameworks/rails-views.md +98 -0
- data/support/agents/frameworks/rails.md +16 -0
- data/support/agents/frameworks/sinatra-views.md +24 -0
- data/support/agents/frameworks/sinatra.md +9 -0
- data/support/agents/modes/local.md +12 -0
- data/support/agents/modes/remote.md +14 -0
- data/support/mobile/android/app/build.gradle.kts +29 -1
- data/support/mobile/ios/App/EverywhereConfig.swift +17 -5
- data/support/mobile/ios/App/SceneDelegate.swift +75 -8
- data/support/mobile/ios/App.xcodeproj/project.pbxproj +2 -2
- data/support/mobile/ios/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +0 -1
- data/support/mobile/ios/README.md +13 -6
- metadata +41 -6
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import AuthenticationServices
|
|
2
2
|
import HotwireNative
|
|
3
|
+
import SwiftUI
|
|
3
4
|
import UIKit
|
|
4
5
|
import WebKit
|
|
5
6
|
|
|
@@ -369,7 +370,15 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|
|
369
370
|
nav.start()
|
|
370
371
|
}
|
|
371
372
|
} else {
|
|
372
|
-
let controller =
|
|
373
|
+
let controller = EverywhereTabBarController(navigatorDelegate: self, lazyLoadTabs: config.lazyLoadsTabs)
|
|
374
|
+
if config.remoteInstances == true {
|
|
375
|
+
controller.leaveTabIndex = entries.firstIndex { $0.path == EverywhereTabBarController.jumpLeavePath }
|
|
376
|
+
controller.onLeaveSelected = { [weak self] in
|
|
377
|
+
guard let self else { return }
|
|
378
|
+
EverywhereConfig.setInstanceURL(nil)
|
|
379
|
+
self.resetApp(to: self.config.startURL)
|
|
380
|
+
}
|
|
381
|
+
}
|
|
373
382
|
tabBarController = controller
|
|
374
383
|
navigator = nil
|
|
375
384
|
window?.rootViewController = controller
|
|
@@ -543,13 +552,23 @@ extension SceneDelegate: NavigatorDelegate {
|
|
|
543
552
|
// App-provided native screens: a path rule's `view_controller`
|
|
544
553
|
// identifier resolves through the extension registry (everywhere.yml
|
|
545
554
|
// native.ios.screens). Unknown identifiers fall through to the web.
|
|
546
|
-
if let identifier = proposal.properties["view_controller"] as? String
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
555
|
+
if let identifier = proposal.properties["view_controller"] as? String {
|
|
556
|
+
if let screen = EverywhereExtensions.screen(for: identifier, url: proposal.url) {
|
|
557
|
+
// A native screen IS first content: without this, an app whose
|
|
558
|
+
// entry path is native never finishes a request and the splash
|
|
559
|
+
// sits until its safety timeout.
|
|
560
|
+
dismissSplash()
|
|
561
|
+
return .acceptCustom(screen)
|
|
562
|
+
}
|
|
563
|
+
// Previewing someone else's app (a picked instance): its rules
|
|
564
|
+
// name native screens compiled into ITS build, not this shell.
|
|
565
|
+
// Say so, instead of falling through to a web 404. Outside a
|
|
566
|
+
// preview an unknown id keeps falling through — there it's a
|
|
567
|
+
// typo, and the web response is the honest answer.
|
|
568
|
+
if config.remoteInstances == true, EverywhereConfig.instanceURL != nil {
|
|
569
|
+
dismissSplash()
|
|
570
|
+
return .acceptCustom(everywhereHost(MissingExtensionScreen(identifier: identifier)))
|
|
571
|
+
}
|
|
553
572
|
}
|
|
554
573
|
return .accept
|
|
555
574
|
}
|
|
@@ -585,3 +604,51 @@ extension SceneDelegate: NavigatorDelegate {
|
|
|
585
604
|
activeNavigator.activeNavigationController.present(errorViewController, animated: true)
|
|
586
605
|
}
|
|
587
606
|
}
|
|
607
|
+
|
|
608
|
+
/// Tab bar that treats the Jump "leave preview" tab as a native action.
|
|
609
|
+
/// The page behind that tab is a gem-served browser fallback with no Turbo,
|
|
610
|
+
/// so letting it become a web visit can only end at Hotwire's "Turbo is not
|
|
611
|
+
/// ready" screen — selecting it must clear the picked instance directly,
|
|
612
|
+
/// and the tap never reaches the web layer.
|
|
613
|
+
final class EverywhereTabBarController: HotwireTabBarController {
|
|
614
|
+
static let jumpLeavePath = "/everywhere/jump/leave"
|
|
615
|
+
|
|
616
|
+
var leaveTabIndex: Int?
|
|
617
|
+
var onLeaveSelected: (() -> Void)?
|
|
618
|
+
|
|
619
|
+
func tabBarController(_ tabBarController: UITabBarController,
|
|
620
|
+
shouldSelect viewController: UIViewController) -> Bool {
|
|
621
|
+
guard let leaveTabIndex,
|
|
622
|
+
tabBarController.viewControllers?.firstIndex(of: viewController) == leaveTabIndex
|
|
623
|
+
else { return true }
|
|
624
|
+
|
|
625
|
+
onLeaveSelected?()
|
|
626
|
+
return false
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/// Shown while PREVIEWING an app whose path rules route here natively: the
|
|
631
|
+
/// screen exists as Swift in that app's native/ios, compiled into its real
|
|
632
|
+
/// build — this shell only carries its own extensions. Honest placeholder
|
|
633
|
+
/// beats a mystery web 404.
|
|
634
|
+
struct MissingExtensionScreen: View {
|
|
635
|
+
let identifier: String
|
|
636
|
+
|
|
637
|
+
var body: some View {
|
|
638
|
+
VStack(spacing: 14) {
|
|
639
|
+
Image(systemName: "puzzlepiece.extension")
|
|
640
|
+
.font(.system(size: 44))
|
|
641
|
+
.foregroundStyle(.secondary)
|
|
642
|
+
Text("This screen is native")
|
|
643
|
+
.font(.title3.bold())
|
|
644
|
+
Text("In the full build, “\(identifier)” is a native screen compiled " +
|
|
645
|
+
"into the app. Jump can't run another app's native code — " +
|
|
646
|
+
"everything else in this preview works.")
|
|
647
|
+
.font(.callout)
|
|
648
|
+
.foregroundStyle(.secondary)
|
|
649
|
+
.multilineTextAlignment(.center)
|
|
650
|
+
}
|
|
651
|
+
.padding(32)
|
|
652
|
+
.navigationTitle("Preview")
|
|
653
|
+
}
|
|
654
|
+
}
|
|
@@ -440,8 +440,8 @@
|
|
|
440
440
|
isa = XCRemoteSwiftPackageReference;
|
|
441
441
|
repositoryURL = "https://github.com/afomera/hotwire-native-ios";
|
|
442
442
|
requirement = {
|
|
443
|
-
|
|
444
|
-
|
|
443
|
+
kind = revision;
|
|
444
|
+
revision = 915194a338d0a4c686ee43ace7450b3aa0e885c3;
|
|
445
445
|
};
|
|
446
446
|
};
|
|
447
447
|
/* End XCRemoteSwiftPackageReference section */
|
|
@@ -42,12 +42,19 @@ recommitting — never in a stamped copy.
|
|
|
42
42
|
|
|
43
43
|
## SPM pin policy
|
|
44
44
|
|
|
45
|
-
The project depends on one package:
|
|
46
|
-
`https://github.com/
|
|
47
|
-
`
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
The project depends on one remote package: the fork
|
|
46
|
+
`https://github.com/afomera/hotwire-native-ios`, pinned to an **exact revision**
|
|
47
|
+
(`kind = revision` in the pbxproj `XCRemoteSwiftPackageReference` requirement).
|
|
48
|
+
A revision pin resolves offline from an existing SPM clone; a branch pin makes
|
|
49
|
+
every build re-check the remote, which is why the template does not use one.
|
|
50
|
+
|
|
51
|
+
Moving the pin is a deliberate two-file edit, and both files must carry the
|
|
52
|
+
same SHA:
|
|
53
|
+
|
|
54
|
+
1. `App.xcodeproj/project.pbxproj` — the `requirement` dict (`kind = revision;`
|
|
55
|
+
/ `revision = <40-char sha>;`)
|
|
56
|
+
2. `App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved` —
|
|
57
|
+
the pin's `state.revision` (no `branch` key)
|
|
51
58
|
|
|
52
59
|
## Building standalone
|
|
53
60
|
|
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.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrea Fomera
|
|
@@ -65,8 +65,27 @@ dependencies:
|
|
|
65
65
|
- - "~>"
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
67
|
version: '0.15'
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: rqrcode
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '3.0'
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '3.0'
|
|
82
|
+
description: RubyEverywhere gives a Rails (or Sinatra, or Hanami) app a native life
|
|
83
|
+
on desktop, iOS, and Android. Desktop is a Tauri shell — in local mode the whole
|
|
84
|
+
app is pressed into a single-file binary with Tebako and runs on-device with no
|
|
85
|
+
Ruby install; in remote mode the shell wraps your deployed app. iOS and Android
|
|
86
|
+
are Hotwire Native shells with a real tab bar, nav-bar buttons, menus, notifications,
|
|
87
|
+
haptics, biometrics, and deep links. One config file, one CLI, one JavaScript bridge,
|
|
88
|
+
with the web app staying the source of truth.
|
|
70
89
|
email:
|
|
71
90
|
- andrea.fomera@gmail.com
|
|
72
91
|
executables:
|
|
@@ -86,6 +105,7 @@ files:
|
|
|
86
105
|
- exe/every
|
|
87
106
|
- exe/rbe
|
|
88
107
|
- lib/everywhere.rb
|
|
108
|
+
- lib/everywhere/agents_guide.rb
|
|
89
109
|
- lib/everywhere/android_resources.rb
|
|
90
110
|
- lib/everywhere/android_sdk.rb
|
|
91
111
|
- lib/everywhere/asset_catalog.rb
|
|
@@ -110,6 +130,7 @@ files:
|
|
|
110
130
|
- lib/everywhere/commands/platform/login.rb
|
|
111
131
|
- lib/everywhere/commands/platform/logout.rb
|
|
112
132
|
- lib/everywhere/commands/platform/runner.rb
|
|
133
|
+
- lib/everywhere/commands/preview.rb
|
|
113
134
|
- lib/everywhere/commands/publish.rb
|
|
114
135
|
- lib/everywhere/commands/release.rb
|
|
115
136
|
- lib/everywhere/commands/shell_dir.rb
|
|
@@ -128,6 +149,7 @@ files:
|
|
|
128
149
|
- lib/everywhere/framework.rb
|
|
129
150
|
- lib/everywhere/icon.rb
|
|
130
151
|
- lib/everywhere/ignore.rb
|
|
152
|
+
- lib/everywhere/jump.rb
|
|
131
153
|
- lib/everywhere/line_pump.rb
|
|
132
154
|
- lib/everywhere/log_filter.rb
|
|
133
155
|
- lib/everywhere/minisign.rb
|
|
@@ -151,6 +173,15 @@ files:
|
|
|
151
173
|
- lib/everywhere/update_manifest.rb
|
|
152
174
|
- lib/everywhere/version.rb
|
|
153
175
|
- lib/ruby_everywhere.rb
|
|
176
|
+
- support/agents/AGENTS.md
|
|
177
|
+
- support/agents/frameworks/hanami-views.md
|
|
178
|
+
- support/agents/frameworks/hanami.md
|
|
179
|
+
- support/agents/frameworks/rails-views.md
|
|
180
|
+
- support/agents/frameworks/rails.md
|
|
181
|
+
- support/agents/frameworks/sinatra-views.md
|
|
182
|
+
- support/agents/frameworks/sinatra.md
|
|
183
|
+
- support/agents/modes/local.md
|
|
184
|
+
- support/agents/modes/remote.md
|
|
154
185
|
- support/desktop/README.md
|
|
155
186
|
- support/desktop/splash/index.html
|
|
156
187
|
- support/desktop/src-tauri/Cargo.lock
|
|
@@ -258,7 +289,11 @@ files:
|
|
|
258
289
|
homepage: https://rubyeverywhere.com
|
|
259
290
|
licenses:
|
|
260
291
|
- MIT
|
|
261
|
-
metadata:
|
|
292
|
+
metadata:
|
|
293
|
+
homepage_uri: https://rubyeverywhere.com
|
|
294
|
+
source_code_uri: https://github.com/RubyEverywhere/gem
|
|
295
|
+
bug_tracker_uri: https://github.com/RubyEverywhere/gem/issues
|
|
296
|
+
rubygems_mfa_required: 'true'
|
|
262
297
|
rdoc_options: []
|
|
263
298
|
require_paths:
|
|
264
299
|
- lib
|
|
@@ -275,6 +310,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
275
310
|
requirements: []
|
|
276
311
|
rubygems_version: 4.0.16
|
|
277
312
|
specification_version: 4
|
|
278
|
-
summary:
|
|
279
|
-
|
|
313
|
+
summary: Ship desktop and mobile apps from the Ruby web apps you already know how
|
|
314
|
+
to build
|
|
280
315
|
test_files: []
|