Commit 84bc8c41 by Dmitriy Stepanets

- Finished Large widget UI

- Added large widget to promotion controller
- Worling on swipe to dismiss
parent 4bf80efc
......@@ -118,6 +118,7 @@
CD7D3185268F1438000D01FA /* OneWeatherUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CD7D3183268F1438000D01FA /* OneWeatherUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
CD7D3189268F33CC000D01FA /* WidgetPromotionCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7D3188268F33CC000D01FA /* WidgetPromotionCoordinator.swift */; };
CD7D318B268F36AF000D01FA /* UIApplication+Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7D318A268F36AF000D01FA /* UIApplication+Version.swift */; };
CD7EB378269C60680088999D /* PromotionLargeWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7EB377269C60680088999D /* PromotionLargeWidgetView.swift */; };
CD7F3ABD262443260041C478 /* MapPinnedLayersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7F3ABC262443260041C478 /* MapPinnedLayersView.swift */; };
CD822FF525D6817000A05501 /* TodayForecastCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD822FF425D6817000A05501 /* TodayForecastCell.swift */; };
CD822FFA25D6890900A05501 /* OneWeatherColorsAsset.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CD822FF925D6890900A05501 /* OneWeatherColorsAsset.xcassets */; };
......@@ -423,6 +424,7 @@
CD7D3183268F1438000D01FA /* OneWeatherUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OneWeatherUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
CD7D3188268F33CC000D01FA /* WidgetPromotionCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetPromotionCoordinator.swift; sourceTree = "<group>"; };
CD7D318A268F36AF000D01FA /* UIApplication+Version.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplication+Version.swift"; sourceTree = "<group>"; };
CD7EB377269C60680088999D /* PromotionLargeWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromotionLargeWidgetView.swift; sourceTree = "<group>"; };
CD7F3ABC262443260041C478 /* MapPinnedLayersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapPinnedLayersView.swift; sourceTree = "<group>"; };
CD822FF425D6817000A05501 /* TodayForecastCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayForecastCell.swift; sourceTree = "<group>"; };
CD822FF925D6890900A05501 /* OneWeatherColorsAsset.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = OneWeatherColorsAsset.xcassets; sourceTree = "<group>"; };
......@@ -1002,6 +1004,7 @@
CD857EA4268B36EA00B5E069 /* PromotionHeaderView.swift */,
CD857EA6268B45DD00B5E069 /* PromotionSmallWidgetView.swift */,
CDC3F857269460E600AAE3BF /* PromotionMediumWidgetView.swift */,
CD7EB377269C60680088999D /* PromotionLargeWidgetView.swift */,
);
path = Views;
sourceTree = "<group>";
......@@ -1858,6 +1861,7 @@
CD251ED82603633800ED7A65 /* ForecastPrecipitationCell.swift in Sources */,
CE13B816262480B3007CBD4D /* NativeAdLoader.swift in Sources */,
CDF9BF8E26133D050037847D /* LocationSearchCoordinator.swift in Sources */,
CD7EB378269C60680088999D /* PromotionLargeWidgetView.swift in Sources */,
CD50555F26983C14006776AB /* CubicCurveAlgorithm.swift in Sources */,
CDC3F858269460E600AAE3BF /* PromotionMediumWidgetView.swift in Sources */,
CD7D318B268F36AF000D01FA /* UIApplication+Version.swift in Sources */,
......@@ -2087,7 +2091,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = 1Weather/1Weather.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 8;
CURRENT_PROJECT_VERSION = 9;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 24W4XMQ38L;
ENABLE_BITCODE = NO;
......@@ -2118,7 +2122,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = 1Weather/1Weather.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 8;
CURRENT_PROJECT_VERSION = 9;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 24W4XMQ38L;
ENABLE_BITCODE = NO;
......@@ -2192,7 +2196,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = OneWeatherNotificationServiceExtension/OneWeatherNotificationServiceExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 8;
CURRENT_PROJECT_VERSION = 9;
DEVELOPMENT_TEAM = 24W4XMQ38L;
INFOPLIST_FILE = OneWeatherNotificationServiceExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.4;
......@@ -2216,7 +2220,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = OneWeatherNotificationServiceExtension/OneWeatherNotificationServiceExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 8;
CURRENT_PROJECT_VERSION = 9;
DEVELOPMENT_TEAM = 24W4XMQ38L;
INFOPLIST_FILE = OneWeatherNotificationServiceExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.4;
......
......@@ -31,7 +31,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>8</string>
<string>9</string>
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-7118865896152167~5937109115</string>
<key>GADNativeAdValidatorEnabled</key>
......
......@@ -73,6 +73,14 @@ class TodayViewController: UIViewController {
}
@objc private func handleNotificationButton() {
#if DEBUG
if #available(iOS 14, *) {
self.present(WidgetPromotionController(coordinator: .init(parentViewController: self)), animated: true)
}
#else
fatalError("This code could't be run in production")
#endif
self.coordinator.openNotificationsScreen()
}
}
......
//
// PromotionLargeWidgetView.swift
// 1Weather
//
// Created by Dmitry Stepanets on 12.07.2021.
//
import UIKit
import SwiftUI
import OneWeatherUI
@available(iOS 14, *)
class PromotionLargeWidgetView: UIView {
//Private
private let widgetController = UIHostingController(rootView: LargeTemperatureWidgetView(widgetViewModel: nil))
override init(frame: CGRect) {
super.init(frame: frame)
prepareWidgetView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//MARK:- Prepare
@available(iOS 14, *)
private extension PromotionLargeWidgetView {
func prepareWidgetView() {
let container = UIView()
container.addSubview(widgetController.view)
container.clipsToBounds = true
container.layer.cornerRadius = 20
addSubview(container)
widgetController.view.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
container.snp.makeConstraints { make in
make.height.greaterThanOrEqualTo(354)
make.left.right.equalToSuperview().inset(18)
make.top.equalToSuperview().inset(20)
make.bottom.equalToSuperview()
}
}
}
......@@ -28,10 +28,17 @@ class PromotionMediumWidgetView: UIView {
@available(iOS 14, *)
private extension PromotionMediumWidgetView {
func prepareWidgetView() {
widgetController.view.layer.cornerRadius = 20
addSubview(widgetController.view)
let container = UIView()
container.addSubview(widgetController.view)
container.clipsToBounds = true
container.layer.cornerRadius = 20
addSubview(container)
widgetController.view.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
container.snp.makeConstraints { make in
make.height.equalTo(164)
make.left.right.equalToSuperview().inset(18)
make.top.equalToSuperview().inset(20)
......
......@@ -59,10 +59,17 @@ class PromotionSmallWidgetView: UIView {
@available(iOS 14, *)
private extension PromotionSmallWidgetView {
func prepareWidget() {
widgetViewController.view.layer.cornerRadius = 20
addSubview(widgetViewController.view)
let container = UIView()
container.addSubview(widgetViewController.view)
container.clipsToBounds = true
container.layer.cornerRadius = 20
addSubview(container)
widgetViewController.view.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
container.snp.makeConstraints { make in
make.width.height.equalTo(158)
make.left.equalToSuperview().inset(18)
make.top.equalToSuperview().inset(16)
......
......@@ -22,6 +22,7 @@ class WidgetPromotionController: UIViewController {
private var initialTouchPoint = CGPoint(x: 0,y: 0)
private lazy var panGesture: UIPanGestureRecognizer = {
let gesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(sender:)))
gesture.delegate = self
return gesture
}()
......@@ -33,7 +34,9 @@ class WidgetPromotionController: UIViewController {
let footerHeight = footerView.frame.height
let safeAreaInset = UIApplication.shared.keyWindow?.safeAreaInsets.bottom ?? 0
return pan + kScrollViewTopInset + stackHeight + scrollViewBottomInset + footerHeight + safeAreaInset
let contentHeight = pan + kScrollViewTopInset + stackHeight + scrollViewBottomInset + footerHeight + safeAreaInset
let height = min(contentHeight, UIScreen.main.bounds.height * 0.85)
return height
}
init(coordinator: WidgetPromotionCoordinator) {
......@@ -82,7 +85,7 @@ class WidgetPromotionController: UIViewController {
@objc private func handlePanGesture(sender: UIPanGestureRecognizer) {
let touchPoint = sender.location(in: self.view?.window)
let originalOffsetY = UIScreen.main.bounds.height - self.view.bounds.height
switch sender.state {
case .began:
initialTouchPoint = touchPoint
......@@ -121,7 +124,7 @@ class WidgetPromotionController: UIViewController {
@available(iOS 14, *)
private extension WidgetPromotionController {
func prepareView() {
view.addGestureRecognizer(panGesture)
// view.addGestureRecognizer(panGesture)
view.clipsToBounds = true
view.layer.cornerRadius = 24
......@@ -161,7 +164,8 @@ private extension WidgetPromotionController {
}
func prepareScrollView() {
view.addSubview(scrollView)
scrollView.delegate = self
view.addSubview(scrollView)s
scrollView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalToSuperview().inset(kScrollViewTopInset)
......@@ -175,7 +179,8 @@ private extension WidgetPromotionController {
stackView.spacing = 0
stackView.addArrangedSubview(PromotionHeaderView())
stackView.addArrangedSubview(PromotionSmallWidgetView())
// stackView.addArrangedSubview(PromotionMediumWidgetView())
stackView.addArrangedSubview(PromotionMediumWidgetView())
stackView.addArrangedSubview(PromotionLargeWidgetView())
scrollView.addSubview(stackView)
stackView.snp.makeConstraints { make in
......@@ -226,3 +231,44 @@ extension WidgetPromotionController: UIViewControllerTransitioningDelegate {
return nil
}
}
//MARK:- UIScrollView Delegate
@available(iOS 14, *)
extension WidgetPromotionController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// if scrollView.contentOffset.y < 0 {
// let originalOffsetY = UIScreen.main.bounds.height - self.view.bounds.height
// view.frame.origin.y = originalOffsetY - (scrollView.contentOffset.y - initialTouchPoint.y)
// return
// }
}
}
//MARK:- UIGesture Delegate
@available(iOS 14, *)
extension WidgetPromotionController: UIGestureRecognizerDelegate {
// func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
// if scrollView.contentOffset.y > 0 {
// return false
// }
//
// scrollView.contentOffset.y = 0
// return true
// }
// func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
// shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
// // Do not begin the pan until the swipe fails.
// if otherGestureRecognizer != self.panGesture {
// print("ScrollView Offset \(scrollView.contentOffset.y)")
// if scrollView.contentOffset.y >= 0 {
// return false
// }
//
// return true
// }
//
// return false
// }
}
......@@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>8</string>
<string>9</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
......
......@@ -13,6 +13,9 @@
CD259C02268DE109008D205E /* OneWeatherUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD259BF8268DE109008D205E /* OneWeatherUI.framework */; };
CD259C07268DE109008D205E /* OneWeatherUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD259C06268DE109008D205E /* OneWeatherUITests.swift */; };
CD259C09268DE109008D205E /* OneWeatherUI.h in Headers */ = {isa = PBXBuildFile; fileRef = CD259BFB268DE109008D205E /* OneWeatherUI.h */; settings = {ATTRIBUTES = (Public, ); }; };
CD2E07BD269C54B5001CBF40 /* WidgetColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD2E07BC269C54B5001CBF40 /* WidgetColor.swift */; };
CD2E07BF269C5834001CBF40 /* SF-Pro-Display-Thin.otf in Resources */ = {isa = PBXBuildFile; fileRef = CD2E07BE269C5834001CBF40 /* SF-Pro-Display-Thin.otf */; };
CD2E07C1269C5ABF001CBF40 /* HourlyTemperatureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD2E07C0269C5ABF001CBF40 /* HourlyTemperatureView.swift */; };
CD3C83C326933ABD0087A225 /* MediumTemperatureWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD3C83C226933ABC0087A225 /* MediumTemperatureWidgetView.swift */; };
CD50556126983C2F006776AB /* CubicCurveAlgorithm.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD50556026983C2E006776AB /* CubicCurveAlgorithm.swift */; };
CD7D3161268EEF49000D01FA /* CityNameView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7D315F268EEF48000D01FA /* CityNameView.swift */; };
......@@ -59,6 +62,9 @@
CD259C01268DE109008D205E /* OneWeatherUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OneWeatherUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
CD259C06268DE109008D205E /* OneWeatherUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OneWeatherUITests.swift; sourceTree = "<group>"; };
CD259C08268DE109008D205E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
CD2E07BC269C54B5001CBF40 /* WidgetColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetColor.swift; sourceTree = "<group>"; };
CD2E07BE269C5834001CBF40 /* SF-Pro-Display-Thin.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-Pro-Display-Thin.otf"; sourceTree = "<group>"; };
CD2E07C0269C5ABF001CBF40 /* HourlyTemperatureView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HourlyTemperatureView.swift; sourceTree = "<group>"; };
CD3C83C226933ABC0087A225 /* MediumTemperatureWidgetView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediumTemperatureWidgetView.swift; sourceTree = "<group>"; };
CD50556026983C2E006776AB /* CubicCurveAlgorithm.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CubicCurveAlgorithm.swift; sourceTree = "<group>"; };
CD6F063D269854A7002A99C2 /* BezierKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = BezierKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
......@@ -188,6 +194,7 @@
CD7D315F268EEF48000D01FA /* CityNameView.swift */,
CDC3F85926946D0700AAE3BF /* HourlyView.swift */,
CD1BF3AE26981B5300F60E2E /* TemperatureGraphView.swift */,
CD2E07C0269C5ABF001CBF40 /* HourlyTemperatureView.swift */,
);
path = SharedViews;
sourceTree = "<group>";
......@@ -210,6 +217,7 @@
CD7D3171268EF81B000D01FA /* SF-Pro-Display-Regular.otf */,
CD7D3172268EF81C000D01FA /* SF-Pro-Display-Light.otf */,
CDC3F85B269471C900AAE3BF /* SF-Pro-Display-Bold.otf */,
CD2E07BE269C5834001CBF40 /* SF-Pro-Display-Thin.otf */,
);
path = Fonts;
sourceTree = "<group>";
......@@ -231,6 +239,7 @@
children = (
CD50556026983C2E006776AB /* CubicCurveAlgorithm.swift */,
CD7D3175268EF8A9000D01FA /* WidgetFont.swift */,
CD2E07BC269C54B5001CBF40 /* WidgetColor.swift */,
);
path = Helpers;
sourceTree = "<group>";
......@@ -332,6 +341,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CD2E07BF269C5834001CBF40 /* SF-Pro-Display-Thin.otf in Resources */,
CD7D3180268F04DD000D01FA /* Assets.xcassets in Resources */,
CD7D3174268EF81C000D01FA /* SF-Pro-Display-Light.otf in Resources */,
CDC3F85C269471C900AAE3BF /* SF-Pro-Display-Bold.otf in Resources */,
......@@ -355,6 +365,7 @@
files = (
CD1BF3AF26981B5300F60E2E /* TemperatureGraphView.swift in Sources */,
CD7D3162268EEF49000D01FA /* HighLowTemperatureView.swift in Sources */,
CD2E07C1269C5ABF001CBF40 /* HourlyTemperatureView.swift in Sources */,
CD7D3161268EEF49000D01FA /* CityNameView.swift in Sources */,
CD7D3164268EEF56000D01FA /* SmallTemperatureWidgetView.swift in Sources */,
CD1BF3B4269829CC00F60E2E /* EdgeInsets+Zero.swift in Sources */,
......@@ -371,6 +382,7 @@
CDC3F85A26946D0700AAE3BF /* HourlyView.swift in Sources */,
CD7D3176268EF8A9000D01FA /* WidgetFont.swift in Sources */,
CD7D3169268EF167000D01FA /* UIColor+Color.swift in Sources */,
CD2E07BD269C54B5001CBF40 /* WidgetColor.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
{
"object": {
"pins": [
{
"package": "BezierKit",
"repositoryURL": "https://github.com/hfutrell/BezierKit.git",
"state": {
"branch": null,
"revision": "385af8c3cbe17f64ce9b3b6d20d205d97df96af3",
"version": "0.11.0"
}
}
]
},
"version": 1
}
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1250"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "CD259BF7268DE109008D205E"
BuildableName = "OneWeatherUI.framework"
BlueprintName = "OneWeatherUI"
ReferencedContainer = "container:OneWeatherUI.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "CD259C00268DE109008D205E"
BuildableName = "OneWeatherUITests.xctest"
BlueprintName = "OneWeatherUITests"
ReferencedContainer = "container:OneWeatherUI.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "CD259BF7268DE109008D205E"
BuildableName = "OneWeatherUI.framework"
BlueprintName = "OneWeatherUI"
ReferencedContainer = "container:OneWeatherUI.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "151",
"green" : "151",
"red" : "151"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "151",
"green" : "151",
"red" : "151"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
......@@ -16,6 +16,7 @@ extension OneWeatherUI {
loadFontWith(name: "SF-Pro-Display-Regular", fileExtension: "otf")
loadFontWith(name: "SF-Pro-Display-Light", fileExtension: "otf")
loadFontWith(name: "SF-Pro-Display-Bold", fileExtension: "otf")
loadFontWith(name: "SF-Pro-Display-Thin", fileExtension: "otf")
}()
internal static func loadFontWith(name: String, fileExtension: String) {
......
//
// WidgetColor.swift
// OneWeatherUI
//
// Created by Dmitry Stepanets on 12.07.2021.
//
import SwiftUI
@available(iOS 14, *)
struct WidgetColor {
static func Name(_ nameString: String) -> Color {
return Color(nameString, bundle: OneWeatherUI.frameworkBundle)
}
}
......@@ -43,5 +43,8 @@ struct WidgetFont {
static func bold(size: CGFloat) -> UIFont {
font(weigth: .bold, size: size)
}
static func thin(size: CGFloat) -> UIFont {
font(weigth: .thin, size: size)
}
}
}
......@@ -13,12 +13,11 @@ public struct LargeTemperatureWidgetView: View {
let widgetViewModel: WidgetViewModel
public init(widgetViewModel: WidgetViewModel?) {
OneWeatherUI.loadFonts
self.widgetViewModel = widgetViewModel ?? WidgetViewModelMock()
}
//Private
private let temps = [25, 31, 22, 19]
@State private var hourlyStackFrame: CGRect = .zero
@Environment(\.colorScheme) private var colorScheme
public var body: some View {
......@@ -30,16 +29,14 @@ public struct LargeTemperatureWidgetView: View {
HStack(spacing: 8) {
Text(widgetViewModel.temperature)
.font(WidgetFont.SFProDisplay.light(size: 32).font)
.foregroundColor(Color("PrimaryTextColor",
bundle: OneWeatherUI.frameworkBundle))
.foregroundColor(WidgetColor.Name("PrimaryTextColor"))
Divider()
.padding(.top, 8)
.padding(.bottom, 8)
Text(widgetViewModel.weatherType)
.font(WidgetFont.SFProDisplay.regular(size: 12).font)
.foregroundColor(Color("PrimaryTextColor",
bundle: OneWeatherUI.frameworkBundle))
.foregroundColor(WidgetColor.Name("PrimaryTextColor"))
.lineLimit(2)
weatherImage(uiImage: widgetViewModel.weatherIcon)
......@@ -60,42 +57,15 @@ public struct LargeTemperatureWidgetView: View {
.padding(.top, 10)
.frame(height: 35)
GeometryReader { geo in
ZStack {
HStack(spacing: 10) {
ForEach(0 ..< temps.count) { index in
HourlyView(hourlyTemps: .init(currentTemp: temps[index],
temps: temps),
viewIndex: index)
.frame(maxWidth: 70)
}
}
.overlay(
GeometryReader { geoInner in
Color(.clear)
.onAppear {
hourlyStackFrame = geoInner.frame(in: .global)
}
}
)
if temps.count >= 2 {
TemperatureGraphView(temps: temps,
viewModel: .init(graphSize: .init(width: hourlyStackFrame.width,
height: 22),
hourlyItemWidth: 70,
spacingPerItem: 10,
graphInset: .zero))
}
}
.frame(width: geo.frame(in: .local).width)
.padding(.top, 14)
}
HourlyTemperatureView(temps: [25, 31, 22, 19])
HStack {
Text("Next few Days")
.font(WidgetFont.SFProDisplay.regular(size: 12).font)
VStack {
Divider()
.background(WidgetColor.Name("Divider"))
.padding(.top, 8)
}
}
.padding(.top, 17)
......@@ -104,14 +74,17 @@ public struct LargeTemperatureWidgetView: View {
ForEach(0..<4) { index in
HStack {
Text("6, Tuesday")
.font(WidgetFont.SFProDisplay.thin(size: 14).font)
Spacer()
weatherDayImage(uiImage: widgetViewModel.weatherIcon)
Spacer()
.frame(width: 52)
Text("75°")
.font(WidgetFont.SFProDisplay.thin(size: 14).font)
Spacer()
.frame(width: 52)
Text("81°")
.font(WidgetFont.SFProDisplay.thin(size: 14).font)
Spacer()
.frame(width: 28)
}
......@@ -120,8 +93,7 @@ public struct LargeTemperatureWidgetView: View {
.padding([.top, .bottom], 20)
}
.padding([.leading, .trailing], 10)
.background(Color("PrimaryBackground",
bundle: OneWeatherUI.frameworkBundle))
.background(WidgetColor.Name("PrimaryBackground"))
}
}
......@@ -151,6 +123,7 @@ private extension View {
public struct LargeTemperatureWidgetView_Preview: PreviewProvider {
public static var previews: some View {
LargeTemperatureWidgetView(widgetViewModel: WidgetViewModelMock())
.previewDevice("iPhone 11")
.preferredColorScheme(.dark)
.frame(width: 338, height: 354)
}
......
......@@ -18,8 +18,6 @@ public struct MediumTemperatureWidgetView: View {
}
//Private
private let temps = [25, 31, 22, 19]
@State private var hourlyStackFrame: CGRect = .zero
@Environment(\.colorScheme) private var colorScheme
public var body: some View {
......@@ -29,16 +27,14 @@ public struct MediumTemperatureWidgetView: View {
HStack(spacing: 8) {
Text(widgetViewModel.temperature)
.font(WidgetFont.SFProDisplay.light(size: 32).font)
.foregroundColor(Color("PrimaryTextColor",
bundle: OneWeatherUI.frameworkBundle))
.foregroundColor(WidgetColor.Name("PrimaryTextColor"))
Divider()
.padding(.top, 8)
.padding(.bottom, 8)
Text(widgetViewModel.weatherType)
.font(WidgetFont.SFProDisplay.regular(size: 12).font)
.foregroundColor(Color("PrimaryTextColor",
bundle: OneWeatherUI.frameworkBundle))
.foregroundColor(WidgetColor.Name("PrimaryTextColor"))
.lineLimit(2)
weatherImage(uiImage: widgetViewModel.weatherIcon)
......@@ -69,41 +65,10 @@ public struct MediumTemperatureWidgetView: View {
}
}
GeometryReader { geo in
ZStack {
HStack(spacing: 10) {
ForEach(0 ..< temps.count) { index in
HourlyView(hourlyTemps: .init(currentTemp: temps[index],
temps: temps),
viewIndex: index)
.frame(maxWidth: 70)
}
}
.overlay(
GeometryReader { geoInner in
Color(.clear)
.onAppear {
hourlyStackFrame = geoInner.frame(in: .global)
}
}
)
if temps.count >= 2 {
TemperatureGraphView(temps: temps,
viewModel: .init(graphSize: .init(width: hourlyStackFrame.width,
height: 22),
hourlyItemWidth: 70,
spacingPerItem: 10,
graphInset: .zero))
}
}
.frame(width: geo.frame(in: .local).width)
}
HourlyTemperatureView(temps: [25, 31, 22, 19])
}
.padding([.leading, .trailing], 10)
.background(Color("PrimaryBackground",
bundle: OneWeatherUI.frameworkBundle))
.background(WidgetColor.Name("PrimaryBackground"))
}
}
}
......@@ -130,6 +95,7 @@ private extension View {
public struct MediumTemperatureWidgetView_Preview: PreviewProvider {
public static var previews: some View {
MediumTemperatureWidgetView(widgetViewModel: WidgetViewModelMock())
.previewDevice("iPhone 11")
.preferredColorScheme(.dark)
.frame(width: 338, height: 158)
}
......
......@@ -17,11 +17,11 @@ struct CityNameView: View {
Text(cityName)
.multilineTextAlignment(.leading)
.font(WidgetFont.SFProDisplay.regular(size: 12).font)
.foregroundColor(Color("PrimaryTintColor", bundle: OneWeatherUI.frameworkBundle))
.foregroundColor(WidgetColor.Name("PrimaryTintColor"))
arrowImage()
.renderingMode(.template)
.frame(width: 8, height: 8, alignment: .center)
.foregroundColor(Color("PrimaryTintColor", bundle: OneWeatherUI.frameworkBundle))
.foregroundColor(WidgetColor.Name("PrimaryTintColor"))
.opacity(isDeviceLocation ? 1 : 0)
}
}
......
......@@ -16,10 +16,10 @@ struct HighLowTemperatureView: View {
HStack {
Text("H \(highTemperature)")
.font(WidgetFont.SFProDisplay.regular(size: 12).font)
.foregroundColor(Color("HighLowTemperatureColor", bundle: OneWeatherUI.frameworkBundle))
.foregroundColor(WidgetColor.Name("HighLowTemperatureColor"))
Text("L \(lowTemperature)")
.font(WidgetFont.SFProDisplay.regular(size: 12).font)
.foregroundColor(Color("HighLowTemperatureColor", bundle: OneWeatherUI.frameworkBundle))
.foregroundColor(WidgetColor.Name("HighLowTemperatureColor"))
}
}
}
//
// HourlyTemperatureView.swift
// OneWeatherUI
//
// Created by Dmitry Stepanets on 12.07.2021.
//
import SwiftUI
@available(iOS 14, *)
struct HourlyTemperatureView: View {
//Public
let temps: [Int]
//Private
@State private var hourlyStackFrame: CGRect = .zero
var body: some View {
GeometryReader { geo in
ZStack {
HStack(spacing: 10) {
ForEach(0 ..< temps.count) { index in
HourlyView(hourlyTemps: .init(currentTemp: temps[index],
temps: temps),
viewIndex: index)
.frame(maxWidth: 70)
}
}
.overlay(
GeometryReader { geoInner in
Color(.clear)
.onAppear {
hourlyStackFrame = geoInner.frame(in: .global)
}
}
)
if temps.count >= 2 {
TemperatureGraphView(temps: temps,
viewModel: .init(graphSize: .init(width: hourlyStackFrame.width,
height: 22),
hourlyItemWidth: 70,
spacingPerItem: 10,
graphInset: .zero))
}
}
.frame(width: geo.frame(in: .local).width)
}
}
}
......@@ -21,28 +21,24 @@ struct HourlyView: View {
var body: some View {
VStack {
Text("\(hourlyTemps.currentTemp)" + "°")
.foregroundColor(Color("PrimaryTextColor",
bundle: OneWeatherUI.frameworkBundle))
.foregroundColor(WidgetColor.Name("PrimaryTextColor"))
.font(WidgetFont.SFProDisplay.bold(size: 16).font)
.padding(.top, 8)
Spacer()
Text("NOW")
.foregroundColor(Color("PrimaryTextColor",
bundle: OneWeatherUI.frameworkBundle))
.foregroundColor(WidgetColor.Name("PrimaryTextColor"))
.font(WidgetFont.SFProDisplay.bold(size: 12).font)
.padding(.bottom, 8)
}
.frame(width: 70)
.background(Color("HourlyContainerBackground",
bundle: OneWeatherUI.frameworkBundle))
.background(WidgetColor.Name("HourlyContainerBackground"))
.compositingGroup()
.cornerRadius(12)
.primaryShadow(for: colorScheme)
.secondaryShadow(for: colorScheme)
.overlay(
RoundedRectangle(cornerRadius: 12)
.stroke(Color("HourlyContainerBorder",
bundle: OneWeatherUI.frameworkBundle),
.stroke(WidgetColor.Name("HourlyContainerBorder"),
lineWidth: 1)
)
}
......@@ -55,13 +51,11 @@ private extension View {
switch colorScheme {
case .light:
return self
.shadow(color: Color("HourlyContainerPrimaryShadow",
bundle: OneWeatherUI.frameworkBundle),
.shadow(color: WidgetColor.Name("HourlyContainerPrimaryShadow"),
radius: 18, x: 5, y: 5)
case .dark:
return self
.shadow(color: Color("HourlyContainerPrimaryShadow",
bundle: OneWeatherUI.frameworkBundle),
.shadow(color: WidgetColor.Name("HourlyContainerPrimaryShadow"),
radius: 5, x: 5, y: 5)
default:
fatalError("[OneWeatherUI] Unsopported color scheme")
......@@ -72,13 +66,11 @@ private extension View {
switch colorScheme {
case .light:
return self
.shadow(color: Color("HourlyContainerSecondaryShadow",
bundle: OneWeatherUI.frameworkBundle),
.shadow(color: WidgetColor.Name("HourlyContainerSecondaryShadow"),
radius: 6, x: -4, y: -2)
case .dark:
return self
.shadow(color: Color("HourlyContainerSecondaryShadow",
bundle: OneWeatherUI.frameworkBundle),
.shadow(color: WidgetColor.Name("HourlyContainerSecondaryShadow"),
radius: 6, x: -4, y: -2)
default:
fatalError("[OneWeatherUI] Unsopported color scheme")
......
......@@ -30,8 +30,7 @@ struct TemperatureGraphView: View {
//Line
if points.count > 1 {
Path(self.linePath.cgPath)
.stroke(Color("GraphLine",
bundle: OneWeatherUI.frameworkBundle),
.stroke(WidgetColor.Name("GraphLine"),
style: .init(lineWidth: 3,
lineCap: .round,
lineJoin: .round))
......@@ -41,8 +40,7 @@ struct TemperatureGraphView: View {
//Tint line
Path(self.tintPathFor(hourlyViewIndex: 0))
.stroke(Color("GraphLineTint",
bundle: OneWeatherUI.frameworkBundle),
.stroke(WidgetColor.Name("GraphLineTint"),
style: .init(lineWidth: 3,
lineCap: .round,
lineJoin: .round))
......@@ -55,8 +53,7 @@ struct TemperatureGraphView: View {
Circle()
.overlay(
Circle()
.stroke(Color("GraphLine",
bundle: OneWeatherUI.frameworkBundle),
.stroke(WidgetColor.Name("GraphLine"),
lineWidth: 2)
)
.frame(width: 5, height: 5)
......
......@@ -21,52 +21,47 @@ public struct SmallTemperatureWidgetView: View {
@Environment(\.colorScheme) private var colorScheme
public var body: some View {
GeometryReader { geometry in
VStack {
HStack(spacing: 4) {
CityNameView(cityName: widgetViewModel.cityName,
isDeviceLocation: widgetViewModel.isDeviceLocation)
Spacer()
}
.padding(.top, 12)
.padding(.leading, 10)
HStack(spacing: 0) {
VStack(alignment: .leading){
Text(widgetViewModel.temperature)
.font(WidgetFont.SFProDisplay.light(size: 32).font)
.padding(.leading, 10)
.padding(.trailing, 4)
.foregroundColor(Color("PrimaryTextColor",
bundle: OneWeatherUI.frameworkBundle))
Text(widgetViewModel.weatherType)
.font(WidgetFont.SFProDisplay.regular(size: 12).font)
.padding(.leading, 10)
.padding(.trailing, 4)
.foregroundColor(Color("PrimaryTextColor",
bundle: OneWeatherUI.frameworkBundle))
Spacer(minLength: 0)
}
.frame(height: 70)
Spacer(minLength: 0)
weatherImage(uiImage: widgetViewModel.weatherIcon)
.frame(width: 70, height: 70, alignment: .center)
.shadow(for: colorScheme)
VStack {
HStack(spacing: 4) {
CityNameView(cityName: widgetViewModel.cityName,
isDeviceLocation: widgetViewModel.isDeviceLocation)
Spacer()
}
.padding(.top, 12)
.padding(.leading, 10)
HStack(spacing: 0) {
VStack(alignment: .leading){
Text(widgetViewModel.temperature)
.font(WidgetFont.SFProDisplay.light(size: 32).font)
.padding(.leading, 10)
.padding(.trailing, 4)
.foregroundColor(WidgetColor.Name("PrimaryTextColor"))
Text(widgetViewModel.weatherType)
.font(WidgetFont.SFProDisplay.regular(size: 12).font)
.padding(.leading, 10)
.padding(.trailing, 4)
.foregroundColor(WidgetColor.Name("PrimaryTextColor"))
Spacer(minLength: 0)
}
HStack {
HighLowTemperatureView(highTemperature: widgetViewModel.highTemperature,
.frame(height: 70)
Spacer(minLength: 0)
weatherImage(uiImage: widgetViewModel.weatherIcon)
.frame(width: 70, height: 70, alignment: .center)
.shadow(for: colorScheme)
.padding(.trailing, 4)
}
HStack {
HighLowTemperatureView(highTemperature: widgetViewModel.highTemperature,
lowTemperature: widgetViewModel.lowTemperature)
Spacer()
}
.padding(.bottom, 21)
.padding(.leading, 10)
Spacer()
}
.background(Color("PrimaryBackground",
bundle: OneWeatherUI.frameworkBundle))
.padding(.bottom, 21)
.padding(.leading, 10)
}
.background(WidgetColor.Name("PrimaryBackground"))
}
}
......
......@@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>8</string>
<string>9</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
......
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