Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tasks and Activity Viewer UI Improvements #1831

Merged
merged 15 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 45 additions & 13 deletions CodeEdit.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions CodeEdit/Features/ActivityViewer/ActivityViewer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,14 @@ struct ActivityViewer: View {
.fixedSize()
}
.fixedSize(horizontal: false, vertical: false)
.padding(.horizontal, 10)
.padding(.horizontal, 5)
.padding(.vertical, 1.5)
.frame(height: 22)
.clipped()
.background {
if colorScheme == .dark {
RoundedRectangle(cornerRadius: 5)
.opacity(0.10)
.opacity(0.1)
} else {
RoundedRectangle(cornerRadius: 5)
.opacity(0.1)
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
//
// CustomLoadingRingView.swift
// CECircularProgressView.swift
// CodeEdit
//
// Created by Tommy Ludwig on 21.06.24.
//

import SwiftUI

struct CustomLoadingRingView: View {
struct CECircularProgressView: View {
@State private var isAnimating = false
@State private var previousValue: Bool = false

var progress: Double?
var currentTaskCount: Int
var currentTaskCount: Int = 1

let lineWidth: CGFloat = 2

var body: some View {
Circle()
.stroke(style: StrokeStyle(lineWidth: lineWidth))
Expand All @@ -22,12 +24,12 @@ struct CustomLoadingRingView: View {
if let progress = progress {
Circle()
.trim(from: 0, to: progress)
.stroke(Color.blue.gradient, style: StrokeStyle(lineWidth: lineWidth, lineCap: .round))
.stroke(Color.accentColor, style: StrokeStyle(lineWidth: lineWidth, lineCap: .round))
.animation(.easeInOut, value: progress)
} else {
Circle()
.trim(from: 0, to: 0.5)
.stroke(Color.blue.gradient, style: StrokeStyle(lineWidth: lineWidth, lineCap: .round))
.stroke(Color.accentColor, style: StrokeStyle(lineWidth: lineWidth, lineCap: .round))
.rotationEffect(
previousValue ?
.degrees(isAnimating ? 0 : -360)
Expand All @@ -41,6 +43,7 @@ struct CustomLoadingRingView: View {
}
}
.rotationEffect(.degrees(-90))
.padding(lineWidth/2)
.overlay {
if currentTaskCount > 1 {
Text("\(currentTaskCount)")
Expand All @@ -52,10 +55,10 @@ struct CustomLoadingRingView: View {

#Preview {
Group {
CustomLoadingRingView(currentTaskCount: 1)
CECircularProgressView(currentTaskCount: 1)
.frame(width: 22, height: 22)

CustomLoadingRingView(progress: 0.65, currentTaskCount: 1)
CECircularProgressView(progress: 0.65, currentTaskCount: 1)
.frame(width: 22, height: 22)
}
.padding()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// TaskNotificationView.swift
// CodeEdit
//
// Created by Tommy Ludwig on 21.06.24.
//

import SwiftUI

struct TaskNotificationView: View {
@ObservedObject var taskNotificationHandler: TaskNotificationHandler
@State private var isPresented: Bool = false
@State var notification: TaskNotificationModel?

var body: some View {
ZStack {
if let notification {
HStack {
Text(notification.title)
.font(.subheadline)
.transition(
.asymmetric(insertion: .move(edge: .top), removal: .move(edge: .bottom))
.combined(with: .opacity)
)
.id("NotificationTitle" + notification.title)

if notification.isLoading {
CECircularProgressView(
progress: notification.percentage,
currentTaskCount: taskNotificationHandler.notifications.count
)
.padding(.horizontal, -1)
.frame(height: 16)
} else {
if taskNotificationHandler.notifications.count > 1 {
Text("\(taskNotificationHandler.notifications.count)")
.font(.caption)
.padding(5)
.background(
Circle()
.foregroundStyle(.gray)
.opacity(0.2)
)
.padding(-5)
}
}
}
.transition(.opacity.combined(with: .move(edge: .trailing)))
.padding(3)
.padding(-3)
.padding(.trailing, 3)
.popover(isPresented: $isPresented, arrowEdge: .bottom) {
TaskNotificationsDetailView(taskNotificationHandler: taskNotificationHandler)
}.onTapGesture {
self.isPresented.toggle()
}
}
}
.animation(.easeInOut, value: notification)
.onChange(of: taskNotificationHandler.notifications) { newValue in
withAnimation {
notification = newValue.first
}
}
}

}

#Preview {
TaskNotificationView(taskNotificationHandler: TaskNotificationHandler())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// TaskNotificationsDetailView.swift
// CodeEdit
//
// Created by Tommy Ludwig on 21.06.24.
//

import SwiftUI

struct TaskNotificationsDetailView: View {
@ObservedObject var taskNotificationHandler: TaskNotificationHandler
@State private var selectedTaskNotificationIndex: Int = 0
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 15) {
ForEach(taskNotificationHandler.notifications, id: \.id) { notification in
HStack(alignment: .center, spacing: 8) {
CECircularProgressView(progress: notification.percentage)
.frame(width: 16, height: 16)
VStack(alignment: .leading) {
Text(notification.title)
.fixedSize(horizontal: false, vertical: true)
.transition(.identity)

if let message = notification.message, !message.isEmpty {
Text(message)
.font(.subheadline)
.foregroundStyle(.secondary)
}
}
Spacer()
}
}
}
}
.padding(15)
.frame(minWidth: 320)
.onChange(of: taskNotificationHandler.notifications) { newValue in
if selectedTaskNotificationIndex >= newValue.count {
selectedTaskNotificationIndex = 0
}
}
}
}

#Preview {
TaskNotificationsDetailView(taskNotificationHandler: TaskNotificationHandler())
}
21 changes: 21 additions & 0 deletions CodeEdit/Features/ActivityViewer/Tasks/ActiveTaskView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// ActiveTaskView.swift
// CodeEdit
//
// Created by Austin Condiff on 8/4/24.
//

import SwiftUI

// We need to observe each active task individually because:
// 1. Active tasks are nested inside TaskManager.
// 2. Reference types (like objects) do not notify observers when their internal state changes.
/// `ActiveTaskView` represents a single active task and observes its state.
/// - Parameter activeTask: The active task to be displayed and observed.
struct ActiveTaskView: View {
@ObservedObject var activeTask: CEActiveTask

var body: some View {
TaskView(task: activeTask.task, status: activeTask.status)
}
}
Loading
Loading