From e24d3e115c5e7813142b278349abd76db0adeb8d Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sat, 3 Dec 2022 10:45:54 +0100 Subject: [PATCH 1/3] Implemented the ProfileView view with dummy data. --- BeReal.xcodeproj/project.pbxproj | 32 +++++ .../Styles/NameAndValueLabelStyle.swift | 38 ++++++ BeReal/Extensions/Views/ProfileView.swift | 109 ++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 BeReal/Extensions/Styles/NameAndValueLabelStyle.swift create mode 100644 BeReal/Extensions/Views/ProfileView.swift diff --git a/BeReal.xcodeproj/project.pbxproj b/BeReal.xcodeproj/project.pbxproj index a49d426..a2b3b16 100644 --- a/BeReal.xcodeproj/project.pbxproj +++ b/BeReal.xcodeproj/project.pbxproj @@ -14,6 +14,8 @@ 02AE650029363DC1005A4AF3 /* BeRealTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02AE64FF29363DC1005A4AF3 /* BeRealTests.swift */; }; 02AE650A29363DC1005A4AF3 /* BeRealUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02AE650929363DC1005A4AF3 /* BeRealUITests.swift */; }; 02AE650C29363DC1005A4AF3 /* BeRealUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02AE650B29363DC1005A4AF3 /* BeRealUITestsLaunchTests.swift */; }; + 02CE5562293B452E00730DC9 /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE5561293B452E00730DC9 /* ProfileView.swift */; }; + 02CE5565293B517700730DC9 /* NameAndValueLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE5564293B517700730DC9 /* NameAndValueLabelStyle.swift */; }; 02FFFD7B29395DD200306533 /* String+Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02FFFD7A29395DD200306533 /* String+Constants.swift */; }; 4694AAA0293A7C8800D54903 /* Modules in Frameworks */ = {isa = PBXBuildFile; productRef = 4694AA9F293A7C8800D54903 /* Modules */; }; /* End PBXBuildFile section */ @@ -47,6 +49,8 @@ 02AE650529363DC1005A4AF3 /* BeRealUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BeRealUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 02AE650929363DC1005A4AF3 /* BeRealUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeRealUITests.swift; sourceTree = ""; }; 02AE650B29363DC1005A4AF3 /* BeRealUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeRealUITestsLaunchTests.swift; sourceTree = ""; }; + 02CE5561293B452E00730DC9 /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = ""; }; + 02CE5564293B517700730DC9 /* NameAndValueLabelStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NameAndValueLabelStyle.swift; sourceTree = ""; }; 02FFFD7A29395DD200306533 /* String+Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Constants.swift"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -101,6 +105,7 @@ 02AE64ED29363DBF005A4AF3 /* BeReal */ = { isa = PBXGroup; children = ( + 02CE555F293B44C900730DC9 /* Profile */, 02FFFD7929395DBF00306533 /* Extensions */, 02AE64EE29363DBF005A4AF3 /* BeRealApp.swift */, 02AE64F029363DBF005A4AF3 /* ContentView.swift */, @@ -135,9 +140,34 @@ path = BeRealUITests; sourceTree = ""; }; + 02CE555F293B44C900730DC9 /* Profile */ = { + isa = PBXGroup; + children = ( + ); + path = Profile; + sourceTree = ""; + }; + 02CE5560293B452400730DC9 /* Views */ = { + isa = PBXGroup; + children = ( + 02CE5561293B452E00730DC9 /* ProfileView.swift */, + ); + path = Views; + sourceTree = ""; + }; + 02CE5563293B516600730DC9 /* Styles */ = { + isa = PBXGroup; + children = ( + 02CE5564293B517700730DC9 /* NameAndValueLabelStyle.swift */, + ); + path = Styles; + sourceTree = ""; + }; 02FFFD7929395DBF00306533 /* Extensions */ = { isa = PBXGroup; children = ( + 02CE5563293B516600730DC9 /* Styles */, + 02CE5560293B452400730DC9 /* Views */, 02FFFD7A29395DD200306533 /* String+Constants.swift */, ); path = Extensions; @@ -284,8 +314,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 02CE5562293B452E00730DC9 /* ProfileView.swift in Sources */, 02AE64F129363DBF005A4AF3 /* ContentView.swift in Sources */, 02AE64EF29363DBF005A4AF3 /* BeRealApp.swift in Sources */, + 02CE5565293B517700730DC9 /* NameAndValueLabelStyle.swift in Sources */, 02FFFD7B29395DD200306533 /* String+Constants.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/BeReal/Extensions/Styles/NameAndValueLabelStyle.swift b/BeReal/Extensions/Styles/NameAndValueLabelStyle.swift new file mode 100644 index 0000000..7e7f232 --- /dev/null +++ b/BeReal/Extensions/Styles/NameAndValueLabelStyle.swift @@ -0,0 +1,38 @@ +// +// NameAndValueLabelStyle.swift +// Profile +// +// Created by Javier Cicchelli on 03/12/2022. +// Copyright © 2022 Röck+Cöde. All rights reserved. +// + +import SwiftUI + +struct NameAndValueLabelStyle: LabelStyle { + func makeBody(configuration: Configuration) -> some View { + VStack( + alignment: .leading, + spacing: 0 + ) { + configuration.icon + .font(.subheadline) + .foregroundColor(.secondary) + + configuration.title + .font(.headline) + .lineLimit(1) + .truncationMode(.middle) + .foregroundColor(.primary) + .frame(maxWidth: .infinity, alignment: .trailing) + } + .padding(.vertical, 8) + } +} + +// MARK: - LabelStyle + +extension LabelStyle where Self == NameAndValueLabelStyle { + static var nameAndValue: Self { + NameAndValueLabelStyle() + } +} diff --git a/BeReal/Extensions/Views/ProfileView.swift b/BeReal/Extensions/Views/ProfileView.swift new file mode 100644 index 0000000..858797d --- /dev/null +++ b/BeReal/Extensions/Views/ProfileView.swift @@ -0,0 +1,109 @@ +// +// ProfileView.swift +// BeReal +// +// Created by Javier Cicchelli on 03/12/2022. +// Copyright © 2022 Röck+Cöde. All rights reserved. +// + +import SwiftUI + +struct ProfileView: View { + var body: some View { + List { + Section { + Image.photo + .resizable() + .scaledToFit() + .frame(width: 160) + .frame(maxWidth: .infinity) + } + .listRowBackground(Color.clear) + + Section { + Label { + Text("Javier") + } icon: { + Text("First name") + } + .labelStyle(.nameAndValue) + + Label { + Text("Cicchelli") + } icon: { + Text("Last name") + } + .labelStyle(.nameAndValue) + } header: { + Text("Names") + } + + Section { + Label { + Text("71207ee4c0573fde80b03643caafe62731406404") + } icon: { + Text("Identifier") + } + .labelStyle(.nameAndValue) + + Label { + Text("Yes") + } icon: { + Text("Is a directory?") + } + .labelStyle(.nameAndValue) + + Label { + Text("3 days ago") + } icon: { + Text("Last modified") + } + .labelStyle(.nameAndValue) + + Label { + Text("My files") + } icon: { + Text("name") + } + .labelStyle(.nameAndValue) + } header: { + Text("Root item information") + } + + Section { + Button { + // TODO: Log out the existing user. + } label: { + Text("Log out") + .fontWeight(.semibold) + .foregroundColor(.primary) + .frame(maxWidth: .infinity) + } + .tint(.orange) + .buttonStyle(.borderedProminent) + .buttonBorderShape(.roundedRectangle(radius: 8)) + .controlSize(.large) + .padding(0) + } + .listRowBackground(Color.clear) + } + .background(Color.red) + .onAppear { + UITableView.appearance().backgroundColor = .clear + } + } +} + +// MARK: - Images+Constants + +private extension Image { + static let photo = Image(systemName: "person.crop.circle.fill") +} + +// MARK: - Previews + +struct ProfileView_Previews: PreviewProvider { + static var previews: some View { + ProfileView() + } +} From 330d79039454e54a9bc464c41169b5ff92adcf83 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sat, 3 Dec 2022 11:37:42 +0100 Subject: [PATCH 2/3] Moved all the Profile UI files into their own Profile module. --- BeReal.xcodeproj/project.pbxproj | 24 ------ BeReal/ContentView.swift | 3 +- Modules/Package.swift | 7 +- .../Resources/en.lproj/Localizable.strings | 19 +++++ .../UI/Components/ClearBackgroundList.swift | 48 ++++++++++++ .../UI}/Styles/NameAndValueLabelStyle.swift | 0 .../Profile/UI}/Views/ProfileView.swift | 77 ++++++++++++++----- 7 files changed, 133 insertions(+), 45 deletions(-) create mode 100644 Modules/Sources/Profile/Resources/en.lproj/Localizable.strings create mode 100644 Modules/Sources/Profile/UI/Components/ClearBackgroundList.swift rename {BeReal/Extensions => Modules/Sources/Profile/UI}/Styles/NameAndValueLabelStyle.swift (100%) rename {BeReal/Extensions => Modules/Sources/Profile/UI}/Views/ProfileView.swift (50%) diff --git a/BeReal.xcodeproj/project.pbxproj b/BeReal.xcodeproj/project.pbxproj index a2b3b16..03762d3 100644 --- a/BeReal.xcodeproj/project.pbxproj +++ b/BeReal.xcodeproj/project.pbxproj @@ -14,8 +14,6 @@ 02AE650029363DC1005A4AF3 /* BeRealTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02AE64FF29363DC1005A4AF3 /* BeRealTests.swift */; }; 02AE650A29363DC1005A4AF3 /* BeRealUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02AE650929363DC1005A4AF3 /* BeRealUITests.swift */; }; 02AE650C29363DC1005A4AF3 /* BeRealUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02AE650B29363DC1005A4AF3 /* BeRealUITestsLaunchTests.swift */; }; - 02CE5562293B452E00730DC9 /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE5561293B452E00730DC9 /* ProfileView.swift */; }; - 02CE5565293B517700730DC9 /* NameAndValueLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE5564293B517700730DC9 /* NameAndValueLabelStyle.swift */; }; 02FFFD7B29395DD200306533 /* String+Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02FFFD7A29395DD200306533 /* String+Constants.swift */; }; 4694AAA0293A7C8800D54903 /* Modules in Frameworks */ = {isa = PBXBuildFile; productRef = 4694AA9F293A7C8800D54903 /* Modules */; }; /* End PBXBuildFile section */ @@ -49,8 +47,6 @@ 02AE650529363DC1005A4AF3 /* BeRealUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BeRealUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 02AE650929363DC1005A4AF3 /* BeRealUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeRealUITests.swift; sourceTree = ""; }; 02AE650B29363DC1005A4AF3 /* BeRealUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeRealUITestsLaunchTests.swift; sourceTree = ""; }; - 02CE5561293B452E00730DC9 /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = ""; }; - 02CE5564293B517700730DC9 /* NameAndValueLabelStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NameAndValueLabelStyle.swift; sourceTree = ""; }; 02FFFD7A29395DD200306533 /* String+Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Constants.swift"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -147,27 +143,9 @@ path = Profile; sourceTree = ""; }; - 02CE5560293B452400730DC9 /* Views */ = { - isa = PBXGroup; - children = ( - 02CE5561293B452E00730DC9 /* ProfileView.swift */, - ); - path = Views; - sourceTree = ""; - }; - 02CE5563293B516600730DC9 /* Styles */ = { - isa = PBXGroup; - children = ( - 02CE5564293B517700730DC9 /* NameAndValueLabelStyle.swift */, - ); - path = Styles; - sourceTree = ""; - }; 02FFFD7929395DBF00306533 /* Extensions */ = { isa = PBXGroup; children = ( - 02CE5563293B516600730DC9 /* Styles */, - 02CE5560293B452400730DC9 /* Views */, 02FFFD7A29395DD200306533 /* String+Constants.swift */, ); path = Extensions; @@ -314,10 +292,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 02CE5562293B452E00730DC9 /* ProfileView.swift in Sources */, 02AE64F129363DBF005A4AF3 /* ContentView.swift in Sources */, 02AE64EF29363DBF005A4AF3 /* BeRealApp.swift in Sources */, - 02CE5565293B517700730DC9 /* NameAndValueLabelStyle.swift in Sources */, 02FFFD7B29395DD200306533 /* String+Constants.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/BeReal/ContentView.swift b/BeReal/ContentView.swift index d783c13..ae915c9 100644 --- a/BeReal/ContentView.swift +++ b/BeReal/ContentView.swift @@ -9,6 +9,7 @@ import SwiftUI import Browse import Login +import Profile struct ContentView: View { var body: some View { @@ -16,7 +17,7 @@ struct ContentView: View { BrowseView() } .sheet(isPresented: .constant(true)) { - LoginView() + ProfileView() } } } diff --git a/Modules/Package.swift b/Modules/Package.swift index 93ead91..6e6f8a9 100644 --- a/Modules/Package.swift +++ b/Modules/Package.swift @@ -13,7 +13,8 @@ let package = Package( name: "Modules", targets: [ "Login", - "Browse" + "Browse", + "Profile" ] ), ], @@ -25,6 +26,10 @@ let package = Package( .target( name: "Browse", resources: [.process("Resources")] + ), + .target( + name: "Profile", + resources: [.process("Resources")] ) ] ) diff --git a/Modules/Sources/Profile/Resources/en.lproj/Localizable.strings b/Modules/Sources/Profile/Resources/en.lproj/Localizable.strings new file mode 100644 index 0000000..683966f --- /dev/null +++ b/Modules/Sources/Profile/Resources/en.lproj/Localizable.strings @@ -0,0 +1,19 @@ +/* + Localizable.strings + Profile + + Created by Javier Cicchelli on 03/12/2022. + Copyright © 2022 Röck+Cöde. All rights reserved. +*/ + +"profile.sections.names.header.text" = "Names"; +"profile.sections.names.label.first_name.text" = "First name"; +"profile.sections.names.label.last_name.text" = "Last name"; + +"profile.sections.root_info.header.text" = "Root item information"; +"profile.sections.root_info.label.identifier.text" = "Identifier"; +"profile.sections.root_info.label.is_directory.text" = "Is a directory?"; +"profile.sections.root_info.label.last_modified.text" = "Last modified"; +"profile.sections.root_info.label.name.text" = "Name"; + +"profile.button.log_out.text" = "Log out"; diff --git a/Modules/Sources/Profile/UI/Components/ClearBackgroundList.swift b/Modules/Sources/Profile/UI/Components/ClearBackgroundList.swift new file mode 100644 index 0000000..4e5d66b --- /dev/null +++ b/Modules/Sources/Profile/UI/Components/ClearBackgroundList.swift @@ -0,0 +1,48 @@ +// +// ClearBackgroundList.swift +// Profile +// +// Created by Javier Cicchelli on 03/12/2022. +// Copyright © 2022 Röck+Cöde. All rights reserved. +// + +import SwiftUI + +struct ClearBackgroundList: View where Content: View { + + // MARK: Properties + + @ViewBuilder let content: Content + + // MARK: Body + + var body: some View { + if #available(iOS 16.0, *) { + List{ + content + } + .scrollContentBackground(.hidden) + .scrollIndicators(.hidden) + } else { + List { + content + } + .onAppear { + UITableView.appearance().backgroundColor = .clear + UITableView.appearance().showsVerticalScrollIndicator = false + } + } + } + +} + +// MARK: - Previews + +struct ClearBackgroundList_Previews: PreviewProvider { + static var previews: some View { + ClearBackgroundList { + Text("Something...") + } + .background(Color.red) + } +} diff --git a/BeReal/Extensions/Styles/NameAndValueLabelStyle.swift b/Modules/Sources/Profile/UI/Styles/NameAndValueLabelStyle.swift similarity index 100% rename from BeReal/Extensions/Styles/NameAndValueLabelStyle.swift rename to Modules/Sources/Profile/UI/Styles/NameAndValueLabelStyle.swift diff --git a/BeReal/Extensions/Views/ProfileView.swift b/Modules/Sources/Profile/UI/Views/ProfileView.swift similarity index 50% rename from BeReal/Extensions/Views/ProfileView.swift rename to Modules/Sources/Profile/UI/Views/ProfileView.swift index 858797d..3539b30 100644 --- a/BeReal/Extensions/Views/ProfileView.swift +++ b/Modules/Sources/Profile/UI/Views/ProfileView.swift @@ -8,9 +8,16 @@ import SwiftUI -struct ProfileView: View { - var body: some View { - List { +public struct ProfileView: View { + + // MARK: Initialisers + + public init() {} + + // MARK: Body + + public var body: some View { + ClearBackgroundList { Section { Image.photo .resizable() @@ -24,73 +31,105 @@ struct ProfileView: View { Label { Text("Javier") } icon: { - Text("First name") + Text( + "profile.sections.names.label.first_name.text", + bundle: .module, + comment: "First name label text." + ) } .labelStyle(.nameAndValue) Label { Text("Cicchelli") } icon: { - Text("Last name") + Text( + "profile.sections.names.label.last_name.text", + bundle: .module, + comment: "Last name label text." + ) } .labelStyle(.nameAndValue) } header: { - Text("Names") + Text( + "profile.sections.names.header.text", + bundle: .module, + comment: "Names section header text." + ) } Section { Label { Text("71207ee4c0573fde80b03643caafe62731406404") } icon: { - Text("Identifier") + Text( + "profile.sections.root_info.label.identifier.text", + bundle: .module, + comment: "Identifier label text." + ) } .labelStyle(.nameAndValue) Label { Text("Yes") } icon: { - Text("Is a directory?") + Text( + "profile.sections.root_info.label.is_directory.text", + bundle: .module, + comment: "Is directory label text." + ) } .labelStyle(.nameAndValue) Label { Text("3 days ago") } icon: { - Text("Last modified") + Text( + "profile.sections.root_info.label.last_modified.text", + bundle: .module, + comment: "Last modified label text." + ) } .labelStyle(.nameAndValue) Label { Text("My files") } icon: { - Text("name") + Text( + "profile.sections.root_info.label.name.text", + bundle: .module, + comment: "Root name label text." + ) } .labelStyle(.nameAndValue) } header: { - Text("Root item information") + Text( + "profile.sections.root_info.header.text", + bundle: .module, + comment: "Root item information header text." + ) } Section { Button { // TODO: Log out the existing user. } label: { - Text("Log out") - .fontWeight(.semibold) - .foregroundColor(.primary) - .frame(maxWidth: .infinity) + Text( + "profile.button.log_out.text", + bundle: .module, + comment: "Log out button text." + ) + .fontWeight(.semibold) + .foregroundColor(.primary) + .frame(maxWidth: .infinity) } .tint(.orange) .buttonStyle(.borderedProminent) .buttonBorderShape(.roundedRectangle(radius: 8)) .controlSize(.large) - .padding(0) } .listRowBackground(Color.clear) } .background(Color.red) - .onAppear { - UITableView.appearance().backgroundColor = .clear - } } } From 2e8b65d8282c269b737c2dad5400ba80b11d3ba8 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sat, 3 Dec 2022 11:45:54 +0100 Subject: [PATCH 3/3] Added the "logOut" closure to the initialiser of the ProfileView view. --- BeReal/ContentView.swift | 2 +- Modules/Sources/Profile/UI/Views/ProfileView.swift | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/BeReal/ContentView.swift b/BeReal/ContentView.swift index ae915c9..12650bb 100644 --- a/BeReal/ContentView.swift +++ b/BeReal/ContentView.swift @@ -17,7 +17,7 @@ struct ContentView: View { BrowseView() } .sheet(isPresented: .constant(true)) { - ProfileView() + ProfileView {} } } } diff --git a/Modules/Sources/Profile/UI/Views/ProfileView.swift b/Modules/Sources/Profile/UI/Views/ProfileView.swift index 3539b30..3794647 100644 --- a/Modules/Sources/Profile/UI/Views/ProfileView.swift +++ b/Modules/Sources/Profile/UI/Views/ProfileView.swift @@ -10,9 +10,15 @@ import SwiftUI public struct ProfileView: View { + // MARK: Properties + + private let logOut: () -> Void + // MARK: Initialisers - public init() {} + public init(logOut: @escaping () -> Void) { + self.logOut = logOut + } // MARK: Body @@ -111,7 +117,7 @@ public struct ProfileView: View { Section { Button { - // TODO: Log out the existing user. + logOut() } label: { Text( "profile.button.log_out.text", @@ -143,6 +149,8 @@ private extension Image { struct ProfileView_Previews: PreviewProvider { static var previews: some View { - ProfileView() + ProfileView { + // closure for log out action. + } } }