Skip to content
Open
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
81 changes: 75 additions & 6 deletions freewrite/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ struct ContentView: View {
@State private var selectedVideoHasTranscript = false
@State private var backspaceDisabled = false // Add state for backspace toggle
@State private var isHoveringBackspaceToggle = false // Add state for backspace toggle hover
@State private var pinnedEntryIds: Set<String> = []
@State private var hoveredPinId: UUID? = nil
@State private var showingVideoRecording = false // Add state for video recording view
@State private var isHoveringVideoButton = false // Add state for video button hover
@State private var currentVideoURL: URL? = nil // Add state for current video being viewed
Expand Down Expand Up @@ -867,7 +869,31 @@ struct ContentView: View {
return colorScheme == .light ? Color.primary : Color.white
}


private var sortedEntries: [HumanEntry] {
let pinned = entries.filter { pinnedEntryIds.contains($0.id.uuidString) }
let unpinned = entries.filter { !pinnedEntryIds.contains($0.id.uuidString) }
return pinned + unpinned
}

private func isEntryPinned(_ entry: HumanEntry) -> Bool {
pinnedEntryIds.contains(entry.id.uuidString)
}

private func togglePin(_ entry: HumanEntry) {
let idString = entry.id.uuidString
if pinnedEntryIds.contains(idString) {
pinnedEntryIds.remove(idString)
} else {
pinnedEntryIds.insert(idString)
}
UserDefaults.standard.set(Array(pinnedEntryIds), forKey: "pinnedEntryIds")
}

private func loadPinnedEntries() {
let saved = UserDefaults.standard.stringArray(forKey: "pinnedEntryIds") ?? []
pinnedEntryIds = Set(saved)
}

var body: some View {
let buttonBackground = colorScheme == .light ? Color.white : Color.black
let navHeight: CGFloat = 68
Expand Down Expand Up @@ -1563,7 +1589,7 @@ struct ContentView: View {
// Entries List
ScrollView {
LazyVStack(spacing: 0) {
ForEach(entries) { entry in
ForEach(sortedEntries) { entry in
Button(action: {
if selectedEntryId != entry.id {
historyDebug("ROW TAP \(debugEntrySummary(entry))")
Expand Down Expand Up @@ -1614,16 +1640,45 @@ struct ContentView: View {

VStack(alignment: .leading, spacing: 4) {
HStack {
if isEntryPinned(entry) && hoveredEntryId != entry.id {
Image(systemName: "pin.fill")
.font(.system(size: 9))
.foregroundColor(.secondary)
.rotationEffect(.degrees(45))
}
Text(entry.previewText)
.font(.system(size: 13))
.lineLimit(1)
.foregroundColor(.primary)

Spacer()
// Export/Trash icons that appear on hover

// Pin/Export/Trash icons that appear on hover
if hoveredEntryId == entry.id {
HStack(spacing: 8) {
// Pin button
Button(action: {
togglePin(entry)
}) {
Image(systemName: isEntryPinned(entry) ? "pin.slash" : "pin")
.font(.system(size: 11))
.foregroundColor(hoveredPinId == entry.id ?
(colorScheme == .light ? .black : .white) :
(colorScheme == .light ? .gray : .gray.opacity(0.8)))
}
.buttonStyle(.plain)
.help(isEntryPinned(entry) ? "Unpin entry" : "Pin entry")
.onHover { hovering in
withAnimation(.easeInOut(duration: 0.2)) {
hoveredPinId = hovering ? entry.id : nil
}
if hovering {
NSCursor.pointingHand.push()
} else {
NSCursor.pop()
}
}

// Export PDF button
Button(action: {
exportEntryAsPDF(entry: entry)
Expand Down Expand Up @@ -1695,8 +1750,21 @@ struct ContentView: View {
}
.help("Click to select this entry") // Add tooltip

if entry.id != entries.last?.id {
Divider()
if entry.id != sortedEntries.last?.id {
// Thicker divider between pinned and unpinned sections
if isEntryPinned(entry) && !pinnedEntryIds.isEmpty {
let sortedList = sortedEntries
if let idx = sortedList.firstIndex(where: { $0.id == entry.id }),
idx + 1 < sortedList.count,
!isEntryPinned(sortedList[idx + 1]) {
Divider().frame(height: 2)
.background(Color.secondary.opacity(0.3))
} else {
Divider()
}
} else {
Divider()
}
}
}
}
Expand Down Expand Up @@ -1729,6 +1797,7 @@ struct ContentView: View {
.preferredColorScheme(colorScheme)
.onAppear {
showingSidebar = false // Hide sidebar by default
loadPinnedEntries()
loadExistingEntries()
}
.onChange(of: showingVideoRecording) { _, isShowing in
Expand Down