diff options
Diffstat (limited to 'iTexSnip/Views')
| -rw-r--r-- | iTexSnip/Views/DetailedSnippetView.swift | 245 | ||||
| -rw-r--r-- | iTexSnip/Views/MenuBarView.swift | 443 | ||||
| -rw-r--r-- | iTexSnip/Views/PreferencesView.swift | 10 | 
3 files changed, 349 insertions, 349 deletions
| diff --git a/iTexSnip/Views/DetailedSnippetView.swift b/iTexSnip/Views/DetailedSnippetView.swift index c7386fa..f63284d 100644 --- a/iTexSnip/Views/DetailedSnippetView.swift +++ b/iTexSnip/Views/DetailedSnippetView.swift @@ -5,141 +5,140 @@  //  Created by Navan Chauhan on 10/21/24.  // -import SwiftUI  import LaTeXSwiftUI +import SwiftUI  struct DetailedSnippetView: View { -    @Environment(\.modelContext) var modelContext -    @Environment(\.dismiss) private var dismiss -     -    @State var showOriginal = false -     -     -    var snippet: ImageSnippet -    var body: some View { -        VStack { -            HStack { -                Toggle("Show Original", isOn: $showOriginal) -                    .toggleStyle(.switch) -                    .padding() -                Spacer() -                HStack { -                    Button { -                        if snippet.rating == true { -                            updateRating(nil) -                        } else { -                            updateRating(true) -                        } -                    } label: { -                        if snippet.rating == true { -                            Image(systemName: "hand.thumbsup") -                                .foregroundStyle(.green) -                                .imageScale(.large) -                        } else { -                            Image(systemName: "hand.thumbsup") -                                .imageScale(.large) -                        } -                    }.buttonStyle(PlainButtonStyle()) -                     -                    Button { -                        if snippet.rating == false { -                            updateRating(nil) -                        } else { -                            updateRating(false) -                        } -                    } label: { -                        if snippet.rating == false { -                            Image(systemName: "hand.thumbsdown") -                                .foregroundStyle(.red) -                                .imageScale(.large) -                        } else { -                            Image(systemName: "hand.thumbsdown") -                                .imageScale(.large) -                        } -                    }.buttonStyle(PlainButtonStyle()) -                     -                    Button(role: .destructive) { -                        withAnimation { -                            modelContext.delete(snippet) -                            do { -                                try modelContext.save() -                                dismiss() -                            } catch { -                                print("Failed to delete snippet: \(error)") -                            } -                        } -                    } label: { -                        Image(systemName: "trash") -                            .imageScale(.large) -                    } -                    .padding() -                    .buttonStyle(PlainButtonStyle()) -               }.padding() +  @Environment(\.modelContext) var modelContext +  @Environment(\.dismiss) private var dismiss + +  @State var showOriginal = false + +  var snippet: ImageSnippet +  var body: some View { +    VStack { +      HStack { +        Toggle("Show Original", isOn: $showOriginal) +          .toggleStyle(.switch) +          .padding() +        Spacer() +        HStack { +          Button { +            if snippet.rating == true { +              updateRating(nil) +            } else { +              updateRating(true)              } -            if (showOriginal) { -                HStack { -                    Spacer() -                    Image(nsImage: NSImage(data: snippet.image)!) -                        .resizable() -                        .clipped() -                        .cornerRadius(10) -                        .scaledToFit() -                        .frame(height: 100) -                    Spacer() -                }.padding() +          } label: { +            if snippet.rating == true { +              Image(systemName: "hand.thumbsup") +                .foregroundStyle(.green) +                .imageScale(.large) +            } else { +              Image(systemName: "hand.thumbsup") +                .imageScale(.large)              } -            HStack { -                Spacer() -                LaTeXEquationView(equation: snippet.transcribedText!) -                    .clipped() -                    .scaledToFit() -                    .frame(height: 100) -                Spacer() +          }.buttonStyle(PlainButtonStyle()) + +          Button { +            if snippet.rating == false { +              updateRating(nil) +            } else { +              updateRating(false)              } -            GeometryReader { geometry in -                HStack { -                    Button { -                        print("Should Copy") -                    } label: { -                        Image(systemName: "document.on.clipboard") -                    } -                        ScrollView(.horizontal) { -                            Text(snippet.transcribedText!) -                                .frame(height: 50) -                                .textSelection(.enabled) -                        } -                        .frame(width: geometry.size.width * 0.8) -                        .border(Color.red) -                     -                    Spacer() -                    Button { -                        print("Should Copy") -                    } label: { -                        Image(systemName: "document.on.clipboard") -                    } -                } +          } label: { +            if snippet.rating == false { +              Image(systemName: "hand.thumbsdown") +                .foregroundStyle(.red) +                .imageScale(.large) +            } else { +              Image(systemName: "hand.thumbsdown") +                .imageScale(.large)              } -            Spacer() -        } -    } -     -    func updateRating(_ rating: Bool?) { -        withAnimation { -            self.snippet.rate(rating) -            do { +          }.buttonStyle(PlainButtonStyle()) + +          Button(role: .destructive) { +            withAnimation { +              modelContext.delete(snippet) +              do {                  try modelContext.save() -            } catch { -                print("Error saving rating: \(error)") +                dismiss() +              } catch { +                print("Failed to delete snippet: \(error)") +              }              } +          } label: { +            Image(systemName: "trash") +              .imageScale(.large) +          } +          .padding() +          .buttonStyle(PlainButtonStyle()) +        }.padding() +      } +      if showOriginal { +        HStack { +          Spacer() +          Image(nsImage: NSImage(data: snippet.image)!) +            .resizable() +            .clipped() +            .cornerRadius(10) +            .scaledToFit() +            .frame(height: 100) +          Spacer() +        }.padding() +      } +      HStack { +        Spacer() +        LaTeXEquationView(equation: snippet.transcribedText!) +          .clipped() +          .scaledToFit() +          .frame(height: 100) +        Spacer() +      } +      GeometryReader { geometry in +        HStack { +          Button { +            print("Should Copy") +          } label: { +            Image(systemName: "document.on.clipboard") +          } +          ScrollView(.horizontal) { +            Text(snippet.transcribedText!) +              .frame(height: 50) +              .textSelection(.enabled) +          } +          .frame(width: geometry.size.width * 0.8) +          .border(Color.red) + +          Spacer() +          Button { +            print("Should Copy") +          } label: { +            Image(systemName: "document.on.clipboard") +          }          } +      } +      Spacer()      } +  } + +  func updateRating(_ rating: Bool?) { +    withAnimation { +      self.snippet.rate(rating) +      do { +        try modelContext.save() +      } catch { +        print("Error saving rating: \(error)") +      } +    } +  }  }  struct LaTeXEquationView: View { -    var equation: String -    var body: some View { -        LaTeX(equation) -            .parsingMode(.all) -            .font(.system(size: 28, weight: .bold)) -    } +  var equation: String +  var body: some View { +    LaTeX(equation) +      .parsingMode(.all) +      .font(.system(size: 28, weight: .bold)) +  }  } diff --git a/iTexSnip/Views/MenuBarView.swift b/iTexSnip/Views/MenuBarView.swift index feea7a8..255ad99 100644 --- a/iTexSnip/Views/MenuBarView.swift +++ b/iTexSnip/Views/MenuBarView.swift @@ -5,254 +5,255 @@  //  Created by Navan Chauhan on 10/20/24.  // +import AppKit  import LaTeXSwiftUI -import SwiftUI  import SwiftData -import AppKit +import SwiftUI  @Model  class ImageSnippet { -    var dateCreated: Date -    var dateModifed: Date -    var image: Data -    var transcribedText: String? -    var rating: Bool? -     -    init(image: NSImage, transcribedText: String? = nil) { -        self.dateCreated = Date() -        self.image = image.tiffRepresentation! -        self.transcribedText = transcribedText -        self.dateModifed = Date() -    } -     -    func updateModifiedDate() { -        self.dateModifed = Date() -    } -     -    func rate(_ rating: Bool?) { -        self.rating = rating -    } +  var dateCreated: Date +  var dateModifed: Date +  var image: Data +  var transcribedText: String? +  var rating: Bool? + +  init(image: NSImage, transcribedText: String? = nil) { +    self.dateCreated = Date() +    self.image = image.tiffRepresentation! +    self.transcribedText = transcribedText +    self.dateModifed = Date() +  } + +  func updateModifiedDate() { +    self.dateModifed = Date() +  } + +  func rate(_ rating: Bool?) { +    self.rating = rating +  }  }  struct MenuBarView: View { -    @Environment(\.modelContext) var modelContext -    @State var model: TexTellerModel? -    @Query(sort: \ImageSnippet.dateModifed, order: .reverse) var snippets: [ImageSnippet] -     -    let columns = [ -        GridItem(.flexible(), spacing: 16), -        GridItem(.flexible(), spacing: 16) -    ] -     -    var body: some View { -        NavigationStack { -            VStack { -                HStack { -                    Text("iTeXSnip") -                        .font(.title) -                    Spacer() -                    Button { -                        pickImageFilesAndAddSnippet() -                    } label: { -                        Image(systemName: "photo.badge.plus") -                            .imageScale(.large) -                    } -                    .accessibilityLabel("Load Image File") -                    .buttonStyle(PlainButtonStyle()) -                     -                    Button { -                        takeScreenshotAndAddSnippet() -                    } label: { -                        Image(systemName: "scissors") -                            .imageScale(.large) -                    } -                    .accessibilityLabel("Screenshot") -                    .buttonStyle(PlainButtonStyle()) -                    Menu { -                        SettingsLink { -                            Text("Open Preferences") -                        } -                        Button("Quit") { -                            NSApplication.shared.terminate(nil) -                        } -                    } label: { -                        Image(systemName: "gear") -                            .imageScale(.large) -                    } -                    .buttonStyle(PlainButtonStyle()) -                    .accessibilityLabel("Preferences") -                }.padding() -                 -                ScrollView { -                    LazyVGrid(columns: columns, spacing: 16) { -                        ForEach(snippets) { snippet in -                            NavigationLink(destination: DetailedSnippetView(snippet: snippet)) { -                                SnippetView(snippet: snippet, deleteSnippet: deleteSnippet) -                                    .frame(height: 200) -                                    .padding() -                            } -                            //                            .frame(height: 300) -                        } -                    } -                    .padding() -                } -                 -                Spacer() -            }.task { -                do { -                    if self.model == nil { -                        let mymodel = try await TexTellerModel.asyncInit() -                        self.model = mymodel -                        print("Loaded da model") -                    } -                } catch { -                    print("Failed to load da model: \(error)") -                } -            } -        } -    } -     -    func pickImageFilesAndAddSnippet() { -        let panel = NSOpenPanel() -        panel.allowedContentTypes = [.image] -        panel.allowsMultipleSelection = false -        panel.canChooseDirectories = false -        panel.title = "Choose an image" -         -        if panel.runModal() == .OK { -            if let url = panel.url, let image = NSImage(contentsOf: url) { -                let newSnippet = ImageSnippet(image: image) -                do { -                    if self.model != nil { -                        let latex = try self.model!.texIt(image) -                        newSnippet.transcribedText = latex -                    } -                    modelContext.insert(newSnippet) -                    try modelContext.save() -                } catch { -                    print("Failed to save new snippet: \(error)") -                } +  @Environment(\.modelContext) var modelContext +  @State var model: TexTellerModel? +  @Query(sort: \ImageSnippet.dateModifed, order: .reverse) var snippets: [ImageSnippet] + +  let columns = [ +    GridItem(.flexible(), spacing: 16), +    GridItem(.flexible(), spacing: 16), +  ] + +  var body: some View { +    NavigationStack { +      VStack { +        HStack { +          Text("iTeXSnip") +            .font(.title) +          Spacer() +          Button { +            pickImageFilesAndAddSnippet() +          } label: { +            Image(systemName: "photo.badge.plus") +              .imageScale(.large) +          } +          .accessibilityLabel("Load Image File") +          .buttonStyle(PlainButtonStyle()) + +          Button { +            takeScreenshotAndAddSnippet() +          } label: { +            Image(systemName: "scissors") +              .imageScale(.large) +          } +          .accessibilityLabel("Screenshot") +          .buttonStyle(PlainButtonStyle()) +          Menu { +            SettingsLink { +              Text("Open Preferences")              } -        } -    } -     -    func takeScreenshotAndAddSnippet() { -        if !CGPreflightScreenCaptureAccess() { -                // App doesn't have permission, request permission -                if !CGRequestScreenCaptureAccess() { -                    // Permission was denied, show alert to the user -                    DispatchQueue.main.async { -                        let alert = NSAlert() -                        alert.messageText = "Screen Recording Permission Denied" -                        alert.informativeText = "Please grant screen recording permissions in System Preferences > Security & Privacy." -                        alert.addButton(withTitle: "OK") -                        alert.runModal() -                    } -                    return -                } +            Button("Quit") { +              NSApplication.shared.terminate(nil)              } -         -        let task = Process() -        task.launchPath = "/usr/sbin/screencapture" -        let tempPath = NSTemporaryDirectory() + "temp_itexsnip_ss.png" -        task.arguments = ["-i", tempPath] -         -        let pipe = Pipe() -        task.standardOutput = pipe -        task.standardError = pipe -         -        task.terminationHandler = { process in -            DispatchQueue.main.async { -                if FileManager.default.fileExists(atPath: tempPath) { -                    if let screenshotImage = NSImage(contentsOfFile: tempPath) { -                        let newSnippet = ImageSnippet(image: screenshotImage) -                        do { -                            if self.model != nil { -                                let latex = try self.model!.texIt(screenshotImage) -                                newSnippet.transcribedText = latex -                            } -                            self.modelContext.insert(newSnippet) -                            try self.modelContext.save() -                        } catch { -                            print("Failed to add snippet: \(error)") -                        } -                    } else { -                        print("Failed to get image...") -                    } -                     -                    do { -                        try FileManager.default.removeItem(atPath: tempPath) -                        print("Temp screenshot cleaned up") -                    } catch { -                        print("Failed to delete screenshot: \(error)") -                    } -                     -                } else { -                    print("Screenshot was cancelled or failed") -                } +          } label: { +            Image(systemName: "gear") +              .imageScale(.large) +          } +          .buttonStyle(PlainButtonStyle()) +          .accessibilityLabel("Preferences") +        }.padding() + +        ScrollView { +          LazyVGrid(columns: columns, spacing: 16) { +            ForEach(snippets) { snippet in +              NavigationLink(destination: DetailedSnippetView(snippet: snippet)) { +                SnippetView(snippet: snippet, deleteSnippet: deleteSnippet) +                  .frame(height: 200) +                  .padding() +              } +              //                            .frame(height: 300)              } +          } +          .padding()          } -         + +        Spacer() +      }.task {          do { -            try task.run() +          if self.model == nil { +            let mymodel = try await TexTellerModel.asyncInit() +            self.model = mymodel +            print("Loaded da model") +          }          } catch { -            print("Failed to launch screencapture process: \(error)") -            return +          print("Failed to load da model: \(error)")          } - +      }      } -     -    func deleteSnippet(snippet: ImageSnippet) { +  } + +  func pickImageFilesAndAddSnippet() { +    let panel = NSOpenPanel() +    panel.allowedContentTypes = [.image] +    panel.allowsMultipleSelection = false +    panel.canChooseDirectories = false +    panel.title = "Choose an image" + +    if panel.runModal() == .OK { +      if let url = panel.url, let image = NSImage(contentsOf: url) { +        let newSnippet = ImageSnippet(image: image)          do { -            modelContext.delete(snippet) -            try modelContext.save() +          if self.model != nil { +            let latex = try self.model!.texIt(image) +            newSnippet.transcribedText = latex +          } +          modelContext.insert(newSnippet) +          try modelContext.save()          } catch { -            print("Failed to delete snippet: \(error)") +          print("Failed to save new snippet: \(error)") +        } +      } +    } +  } + +  func takeScreenshotAndAddSnippet() { +    if !CGPreflightScreenCaptureAccess() { +      // App doesn't have permission, request permission +      if !CGRequestScreenCaptureAccess() { +        // Permission was denied, show alert to the user +        DispatchQueue.main.async { +          let alert = NSAlert() +          alert.messageText = "Screen Recording Permission Denied" +          alert.informativeText = +            "Please grant screen recording permissions in System Preferences > Security & Privacy." +          alert.addButton(withTitle: "OK") +          alert.runModal()          } +        return +      }      } + +    let task = Process() +    task.launchPath = "/usr/sbin/screencapture" +    let tempPath = NSTemporaryDirectory() + "temp_itexsnip_ss.png" +    task.arguments = ["-i", tempPath] + +    let pipe = Pipe() +    task.standardOutput = pipe +    task.standardError = pipe + +    task.terminationHandler = { process in +      DispatchQueue.main.async { +        if FileManager.default.fileExists(atPath: tempPath) { +          if let screenshotImage = NSImage(contentsOfFile: tempPath) { +            let newSnippet = ImageSnippet(image: screenshotImage) +            do { +              if self.model != nil { +                let latex = try self.model!.texIt(screenshotImage) +                newSnippet.transcribedText = latex +              } +              self.modelContext.insert(newSnippet) +              try self.modelContext.save() +            } catch { +              print("Failed to add snippet: \(error)") +            } +          } else { +            print("Failed to get image...") +          } + +          do { +            try FileManager.default.removeItem(atPath: tempPath) +            print("Temp screenshot cleaned up") +          } catch { +            print("Failed to delete screenshot: \(error)") +          } + +        } else { +          print("Screenshot was cancelled or failed") +        } +      } +    } + +    do { +      try task.run() +    } catch { +      print("Failed to launch screencapture process: \(error)") +      return +    } + +  } + +  func deleteSnippet(snippet: ImageSnippet) { +    do { +      modelContext.delete(snippet) +      try modelContext.save() +    } catch { +      print("Failed to delete snippet: \(error)") +    } +  }  }  struct SnippetView: View { -    var snippet: ImageSnippet -    var deleteSnippet: (ImageSnippet) -> Void -     -    var body: some View { -        VStack { -            if let nsImage = NSImage(data: snippet.image) { -                GeometryReader { geometry in -                    Image(nsImage: nsImage) -                        .resizable() -                        .scaledToFit() -                        .frame(maxWidth: .infinity) -                        .frame(height: 100) -                        .clipped() -                        .cornerRadius(10) -                } -                .contextMenu { -                    Button(role: .destructive) { -                        deleteSnippet(snippet) -                    } label: { -                        Label("Delete", systemImage: "trash") -                    } -                } -            } -            ScrollView(.horizontal) { -                HStack{ -                    Spacer() -                    LaTeX(snippet.transcribedText ?? "") -                        .parsingMode(.all) -                        .frame(maxWidth: .infinity) -                        .frame(height: 100) -                        .layoutPriority(1) -                        .font(.system(size: 28, weight: .bold)) -                    Spacer() -                } -            }.scrollBounceBehavior(.basedOnSize, axes: [.horizontal]) +  var snippet: ImageSnippet +  var deleteSnippet: (ImageSnippet) -> Void +  var body: some View { +    VStack { +      if let nsImage = NSImage(data: snippet.image) { +        GeometryReader { geometry in +          Image(nsImage: nsImage) +            .resizable() +            .scaledToFit() +            .frame(maxWidth: .infinity) +            .frame(height: 100) +            .clipped() +            .cornerRadius(10) +        } +        .contextMenu { +          Button(role: .destructive) { +            deleteSnippet(snippet) +          } label: { +            Label("Delete", systemImage: "trash") +          }          } +      } +      ScrollView(.horizontal) { +        HStack { +          Spacer() +          LaTeX(snippet.transcribedText ?? "") +            .parsingMode(.all) +            .frame(maxWidth: .infinity) +            .frame(height: 100) +            .layoutPriority(1) +            .font(.system(size: 28, weight: .bold)) +          Spacer() +        } +      }.scrollBounceBehavior(.basedOnSize, axes: [.horizontal]) +      } +  }  }  #Preview { -    MenuBarView() +  MenuBarView()  } diff --git a/iTexSnip/Views/PreferencesView.swift b/iTexSnip/Views/PreferencesView.swift index 98eb4b9..9837b88 100644 --- a/iTexSnip/Views/PreferencesView.swift +++ b/iTexSnip/Views/PreferencesView.swift @@ -8,9 +8,9 @@  import SwiftUI  struct PreferencesView: View { -    var body: some View { -        Text("Where are my preferences?!") -            .padding() -            .frame(width: 300, height: 200) -    } +  var body: some View { +    Text("Where are my preferences?!") +      .padding() +      .frame(width: 300, height: 200) +  }  } | 
