diff --git a/BeReal.xcodeproj/project.pbxproj b/BeReal.xcodeproj/project.pbxproj index c9f7f8b..a49d426 100644 --- a/BeReal.xcodeproj/project.pbxproj +++ b/BeReal.xcodeproj/project.pbxproj @@ -76,13 +76,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 027F60592937662300467238 /* Login */ = { - isa = PBXGroup; - children = ( - ); - path = Login; - sourceTree = ""; - }; 02AE64E229363DBF005A4AF3 = { isa = PBXGroup; children = ( @@ -109,7 +102,6 @@ isa = PBXGroup; children = ( 02FFFD7929395DBF00306533 /* Extensions */, - 027F60592937662300467238 /* Login */, 02AE64EE29363DBF005A4AF3 /* BeRealApp.swift */, 02AE64F029363DBF005A4AF3 /* ContentView.swift */, 02AE64F229363DC1005A4AF3 /* Assets.xcassets */, diff --git a/BeReal/ContentView.swift b/BeReal/ContentView.swift index e9aef05..d783c13 100644 --- a/BeReal/ContentView.swift +++ b/BeReal/ContentView.swift @@ -7,17 +7,14 @@ // import SwiftUI +import Browse import Login struct ContentView: View { var body: some View { - VStack { - Image(systemName: "globe") - .imageScale(.large) - .foregroundColor(.accentColor) - Text("Hello, world!") + NavigationView { + BrowseView() } - .padding() .sheet(isPresented: .constant(true)) { LoginView() } diff --git a/Modules/Package.swift b/Modules/Package.swift index 98ab061..93ead91 100644 --- a/Modules/Package.swift +++ b/Modules/Package.swift @@ -12,7 +12,8 @@ let package = Package( .library( name: "Modules", targets: [ - "Login" + "Login", + "Browse" ] ), ], @@ -21,5 +22,9 @@ let package = Package( name: "Login", resources: [.process("Resources")] ), + .target( + name: "Browse", + resources: [.process("Resources")] + ) ] ) diff --git a/Modules/Sources/Browse/Resources/en.lproj/Localizable.strings b/Modules/Sources/Browse/Resources/en.lproj/Localizable.strings new file mode 100644 index 0000000..2724f95 --- /dev/null +++ b/Modules/Sources/Browse/Resources/en.lproj/Localizable.strings @@ -0,0 +1,14 @@ +/* + Localizable.strings + Browse + + Created by Javier Cicchelli on 03/12/2022. + Copyright © 2022 Röck+Cöde. All rights reserved. +*/ + +"browse.toolbar_item.menu.add_actions.text" = "Add file and/or folder"; +"browse.toolbar_item.button.add_folder.text" = "Create a new folder"; +"browse.toolbar_item.button.add_file.text" = "Upload a file"; +"browse.toolbar_item.button.show_profile.text" = "Show profile"; +"browse.swipe_action.delete_item.text" = "Delete item"; +"browse.swipe_action.download_item.text" = "Download item"; diff --git a/Modules/Sources/Browse/UI/Components/DocumentItem.swift b/Modules/Sources/Browse/UI/Components/DocumentItem.swift new file mode 100644 index 0000000..11ee561 --- /dev/null +++ b/Modules/Sources/Browse/UI/Components/DocumentItem.swift @@ -0,0 +1,71 @@ +// +// DocumentItem.swift +// Browse +// +// Created by Javier Cicchelli on 03/12/2022. +// Copyright © 2022 Röck+Cöde. All rights reserved. +// + +import SwiftUI + +struct DocumentItem: View { + + // MARK: Properties + + let name: String + let lastModified: String + let fileSize: String + + // MARK: Body + + var body: some View { + HStack(spacing: 16) { + Image.document + .icon(size: 32) + .foregroundColor(.red) + + VStack { + Text(name) + .itemName() + + HStack { + Text(lastModified) + + Spacer() + + Text(fileSize) + } + .font(.subheadline) + .foregroundColor(.secondary) + } + } + .padding(.vertical, 8) + } + +} + +// MARK: - Image+Constants + +private extension Image { + static let document = Image(systemName: "doc.fill") +} + +// MARK: - Previews + +struct DocumentItem_Previews: PreviewProvider { + static var previews: some View { + DocumentItem( + name: "Some document name goes in here...", + lastModified: "Some few hours ago", + fileSize: "23,5 Mbytes" + ) + .previewDisplayName("Document item") + + DocumentItem( + name: "Some very, extremely long document name goes in here...", + lastModified: "Yesterday", + fileSize: "235,6 Kbytes" + ) + .previewDisplayName("Document item with long name") + } +} diff --git a/Modules/Sources/Browse/UI/Components/FolderItem.swift b/Modules/Sources/Browse/UI/Components/FolderItem.swift new file mode 100644 index 0000000..fd89e77 --- /dev/null +++ b/Modules/Sources/Browse/UI/Components/FolderItem.swift @@ -0,0 +1,55 @@ +// +// FolderItem.swift +// Browse +// +// Created by Javier Cicchelli on 02/12/2022. +// Copyright © 2022 Röck+Cöde. All rights reserved. +// + +import SwiftUI + +struct FolderItem: View { + + // MARK: Properties + + let name: String + + // MARK: Body + + var body: some View { + HStack(spacing: 16) { + Image.folder + .icon(size: 32) + .foregroundColor(.red) + + Text(name) + .itemName() + + Image.chevronRight + .icon(size: 16) + .foregroundColor(.secondary) + .font(.headline) + } + .padding(.vertical, 8) + } + +} + +// MARK: - Image+Constants + +private extension Image { + static let folder = Image(systemName: "folder.fill") + static let chevronRight = Image(systemName: "chevron.right") +} + +// MARK: - Previews + +struct BrowseItem_Previews: PreviewProvider { + static var previews: some View { + FolderItem(name: "Some folder name goes in here...") + .previewDisplayName("Folder item") + + FolderItem(name: "Some very, extremely long folder name goes in here...") + .previewDisplayName("Folder item with long name") + } +} diff --git a/Modules/Sources/Browse/UI/Extensions/Image+Helpers.swift b/Modules/Sources/Browse/UI/Extensions/Image+Helpers.swift new file mode 100644 index 0000000..8cf4ed6 --- /dev/null +++ b/Modules/Sources/Browse/UI/Extensions/Image+Helpers.swift @@ -0,0 +1,24 @@ +// +// Image+Helpers.swift +// Browse +// +// Created by Javier Cicchelli on 03/12/2022. +// Copyright © 2022 Röck+Cöde. All rights reserved. +// + +import SwiftUI + +extension Image { + + /// Resizes an image to a given size. + /// - Parameter size: A size to which an image will be resized. + /// - Returns: An resized image rendered as an erasured view. + func icon(size: CGFloat) -> some View { + self + .resizable() + .renderingMode(.template) + .scaledToFit() + .frame(width: size, height: size) + } + +} diff --git a/Modules/Sources/Browse/UI/Extensions/Text+Helpers.swift b/Modules/Sources/Browse/UI/Extensions/Text+Helpers.swift new file mode 100644 index 0000000..1c0a9aa --- /dev/null +++ b/Modules/Sources/Browse/UI/Extensions/Text+Helpers.swift @@ -0,0 +1,23 @@ +// +// Text+Helpers.swift +// Browse +// +// Created by Javier Cicchelli on 03/12/2022. +// Copyright © 2022 Röck+Cöde. All rights reserved. +// + +import SwiftUI + +extension Text { + + /// Renders a text for the name of a folder or document item. + /// - Returns: A formatted text rendered as an erasured view. + func itemName() -> some View { + self + .font(.headline) + .lineLimit(1) + .truncationMode(.middle) + .foregroundColor(.primary) + .frame(maxWidth: .infinity, alignment: .leading) + } +} diff --git a/Modules/Sources/Browse/UI/Toolbars/BrowseToolbar.swift b/Modules/Sources/Browse/UI/Toolbars/BrowseToolbar.swift new file mode 100644 index 0000000..746a3ba --- /dev/null +++ b/Modules/Sources/Browse/UI/Toolbars/BrowseToolbar.swift @@ -0,0 +1,82 @@ +// +// BrowseToolbar.swift +// BeReal +// +// Created by Javier Cicchelli on 03/12/2022. +// Copyright © 2022 Röck+Cöde. All rights reserved. +// + +import SwiftUI + +struct BrowseToolbar: ToolbarContent { + var body: some ToolbarContent { + ToolbarItem(placement: .primaryAction) { + Menu { + Button { + // TODO: Implement the creation of a new folder. + } label: { + Label { + Text( + "browse.toolbar_item.button.add_folder.text", + bundle: .module, + comment: "Add folder button text." + ) + } icon: { + Image.newFolder + } + } + + Button { + // TODO: Implement the upload of a file from the device to the API. + } label: { + Label { + Text( + "browse.toolbar_item.button.add_file.text", + bundle: .module, + comment: "Add file button text." + ) + } icon: { + Image.newFile + } + } + } label: { + Label { + Text( + "browse.toolbar_item.menu.add_actions.text", + bundle: .module, + comment: "Add actions menu text." + ) + } icon: { + Image.add + .foregroundColor(.red) + } + } + } + + ToolbarItem(placement: .navigationBarTrailing) { + Button { + // TODO: Implement the show of the user profile. + } label: { + Label { + Text( + "browse.toolbar_item.button.show_profile.text", + bundle: .module, + comment: "Show profile button text." + ) + } icon: { + Image.profile + .foregroundColor(.red) + } + } + } + } +} + +// MARK: - Image+Constants + +private extension Image { + static let profile = Image(systemName: "person.crop.circle.fill") + static let add = Image(systemName: "plus.circle.fill") + static let newFolder = Image(systemName: "folder.badge.plus") + static let newFile = Image(systemName: "doc.badge.plus") +} diff --git a/Modules/Sources/Browse/UI/Views/BrowseView.swift b/Modules/Sources/Browse/UI/Views/BrowseView.swift new file mode 100644 index 0000000..18fcf98 --- /dev/null +++ b/Modules/Sources/Browse/UI/Views/BrowseView.swift @@ -0,0 +1,129 @@ +// +// BrowseView.swift +// Browse +// +// Created by Javier Cicchelli on 03/12/2022. +// Copyright © 2022 Röck+Cöde. All rights reserved. +// + +import SwiftUI + +public struct BrowseView: View { + + // MARK: Initialisers + + public init() {} + + // MARK: Body + + public var body: some View { + List { + Group { + Group { + FolderItem(name: "Some folder #1 name") + FolderItem(name: "Some folder #2 name") + FolderItem(name: "Some folder #3 name") + FolderItem(name: "Some folder #4 name") + FolderItem(name: "Some folder #5 name") + FolderItem(name: "Some folder #6 name") + FolderItem(name: "Some folder #7 name") + } + Group { + DocumentItem( + name: "Some document #1 name", + lastModified: "3 months ago", + fileSize: "1,23 Mbytes" + ) + DocumentItem( + name: "Some document #2 name", + lastModified: "2 years ago", + fileSize: "123 Kbytes" + ) + DocumentItem( + name: "Some document #3 name", + lastModified: "13 days ago", + fileSize: "12 bytes" + ) + DocumentItem( + name: "Some document #4 name", + lastModified: "13 hours ago", + fileSize: "12,3 Gbytes" + ) + DocumentItem( + name: "Some document #5 name", + lastModified: "13 minutes ago", + fileSize: "123 Tbytes" + ) + DocumentItem( + name: "Some document #6 name", + lastModified: "13 seconds ago", + fileSize: "123 Tbytes" + ) + DocumentItem( + name: "Some document #7 name", + lastModified: "13 nanoseconds ago", + fileSize: "123 Tbytes" + ) + } + } + .swipeActions( + edge: .trailing, + allowsFullSwipe: true + ) { + Button { + // TODO: Implement the removal of the item from the API. + } label: { + Label { + Text( + "browse.swipe_action.delete_item.text", + bundle: .module, + comment: "Delete item swipe action text." + ) + } icon: { + Image.trash + } + } + .tint(.red) + + // TODO: allow download only if item is a file. + Button { + // TODO: Implement the downloading of the data of the item from the API into the device. + } label: { + Label { + Text( + "browse.swipe_action.download_item.text", + bundle: .module, + comment: "Download item swipe action text." + ) + } icon: { + Image.download + } + } + .tint(.orange) + } + } + .listStyle(.inset) + .background(Color.red) + .navigationTitle("Folder name") + .toolbar { + BrowseToolbar() + } + } +} + +// MARK: - Image+Constants + +private extension Image { + static let trash = Image(systemName: "trash") + static let download = Image(systemName: "arrow.down.doc") +} + +// MARK: - Previews + +struct BrowseView_Previews: PreviewProvider { + static var previews: some View { + NavigationView { + BrowseView() + } + } +}