Skip to content

Commit

Permalink
Merge pull request #280 from aapis/feature/1.9/post-interface-header-…
Browse files Browse the repository at this point in the history
…add-context

Refactoring, UI tweaks to Today view posting interface
  • Loading branch information
aapis authored Oct 8, 2024
2 parents 7bd26d3 + 4cac619 commit 92b1fde
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 131 deletions.
4 changes: 2 additions & 2 deletions KWCore/Sources/UI/TypedListRowBackground.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ struct TypedListRowBackground: View {
.opacity(0.1)
type.icon
.font(.system(size: 70))
.foregroundStyle(self.colour.isBright() ? self.colour : .black.opacity(0.1))
.foregroundStyle(self.colour.isBright() ? self.colour : .black.opacity(0.2))
.opacity(0.3)
.shadow(color: self.colour.isBright() ? .black.opacity(0.1) : .white.opacity(0.2), radius: 4, x: 1, y: 1)
.shadow(color: self.colour.isBright() ? .black.opacity(0.2) : .white.opacity(0.2), radius: 4, x: 1, y: 1)
}
}
}
4 changes: 4 additions & 0 deletions KlockWork.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
53967D8429EC6D14006616A0 /* TodaySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53967D8329EC6D14006616A0 /* TodaySettings.swift */; };
53967D8629EC7DEB006616A0 /* ViewModeSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53967D8529EC7DEB006616A0 /* ViewModeSelector.swift */; };
53999C1F29669C4E00125E65 /* NoteCreate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53999C1E29669C4E00125E65 /* NoteCreate.swift */; };
5399AF762CB4995A00211ECD /* EntityTypeHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5399AF752CB4995400211ECD /* EntityTypeHeader.swift */; };
539F68DB2BF6BD310086F89A /* FancyDropdown.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539F68DA2BF6BD310086F89A /* FancyDropdown.swift */; };
539F68DD2BF70A260086F89A /* IntroToKlockWork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539F68DC2BF70A260086F89A /* IntroToKlockWork.swift */; };
53B0BE7F2972542A007CB663 /* ProjectsDashboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53B0BE7E2972542A007CB663 /* ProjectsDashboard.swift */; };
Expand Down Expand Up @@ -432,6 +433,7 @@
53967D8329EC6D14006616A0 /* TodaySettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodaySettings.swift; sourceTree = "<group>"; };
53967D8529EC7DEB006616A0 /* ViewModeSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModeSelector.swift; sourceTree = "<group>"; };
53999C1E29669C4E00125E65 /* NoteCreate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteCreate.swift; sourceTree = "<group>"; };
5399AF752CB4995400211ECD /* EntityTypeHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntityTypeHeader.swift; sourceTree = "<group>"; };
539F68DA2BF6BD310086F89A /* FancyDropdown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FancyDropdown.swift; sourceTree = "<group>"; };
539F68DC2BF70A260086F89A /* IntroToKlockWork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroToKlockWork.swift; sourceTree = "<group>"; };
53B0BE7E2972542A007CB663 /* ProjectsDashboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectsDashboard.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1248,6 +1250,7 @@
53EDDF9C29634840008D34C7 /* Shared */ = {
isa = PBXGroup;
children = (
5399AF752CB4995400211ECD /* EntityTypeHeader.swift */,
53E9187D2B47C9CC00912C6F /* PanelGroup */,
53790C012A72F15200D3FFD4 /* AppSidebar */,
53B0BE822972610C007CB663 /* Fancy */,
Expand Down Expand Up @@ -1635,6 +1638,7 @@
53013A962CAB825B0024BA30 /* GlobalSidebar.swift in Sources */,
53C000962B3A7BD500D5EC04 /* String.swift in Sources */,
537628A22966525500DE8ECF /* ToolbarButtons.swift in Sources */,
5399AF762CB4995A00211ECD /* EntityTypeHeader.swift in Sources */,
537AEBA1296287B900385787 /* LogRow.swift in Sources */,
53C3419029996C070071B855 /* FancyRandomJobColourPicker.swift in Sources */,
537368D124B93DB600193E88 /* Today.swift in Sources */,
Expand Down
Binary file removed KlockWork/.DS_Store
Binary file not shown.
198 changes: 78 additions & 120 deletions KlockWork/Views/Entities/Today/PostingInterface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,19 @@ extension Today {
TypedListRowBackground(colour: self.nav.session.job?.backgroundColor ?? Theme.rowColour, type: .jobs)
.frame(height: 60)
.clipShape(.rect(topLeadingRadius: 5, topTrailingRadius: 5))
ResourcePath()
EntityTypeHeader()
Buttons(text: $text, onActionSubmit: self.submitAction, onActionClear: self.clearAction)
}

ZStack(alignment: .topLeading) {
FancyTextField(
placeholder: "What are you working on?",
lineLimit: 11,
onSubmit: submitAction,
fgColour: nav.session.job != nil ? nav.session.job!.colour_from_stored().isBright() ? .black : .white : .white,
fgColour: self.nav.session.job?.backgroundColor.isBright() ?? false ? Theme.base : .white,
text: $text
)
.background(nav.session.job != nil ? nav.session.job!.colour_from_stored() : .clear)
.background(self.nav.session.job?.backgroundColor.opacity(0.6) ?? .clear)
.focused($primaryTextFieldInFocus)
.onAppear {
// thx https://www.kodeco.com/31569019-focus-management-in-swiftui-getting-started#toc-anchor-002
Expand All @@ -55,61 +56,18 @@ extension Today {
Button("Ok", role: .cancel) {}
}

VStack(alignment: .trailing, spacing: 0) {
Spacer()
HStack(spacing: 1) {
Spacer()
LinearGradient(colors: [Theme.base, .clear], startPoint: .top, endPoint: .bottom)
.blendMode(.softLight)
.frame(height: 80)
.opacity(0.1)

if allowCLIMode {
FancyButtonv2(
text: "Command line mode",
action: {commandLineMode.toggle()},
icon: "apple.terminal",
fgColour: nav.session.job != nil ? Color.fromStored(nav.session.job!.colour!).isBright() ? Theme.base : .white : .white,
showLabel: false,
size: .tiny,
type: .clear
)
.help("Enter CLI mode")
.frame(width: 30, height: 30)
.background(nav.session.job != nil ? nav.session.job!.colour_from_stored() : self.page.primaryColour.opacity(0.5))
.disabled(false)
}

FancyButtonv2(
text: "Reset interface to default state",
action: clearAction,
icon: "arrow.clockwise",
fgColour: nav.session.job != nil ? Color.fromStored(nav.session.job!.colour!).isBright() ? Theme.base : .white : .white,
showLabel: false,
size: .tiny,
type: .clear
)
.help("Reset interface to default state")
.frame(width: 30, height: 30)
.background(nav.session.job != nil ? nav.session.job!.colour_from_stored() : self.page.primaryColour.opacity(0.5))
.disabled(nav.session.job == nil)
.opacity(nav.session.job == nil ? 0.5 : 1)

FancyButtonv2(
text: nav.session.job != nil ? "Log to job \(nav.session.job!.jid.string)" : "Log",
action: submitAction,
icon: "plus",
fgColour: nav.session.job != nil ? Color.fromStored(nav.session.job!.colour!).isBright() ? Theme.base : .white : .white,
showLabel: false,
size: .tiny,
type: .clear
)
.help("Create a new record (alternatively, press Return!)")
.frame(width: 30, height: 30)
.background(nav.session.job != nil ? nav.session.job!.colour_from_stored() : self.page.primaryColour.opacity(0.5))
.disabled(nav.session.job == nil)
.opacity(nav.session.job == nil ? 0.5 : 1)
}
Divider().frame(height: 1).foregroundStyle(.clear)
}
}
.frame(height: 215)

FancyHelpText(
text: "Choose a job from the sidebar, type into the field below. Enter/Return/+ to create records.",
page: self.page
)
}
.onChange(of: text) {
if self.text.isEmpty {
Expand All @@ -122,81 +80,75 @@ extension Today {
}
}
}
}

struct ResourcePath: View {
@EnvironmentObject public var state: Navigation
@State private var resourcePath: String = ""
@State private var parts: [ResourcePathItem] = []

var body: some View {
HStack(alignment: .center, spacing: 8) {
if self.parts.count > 0 {
ForEach(self.parts, id: \.id) { part in part }
} else {
ResourcePathItem(text: "Choose a job from the sidebar, type into the field below. Enter/Return/+ to create records.")
}
}
.padding([.leading, .trailing])
.font(.title2)
.foregroundStyle((self.state.session.job?.backgroundColor ?? Theme.rowColour).isBright() ? Theme.base.opacity(0.55) : .white.opacity(0.55))
.onAppear(perform: self.actionSetViewState)
.onChange(of: self.state.session.job) { self.actionSetViewState() }
.onChange(of: self.state.session.project) { self.actionSetViewState() }
.onChange(of: self.state.session.company) { self.actionSetViewState() }
}

struct ResourcePathItem: View, Identifiable {
struct Buttons: View {
@EnvironmentObject public var state: Navigation
public var id: UUID = UUID()
public var text: String
public var target: Page = .dashboard
@State private var isHighlighted: Bool = false
@AppStorage("today.commandLineMode") private var commandLineMode: Bool = false
@AppStorage("general.experimental.cli") private var allowCLIMode: Bool = false
@State private var errorNoJob: Bool = false
@State private var errorNoContent: Bool = false
private let page: PageConfiguration.AppPage = .today
@Binding public var text: String
public var onActionSubmit: (() -> Void) = {}
public var onActionClear: (() -> Void) = {}

var body: some View {
HStack(alignment: .center) {
Button {
self.state.to(self.target)
} label: {
Text(self.text)
.underline(self.isHighlighted && self.target != .dashboard) // using .dashboard as "default"
HStack(alignment: .center, spacing: 8) {
Spacer()
if allowCLIMode {
FancyButtonv2(
text: "Command line mode",
action: {commandLineMode.toggle()},
icon: "apple.terminal",
iconWhenHighlighted: "apple.terminal.fill",
fgColour: self.state.session.job?.backgroundColor.isBright() ?? false ? Theme.base : .white,
showLabel: false,
size: .small,
type: .clear
)
.help("Enter CLI mode")
.frame(width: 25)
}
.buttonStyle(.plain)

if self.text != self.state.session.job?.title && self.target != .dashboard {
Image(systemName: "chevron.right")
}
FancyButtonv2(
text: "Reset interface to default state",
action: self.onActionClear,
icon: "arrow.clockwise.square",
iconWhenHighlighted: "arrow.clockwise.square.fill",
fgColour: self.state.session.job?.backgroundColor.isBright() ?? false ? Theme.base : .white,
showLabel: false,
size: .small,
type: .clear
)
.help("Reset interface to default state")
.frame(width: 25)
.disabled(self.state.session.job == nil)
.opacity(self.state.session.job == nil ? 0.5 : 1)

FancyButtonv2(
text: self.state.session.job != nil ? "Log to job \(self.state.session.job!.title ?? self.state.session.job!.jid.string)" : "Log",
action: self.onActionSubmit,
icon: "plus.square",
iconWhenHighlighted: "plus.square.fill",
fgColour: self.state.session.job?.backgroundColor.isBright() ?? false ? Theme.base : .white,
showLabel: false,
size: .small,
type: .clear
)
.help("Create a new record (alternatively, press Return!)")
.frame(width: 25)
.disabled(self.state.session.job == nil)
.opacity(self.state.session.job == nil ? 0.5 : 1)
}
.useDefaultHover({ hover in self.isHighlighted = hover})
.padding(.trailing)
}
}
}
}

extension Today.ResourcePath {
/// Fires onload and whenever the session job is changed. Compiles a breadcrumb based on selected job/project/company
/// - Returns: Void
private func actionSetViewState() -> Void {
self.parts = []
if let company = self.state.session.company {
if company.name != nil {
self.parts.append(ResourcePathItem(text: company.name!, target: company.pageDetailType))
}
}

if let project = self.state.session.project {
if project.name != nil {
self.parts.append(ResourcePathItem(text: project.name!, target: project.pageDetailType))
}
}

if let job = self.state.session.job {
self.parts.append(ResourcePathItem(text: job.title ?? job.jid.string, target: job.pageDetailType))
}
}
}

extension Today.PostingInterface {
/// Begin the process of creating new entities
/// - Returns: Void
private func submitAction() -> Void {
if !text.isEmpty && nav.session.job != nil {
Task {
Expand All @@ -212,7 +164,9 @@ extension Today.PostingInterface {
}
}
}


/// Fires during the submitAction process. Creates new records & other entities.
/// - Returns: Void
private func save() async -> Void {
if let job = nav.session.job {
let record = LogRecord(context: moc)
Expand Down Expand Up @@ -267,8 +221,12 @@ extension Today.PostingInterface {
}
}

/// Clear the text field
/// - Returns: Void
private func clearAction() -> Void {
text = ""
nav.session.job = nil
self.text = ""
self.nav.session.job = nil
self.nav.session.company = nil
self.nav.session.project = nil
}
}
Loading

0 comments on commit 92b1fde

Please sign in to comment.