diff --git a/ResumeBuilder.xcodeproj/project.pbxproj b/ResumeBuilder.xcodeproj/project.pbxproj
index 1e0c36f..f46d3d8 100644
--- a/ResumeBuilder.xcodeproj/project.pbxproj
+++ b/ResumeBuilder.xcodeproj/project.pbxproj
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
+ 880A8C212AFE3B0C000ABBFA /* PhoneNumberKit in Frameworks */ = {isa = PBXBuildFile; productRef = 880A8C202AFE3B0C000ABBFA /* PhoneNumberKit */; };
886AD6452AB9CD9100B1A00D /* ColorScheme+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 886AD6442AB9CD9100B1A00D /* ColorScheme+Extensions.swift */; };
E267D1742A8E0DE80069112B /* ResumeBuilderApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = E267D1732A8E0DE80069112B /* ResumeBuilderApp.swift */; };
E267D1762A8E0DE80069112B /* CV.swift in Sources */ = {isa = PBXBuildFile; fileRef = E267D1752A8E0DE80069112B /* CV.swift */; };
@@ -84,6 +85,7 @@
buildActionMask = 2147483647;
files = (
E267D1882A8E12D60069112B /* SFSafeSymbols in Frameworks */,
+ 880A8C212AFE3B0C000ABBFA /* PhoneNumberKit in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -220,6 +222,7 @@
name = ResumeBuilder;
packageProductDependencies = (
E267D1872A8E12D60069112B /* SFSafeSymbols */,
+ 880A8C202AFE3B0C000ABBFA /* PhoneNumberKit */,
);
productName = ResumeBuilder;
productReference = E267D1702A8E0DE80069112B /* ResumeBuilder.app */;
@@ -251,6 +254,7 @@
mainGroup = E267D1672A8E0DE80069112B;
packageReferences = (
E267D1862A8E12D60069112B /* XCRemoteSwiftPackageReference "SFSafeSymbols" */,
+ 880A8C1F2AFE3B0C000ABBFA /* XCRemoteSwiftPackageReference "PhoneNumberKit" */,
);
productRefGroup = E267D1712A8E0DE80069112B /* Products */;
projectDirPath = "";
@@ -516,6 +520,14 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
+ 880A8C1F2AFE3B0C000ABBFA /* XCRemoteSwiftPackageReference "PhoneNumberKit" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/marmelroy/PhoneNumberKit";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 3.7.4;
+ };
+ };
E267D1862A8E12D60069112B /* XCRemoteSwiftPackageReference "SFSafeSymbols" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SFSafeSymbols/SFSafeSymbols";
@@ -527,6 +539,11 @@
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
+ 880A8C202AFE3B0C000ABBFA /* PhoneNumberKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 880A8C1F2AFE3B0C000ABBFA /* XCRemoteSwiftPackageReference "PhoneNumberKit" */;
+ productName = PhoneNumberKit;
+ };
E267D1872A8E12D60069112B /* SFSafeSymbols */ = {
isa = XCSwiftPackageProductDependency;
package = E267D1862A8E12D60069112B /* XCRemoteSwiftPackageReference "SFSafeSymbols" */;
diff --git a/ResumeBuilder.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ResumeBuilder.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index e8341d6..07827d5 100644
--- a/ResumeBuilder.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/ResumeBuilder.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -1,5 +1,14 @@
{
"pins" : [
+ {
+ "identity" : "phonenumberkit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/marmelroy/PhoneNumberKit",
+ "state" : {
+ "revision" : "b456f2f9be10c1d183158220b831afd22697dd68",
+ "version" : "3.7.4"
+ }
+ },
{
"identity" : "sfsafesymbols",
"kind" : "remoteSourceControl",
diff --git a/ResumeBuilder.xcodeproj/project.xcworkspace/xcuserdata/imac.xcuserdatad/UserInterfaceState.xcuserstate b/ResumeBuilder.xcodeproj/project.xcworkspace/xcuserdata/imac.xcuserdatad/UserInterfaceState.xcuserstate
new file mode 100644
index 0000000..fb1063b
Binary files /dev/null and b/ResumeBuilder.xcodeproj/project.xcworkspace/xcuserdata/imac.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/ResumeBuilder.xcodeproj/xcuserdata/imac.xcuserdatad/xcschemes/xcschememanagement.plist b/ResumeBuilder.xcodeproj/xcuserdata/imac.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 0000000..f00878d
--- /dev/null
+++ b/ResumeBuilder.xcodeproj/xcuserdata/imac.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,14 @@
+
+
+
+
+ SchemeUserState
+
+ ResumeBuilder.xcscheme_^#shared#^_
+
+ orderHint
+ 0
+
+
+
+
diff --git a/ResumeBuilder/Generic Elements/LeftImageLabel.swift b/ResumeBuilder/Generic Elements/LeftImageLabel.swift
index 79b0ca6..c69aca5 100644
--- a/ResumeBuilder/Generic Elements/LeftImageLabel.swift
+++ b/ResumeBuilder/Generic Elements/LeftImageLabel.swift
@@ -1,20 +1,20 @@
import SwiftUI
import SFSafeSymbols
-struct LeftImageLabel: View {
-
- let text: String
+struct LeftImageLabel: View where Content: View {
let systemSymbol: SFSymbol
+
+ let content: Content
- init(_ text: String, systemSymbol: SFSymbol) {
- self.text = text
+ init(systemSymbol: SFSymbol, @ViewBuilder content: () -> Content) {
self.systemSymbol = systemSymbol
+ self.content = content()
}
var body: some View {
- HStack(alignment: .firstTextBaseline, spacing: 0) {
- Text(text)
+ HStack(alignment: .center, spacing: 0) {
+ content
Image(systemSymbol: systemSymbol)
.frame(width: 20)
}
@@ -23,6 +23,6 @@ struct LeftImageLabel: View {
struct LeftImageLabel_Previews: PreviewProvider {
static var previews: some View {
- LeftImageLabel("Home address", systemSymbol: .house)
+ LeftImageLabel(systemSymbol: .house) { Text("Home address") }
}
}
diff --git a/ResumeBuilder/Main Elements/TopView.swift b/ResumeBuilder/Main Elements/TopView.swift
index 67ece5b..f613169 100644
--- a/ResumeBuilder/Main Elements/TopView.swift
+++ b/ResumeBuilder/Main Elements/TopView.swift
@@ -1,5 +1,8 @@
import SwiftUI
import SFSafeSymbols
+import PhoneNumberKit
+
+private let emailPattern = #"^\S+@\S+\.\S+$"#
struct TopView: View {
@@ -8,6 +11,21 @@ struct TopView: View {
let style: HeaderStyle
let accent: Color
+
+ private let phoneNumberKit = PhoneNumberKit()
+
+ var isValidEmail: Bool {
+ info.email.range(of: emailPattern, options: .regularExpression) != nil
+ }
+
+ var isValidPhoneNumber: Bool {
+ do {
+ _ = try phoneNumberKit.parse(info.phone)
+ return true
+ } catch {
+ return false
+ }
+ }
var body: some View {
GeometryReader { geo in
@@ -34,18 +52,26 @@ struct TopView: View {
shadow: style.imageShadowSize,
lineWidth: style.imageBorderWidth)
VStack(alignment: .trailing) {
- LeftImageLabel(info.web, systemSymbol: .globe)
- .frame(maxHeight: style.iconHeight)
+ LeftImageLabel(systemSymbol: .globe) {
+ Link(info.web, destination: URL(string: "https://" + info.web)!)
+ }
+ .frame(maxHeight: style.iconHeight)
Spacer()
- LeftImageLabel(info.email, systemSymbol: .envelope)
- .frame(maxHeight: style.iconHeight)
+ LeftImageLabel(systemSymbol: .envelope) {
+ Link(info.email, destination: URL(string: "mailto:" + info.email)!)
+ .disabled(!isValidEmail)
+ }
+ .frame(maxHeight: style.iconHeight)
Spacer()
- LeftImageLabel(info.phone, systemSymbol: .phone)
- .frame(maxHeight: style.iconHeight)
+ LeftImageLabel(systemSymbol: .phone) {
+ Link(info.phone, destination: URL(string: "tel:" + info.phone)!)
+ .disabled(!isValidPhoneNumber)
+ }
+ .frame(maxHeight: style.iconHeight)
Spacer()
HStack(spacing: 0) {
Spacer()
- Text(info.github)
+ Link(info.github, destination: URL(string: "https://" + info.github)!)
Image("Github")
.resizable()
.aspectRatio(1.0, contentMode: .fit)
@@ -55,6 +81,7 @@ struct TopView: View {
}
.font(.subheadline)
.frame(width: sideWidth)
+ .foregroundStyle(.primary)
}
}
}