Commit 5b4208dbee
Verified · cmc
Layout: unified · split
App/Sources/LaunchesScreen.swift +18 −18
| @@ -18,11 +18,11 @@ struct LaunchesScreen: View { | ||
| 18 | 18 | var body: some View { |
| 19 | 19 | ScrollView { |
| 20 | 20 | VStack(alignment: .leading, spacing: 0) { |
| 21 | Text("Launches").font(.system(size: 28, weight: .medium)) | |
| 21 | Text("Launches").font(.title.weight(.medium)) | |
| 22 | 22 | Rectangle().fill(accent).frame(width: 48, height: 5).padding(.top, 8).padding(.bottom, 8) |
| 23 | 23 | |
| 24 | 24 | if let error { |
| 25 | Text(error).font(.system(size: 13)).foregroundStyle(accent).padding(.vertical, 12) | |
| 25 | Text(error).font(.footnote).foregroundStyle(accent).padding(.vertical, 12) | |
| 26 | 26 | } |
| 27 | 27 | if let list { |
| 28 | 28 | ForEach(Array(list.launches.enumerated()), id: \.element.id) { i, launch in |
| @@ -30,7 +30,7 @@ struct LaunchesScreen: View { | ||
| 30 | 30 | .buttonStyle(.plain) |
| 31 | 31 | } |
| 32 | 32 | Text("Launch data: The Space Devs, Launch Library 2.") |
| 33 | .font(.system(size: 10)).opacity(0.5).padding(.vertical, 16) | |
| 33 | .font(.caption2).opacity(0.5).padding(.vertical, 16) | |
| 34 | 34 | } else if error == nil { |
| 35 | 35 | ProgressView().tint(ink).padding(.top, 40).frame(maxWidth: .infinity) |
| 36 | 36 | } |
| @@ -57,18 +57,18 @@ struct LaunchesScreen: View { | ||
| 57 | 57 | private func row(_ l: Launch, index: Int) -> some View { |
| 58 | 58 | VStack(alignment: .leading, spacing: 6) { |
| 59 | 59 | HStack(alignment: .firstTextBaseline) { |
| 60 | Text(String(format: "%02d", index)).font(.system(size: 10).monospacedDigit()).opacity(0.5) | |
| 60 | Text(String(format: "%02d", index)).font(.caption2.monospacedDigit()).opacity(0.5) | |
| 61 | 61 | Text(l.net.formatted(.dateTime.weekday(.abbreviated).day().month(.abbreviated).hour().minute())) |
| 62 | .font(.system(size: 11)).opacity(0.7) | |
| 62 | .font(.caption2).opacity(0.7) | |
| 63 | 63 | Spacer() |
| 64 | 64 | StatusTag(status: l.status, ink: ink, accent: accent) |
| 65 | 65 | } |
| 66 | Text(l.rocket).font(.system(size: 22, weight: .medium)) | |
| 67 | if let m = l.mission { Text(m).font(.system(size: 14)).lineLimit(1) } | |
| 66 | Text(l.rocket).font(.title2.weight(.medium)) | |
| 67 | if let m = l.mission { Text(m).font(.subheadline).lineLimit(1) } | |
| 68 | 68 | HStack { |
| 69 | Text("\(l.provider) · \(l.location)").font(.system(size: 11)).opacity(0.6).lineLimit(1) | |
| 69 | Text("\(l.provider) · \(l.location)").font(.caption2).opacity(0.6).lineLimit(1) | |
| 70 | 70 | Spacer() |
| 71 | Countdown(to: l.net).font(.system(size: 13, weight: .medium).monospacedDigit()) | |
| 71 | Countdown(to: l.net).font(.footnote.weight(.medium).monospacedDigit()) | |
| 72 | 72 | } |
| 73 | 73 | } |
| 74 | 74 | .padding(.vertical, 14) |
| @@ -84,7 +84,7 @@ struct StatusTag: View { | ||
| 84 | 84 | |
| 85 | 85 | var body: some View { |
| 86 | 86 | Text(status.uppercased()) |
| 87 | .font(.system(size: 10, weight: .medium)) | |
| 87 | .font(.caption2.weight(.medium)) | |
| 88 | 88 | .tracking(0.6) |
| 89 | 89 | .padding(.horizontal, 6).padding(.vertical, 2) |
| 90 | 90 | .foregroundStyle(status == "Go" ? Color.black : ink) |
| @@ -121,11 +121,11 @@ struct LaunchDetail: View { | ||
| 121 | 121 | VStack(alignment: .leading, spacing: 10) { |
| 122 | 122 | HStack { |
| 123 | 123 | StatusTag(status: launch.status, ink: ink, accent: accent) |
| 124 | Text(launch.statusName).font(.system(size: 12)).opacity(0.7) | |
| 124 | Text(launch.statusName).font(.caption).opacity(0.7) | |
| 125 | 125 | } |
| 126 | Text(launch.rocket).font(.system(size: 28, weight: .medium)) | |
| 127 | if let m = launch.mission { Text(m).font(.system(size: 17)) } | |
| 128 | Countdown(to: launch.net).font(.system(size: 34, weight: .medium).monospacedDigit()).padding(.vertical, 6) | |
| 126 | Text(launch.rocket).font(.title.weight(.medium)) | |
| 127 | if let m = launch.mission { Text(m).font(.body) } | |
| 128 | Countdown(to: launch.net).font(.largeTitle.weight(.medium).monospacedDigit()).padding(.vertical, 6) | |
| 129 | 129 | Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 6) { |
| 130 | 130 | fact("Provider", launch.provider) |
| 131 | 131 | fact("Launch time", launch.net.formatted(date: .abbreviated, time: .shortened)) |
| @@ -137,11 +137,11 @@ struct LaunchDetail: View { | ||
| 137 | 137 | fact("Pad", launch.pad) |
| 138 | 138 | fact("Location", launch.location) |
| 139 | 139 | } |
| 140 | .font(.system(size: 14)) | |
| 140 | .font(.subheadline) | |
| 141 | 141 | followButton.padding(.top, 8) |
| 142 | if let message { Text(message).font(.system(size: 12)).opacity(0.7) } | |
| 142 | if let message { Text(message).font(.caption).opacity(0.7) } | |
| 143 | 143 | if let d = launch.missionDescription { |
| 144 | Text(d).font(.system(size: 14)).opacity(0.85).padding(.top, 8) | |
| 144 | Text(d).font(.subheadline).opacity(0.85).padding(.top, 8) | |
| 145 | 145 | } |
| 146 | 146 | } |
| 147 | 147 | .padding(20) |
| @@ -160,7 +160,7 @@ struct LaunchDetail: View { | ||
| 160 | 160 | following ? unfollow() : follow() |
| 161 | 161 | } label: { |
| 162 | 162 | Label(following ? "Stop following" : "Follow on Lock Screen", systemImage: following ? "bell.slash" : "bell") |
| 163 | .font(.system(size: 15, weight: .medium)) | |
| 163 | .font(.subheadline.weight(.medium)) | |
| 164 | 164 | .frame(maxWidth: .infinity) |
| 165 | 165 | .padding(.vertical, 10) |
| 166 | 166 | .overlay(RoundedRectangle(cornerRadius: 6).stroke(ink.opacity(0.5), lineWidth: 0.5)) |
App/Sources/LibraryScreen.swift +8 −8
| @@ -17,9 +17,9 @@ struct LibraryScreen: View { | ||
| 17 | 17 | if !pages.isEmpty { |
| 18 | 18 | NavigationLink(value: section) { |
| 19 | 19 | HStack { |
| 20 | Text(section.title).font(.system(size: 17)) | |
| 20 | Text(section.title).font(.body) | |
| 21 | 21 | Spacer() |
| 22 | Text("\(pages.count)").font(.system(size: 13).monospacedDigit()).opacity(0.5) | |
| 22 | Text("\(pages.count)").font(.footnote.monospacedDigit()).opacity(0.5) | |
| 23 | 23 | } |
| 24 | 24 | } |
| 25 | 25 | .listRowBackground(pageBackground) |
| @@ -66,7 +66,7 @@ struct PageRow: View { | ||
| 66 | 66 | var body: some View { |
| 67 | 67 | VStack(alignment: .leading, spacing: 2) { |
| 68 | 68 | Text(page.title).font(.body) |
| 69 | Text(page.subtitle).font(.system(size: 12)).opacity(0.6).lineLimit(1) | |
| 69 | Text(page.subtitle).font(.caption).opacity(0.6).lineLimit(1) | |
| 70 | 70 | } |
| 71 | 71 | .padding(.vertical, 2) |
| 72 | 72 | } |
| @@ -78,7 +78,7 @@ struct LibraryPageView: View { | ||
| 78 | 78 | var body: some View { |
| 79 | 79 | ScrollView { |
| 80 | 80 | VStack(alignment: .leading, spacing: 0) { |
| 81 | Text(page.section.title).font(.system(size: 11, weight: .medium)).textCase(.uppercase).tracking(0.8).opacity(0.6) | |
| 81 | Text(page.section.title).font(.caption2.weight(.medium)).textCase(.uppercase).tracking(0.8).opacity(0.6) | |
| 82 | 82 | Text(page.title).font(.largeTitle.weight(.medium)).padding(.top, 4) |
| 83 | 83 | Text(page.subtitle).font(.subheadline).opacity(0.75).padding(.top, 2) |
| 84 | 84 | Rectangle().fill(accent).frame(width: 48, height: 5).padding(.top, 10).padding(.bottom, 16) |
| @@ -121,23 +121,23 @@ struct LibraryPageView: View { | ||
| 121 | 121 | AsyncImage(url: image.url) { phase in |
| 122 | 122 | switch phase { |
| 123 | 123 | case .success(let img): img.resizable().scaledToFit() |
| 124 | case .failure: Color.black.frame(height: 120).overlay(Text("Image unavailable").font(.system(size: 12)).opacity(0.6)) | |
| 124 | case .failure: Color.black.frame(height: 120).overlay(Text("Image unavailable").font(.caption).opacity(0.6)) | |
| 125 | 125 | default: Color.black.frame(height: 200).overlay(ProgressView().tint(ink)) |
| 126 | 126 | } |
| 127 | 127 | } |
| 128 | 128 | Text(image.caption).font(.footnote).opacity(0.75) |
| 129 | 129 | Link(destination: image.page) { |
| 130 | Text("\(image.credit) · \(image.licence)").font(.system(size: 10)).opacity(0.55) | |
| 130 | Text("\(image.credit) · \(image.licence)").font(.caption2).opacity(0.55) | |
| 131 | 131 | } |
| 132 | 132 | } |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | 135 | private var sources: some View { |
| 136 | 136 | VStack(alignment: .leading, spacing: 6) { |
| 137 | Text("Sources").font(.system(size: 11, weight: .medium)).textCase(.uppercase).tracking(0.8).opacity(0.6) | |
| 137 | Text("Sources").font(.caption2.weight(.medium)).textCase(.uppercase).tracking(0.8).opacity(0.6) | |
| 138 | 138 | ForEach(Array(page.sources.enumerated()), id: \.offset) { i, s in |
| 139 | 139 | Link(destination: s.url) { |
| 140 | Text("\(i + 1). \(s.title)").font(.system(size: 12)).underline().opacity(0.8) | |
| 140 | Text("\(i + 1). \(s.title)").font(.caption).underline().opacity(0.8) | |
| 141 | 141 | } |
| 142 | 142 | } |
| 143 | 143 | } |
App/Sources/SkyScreen.swift +12 −10
| @@ -123,13 +123,15 @@ struct SkyScreen: View { | ||
| 123 | 123 | HStack(alignment: .top) { |
| 124 | 124 | VStack(alignment: .leading, spacing: 4) { |
| 125 | 125 | Text(model.offsetHours == 0 ? "Tonight" : "Sky at \(model.displayedDate.formatted(date: .omitted, time: .shortened))") |
| 126 | .font(.system(size: 22, weight: .medium)) | |
| 126 | .font(.title2.weight(.medium)) | |
| 127 | 127 | Text(model.placeName) |
| 128 | .font(.system(size: 11)).opacity(0.7) | |
| 128 | .font(.caption2).opacity(0.7) | |
| 129 | #if DEBUG | |
| 129 | 130 | TimelineView(.periodic(from: .now, by: 1)) { _ in |
| 130 | 131 | Text(stats.summary(build: model.lastBuild)) |
| 131 | .font(.system(size: 10).monospacedDigit()).opacity(0.7) | |
| 132 | .font(.caption2.monospacedDigit()).opacity(0.7) | |
| 132 | 133 | } |
| 134 | #endif | |
| 133 | 135 | } |
| 134 | 136 | Spacer() |
| 135 | 137 | if pointer.available { |
| @@ -137,14 +139,14 @@ struct SkyScreen: View { | ||
| 137 | 139 | pointer.active ? pointer.stop() : pointer.start() |
| 138 | 140 | } label: { |
| 139 | 141 | Image(systemName: pointer.active ? "scope" : "hand.draw") |
| 140 | .font(.system(size: 17)) | |
| 142 | .font(.body) | |
| 141 | 143 | .frame(width: 44, height: 44) |
| 142 | 144 | } |
| 143 | 145 | .accessibilityLabel(pointer.active ? "Stop following the phone" : "Point the phone at the sky") |
| 144 | 146 | } |
| 145 | 147 | Button { showSettings = true } label: { |
| 146 | 148 | Image(systemName: "gearshape") |
| 147 | .font(.system(size: 17)) | |
| 149 | .font(.body) | |
| 148 | 150 | .frame(width: 44, height: 44) |
| 149 | 151 | } |
| 150 | 152 | .accessibilityLabel("Settings") |
| @@ -152,7 +154,7 @@ struct SkyScreen: View { | ||
| 152 | 154 | nightMode = night ? "off" : "on" |
| 153 | 155 | } label: { |
| 154 | 156 | Image(systemName: night ? "eye.fill" : "eye") |
| 155 | .font(.system(size: 17)) | |
| 157 | .font(.body) | |
| 156 | 158 | .frame(width: 44, height: 44) |
| 157 | 159 | } |
| 158 | 160 | .accessibilityLabel(night ? "Turn off night mode" : "Turn on night mode") |
| @@ -165,7 +167,7 @@ struct SkyScreen: View { | ||
| 165 | 167 | private func card(for object: SkyObject) -> some View { |
| 166 | 168 | VStack(alignment: .leading, spacing: 8) { |
| 167 | 169 | HStack { |
| 168 | Text(title(for: object)).font(.system(size: 20, weight: .medium)) | |
| 170 | Text(title(for: object)).font(.title3.weight(.medium)) | |
| 169 | 171 | Spacer() |
| 170 | 172 | Button { selection = nil } label: { Image(systemName: "xmark").frame(width: 32, height: 32) } |
| 171 | 173 | .accessibilityLabel("Close") |
| @@ -174,11 +176,11 @@ struct SkyScreen: View { | ||
| 174 | 176 | case .body: |
| 175 | 177 | if let d = details { bodyFacts(d) } else { ProgressView().tint(ink) } |
| 176 | 178 | case .constellation(let id): |
| 177 | Text("Constellation · \(id)").font(.system(size: 13)).opacity(0.7) | |
| 179 | Text("Constellation · \(id)").font(.footnote).opacity(0.7) | |
| 178 | 180 | } |
| 179 | 181 | if let page = libraryPage(for: object) { |
| 180 | 182 | Button { libraryPage = page } label: { |
| 181 | Label("Read more", systemImage: "book").font(.system(size: 13, weight: .medium)) | |
| 183 | Label("Read more", systemImage: "book").font(.footnote.weight(.medium)) | |
| 182 | 184 | } |
| 183 | 185 | .buttonStyle(.plain) |
| 184 | 186 | .padding(.top, 4) |
| @@ -223,7 +225,7 @@ struct SkyScreen: View { | ||
| 223 | 225 | Text(row.0).opacity(0.7) |
| 224 | 226 | Text(row.1).monospacedDigit() |
| 225 | 227 | } |
| 226 | .font(.system(size: 13)) | |
| 228 | .font(.footnote) | |
| 227 | 229 | } |
| 228 | 230 | } |
| 229 | 231 | } |
App/Sources/SunScreen.swift +15 −15
| @@ -19,7 +19,7 @@ struct SunScreen: View { | ||
| 19 | 19 | var body: some View { |
| 20 | 20 | ScrollView { |
| 21 | 21 | VStack(alignment: .leading, spacing: 0) { |
| 22 | Text("Sun").font(.system(size: 28, weight: .medium)) | |
| 22 | Text("Sun").font(.title.weight(.medium)) | |
| 23 | 23 | Rectangle().fill(accent).frame(width: 48, height: 5).padding(.top, 8).padding(.bottom, 16) |
| 24 | 24 | |
| 25 | 25 | image |
| @@ -28,17 +28,17 @@ struct SunScreen: View { | ||
| 28 | 28 | } |
| 29 | 29 | .pickerStyle(.segmented) |
| 30 | 30 | .padding(.top, 12) |
| 31 | Text(wavelength.caption).font(.system(size: 13)).opacity(0.75).padding(.top, 8) | |
| 32 | Text(SolarImage.credit).font(.system(size: 10)).opacity(0.5).padding(.top, 4) | |
| 31 | Text(wavelength.caption).font(.footnote).opacity(0.75).padding(.top, 8) | |
| 32 | Text(SolarImage.credit).font(.caption2).opacity(0.5).padding(.top, 4) | |
| 33 | 33 | |
| 34 | 34 | section("Aurora") { auroraMap } |
| 35 | 35 | section("Solar flares, last 24 h") { flares } |
| 36 | 36 | section("Geomagnetic activity (Kp)") { kpChart } |
| 37 | 37 | |
| 38 | 38 | if failed { |
| 39 | Text("Couldn't load space weather. Pull to retry.").font(.system(size: 13)).foregroundStyle(accent).padding(.top, 12) | |
| 39 | Text("Couldn't load space weather. Pull to retry.").font(.footnote).foregroundStyle(accent).padding(.top, 12) | |
| 40 | 40 | } |
| 41 | Text("Space weather data: NOAA Space Weather Prediction Center. Coastlines: Natural Earth.").font(.system(size: 10)).opacity(0.5).padding(.vertical, 16) | |
| 41 | Text("Space weather data: NOAA Space Weather Prediction Center. Coastlines: Natural Earth.").font(.caption2).opacity(0.5).padding(.vertical, 16) | |
| 42 | 42 | } |
| 43 | 43 | .padding(.horizontal, 20) |
| 44 | 44 | } |
| @@ -64,7 +64,7 @@ struct SunScreen: View { | ||
| 64 | 64 | AsyncImage(url: wavelength.url(size: 1024)) { phase in |
| 65 | 65 | switch phase { |
| 66 | 66 | case .success(let img): img.resizable().scaledToFit() |
| 67 | case .failure: Color.black.overlay(Text("Image unavailable").font(.system(size: 13)).opacity(0.6)) | |
| 67 | case .failure: Color.black.overlay(Text("Image unavailable").font(.footnote).opacity(0.6)) | |
| 68 | 68 | default: Color.black.overlay(ProgressView().tint(ink)) |
| 69 | 69 | } |
| 70 | 70 | } |
| @@ -75,7 +75,7 @@ struct SunScreen: View { | ||
| 75 | 75 | |
| 76 | 76 | private func section(_ title: String, @ViewBuilder content: () -> some View) -> some View { |
| 77 | 77 | VStack(alignment: .leading, spacing: 10) { |
| 78 | Text(title).font(.system(size: 11, weight: .medium)).textCase(.uppercase).tracking(0.8).opacity(0.6) | |
| 78 | Text(title).font(.caption2.weight(.medium)).textCase(.uppercase).tracking(0.8).opacity(0.6) | |
| 79 | 79 | content() |
| 80 | 80 | } |
| 81 | 81 | .padding(.top, 24) |
| @@ -94,9 +94,9 @@ struct SunScreen: View { | ||
| 94 | 94 | .accessibilityElement() |
| 95 | 95 | .accessibilityLabel(auroraDescription(ovation)) |
| 96 | 96 | Text("Chance of visible aurora overhead, OVATION model, for \(ovation.forecastTime.formatted(date: .omitted, time: .shortened)). Brighter green is more likely.") |
| 97 | .font(.system(size: 11)).opacity(0.6) | |
| 97 | .font(.caption2).opacity(0.6) | |
| 98 | 98 | } else { |
| 99 | Text("Loading").font(.system(size: 13)).opacity(0.6) | |
| 99 | Text("Loading").font(.footnote).opacity(0.6) | |
| 100 | 100 | } |
| 101 | 101 | } |
| 102 | 102 | |
| @@ -127,7 +127,7 @@ struct SunScreen: View { | ||
| 127 | 127 | .foregroundStyle(c.0 == "C" ? ink.opacity(0.25) : accent.opacity(0.6)) |
| 128 | 128 | .lineStyle(StrokeStyle(lineWidth: 0.5, dash: [3, 3])) |
| 129 | 129 | .annotation(position: .top, alignment: .leading) { |
| 130 | Text(c.0).font(.system(size: 10)).opacity(0.7) | |
| 130 | Text(c.0).font(.caption2).opacity(0.7) | |
| 131 | 131 | } |
| 132 | 132 | } |
| 133 | 133 | } |
| @@ -141,14 +141,14 @@ struct SunScreen: View { | ||
| 141 | 141 | } |
| 142 | 142 | .frame(height: 160) |
| 143 | 143 | } else { |
| 144 | Text("Loading").font(.system(size: 13)).opacity(0.6) | |
| 144 | Text("Loading").font(.footnote).opacity(0.6) | |
| 145 | 145 | } |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | 148 | @ViewBuilder |
| 149 | 149 | private var kpChart: some View { |
| 150 | 150 | if kp.isEmpty { |
| 151 | Text("Loading").font(.system(size: 13)).opacity(0.6) | |
| 151 | Text("Loading").font(.footnote).opacity(0.6) | |
| 152 | 152 | } else { |
| 153 | 153 | Chart(kp) { bar in |
| 154 | 154 | BarMark(x: .value("Start", bar.start, unit: .hour), y: .value("Kp", bar.kp), width: .ratio(0.8)) |
| @@ -169,14 +169,14 @@ struct SunScreen: View { | ||
| 169 | 169 | } |
| 170 | 170 | .frame(height: 140) |
| 171 | 171 | Text("Solid: observed. Faint: forecast. Red: storm level (Kp 5 or more).") |
| 172 | .font(.system(size: 11)).opacity(0.6) | |
| 172 | .font(.caption2).opacity(0.6) | |
| 173 | 173 | } |
| 174 | 174 | } |
| 175 | 175 | |
| 176 | 176 | private func stat(_ label: String, _ value: String) -> some View { |
| 177 | 177 | VStack(alignment: .leading, spacing: 2) { |
| 178 | Text(label).font(.system(size: 10)).opacity(0.6) | |
| 179 | Text(value).font(.system(size: 20, weight: .medium).monospacedDigit()) | |
| 178 | Text(label).font(.caption2).opacity(0.6) | |
| 179 | Text(value).font(.title3.weight(.medium).monospacedDigit()) | |
| 180 | 180 | } |
| 181 | 181 | } |
| 182 | 182 | } |
App/Sources/SystemScreen.swift +8 −8
| @@ -22,7 +22,7 @@ struct SystemScreen: View { | ||
| 22 | 22 | var body: some View { |
| 23 | 23 | ScrollView { |
| 24 | 24 | VStack(alignment: .leading, spacing: 0) { |
| 25 | Text("Solar system").font(.system(size: 28, weight: .medium)) | |
| 25 | Text("Solar system").font(.title.weight(.medium)) | |
| 26 | 26 | Rectangle().fill(accent).frame(width: 48, height: 5).padding(.top, 8).padding(.bottom, 16) |
| 27 | 27 | |
| 28 | 28 | OrreryView(date: date, ink: ink, accent: accent) |
| @@ -35,17 +35,17 @@ struct SystemScreen: View { | ||
| 35 | 35 | } |
| 36 | 36 | .accessibilityLabel(playing ? "Pause" : "Play") |
| 37 | 37 | Text(date.formatted(.dateTime.year().month(.abbreviated))) |
| 38 | .font(.system(size: 15, weight: .medium).monospacedDigit()) | |
| 38 | .font(.subheadline.weight(.medium).monospacedDigit()) | |
| 39 | 39 | .frame(width: 80, alignment: .leading) |
| 40 | 40 | Slider(value: $offsetDays, in: range).tint(ink) |
| 41 | 41 | Button("Today") { playing = false; offsetDays = 0 } |
| 42 | .font(.system(size: 13, weight: .medium)) | |
| 42 | .font(.footnote.weight(.medium)) | |
| 43 | 43 | .opacity(abs(offsetDays) < 1 ? 0.4 : 1) |
| 44 | 44 | } |
| 45 | 45 | .padding(.top, 12) |
| 46 | 46 | |
| 47 | 47 | Text("Distances beyond 1 AU are drawn on a logarithmic scale. Rings: planet orbits, then 50, 100 and 200 AU.") |
| 48 | .font(.system(size: 11)).opacity(0.6).padding(.top, 8) | |
| 48 | .font(.caption2).opacity(0.6).padding(.top, 8) | |
| 49 | 49 | |
| 50 | 50 | section("Spacecraft") { |
| 51 | 51 | Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 6) { |
| @@ -54,7 +54,7 @@ struct SystemScreen: View { | ||
| 54 | 54 | Text("From Sun").opacity(0.6) |
| 55 | 55 | Text("Light time").opacity(0.6) |
| 56 | 56 | } |
| 57 | .font(.system(size: 11)) | |
| 57 | .font(.caption2) | |
| 58 | 58 | ForEach(Spacecraft.all) { craft in |
| 59 | 59 | GridRow { |
| 60 | 60 | if let page = Library.page(spacecraft: craft.name) { |
| @@ -70,12 +70,12 @@ struct SystemScreen: View { | ||
| 70 | 70 | Text("") |
| 71 | 71 | } |
| 72 | 72 | } |
| 73 | .font(.system(size: 14)) | |
| 73 | .font(.subheadline) | |
| 74 | 74 | } |
| 75 | 75 | } |
| 76 | 76 | } |
| 77 | 77 | Text("Spacecraft positions: NASA/JPL Horizons. Pioneer 10 and 11 positions after contact was lost are predictions.") |
| 78 | .font(.system(size: 10)).opacity(0.5).padding(.vertical, 16) | |
| 78 | .font(.caption2).opacity(0.5).padding(.vertical, 16) | |
| 79 | 79 | } |
| 80 | 80 | .padding(.horizontal, 20) |
| 81 | 81 | } |
| @@ -102,7 +102,7 @@ struct SystemScreen: View { | ||
| 102 | 102 | |
| 103 | 103 | private func section(_ title: String, @ViewBuilder content: () -> some View) -> some View { |
| 104 | 104 | VStack(alignment: .leading, spacing: 10) { |
| 105 | Text(title).font(.system(size: 11, weight: .medium)).textCase(.uppercase).tracking(0.8).opacity(0.6) | |
| 105 | Text(title).font(.caption2.weight(.medium)).textCase(.uppercase).tracking(0.8).opacity(0.6) | |
| 106 | 106 | content() |
| 107 | 107 | } |
| 108 | 108 | .padding(.top, 24) |
App/Sources/TodaySheet.swift +8 −8
| @@ -18,7 +18,7 @@ struct TodaySheet: View { | ||
| 18 | 18 | } |
| 19 | 19 | section("Space weather") { weather } |
| 20 | 20 | Text("Space weather data: NOAA Space Weather Prediction Center.") |
| 21 | .font(.system(size: 11)).opacity(0.5).padding(.top, 8) | |
| 21 | .font(.caption2).opacity(0.5).padding(.top, 8) | |
| 22 | 22 | } |
| 23 | 23 | .padding(.horizontal, 20) |
| 24 | 24 | .padding(.top, 18) |
| @@ -29,7 +29,7 @@ struct TodaySheet: View { | ||
| 29 | 29 | |
| 30 | 30 | private func section(_ title: String, @ViewBuilder content: () -> some View) -> some View { |
| 31 | 31 | VStack(alignment: .leading, spacing: 8) { |
| 32 | Text(title).font(.system(size: 11, weight: .medium)).textCase(.uppercase).tracking(0.8).opacity(0.6) | |
| 32 | Text(title).font(.caption2.weight(.medium)).textCase(.uppercase).tracking(0.8).opacity(0.6) | |
| 33 | 33 | content() |
| 34 | 34 | } |
| 35 | 35 | .frame(maxWidth: .infinity, alignment: .leading) |
| @@ -86,7 +86,7 @@ struct TodaySheet: View { | ||
| 86 | 86 | ("Updated", time(w.observedAt)), |
| 87 | 87 | ]) |
| 88 | 88 | } else { |
| 89 | Text("Loading").font(.system(size: 13)).opacity(0.6) | |
| 89 | Text("Loading").font(.footnote).opacity(0.6) | |
| 90 | 90 | } |
| 91 | 91 | } |
| 92 | 92 | |
| @@ -97,7 +97,7 @@ struct TodaySheet: View { | ||
| 97 | 97 | Text(item.0).opacity(0.7) |
| 98 | 98 | Text(item.1).monospacedDigit() |
| 99 | 99 | } |
| 100 | .font(.system(size: 14)) | |
| 100 | .font(.subheadline) | |
| 101 | 101 | } |
| 102 | 102 | } |
| 103 | 103 | } |
| @@ -121,9 +121,9 @@ struct TodayBar: View { | ||
| 121 | 121 | scrubber |
| 122 | 122 | Button(action: onExpand) { |
| 123 | 123 | HStack { |
| 124 | Text(summary).font(.system(size: 13)).opacity(0.75).lineLimit(1) | |
| 124 | Text(summary).font(.footnote).opacity(0.75).lineLimit(2) | |
| 125 | 125 | Spacer() |
| 126 | Image(systemName: "chevron.up").font(.system(size: 12, weight: .medium)).opacity(0.6) | |
| 126 | Image(systemName: "chevron.up").font(.caption.weight(.medium)).opacity(0.6) | |
| 127 | 127 | } |
| 128 | 128 | } |
| 129 | 129 | .buttonStyle(.plain) |
| @@ -154,11 +154,11 @@ struct TodayBar: View { | ||
| 154 | 154 | private var scrubber: some View { |
| 155 | 155 | HStack(spacing: 12) { |
| 156 | 156 | Text(model.displayedDate.formatted(date: .omitted, time: .shortened)) |
| 157 | .font(.system(size: 13).monospacedDigit()) | |
| 157 | .font(.footnote.monospacedDigit()) | |
| 158 | 158 | .frame(width: 70, alignment: .leading) |
| 159 | 159 | Slider(value: $model.offsetHours, in: -12...12, step: 0.25).tint(ink) |
| 160 | 160 | Button("Now") { model.offsetHours = 0 } |
| 161 | .font(.system(size: 13, weight: .medium)) | |
| 161 | .font(.footnote.weight(.medium)) | |
| 162 | 162 | .opacity(model.offsetHours == 0 ? 0.4 : 1) |
| 163 | 163 | } |
| 164 | 164 | } |