Browse Source

way better

batman
boB Rudis 3 years ago
parent
commit
31c9eb7031
No known key found for this signature in database GPG Key ID: 1D7529BE14E2BBA9
  1. 23
      f5-weather/ContentView.swift
  2. 48
      f5-weather/f5wxApp.swift
  3. 2
      f5-weather/globals.swift
  4. 19
      f5-weather/model.swift
  5. 22
      f5-weather/utils.swift

23
f5-weather/ContentView.swift

@ -84,7 +84,7 @@ struct DayView: View {
}
// MARK: The main view/window
// dynamically resize window based on the number of forecast day lines we have
struct ContentView: View {
@EnvironmentObject var model: AppModel // set in f5wxApp.swift
@ -93,12 +93,17 @@ struct ContentView: View {
GeometryReader { g in // greedy view in the event we want to do more complex things
VStack {
List { // list view for each day forecast
ForEach(model.forecast) {
(day) in DayView(dayCast: day, minTemp: model.minTemp, maxTemp: model.maxTemp)
}
ForEach(model.forecast) {
(day) in DayView(dayCast: day, minTemp: model.minTemp, maxTemp: model.maxTemp)
.frame(
minWidth: 0,
maxWidth: .infinity,
minHeight: 0,
maxHeight: .infinity,
alignment: .topLeading
)
}
}
}.padding()
}
.onReceive(NotificationCenter.default.publisher(for: NSApplication.willBecomeActiveNotification)) { _ in
model.getForecast()
@ -107,9 +112,9 @@ struct ContentView: View {
minWidth: VIEW_WIDTH,
idealWidth: VIEW_WIDTH,
maxWidth: VIEW_WIDTH,
minHeight: VIEW_MIN_HEIGHT,
idealHeight: CGFloat((model.forecast.count > 0 ? model.forecast.count : MIN_ROWS) * (ROW_HEIGHT + INSETS) + 2*INSETS), // dynamically resize window based on the number of forecast day lines we have
maxHeight: CGFloat(MAX_ROWS * (ROW_HEIGHT + INSETS) + 2*INSETS)
minHeight: model.height(),
idealHeight: model.height(),
maxHeight: model.height()
)
.alert(
isPresented: $model.showAlert,

48
f5-weather/f5wxApp.swift

@ -2,6 +2,39 @@ import SwiftUI
var model = AppModel() // initialize the app model
// MARK: Settings are a WIP
struct GeneralSettingsView: View {
@AppStorage("maxUpdateFrequency") private var maxUpdateFrequency = 360.0
var body: some View {
Form {
Slider(value: $maxUpdateFrequency, in: 360...2160, step:60) {
Text("Update Frequency\n(\(maxUpdateFrequency, specifier: "%f.") seconds)")
}
}
.padding(20)
.frame(width: 350, height: 100)
}
}
struct SettingsView: View {
private enum Tabs: Hashable {
case general, advanced
}
var body: some View {
TabView {
GeneralSettingsView()
.tabItem {
Label("General", systemImage: "gear")
}
.tag(Tabs.general)
}
.padding(20)
.frame(width: 375, height: 150)
}
}
@main
struct f5wxApp: App {
@ -15,19 +48,26 @@ struct f5wxApp: App {
.navigationTitle("F5 Weather • ECMWF • Berwick, Maine") // set a title for the app
.environmentObject(model) // place our initialized app model into the Environment
.fixedSize() // set window to fixed size so we can programmatically resize it
}.commands {
}
.windowStyle(TitleBarWindowStyle())
.commands {
CommandMenu("Tools") { // add a "Tools" menu
MenuItem(action: { // Add a menu item and shortcut that will grab new forecast data
model.getForecast()
model.getForecast(force: true)
}) {
Text("Refresh")
}.keyboardShortcut("r", modifiers: .command)
}
}
#if os(macOS)
Settings {
SettingsView()
}
#endif
}
}

2
f5-weather/globals.swift

@ -18,6 +18,8 @@ let MIN_ROWS: Int = 10
let MAX_ROWS: Int = 20
let INSETS: Int = 4 + 4 // top + bottom of each view
let ROW_HEIGHT_WITH_INSETS: Int = ROW_HEIGHT + INSETS
// width of a char (not great to hardcode this)
let CHAR_WIDTH: CGFloat = 12

19
f5-weather/model.swift

@ -25,11 +25,28 @@ class AppModel: ObservableObject {
@Published var showAlert: Bool = false // in case there are errors
@Published var alertMessage: String = ""
var lastGrab : Date?
init() {
getForecast() // get the forecast right away
}
func getForecast() {
func height() -> CGFloat {
let nRows = forecast.count > 0 ? forecast.count : MIN_ROWS
return(CGFloat(Double((nRows * ROW_HEIGHT_WITH_INSETS)) + (2*Double(INSETS))))
}
func getForecast(force: Bool = false) {
if (!force) {
if let g = lastGrab {
if (g.timeIntervalSinceNow < 60*60) { return }
} else {
lastGrab = Date()
minTemp = Double.infinity
maxTemp = -Double.infinity
}
}
if let urlBaseString = Bundle.main.object(forInfoDictionaryKey: "ForecastURL") as? String {

22
f5-weather/utils.swift

@ -9,7 +9,7 @@ import Foundation
import SwiftUI
extension Double {
func rescale(from domain: ClosedRange<Self>, to range: ClosedRange<Self>) -> Self {
func rescale(from domain: ClosedRange<Self>, to range: ClosedRange<Self>) -> Self {
let x = (range.upperBound - range.lowerBound) * (self - domain.lowerBound)
let y = (domain.upperBound - domain.lowerBound)
return x / y + range.lowerBound
@ -33,14 +33,14 @@ extension BinaryInteger {
}
public extension Color {
#if os(macOS)
static let background = Color(NSColor.windowBackgroundColor)
static let secondaryBackground = Color(NSColor.underPageBackgroundColor)
static let tertiaryBackground = Color(NSColor.controlBackgroundColor)
#else
static let background = Color(UIColor.systemBackground)
static let secondaryBackground = Color(UIColor.secondarySystemBackground)
static let tertiaryBackground = Color(UIColor.tertiarySystemBackground)
#endif
#if os(macOS)
static let background = Color(NSColor.windowBackgroundColor)
static let secondaryBackground = Color(NSColor.underPageBackgroundColor)
static let tertiaryBackground = Color(NSColor.controlBackgroundColor)
#else
static let background = Color(UIColor.systemBackground)
static let secondaryBackground = Color(UIColor.secondarySystemBackground)
static let tertiaryBackground = Color(UIColor.tertiarySystemBackground)
#endif
}

Loading…
Cancel
Save