aboutsummaryrefslogtreecommitdiff
path: root/iTexSnip/Views/MenuBarView.swift
diff options
context:
space:
mode:
Diffstat (limited to 'iTexSnip/Views/MenuBarView.swift')
-rw-r--r--iTexSnip/Views/MenuBarView.swift443
1 files changed, 222 insertions, 221 deletions
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()
}