Commit f4fb00c6 by Dmitriy Stepanets

Added snapshotter to radar widget

parent 4c0f7351
......@@ -156,6 +156,7 @@
CD8E041225F8F775001785B6 /* ForecastViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8E041125F8F775001785B6 /* ForecastViewModel.swift */; };
CD8E041625F8F91B001785B6 /* ForecastCellFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8E041525F8F91B001785B6 /* ForecastCellFactory.swift */; };
CD9B6B1425DBCDE2001D9B80 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD9B6B1325DBCDE2001D9B80 /* GraphView.swift */; };
CD9E563026B14CA7001186AD /* SnapshotLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD9E562F26B14CA7001186AD /* SnapshotLoader.swift */; };
CDA02A1926A6F92F00A8F2F6 /* WeatherLocationMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA02A1826A6F92F00A8F2F6 /* WeatherLocationMock.swift */; };
CDA02A1D26A7021D00A8F2F6 /* SF-Pro-Display-Thin.otf in Resources */ = {isa = PBXBuildFile; fileRef = CDA02A1C26A7021D00A8F2F6 /* SF-Pro-Display-Thin.otf */; };
CDA02A1E26A7021D00A8F2F6 /* SF-Pro-Display-Thin.otf in Resources */ = {isa = PBXBuildFile; fileRef = CDA02A1C26A7021D00A8F2F6 /* SF-Pro-Display-Thin.otf */; };
......@@ -470,6 +471,7 @@
CD8E041125F8F775001785B6 /* ForecastViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastViewModel.swift; sourceTree = "<group>"; };
CD8E041525F8F91B001785B6 /* ForecastCellFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastCellFactory.swift; sourceTree = "<group>"; };
CD9B6B1325DBCDE2001D9B80 /* GraphView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = "<group>"; };
CD9E562F26B14CA7001186AD /* SnapshotLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotLoader.swift; sourceTree = "<group>"; };
CDA02A1826A6F92F00A8F2F6 /* WeatherLocationMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeatherLocationMock.swift; sourceTree = "<group>"; };
CDA02A1C26A7021D00A8F2F6 /* SF-Pro-Display-Thin.otf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "SF-Pro-Display-Thin.otf"; path = "OneWeatherUI/OneWeatherUI/Fonts/SF-Pro-Display-Thin.otf"; sourceTree = SOURCE_ROOT; };
CDA5542725EF734200A2E08C /* TodayCellFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayCellFactory.swift; sourceTree = "<group>"; };
......@@ -826,6 +828,7 @@
CD5293DB2669099B009547C8 /* UI */ = {
isa = PBXGroup;
children = (
CD9E562F26B14CA7001186AD /* SnapshotLoader.swift */,
CD5293D7266908DB009547C8 /* WidgetPlaceholderView.swift */,
);
path = UI;
......@@ -1964,6 +1967,7 @@
CD5293D8266908DB009547C8 /* WidgetPlaceholderView.swift in Sources */,
CD5293EA266A564E009547C8 /* ThemeProtocol.swift in Sources */,
CD1B71402660F95000916E71 /* TemperatureWidget.swift in Sources */,
CD9E563026B14CA7001186AD /* SnapshotLoader.swift in Sources */,
CD5293E8266A561F009547C8 /* DefaultTheme.swift in Sources */,
CD5293E7266A560C009547C8 /* ThemeManager.swift in Sources */,
CE5F0CBC268A031800B99572 /* OneWeatherWidgetsBundle.swift in Sources */,
......
......@@ -40,8 +40,6 @@
CDC3F85A26946D0700AAE3BF /* HourlyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC3F85926946D0700AAE3BF /* HourlyView.swift */; };
CDC3F85C269471C900AAE3BF /* SF-Pro-Display-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = CDC3F85B269471C900AAE3BF /* SF-Pro-Display-Bold.otf */; };
CDC694D426AFFC0800C57B01 /* LargeRadarWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC694D326AFFC0800C57B01 /* LargeRadarWidgetView.swift */; };
CDC694D626B002B900C57B01 /* MapShapshotView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC694D526B002B900C57B01 /* MapShapshotView.swift */; };
CDC694D826B0062000C57B01 /* SnapshotLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC694D726B0062000C57B01 /* SnapshotLoader.swift */; };
CDF969A126A848580099C3C4 /* LargeWindWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF969A026A848580099C3C4 /* LargeWindWidgetView.swift */; };
/* End PBXBuildFile section */
......@@ -97,8 +95,6 @@
CDC3F85926946D0700AAE3BF /* HourlyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HourlyView.swift; sourceTree = "<group>"; };
CDC3F85B269471C900AAE3BF /* SF-Pro-Display-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-Pro-Display-Bold.otf"; sourceTree = "<group>"; };
CDC694D326AFFC0800C57B01 /* LargeRadarWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LargeRadarWidgetView.swift; sourceTree = "<group>"; };
CDC694D526B002B900C57B01 /* MapShapshotView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapShapshotView.swift; sourceTree = "<group>"; };
CDC694D726B0062000C57B01 /* SnapshotLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotLoader.swift; sourceTree = "<group>"; };
CDC694D926B022B600C57B01 /* Combine.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Combine.framework; path = System/Library/Frameworks/Combine.framework; sourceTree = SDKROOT; };
CDF969A026A848580099C3C4 /* LargeWindWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LargeWindWidgetView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
......@@ -280,8 +276,6 @@
isa = PBXGroup;
children = (
CDC694D326AFFC0800C57B01 /* LargeRadarWidgetView.swift */,
CDC694D526B002B900C57B01 /* MapShapshotView.swift */,
CDC694D726B0062000C57B01 /* SnapshotLoader.swift */,
);
path = Radar;
sourceTree = "<group>";
......@@ -423,7 +417,6 @@
CD7D3164268EEF56000D01FA /* SmallTemperatureWidgetView.swift in Sources */,
CD1BF3B4269829CC00F60E2E /* EdgeInsets+Zero.swift in Sources */,
CD55516126A8195B00C0796C /* MediumWindWidgetView.swift in Sources */,
CDC694D826B0062000C57B01 /* SnapshotLoader.swift in Sources */,
CD3C83C326933ABD0087A225 /* MediumTemperatureWidgetView.swift in Sources */,
CDC694D426AFFC0800C57B01 /* LargeRadarWidgetView.swift in Sources */,
CD7D3168268EF167000D01FA /* UIFont+Font.swift in Sources */,
......@@ -439,7 +432,6 @@
CD7D3176268EF8A9000D01FA /* WidgetFont.swift in Sources */,
CDF969A126A848580099C3C4 /* LargeWindWidgetView.swift in Sources */,
CD7D3169268EF167000D01FA /* UIColor+Color.swift in Sources */,
CDC694D626B002B900C57B01 /* MapShapshotView.swift in Sources */,
CD2E07BD269C54B5001CBF40 /* WidgetColor.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
......
......@@ -31,16 +31,13 @@ public struct LargeRadarWidgetView: View {
}
.padding([.leading, .trailing], 10)
MapSnapshotView(widgetViewModel: WidgetViewModelMock(),
size: .init(width: 340, height: 280),
image: {
Image(uiImage: $0)
if let image = widgetViewModel.radarImage {
Image(uiImage: image)
.resizable()
}
)
.cornerRadius(12)
.padding(.top, 7)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(WidgetColor.Name("PrimaryBackground"))
}
......
//
// SnapshotView.swift
// Test
//
// Created by Dmitry Stepanets on 27.07.2021.
//
import SwiftUI
import MapKit
@available(iOS 14, *)
struct MapSnapshotView: View {
//Private
@Environment(\.colorScheme) private var colorScheme
@StateObject private var loader: SnapshotLoader
private let image: (UIImage) -> Image
//Public
let widgetViewModel: WidgetViewModel
init(widgetViewModel: WidgetViewModel,
size: CGSize,
@ViewBuilder image: @escaping (UIImage) -> Image = Image.init(uiImage:)
) {
self.widgetViewModel = widgetViewModel
self.image = image
let snapshotLoader = SnapshotLoader(coordinates: widgetViewModel.coordinates, size: size)
_loader = StateObject(wrappedValue: snapshotLoader)
}
var body: some View {
content
.onAppear(perform: loader.load)
}
private var content: some View {
Group {
if loader.image != nil {
image(loader.image!)
} else {
Spacer()
}
}
}
}
......@@ -65,4 +65,5 @@ public protocol WidgetViewModel {
var smartText: String { get }
var hourlyWeather: [WidgetHourlyWeather] { get }
var dailyWather: [WidgetDailyWeather] { get }
var radarImage: UIImage? { get }
}
......@@ -57,6 +57,7 @@ struct WidgetViewModelMock: WidgetViewModel {
let lowTemperature = "89°"
let isDeviceLocation = true
let smartText = "Feels like 101° due to high humidity (77%)."
let radarImage: UIImage? = nil
let hourlyWeather: [WidgetHourlyWeather] = {
var array = [WidgetHourlyWeather]()
......
......@@ -8,13 +8,16 @@
import Foundation
import WidgetKit
import OneWeatherCore
import UIKit
struct WeatherEntry: TimelineEntry {
let date: Date
let location: Location
let radarMapImage: UIImage?
init(location:Location? = nil, date:Date = Date()) {
init(location:Location? = nil, date:Date = Date(), radarMapImage: UIImage? = nil) {
self.location = location ?? WeatherLocationMock().location
self.date = date
self.radarMapImage = radarMapImage
}
}
......@@ -69,6 +69,18 @@ class WeatherProvider: TimelineProvider {
return
}
if let coordinates = fetchedLocation.coordinates {
SnapshotLoader.load(at: coordinates,
size: .init(width: 340, height: 280)
) { mapImage in
let nextRefresh = Calendar.current.date(byAdding: .minute, value: 30, to: Date())!
let entry = WeatherEntry(location: fetchedLocation, date: nextRefresh, radarMapImage: mapImage)
let timeline = Timeline(entries: [entry], policy: .atEnd)
WidgetManager.shared.logUpdate()
completion(timeline)
}
}
else {
let nextRefresh = Calendar.current.date(byAdding: .minute, value: 30, to: Date())!
let entry = WeatherEntry(location: fetchedLocation, date: nextRefresh)
let timeline = Timeline(entries: [entry], policy: .atEnd)
......@@ -76,4 +88,5 @@ class WeatherProvider: TimelineProvider {
completion(timeline)
}
}
}
}
......@@ -10,31 +10,17 @@ import MapKit
@available(iOS 14, *)
class SnapshotLoader: ObservableObject {
//Public
@Published private(set) var image: UIImage?
let coordinates: CLLocationCoordinate2D
let size: CGSize
//Private
private let snapshotter: MKMapSnapshotter
init(coordinates: CLLocationCoordinate2D, size: CGSize) {
self.coordinates = coordinates
self.size = size
static func load(at coordinates: CLLocationCoordinate2D, size: CGSize, completion:@escaping (_ snapshot:UIImage?) -> Void) {
let options = MKMapSnapshotter.Options()
options.mapType = .standard
options.showsBuildings = true
options.region = MKCoordinateRegion(center: coordinates,
latitudinalMeters: 10000,
longitudinalMeters: 10000)
options.size = size
self.snapshotter = MKMapSnapshotter(options: options)
}
func load() {
options.region = MKCoordinateRegion(center: coordinates,
latitudinalMeters: 30000,
longitudinalMeters: 30000)
let snapshotter = MKMapSnapshotter(options: options)
snapshotter.start { snapshot, error in
self.image = snapshot?.image
completion(snapshot?.image)
}
}
}
......@@ -52,8 +52,9 @@ struct ForecastWidgetViewModel: WidgetViewModel {
let smartText: String
let hourlyWeather: [WidgetHourlyWeather]
let dailyWather: [WidgetDailyWeather]
let radarImage: UIImage?
init(location: Location) {
init(location: Location, radarImage: UIImage? = nil) {
func convertToWidgetHourly(modelHourly: [HourlyWeather]) -> [WidgetHourlyWeather] {
var array = [WidgetHourlyWeather]()
......@@ -100,6 +101,7 @@ struct ForecastWidgetViewModel: WidgetViewModel {
self.highTemperature = location.today?.maxTemp?.shortString ?? "--"
self.lowTemperature = location.today?.minTemp?.shortString ?? "--"
self.isDeviceLocation = location.deviceLocation
self.radarImage = radarImage
if let lastTimeUpdated = location.lastWeatherUpdateDate {
let oneHour = TimeInterval(3600)
......
......@@ -19,7 +19,8 @@ struct RadarWidget: Widget {
StaticConfiguration(kind: kind,
provider: WeatherProvider()
) { weatherEntry in
LargeRadarWidgetView(widgetViewModel: ForecastWidgetViewModel(location: weatherEntry.location))
LargeRadarWidgetView(widgetViewModel: ForecastWidgetViewModel(location: weatherEntry.location,
radarImage: weatherEntry.radarMapImage))
.widgetURL(URL(string: "ow-widget://radar-large"))
}
.configurationDisplayName("widget.radar.title".localized())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment