add FileFormat enum and file tracking to AppState

This commit is contained in:
jess 2026-04-06 13:23:18 -07:00
parent 23cdf0f8ee
commit 93d00f4282
1 changed files with 87 additions and 0 deletions

View File

@ -1,6 +1,82 @@
import Foundation
import Combine
enum FileFormat: String, CaseIterable {
case markdown, csv, json, toml, yaml, xml, svg
case rust, c, cpp, objc
case javascript, typescript, jsx, tsx
case html, css, scss, less
case python, go, ruby, php, lua
case shell, java, kotlin, swift, zig, sql
case makefile, dockerfile
case config, lock, plainText
case unknown
static func from(extension ext: String) -> FileFormat {
switch ext.lowercased() {
case "md", "markdown", "mdown": return .markdown
case "csv": return .csv
case "json": return .json
case "toml": return .toml
case "yaml", "yml": return .yaml
case "xml": return .xml
case "svg": return .svg
case "rs": return .rust
case "c": return .c
case "cpp", "cc", "cxx": return .cpp
case "h", "hpp", "hxx": return .cpp
case "m": return .objc
case "js": return .javascript
case "jsx": return .jsx
case "ts": return .typescript
case "tsx": return .tsx
case "html", "htm": return .html
case "css": return .css
case "scss": return .scss
case "less": return .less
case "py": return .python
case "go": return .go
case "rb": return .ruby
case "php": return .php
case "lua": return .lua
case "sh", "bash", "zsh", "fish": return .shell
case "java": return .java
case "kt", "kts": return .kotlin
case "swift": return .swift
case "zig": return .zig
case "sql": return .sql
case "mk": return .makefile
case "ini", "cfg", "conf", "env": return .config
case "lock": return .lock
case "txt", "text", "log": return .plainText
default: return .unknown
}
}
static func from(filename: String) -> FileFormat {
let lower = filename.lowercased()
if lower == "makefile" { return .makefile }
if lower == "dockerfile" { return .dockerfile }
let ext = (filename as NSString).pathExtension
if ext.isEmpty { return .unknown }
return from(extension: ext)
}
var isCode: Bool {
switch self {
case .rust, .c, .cpp, .objc, .javascript, .typescript, .jsx, .tsx,
.html, .css, .scss, .less, .python, .go, .ruby, .php, .lua,
.shell, .java, .kotlin, .swift, .zig, .sql, .makefile, .dockerfile:
return true
default:
return false
}
}
var isMarkdown: Bool { self == .markdown }
var isCSV: Bool { self == .csv }
}
class AppState: ObservableObject {
@Published var documentText: String = "" {
didSet {
@ -16,6 +92,8 @@ class AppState: ObservableObject {
@Published var currentNoteID: UUID
@Published var selectedNoteIDs: Set<UUID> = []
@Published var modified: Bool = false
@Published var currentFileURL: URL? = nil
@Published var currentFileFormat: FileFormat = .markdown
private let bridge = RustBridge.shared
private var autoSaveTimer: DispatchSourceTimer?
@ -120,6 +198,8 @@ class AppState: ObservableObject {
documentText = ""
evalResults = [:]
modified = false
currentFileURL = nil
currentFileFormat = .markdown
refreshNoteList()
}
@ -162,6 +242,9 @@ class AppState: ObservableObject {
func saveNote() {
bridge.setText(currentNoteID, text: documentText)
if let url = currentFileURL {
let _ = bridge.saveNote(currentNoteID, path: url.path)
}
let _ = bridge.cacheSave(currentNoteID)
modified = false
refreshNoteList()
@ -169,6 +252,8 @@ class AppState: ObservableObject {
func saveNoteToFile(_ url: URL) {
let _ = bridge.saveNote(currentNoteID, path: url.path)
currentFileURL = url
currentFileFormat = FileFormat.from(filename: url.lastPathComponent)
modified = false
}
@ -176,6 +261,8 @@ class AppState: ObservableObject {
if let (id, text) = bridge.loadNote(path: url.path) {
currentNoteID = id
documentText = text
currentFileURL = url
currentFileFormat = FileFormat.from(filename: url.lastPathComponent)
modified = false
let _ = bridge.cacheSave(id)
evaluate()