diff --git a/freewrite/ContentView.swift b/freewrite/ContentView.swift index cb973af..b3813eb 100644 --- a/freewrite/ContentView.swift +++ b/freewrite/ContentView.swift @@ -85,6 +85,22 @@ struct ContentView: View { @State private var colorScheme: ColorScheme = .light // Add state for color scheme @State private var isHoveringThemeToggle = false // Add state for theme toggle hover @State private var didCopyPrompt: Bool = false // Add state for copy prompt feedback + @State private var searchText: String = "" + + var filteredEntries: [HumanEntry] { + let query = searchText.trimmed().lowercased() + guard !query.isEmpty else { return entries } + + return entries.filter { entry in + let fileURL = getDocumentsDirectory().appendingPathComponent(entry.filename) + if let content = try? String(contentsOf: fileURL, encoding: .utf8) { + return content.lowercased().contains(query) + } + return false + } + } + + let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect() let entryHeight: CGFloat = 40 @@ -382,6 +398,8 @@ struct ContentView: View { return colorScheme == .light ? Color.primary : Color.white } + @State private var viewHeight: CGFloat = 0 + var body: some View { let buttonBackground = colorScheme == .light ? Color.white : Color.black let navHeight: CGFloat = 68 @@ -394,17 +412,18 @@ struct ContentView: View { Color(colorScheme == .light ? .white : .black) .ignoresSafeArea() - TextEditor(text: Binding( - get: { text }, - set: { newValue in - // Ensure the text always starts with two newlines - if !newValue.hasPrefix("\n\n") { - text = "\n\n" + newValue.trimmingCharacters(in: .newlines) - } else { - text = newValue + + TextEditor(text: Binding( + get: { text }, + set: { newValue in + // Ensure the text always starts with two newlines + if !newValue.hasPrefix("\n\n") { + text = "\n\n" + newValue.trimmingCharacters(in: .newlines) + } else { + text = newValue + } } - } - )) + )) .background(Color(colorScheme == .light ? .white : .black)) .font(.custom(selectedFont, size: fontSize)) .foregroundColor(colorScheme == .light ? Color(red: 0.20, green: 0.20, blue: 0.20) : Color(red: 0.9, green: 0.9, blue: 0.9)) @@ -412,6 +431,8 @@ struct ContentView: View { .scrollIndicators(.never) .lineSpacing(lineHeight) .frame(maxWidth: 650) + + .id("\(selectedFont)-\(fontSize)-\(colorScheme)") .padding(.bottom, bottomNavOpacity > 0 ? navHeight : 0) .ignoresSafeArea() @@ -426,13 +447,20 @@ struct ContentView: View { Text(placeholderText) .font(.custom(selectedFont, size: fontSize)) .foregroundColor(colorScheme == .light ? .gray.opacity(0.5) : .gray.opacity(0.6)) - // .padding(.top, 8) - // .padding(.leading, 8) + // .padding(.top, 8) + // .padding(.leading, 8) .allowsHitTesting(false) .offset(x: 5, y: placeholderOffset) } }, alignment: .topLeading ) + .onGeometryChange(for: CGFloat.self) { proxy in + proxy.size.height + } action: { height in + viewHeight = height + } + .contentMargins(.bottom, viewHeight / 4) + VStack { Spacer() @@ -909,10 +937,21 @@ struct ContentView: View { Divider() + HStack { + TextField("Search entries...", text: $searchText) + .textFieldStyle(PlainTextFieldStyle()) + .padding(8) + .background(Color.gray.opacity(0.1)) + .cornerRadius(8) + } + .padding([.horizontal, .vertical], 12) + + Divider() + // Entries List ScrollView { LazyVStack(spacing: 0) { - ForEach(entries) { entry in + ForEach(filteredEntries) { entry in Button(action: { if selectedEntryId != entry.id { // Save current entry before switching @@ -944,9 +983,9 @@ struct ContentView: View { }) { Image(systemName: "arrow.down.circle") .font(.system(size: 11)) - .foregroundColor(hoveredExportId == entry.id ? - (colorScheme == .light ? .black : .white) : - (colorScheme == .light ? .gray : .gray.opacity(0.8))) + .foregroundColor(hoveredExportId == entry.id ? + (colorScheme == .light ? .black : .white) : + (colorScheme == .light ? .gray : .gray.opacity(0.8))) } .buttonStyle(.plain) .help("Export entry as PDF") @@ -1397,6 +1436,13 @@ extension NSView { } } +extension String { + func trimmed() -> String { + self.trimmingCharacters(in: .whitespacesAndNewlines) + } +} + + #Preview { ContentView() -} \ No newline at end of file +}