Skip to content

Commit

Permalink
reuse the item details header across details/edit views #33
Browse files Browse the repository at this point in the history
  • Loading branch information
sobri909 committed Apr 28, 2020
1 parent 0718a7e commit 4379d39
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 131 deletions.
4 changes: 4 additions & 0 deletions Arc Mini.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
C9C827B2243DDA7100F3199B /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = C9C827B1243DDA7100F3199B /* Logging */; };
C9C827B5243DEB0000F3199B /* LoggingFormatAndPipe in Frameworks */ = {isa = PBXBuildFile; productRef = C9C827B4243DEB0000F3199B /* LoggingFormatAndPipe */; };
C9C827B7243DEB7F00F3199B /* DebugLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9C827B6243DEB7F00F3199B /* DebugLogger.swift */; };
C9C874F32458484000BAB9A3 /* ItemDetailsHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9C874F22458484000BAB9A3 /* ItemDetailsHeader.swift */; };
C9C96AAF242760A2006D2E5B /* VisitEditView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9C96AAE242760A2006D2E5B /* VisitEditView.swift */; };
C9C96AB224278052006D2E5B /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = C9C96AB124278052006D2E5B /* Introspect */; };
C9DBE4272437462B00FCB8E5 /* Pager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9DBE4262437462B00FCB8E5 /* Pager.swift */; };
Expand Down Expand Up @@ -162,6 +163,7 @@
C9C827AC243C7B1E00F3199B /* Calendar+extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Calendar+extensions.swift"; sourceTree = "<group>"; };
C9C827AE243C830500F3199B /* DispatchQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispatchQueue.swift; sourceTree = "<group>"; };
C9C827B6243DEB7F00F3199B /* DebugLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugLogger.swift; sourceTree = "<group>"; };
C9C874F22458484000BAB9A3 /* ItemDetailsHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDetailsHeader.swift; sourceTree = "<group>"; };
C9C96AAE242760A2006D2E5B /* VisitEditView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisitEditView.swift; sourceTree = "<group>"; };
C9DBE4262437462B00FCB8E5 /* Pager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pager.swift; sourceTree = "<group>"; };
C9DBE428243746FF00FCB8E5 /* TimelineScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineScrollView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -446,6 +448,7 @@
isa = PBXGroup;
children = (
C97DCDEA242395C3006437B7 /* ItemDetailsView.swift */,
C9C874F22458484000BAB9A3 /* ItemDetailsHeader.swift */,
C9C96AAE242760A2006D2E5B /* VisitEditView.swift */,
C90D78532428FBA2004ABFD0 /* PathEditView.swift */,
C9F98B76242FAB38003D2A23 /* ItemSegmentsView.swift */,
Expand Down Expand Up @@ -630,6 +633,7 @@
C9B86B88242CAD8900D52C0D /* ArcError.swift in Sources */,
C9F98B77242FAB38003D2A23 /* ItemSegmentsView.swift in Sources */,
C95E0E252417AEB8008418A1 /* VisitListBox.swift in Sources */,
C9C874F32458484000BAB9A3 /* ItemDetailsHeader.swift in Sources */,
C93062B1243F1B0D00DE47CC /* DebugLogsView.swift in Sources */,
C9C96AAF242760A2006D2E5B /* VisitEditView.swift in Sources */,
C9EB6644241A60FA00F545AF /* ArcStore.swift in Sources */,
Expand Down
156 changes: 156 additions & 0 deletions Arc Mini/Views/TimelineItem/ItemDetailsHeader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
//
// ItemDetailsHeader.swift
// Arc Mini
//
// Created by Matt Greenfield on 28/4/20.
// Copyright © 2020 Matt Greenfield. All rights reserved.
//

import SwiftUI
import LocoKit

struct ItemDetailsHeader: View {

@ObservedObject var timelineItem: TimelineItem
var arcItem: ArcTimelineItem { return timelineItem as! ArcTimelineItem }

@State var tappedSegmentsButton = false
@State var tappedEditButton = false
@State var showDeleteAlert = false

var body: some View {
VStack(alignment: .leading) {
Spacer().frame(height: 24)
Text(arcItem.title)
.font(.system(size: 22, weight: .bold))
.foregroundColor(Color("brandTertiaryDark"))
.padding([.leading, .trailing], 20)
.frame(height: 28)
Spacer().frame(height: 2)
Text(self.dateRangeString)
.font(.system(size: 18, weight: .semibold))
.foregroundColor(Color("brandTertiaryLight"))
.padding([.leading, .trailing], 20)
.frame(height: 26)
HStack(spacing: 0) {
self.segmentsButton
Spacer()
self.deleteButton.opacity(self.canDelete ? 1 : 0)
self.editButton
}
Rectangle().fill(Color("brandSecondary10")).frame(height: 0.5)
}
.listRowInsets(EdgeInsets())
.background(Color("background"))
}

// MARK: -

var dateRangeString: String {
guard let dateRange = timelineItem.dateRange else { return "" }
guard let startString = arcItem.startTimeString else { return "" }

if dateRange.start.isToday, let endString = arcItem.endTimeString {
return String(format: "%@ · %@ - %@", dateRange.shortDurationString, startString, endString)
}

if let endDateString = arcItem.startString(dateStyle: .long, timeStyle: .none, relative: true) {
return String(format: "%@ · %@, %@", dateRange.shortDurationString, startString, endDateString)
}

return ""
}

var canDelete: Bool {
guard timelineItem is ArcVisit else { return false }
return !timelineItem.isCurrentItem
}

func editView(for timelineItem: TimelineItem) -> AnyView {
if let visit = timelineItem as? ArcVisit {
return AnyView(VisitEditView(visit: visit, placeClassifier: visit.placeClassifier))
}
if let path = timelineItem as? ArcPath {
return AnyView(PathEditView(path: path))
}
return AnyView(EmptyView())
}

// MARK: - Buttons

var segmentsButton: some View {
ZStack(alignment: .leading) {
Button(action: {
self.tappedSegmentsButton = true
}) {
HStack(alignment: .center) {
Image(systemName: "circle.grid.2x2")
.font(.system(size: 18, weight: .regular))
.foregroundColor(Color("brandSecondary80"))
.frame(width: 24, height: 24)
Text("Segments")
.font(.system(size: 15, weight: .regular))
.foregroundColor(Color("brandSecondaryDark"))
}.padding(.leading, 20)
}
.frame(height: 64)
NavigationLink(destination: ItemSegmentsView(timelineItem: timelineItem), isActive: $tappedSegmentsButton) {
EmptyView()
}.hidden()
}
}

var deleteButton: some View {
ZStack(alignment: .trailing) {
Button(action: {
self.showDeleteAlert = true
}) {
HStack(alignment: .center) {
Spacer().frame(width: 20)
Image(systemName: "trash")
.font(.system(size: 18, weight: .regular))
.foregroundColor(Color("brandSecondary80"))
.frame(width: 24, height: 24)
.offset(x: 0, y: -1)
Spacer().frame(width: 20)
Rectangle().fill(Color("grey")).frame(width: 1, height: 24)
}
}
.frame(height: 64)
}
.alert(isPresented: $showDeleteAlert) {
Alert.delete(visit: self.timelineItem as! ArcVisit)
}
}

var editButton: some View {
ZStack(alignment: .trailing) {
Button(action: {
self.tappedEditButton = true
}) {
HStack(alignment: .center) {
Image(systemName: "square.and.pencil")
.font(.system(size: 18, weight: .regular))
.foregroundColor(Color("brandSecondary80"))
.frame(width: 24, height: 24)
.offset(x: 0, y: -1.5)
Text("Edit")
.font(.system(size: 15, weight: .regular))
.foregroundColor(Color("brandSecondaryDark"))
}
.padding([.leading, .trailing], 20)
}
.frame(height: 64)
NavigationLink(destination: editView(for: timelineItem), isActive: $tappedEditButton) {
EmptyView()
}.hidden()
}
}

}

//struct ItemDetailsHeader_Previews: PreviewProvider {
// static var previews: some View {
// ItemDetailsHeader()
// }
//}
132 changes: 1 addition & 131 deletions Arc Mini/Views/TimelineItem/ItemDetailsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ struct ItemDetailsView: View {
@ObservedObject var timelineItem: TimelineItem
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

@State var tappedEditButton = false
@State var tappedSegmentsButton = false
@State var showDeleteAlert = false

var arcItem: ArcTimelineItem { return timelineItem as! ArcTimelineItem }

Expand All @@ -32,7 +29,7 @@ struct ItemDetailsView: View {

var body: some View {
List {
Section(header: self.header) {
Section(header: ItemDetailsHeader(timelineItem: self.timelineItem)) {
EmptyView()
}
}
Expand All @@ -54,133 +51,6 @@ struct ItemDetailsView: View {
}
}

var header: some View {
VStack(alignment: .leading) {
Spacer().frame(height: 24)
Text(arcItem.title)
.font(.system(size: 22, weight: .bold))
.foregroundColor(Color("brandTertiaryDark"))
.padding([.leading, .trailing], 20)
.frame(height: 28)
Spacer().frame(height: 2)
Text(self.dateRangeString)
.font(.system(size: 18, weight: .semibold))
.foregroundColor(Color("brandTertiaryLight"))
.padding([.leading, .trailing], 20)
.frame(height: 26)
HStack(spacing: 0) {
self.segmentsButton
Spacer()
self.deleteButton.opacity(self.canDelete ? 1 : 0)
self.editButton
}
Rectangle().fill(Color("brandSecondary10")).frame(height: 0.5)
}
.listRowInsets(EdgeInsets())
.background(Color("background"))
}

var dateRangeString: String {
guard let dateRange = timelineItem.dateRange else { return "" }
guard let startString = arcItem.startTimeString else { return "" }

if dateRange.start.isToday, let endString = arcItem.endTimeString {
return String(format: "%@ · %@ - %@", dateRange.shortDurationString, startString, endString)
}

if let endDateString = arcItem.startString(dateStyle: .long, timeStyle: .none, relative: true) {
return String(format: "%@ · %@, %@", dateRange.shortDurationString, startString, endDateString)
}

return ""
}

// MARK: - Buttons

var segmentsButton: some View {
ZStack(alignment: .leading) {
Button(action: {
self.tappedSegmentsButton = true
}) {
HStack(alignment: .center) {
Image(systemName: "circle.grid.2x2")
.font(.system(size: 18, weight: .regular))
.foregroundColor(Color("brandSecondary80"))
.frame(width: 24, height: 24)
Text("Segments")
.font(.system(size: 15, weight: .regular))
.foregroundColor(Color("brandSecondaryDark"))
}.padding(.leading, 20)
}
.frame(height: 64)
NavigationLink(destination: ItemSegmentsView(timelineItem: timelineItem), isActive: $tappedSegmentsButton) {
EmptyView()
}.hidden()
}
}

var canDelete: Bool {
guard timelineItem is ArcVisit else { return false }
return !timelineItem.isCurrentItem
}

var deleteButton: some View {
ZStack(alignment: .trailing) {
Button(action: {
self.showDeleteAlert = true
}) {
HStack(alignment: .center) {
Spacer().frame(width: 20)
Image(systemName: "trash")
.font(.system(size: 18, weight: .regular))
.foregroundColor(Color("brandSecondary80"))
.frame(width: 24, height: 24)
.offset(x: 0, y: -1)
Spacer().frame(width: 20)
Rectangle().fill(Color("grey")).frame(width: 1, height: 24)
}
}
.frame(height: 64)
}
.alert(isPresented: $showDeleteAlert) {
Alert.delete(visit: self.timelineItem as! ArcVisit)
}
}

var editButton: some View {
ZStack(alignment: .trailing) {
Button(action: {
self.tappedEditButton = true
}) {
HStack(alignment: .center) {
Image(systemName: "square.and.pencil")
.font(.system(size: 18, weight: .regular))
.foregroundColor(Color("brandSecondary80"))
.frame(width: 24, height: 24)
.offset(x: 0, y: -1.5)
Text("Edit")
.font(.system(size: 15, weight: .regular))
.foregroundColor(Color("brandSecondaryDark"))
}
.padding([.leading, .trailing], 20)
}
.frame(height: 64)
NavigationLink(destination: editView(for: timelineItem), isActive: $tappedEditButton) {
EmptyView()
}.hidden()
}
}

func editView(for timelineItem: TimelineItem) -> AnyView {
if let visit = timelineItem as? ArcVisit {
return AnyView(VisitEditView(visit: visit, placeClassifier: visit.placeClassifier))
}
if let path = timelineItem as? ArcPath {
return AnyView(PathEditView(path: path))
}
return AnyView(EmptyView())
}

}

//struct ItemDetailsView_Previews: PreviewProvider {
Expand Down
1 change: 1 addition & 0 deletions Arc Mini/Views/TimelineItem/PathEditView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct PathEditView: View {

var body: some View {
List {
ItemDetailsHeader(timelineItem: self.path)
ForEach(Array(classifierResults), id: \.name) { result in
Button(action: {
self.path.trainActivityType(to: result.name)
Expand Down
1 change: 1 addition & 0 deletions Arc Mini/Views/TimelineItem/VisitEditView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct VisitEditView: View {
var body: some View {
VStack {
List {
ItemDetailsHeader(timelineItem: self.visit)
ForEach(placeClassifier.results, id: \.place.placeId) { result in
Button(action: {
self.visit.usePlace(result.place, manualPlace: true)
Expand Down

0 comments on commit 4379d39

Please sign in to comment.