krz/moonrise

Night-sky companion for iPhone, Apple Watch and Vision Pro: what's up tonight, the Moon, planets, launches and missions, and a Library of the solar system. SwiftUI app with a Cloudflare Workers backend. astronomy cloudflare-workers ios night-sky space swiftui visionos watchos

Commit b36357c3f5

b36357c3f59b996320256a8bb402c0900257574f

parent: 19fe0d0d89

Verified · cmc

cmc <hello@cleberg.net> · 2026-10-18 08:51 UTC

Support iPad

- TARGETED_DEVICE_FAMILY 1,2 for the app, widgets and UI tests; all
  orientations on iPad, portrait on iPhone.
- Sidebar-adaptable tab bar (top bar with sidebar toggle on iPad).
- System, Sun, Launches, Library pages and the first-run screen keep a
  readable width (720 pt, first run 560 pt), centred.
- First-run text says device instead of phone.

Layout: unified · split

App/Sources/LaunchesScreen.swift +1
@@ -36,6 +36,7 @@ struct LaunchesScreen: View {
36 } 36 }
37 } 37 }
38 .padding(.horizontal, 20) 38 .padding(.horizontal, 20)
39 .readableWidth()
39 } 40 }
40 .foregroundStyle(ink) 41 .foregroundStyle(ink)
41 .background(background.ignoresSafeArea()) 42 .background(background.ignoresSafeArea())
App/Sources/LibraryScreen.swift +1
@@ -98,6 +98,7 @@ struct LibraryPageView: View {
98 } 98 }
99 .padding(.horizontal, 20) 99 .padding(.horizontal, 20)
100 .frame(maxWidth: .infinity, alignment: .leading) 100 .frame(maxWidth: .infinity, alignment: .leading)
101 .readableWidth()
101 } 102 }
102 .foregroundStyle(ink) 103 .foregroundStyle(ink)
103 .background(pageBackground.ignoresSafeArea()) 104 .background(pageBackground.ignoresSafeArea())
App/Sources/MoonriseApp.swift +1
@@ -22,6 +22,7 @@ struct MoonriseApp: App {
22 Tab("Launches", systemImage: "airplane.departure", value: "launches") { LaunchesScreen() } 22 Tab("Launches", systemImage: "airplane.departure", value: "launches") { LaunchesScreen() }
23 Tab("Library", systemImage: "books.vertical", value: "library") { LibraryScreen() } 23 Tab("Library", systemImage: "books.vertical", value: "library") { LibraryScreen() }
24 } 24 }
25 .tabViewStyle(.sidebarAdaptable)
25 // Red tab highlight while the Sky tab is in night mode. 26 // Red tab highlight while the Sky tab is in night mode.
26 .tint(tab == "sky" && nightActive ? SkyStyle.nightRed : nil) 27 .tint(tab == "sky" && nightActive ? SkyStyle.nightRed : nil)
27 .preferredColorScheme(.dark) 28 .preferredColorScheme(.dark)
App/Sources/OnboardingScreen.swift +3 −1
@@ -20,7 +20,7 @@ struct OnboardingScreen: View {
20 Rectangle().fill(accent).frame(width: 48, height: 5).padding(.top, 10).padding(.bottom, 24) 20 Rectangle().fill(accent).frame(width: 48, height: 5).padding(.top, 10).padding(.bottom, 24)
21 VStack(alignment: .leading, spacing: 14) { 21 VStack(alignment: .leading, spacing: 14) {
22 Text("The sky above you tonight, the Sun today, launches, the solar system, and a library of everything up there.") 22 Text("The sky above you tonight, the Sun today, launches, the solar system, and a library of everything up there.")
23 Text("To draw the sky for where you are, Moonrise uses your location. It is used on this phone to work out positions and is not sent to us or anyone else.") 23 Text("To draw the sky for where you are, Moonrise uses your location. It is used on this device to work out positions and is not sent to us or anyone else.")
24 .foregroundStyle(ink.opacity(0.75)) 24 .foregroundStyle(ink.opacity(0.75))
25 } 25 }
26 .font(.body) 26 .font(.body)
@@ -49,6 +49,8 @@ struct OnboardingScreen: View {
49 } 49 }
50 .padding(.horizontal, 24) 50 .padding(.horizontal, 24)
51 .padding(.bottom, 24) 51 .padding(.bottom, 24)
52 .frame(maxWidth: 560)
53 .frame(maxWidth: .infinity)
52 .foregroundStyle(ink) 54 .foregroundStyle(ink)
53 .background(background.ignoresSafeArea()) 55 .background(background.ignoresSafeArea())
54 } 56 }
App/Sources/ReadableWidth.swift added +8
@@ -0,0 +1,8 @@
1import SwiftUI
2
3extension View {
4 /// Keeps text columns to a comfortable reading width on iPad, centred.
5 func readableWidth() -> some View {
6 frame(maxWidth: 720).frame(maxWidth: .infinity)
7 }
8}
App/Sources/SunScreen.swift +1
@@ -41,6 +41,7 @@ struct SunScreen: View {
41 Text("Space weather data: NOAA Space Weather Prediction Center. Coastlines: Natural Earth.").font(.caption2).dimmed(0.5).padding(.vertical, 16) 41 Text("Space weather data: NOAA Space Weather Prediction Center. Coastlines: Natural Earth.").font(.caption2).dimmed(0.5).padding(.vertical, 16)
42 } 42 }
43 .padding(.horizontal, 20) 43 .padding(.horizontal, 20)
44 .readableWidth()
44 } 45 }
45 .foregroundStyle(ink) 46 .foregroundStyle(ink)
46 .background(background.ignoresSafeArea()) 47 .background(background.ignoresSafeArea())
App/Sources/SystemScreen.swift +1
@@ -93,6 +93,7 @@ struct SystemScreen: View {
93 .font(.caption2).dimmed(0.5).padding(.vertical, 16) 93 .font(.caption2).dimmed(0.5).padding(.vertical, 16)
94 } 94 }
95 .padding(.horizontal, 20) 95 .padding(.horizontal, 20)
96 .readableWidth()
96 } 97 }
97 .foregroundStyle(ink) 98 .foregroundStyle(ink)
98 .background(background.ignoresSafeArea()) 99 .background(background.ignoresSafeArea())
App/project.yml +5 −4
@@ -46,7 +46,7 @@ targets:
46 DEVELOPMENT_TEAM: ZCNAX3VL9D 46 DEVELOPMENT_TEAM: ZCNAX3VL9D
47 CODE_SIGN_STYLE: Automatic 47 CODE_SIGN_STYLE: Automatic
48 SWIFT_VERSION: "6.0" 48 SWIFT_VERSION: "6.0"
49 TARGETED_DEVICE_FAMILY: "1" 49 TARGETED_DEVICE_FAMILY: "1,2"
50 MARKETING_VERSION: "1.0" 50 MARKETING_VERSION: "1.0"
51 CURRENT_PROJECT_VERSION: "1" 51 CURRENT_PROJECT_VERSION: "1"
52 GENERATE_INFOPLIST_FILE: YES 52 GENERATE_INFOPLIST_FILE: YES
@@ -58,7 +58,8 @@ targets:
58 ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon 58 ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
59 INFOPLIST_KEY_UILaunchScreen_Generation: YES 59 INFOPLIST_KEY_UILaunchScreen_Generation: YES
60 INFOPLIST_KEY_UIStatusBarStyle: UIStatusBarStyleLightContent 60 INFOPLIST_KEY_UIStatusBarStyle: UIStatusBarStyleLightContent
61 INFOPLIST_KEY_UISupportedInterfaceOrientations: UIInterfaceOrientationPortrait 61 INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone: UIInterfaceOrientationPortrait
62 INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad: UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight
62 INFOPLIST_KEY_NSLocationWhenInUseUsageDescription: Moonrise uses your location to draw the sky above you. 63 INFOPLIST_KEY_NSLocationWhenInUseUsageDescription: Moonrise uses your location to draw the sky above you.
63 MoonriseWidgets: 64 MoonriseWidgets:
64 type: app-extension 65 type: app-extension
@@ -84,7 +85,7 @@ targets:
84 DEVELOPMENT_TEAM: ZCNAX3VL9D 85 DEVELOPMENT_TEAM: ZCNAX3VL9D
85 CODE_SIGN_STYLE: Automatic 86 CODE_SIGN_STYLE: Automatic
86 SWIFT_VERSION: "6.0" 87 SWIFT_VERSION: "6.0"
87 TARGETED_DEVICE_FAMILY: "1" 88 TARGETED_DEVICE_FAMILY: "1,2"
88 MARKETING_VERSION: "1.0" 89 MARKETING_VERSION: "1.0"
89 CURRENT_PROJECT_VERSION: "1" 90 CURRENT_PROJECT_VERSION: "1"
90 MoonriseUITests: 91 MoonriseUITests:
@@ -99,5 +100,5 @@ targets:
99 DEVELOPMENT_TEAM: ZCNAX3VL9D 100 DEVELOPMENT_TEAM: ZCNAX3VL9D
100 CODE_SIGN_STYLE: Automatic 101 CODE_SIGN_STYLE: Automatic
101 SWIFT_VERSION: "5.0" 102 SWIFT_VERSION: "5.0"
102 TARGETED_DEVICE_FAMILY: "1" 103 TARGETED_DEVICE_FAMILY: "1,2"
103 GENERATE_INFOPLIST_FILE: YES 104 GENERATE_INFOPLIST_FILE: YES