Skip to content
Open
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
30 changes: 28 additions & 2 deletions ora/Modules/Sidebar/ContainerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ struct ContainerView: View {
@EnvironmentObject var privacyMode: PrivacyMode

@State var isDragging = false
@State private var isHovered = false
@State private var draggedItem: UUID?
@State private var editingURLString: String = ""

var body: some View {
VStack(alignment: .leading, spacing: 16) {
VStack(alignment: .leading, spacing: 0) {
if toolbarManager.isToolbarHidden, let tab = tabManager.activeTab {
SidebarURLDisplay(
tab: tab,
Expand Down Expand Up @@ -73,7 +74,27 @@ struct ContainerView: View {
onMoveToContainer: moveTab,
containers: containers
)
Divider()

HStack {
ZStack {
Capsule()
.frame(height: 1)
Text("Clear").bold().font(.footnote).opacity(0)
}
if isHovered, !normalTabs.isEmpty {
Button("Clear") {
withAnimation {
for tab in container.tabs where tab.type == .normal {
tabManager.closeTab(tab: tab)
}
}
}
.bold()
.font(.footnote)
.buttonStyle(.plain)
}
}
.foregroundStyle(.secondary)
}
NormalTabsList(
tabs: normalTabs,
Expand All @@ -91,6 +112,11 @@ struct ContainerView: View {
}
}
.modifier(OraWindowDragGesture(isDragging: $isDragging))
.onHover { hov in
withAnimation {
isHovered = hov
}
}
}

private var favoriteTabs: [Tab] {
Expand Down
2 changes: 1 addition & 1 deletion ora/Modules/Sidebar/SidebarView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct SidebarView: View {
}

var body: some View {
VStack(alignment: .leading, spacing: 16) {
VStack(alignment: .leading) {
SidebarToolbar()
NSPageView(
selection: selectedContainerIndex,
Expand Down
37 changes: 27 additions & 10 deletions ora/Modules/Sidebar/TabList/FavTabsList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import SwiftUI
struct FavTabsGrid: View {
@Environment(\.theme) var theme
@EnvironmentObject var tabManager: TabManager
@EnvironmentObject var sidebarManager: SidebarManager
@State private var isHoveringOverEmpty: Bool = false
let tabs: [Tab]
@Binding var draggedItem: UUID?
let onDrag: (UUID) -> NSItemProvider
Expand All @@ -25,18 +27,28 @@ struct FavTabsGrid: View {
}

var body: some View {
LazyVGrid(columns: adaptiveColumns, spacing: 10) {
let isShowingHidden = tabs.isEmpty && !(
sidebarManager.stickyFavs || isHoveringOverEmpty
)
LazyVGrid(columns: adaptiveColumns, spacing: isShowingHidden ? 0 : 10) {
if tabs.isEmpty {
EmptyFavTabItem()
.onDrop(
of: [.text],
delegate: SectionDropDelegate(
items: tabs,
draggedItem: $draggedItem,
targetSection: .fav,
tabManager: tabManager
)
Group {
if sidebarManager.stickyFavs || isHoveringOverEmpty {
EmptyFavTabItem()
} else {
Capsule().frame(height: 3).opacity(0)
}
}
.onDrop(
of: [.text],
delegate: SectionDropDelegate(
items: tabs,
draggedItem: $draggedItem,
targetSection: .fav,
tabManager: tabManager,
isHovering: $isHoveringOverEmpty
)
)
} else {
ForEach(tabs) { tab in
FavTabItem(
Expand Down Expand Up @@ -71,5 +83,10 @@ struct FavTabsGrid: View {
tabManager: tabManager
)
)
.onChange(of: tabs.count) { _, newTabs in
if newTabs > 0 {
sidebarManager.stickyFavs = false
}
}
}
}
27 changes: 24 additions & 3 deletions ora/Modules/Sidebar/TabList/PinnedTabsList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import SwiftUI
struct PinnedTabsList: View {
let tabs: [Tab]
@Binding var draggedItem: UUID?
@State private var isHoveringOverEmpty = false
let onDrag: (UUID) -> NSItemProvider
let onSelect: (Tab) -> Void
let onPinToggle: (Tab) -> Void
Expand All @@ -13,17 +14,31 @@ struct PinnedTabsList: View {
let onMoveToContainer: (Tab, TabContainer) -> Void
let containers: [TabContainer]
@EnvironmentObject var tabManager: TabManager
@EnvironmentObject var sidebarManager: SidebarManager
@Environment(\.theme) var theme

private var spaceName: String? {
if let active = tabManager.activeContainer {
return "\(active.emoji) \(active.name)"
}
return nil
}

var body: some View {
VStack(spacing: 8) {
Text("Pinned")
Text(spaceName ?? "Pinned")
.font(.callout)
.foregroundColor(theme.mutedForeground)
.padding(.top, 8)
.frame(maxWidth: .infinity, alignment: .leading)
if tabs.isEmpty {
EmptyPinnedTabs()
Group {
if sidebarManager.stickyPinned || isHoveringOverEmpty {
EmptyPinnedTabs()
} else {
Capsule().frame(height: 3).opacity(0)
}
}
} else {
ForEach(tabs) { tab in
TabItem(
Expand Down Expand Up @@ -57,8 +72,14 @@ struct PinnedTabsList: View {
items: tabs,
draggedItem: $draggedItem,
targetSection: .pinned,
tabManager: tabManager
tabManager: tabManager,
isHovering: $isHoveringOverEmpty
)
)
.onChange(of: tabs.count) { _, new in
if new > 0 {
sidebarManager.stickyPinned = false
}
}
}
}
37 changes: 29 additions & 8 deletions ora/Services/SectionDropDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,39 @@ import SwiftUI
struct SectionDropDelegate: DropDelegate {
let items: [Tab]
@Binding var draggedItem: UUID?
@Binding var isHovering: Bool
let targetSection: TabSection
let tabManager: TabManager

init(
items: [Tab],
draggedItem: Binding<UUID?>,
targetSection: TabSection,
tabManager: TabManager,
isHovering: Binding<Bool>? = nil
) {
self.items = items
self._draggedItem = draggedItem
self.targetSection = targetSection
self.tabManager = tabManager
self._isHovering = isHovering ?? .constant(false)
}

func dropEntered(info: DropInfo) {
guard let provider = info.itemProviders(for: [.text]).first else { return }
isHovering = true
}

func dropExited(info: DropInfo) {
isHovering = false
}

func dropUpdated(info: DropInfo) -> DropProposal? {
DropProposal(operation: .move)
}

func performDrop(info: DropInfo) -> Bool {
isHovering = false
guard let provider = info.itemProviders(for: [.text]).first else { return false }
performHapticFeedback(pattern: .alignment)

provider.loadObject(ofClass: NSString.self) { object, _ in
Expand Down Expand Up @@ -48,13 +76,6 @@ struct SectionDropDelegate: DropDelegate {
// }
}
}
}

func dropUpdated(info: DropInfo) -> DropProposal? {
DropProposal(operation: .move)
}

func performDrop(info: DropInfo) -> Bool {
draggedItem = nil
return true
}
Expand Down
2 changes: 2 additions & 0 deletions ora/Services/SidebarManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ enum SidebarPosition: String, Hashable {

@MainActor
class SidebarManager: ObservableObject {
@AppStorage("ui.sidebar.favorites.sticky") var stickyFavs: Bool = true
@AppStorage("ui.sidebar.pinned.sticky") var stickyPinned: Bool = true
@AppStorage("ui.sidebar.hidden") var isSidebarHidden: Bool = false
@AppStorage("ui.sidebar.position") var sidebarPosition: SidebarPosition = .primary

Expand Down