Skip to content

Commit

Permalink
feat(Widget): move Widget related logic to its own module
Browse files Browse the repository at this point in the history
  • Loading branch information
renaudjenny committed Apr 23, 2023
1 parent 2e44632 commit 18e3de5
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 127 deletions.
40 changes: 38 additions & 2 deletions Package.resolved
Expand Up @@ -9,6 +9,15 @@
"version" : "0.9.1"
}
},
{
"identity" : "renaudjennyaboutview",
"kind" : "remoteSourceControl",
"location" : "https://github.com/renaudjenny/RenaudJennyAboutView",
"state" : {
"revision" : "88b458bdb1cfed265a025f7d257d4fad4d5a5b24",
"version" : "1.1.0"
}
},
{
"identity" : "swift-case-paths",
"kind" : "remoteSourceControl",
Expand Down Expand Up @@ -59,8 +68,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-dependencies",
"state" : {
"revision" : "6bb1034e8a1bfbf46dfb766b6c09b7b17e1cba10",
"version" : "0.2.0"
"revision" : "98650d886ec950b587d671261f06d6b59dec4052",
"version" : "0.4.1"
}
},
{
Expand All @@ -72,6 +81,15 @@
"version" : "0.7.0"
}
},
{
"identity" : "swift-past-ten",
"kind" : "remoteSourceControl",
"location" : "https://github.com/renaudjenny/swift-past-ten",
"state" : {
"branch" : "main",
"revision" : "d5bd80b859811eaf4bf56c98d90dff3339f3f418"
}
},
{
"identity" : "swift-snapshot-testing",
"kind" : "remoteSourceControl",
Expand All @@ -90,6 +108,15 @@
"revision" : "d405095aed8069fece60badb17b5c93449b65cf1"
}
},
{
"identity" : "swift-to-ten",
"kind" : "remoteSourceControl",
"location" : "https://github.com/renaudjenny/swift-to-ten",
"state" : {
"branch" : "main",
"revision" : "b7379ed384c052df74a08ef5a988c5281eda0aeb"
}
},
{
"identity" : "swift-tts",
"kind" : "remoteSourceControl",
Expand All @@ -108,6 +135,15 @@
"version" : "2.0.0"
}
},
{
"identity" : "swiftregex5",
"kind" : "remoteSourceControl",
"location" : "https://github.com/johnno1962/SwiftRegex5",
"state" : {
"revision" : "8ecb4a8570757b7f8bce72f82242742e13891f99",
"version" : "5.2.3"
}
},
{
"identity" : "swiftui-navigation",
"kind" : "remoteSourceControl",
Expand Down
13 changes: 13 additions & 0 deletions Package.swift
Expand Up @@ -11,10 +11,13 @@ let package = Package(
.library(name: "ConfigurationFeature", targets: ["ConfigurationFeature"]),
.library(name: "SpeechRecognizerCore", targets: ["SpeechRecognizerCore"]),
.library(name: "TTSCore", targets: ["TTSCore"]),
.library(name: "WidgetFeature", targets: ["WidgetFeature"]),
],
dependencies: [
.package(url: "https://github.com/renaudjenny/RenaudJennyAboutView", from: "1.1.0"),
.package(url: "https://github.com/renaudjenny/SwiftClockUI", from: "2.0.0"),
.package(url: "https://github.com/pointfreeco/swift-composable-architecture", from: "0.52.0"),
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "0.4.1"),
.package(url: "https://github.com/renaudjenny/swift-past-ten", branch: "main"),
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.11.0"),
.package(url: "https://github.com/renaudjenny/swift-speech-recognizer", branch: "main"),
Expand All @@ -27,7 +30,9 @@ let package = Package(
dependencies: [
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
"ConfigurationFeature",
.product(name: "RenaudJennyAboutView", package: "RenaudJennyAboutView"),
"SpeechRecognizerCore",
.product(name: "SwiftClockUI", package: "SwiftClockUI"),
.product(name: "SwiftPastTenDependency", package: "swift-past-ten"),
.product(name: "SwiftToTenDependency", package: "swift-to-ten"),
"TTSCore",
Expand Down Expand Up @@ -70,5 +75,13 @@ let package = Package(
.product(name: "SnapshotTesting", package: "swift-snapshot-testing"),
]
),
.target(
name: "WidgetFeature",
dependencies: [
.product(name: "Dependencies", package: "swift-dependencies"),
.product(name: "SwiftClockUI", package: "SwiftClockUI"),
.product(name: "SwiftPastTenDependency", package: "swift-past-ten"),
]
)
]
)
125 changes: 125 additions & 0 deletions Sources/WidgetFeature/Widget.swift
@@ -0,0 +1,125 @@
import Dependencies
import SwiftClockUI
import SwiftUI
import SwiftPastTenDependency
import WidgetKit

public struct WidgetView: View {
let date: Date
let design: Design
@Environment(\.widgetFamily) var family: WidgetFamily

public init(date: Date, design: Int) {
self.date = date
self.design = Design(rawValue: design) ?? .classic
}

public var body: some View {
switch family {
case .systemSmall: smallView
case .systemMedium: mediumView
case .systemLarge: largeView
default: Text("Error")
}
}

private var smallView: some View {
VStack {
switch design {
case .unknown, .text: Text(time).padding()
default: clock.padding()
}
}
.widgetURL(url())
}

private var mediumView: some View {
HStack {
clock
VStack {
Text(time)
Spacer()
Link(destination: url(speak: true)) {
speakButton
}
}
}
.padding()
.widgetURL(url())
}

private var largeView: some View {
VStack {
clock
Spacer()
HStack {
Spacer()
Text(time)
Spacer()
Link(destination: url(speak: true)) {
speakButton
}
}
Spacer()
}
.padding()
.widgetURL(url())
}

private var clock: some View {
ClockView()
.allowsHitTesting(false)
.environment(\.clockDate, .constant(date))
.environment(\.clockStyle, design.clockStyle)
}

private var speakButton: some View {
Image(systemName: "speaker.2")
.foregroundColor(.white)
.padding()
.cornerRadius(8)
.background(Color.red.cornerRadius(8))
}

private var time: String {
@Dependency(\.calendar) var calendar
@Dependency(\.tellTime) var tellTime
guard let time = try? tellTime(time: SwiftPastTen.formattedDate(date, calendar: calendar))
else { return "" }
return time
}

private func url(speak: Bool = false) -> URL {
var urlComponents = URLComponents()
urlComponents.host = "renaud.jenny.telltime"
urlComponents.queryItems = [
URLQueryItem(name: "clockStyle", value: "\(design.clockStyle.id)"),
URLQueryItem(name: "speak", value: "\(speak)"),
]
guard let url = urlComponents.url else {
fatalError("Cannot build the URL from the Widget")
}
return url
}
}

/// Design needs to be a perfect match with TellTimeWidget Design
enum Design: Int {
case unknown
case classic
case artNouveau
case drawing
case steampunk
case text
}

extension Design {
var clockStyle: ClockStyle {
switch self {
case .unknown, .classic, .text: return .classic
case .artNouveau: return .artNouveau
case .drawing: return .drawing
case .steampunk: return .steampunk
}
}
}
7 changes: 7 additions & 0 deletions telltime/TellTime.xcodeproj/project.pbxproj
Expand Up @@ -17,6 +17,7 @@
4C3CCC6F24B39356008F0699 /* TellTimeWidgetExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 4C3CCC5F24B39353008F0699 /* TellTimeWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4C4A811929CFC03600463169 /* TTSCore in Frameworks */ = {isa = PBXBuildFile; productRef = 4C4A811829CFC03600463169 /* TTSCore */; };
4C5FD3DC29F4C7F1008EB5C9 /* AppFeature in Frameworks */ = {isa = PBXBuildFile; productRef = 4C5FD3DB29F4C7F1008EB5C9 /* AppFeature */; };
4C5FD3DE29F4CCA2008EB5C9 /* WidgetFeature in Frameworks */ = {isa = PBXBuildFile; productRef = 4C5FD3DD29F4CCA2008EB5C9 /* WidgetFeature */; };
4CB1D4BC22A7293300786385 /* TellTimeUKApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB1D4BB22A7293300786385 /* TellTimeUKApp.swift */; };
4CB1D4C222A7293500786385 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4CB1D4C122A7293500786385 /* Assets.xcassets */; };
4CB1D4C522A7293500786385 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4CB1D4C422A7293500786385 /* Preview Assets.xcassets */; };
Expand Down Expand Up @@ -82,6 +83,7 @@
buildActionMask = 2147483647;
files = (
4C3CCC6324B39353008F0699 /* SwiftUI.framework in Frameworks */,
4C5FD3DE29F4CCA2008EB5C9 /* WidgetFeature in Frameworks */,
4C3CCC6124B39353008F0699 /* WidgetKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -178,6 +180,7 @@
);
name = TellTimeWidgetExtension;
packageProductDependencies = (
4C5FD3DD29F4CCA2008EB5C9 /* WidgetFeature */,
);
productName = TellTimeWidgetExtension;
productReference = 4C3CCC5F24B39353008F0699 /* TellTimeWidgetExtension.appex */;
Expand Down Expand Up @@ -579,6 +582,10 @@
isa = XCSwiftPackageProductDependency;
productName = AppFeature;
};
4C5FD3DD29F4CCA2008EB5C9 /* WidgetFeature */ = {
isa = XCSwiftPackageProductDependency;
productName = WidgetFeature;
};
4CC951C229E291440022C537 /* ConfigurationFeature */ = {
isa = XCSwiftPackageProductDependency;
productName = ConfigurationFeature;
Expand Down
Expand Up @@ -9,6 +9,15 @@
"version" : "0.9.1"
}
},
{
"identity" : "renaudjennyaboutview",
"kind" : "remoteSourceControl",
"location" : "https://github.com/renaudjenny/RenaudJennyAboutView",
"state" : {
"revision" : "88b458bdb1cfed265a025f7d257d4fad4d5a5b24",
"version" : "1.1.0"
}
},
{
"identity" : "swift-case-paths",
"kind" : "remoteSourceControl",
Expand Down

0 comments on commit 18e3de5

Please sign in to comment.