Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
glushchenko committed Mar 10, 2024
1 parent 0d11d53 commit 7d9912a
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 46 deletions.
2 changes: 1 addition & 1 deletion FSNotes iOS/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -4514,7 +4514,7 @@
}
},
"Notes" : {
"comment" : "Sidebar items\nSidebar label\nNotes in sidebar",
"comment" : "Notes in sidebar\nSidebar items\nSidebar label",
"localizations" : {
"de" : {
"stringUnit" : {
Expand Down
2 changes: 1 addition & 1 deletion FSNotes iOS/View/EditTextView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ class EditTextView: UITextView, UITextViewDelegate {
if let imageUrl = note.getImageUrl(imageName: path) {

let range = NSRange(location: selectedRange.location, length: 1)
let attachment = NoteAttachment(editor: self, title: "", path: path, url: imageUrl, invalidateRange: range, note: note)
let attachment = NoteAttachment(editor: self, title: "", path: path, url: imageUrl, note: note)

if let attributedString = attachment.getAttributedString() {

Expand Down
17 changes: 17 additions & 0 deletions FSNotes.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@
D76025C0204F078A000B9F59 /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = D76025BD204F078A000B9F59 /* [email protected] */; };
D76025C1204F078A000B9F59 /* bold.png in Resources */ = {isa = PBXBuildFile; fileRef = D76025BE204F078A000B9F59 /* bold.png */; };
D76447DC1F3A4F0700965F01 /* UserDefaultsManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = D76447DB1F3A4F0700965F01 /* UserDefaultsManagement.swift */; };
D76755652B9E2840003714C8 /* SwiftSoup in Frameworks */ = {isa = PBXBuildFile; productRef = D76755642B9E2840003714C8 /* SwiftSoup */; };
D7679376201F0BFD000F7BBF /* SortBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7679375201F0BFD000F7BBF /* SortBy.swift */; };
D7679377201F0BFD000F7BBF /* SortBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7679375201F0BFD000F7BBF /* SortBy.swift */; };
D7679389201F21F5000F7BBF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7679388201F21F5000F7BBF /* AppDelegate.swift */; };
Expand Down Expand Up @@ -1614,6 +1615,7 @@
D7F1AEB32921774B0088F473 /* SoulverCore in Frameworks */,
D70F830428CE858E004818C5 /* Git in Frameworks */,
BE957A4A1B908EC91BECB3D3 /* Pods_FSNotes__iCloud_.framework in Frameworks */,
D76755652B9E2840003714C8 /* SwiftSoup in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -2670,6 +2672,7 @@
D70F830328CE858E004818C5 /* Git */,
D7F1AEB1292177060088F473 /* SoulverCore */,
D7D2F27D2B54BD42003DCA47 /* Shout */,
D76755642B9E2840003714C8 /* SwiftSoup */,
);
productName = FSNotes;
productReference = D7E81C5A1F925B5F00416A91 /* FSNotes.app */;
Expand Down Expand Up @@ -2793,6 +2796,7 @@
D7B4CC5428C7B8860046A25F /* XCRemoteSwiftPackageReference "swift-git" */,
D7F1AEB0292177060088F473 /* XCRemoteSwiftPackageReference "SoulverCore" */,
D7D2F27C2B54BD42003DCA47 /* XCRemoteSwiftPackageReference "Shout" */,
D76755632B9E2840003714C8 /* XCRemoteSwiftPackageReference "SwiftSoup" */,
);
productRefGroup = D7793C701F211C6000CA39B7 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -4702,6 +4706,14 @@
minimumVersion = 2.2.0;
};
};
D76755632B9E2840003714C8 /* XCRemoteSwiftPackageReference "SwiftSoup" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/scinfu/SwiftSoup.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.7.1;
};
};
D7B4CC5428C7B8860046A25F /* XCRemoteSwiftPackageReference "swift-git" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/glushchenko/swift-git";
Expand Down Expand Up @@ -4749,6 +4761,11 @@
package = D7B4CC5428C7B8860046A25F /* XCRemoteSwiftPackageReference "swift-git" */;
productName = Git;
};
D76755642B9E2840003714C8 /* SwiftSoup */ = {
isa = XCSwiftPackageProductDependency;
package = D76755632B9E2840003714C8 /* XCRemoteSwiftPackageReference "SwiftSoup" */;
productName = SwiftSoup;
};
D7A9C1DA29107A0800905619 /* Git */ = {
isa = XCSwiftPackageProductDependency;
package = D7B4CC5428C7B8860046A25F /* XCRemoteSwiftPackageReference "swift-git" */;
Expand Down
2 changes: 1 addition & 1 deletion FSNotes/Extensions/ImageAttachment+.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extension NoteAttachment {
var sizeTitle = String()

if fileSize > 10000 {
sizeTitle = String(format: "%.2f", fileSize / 1000000) + " MB"
sizeTitle = String(format: "%.2f", Double(fileSize) / 1000000) + " MB"
} else {
sizeTitle = String(fileSize) + " bytes"
}
Expand Down
115 changes: 76 additions & 39 deletions FSNotes/View/EditTextView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Cocoa
import Highlightr
import Carbon.HIToolbox
import FSNotesCore_macOS
import SwiftSoup

class EditTextView: NSTextView, NSTextFinderClient, NSSharingServicePickerDelegate {

Expand Down Expand Up @@ -987,7 +988,8 @@ class EditTextView: NSTextView, NSTextFinderClient, NSSharingServicePickerDelega
unregisterDraggedTypes()
registerForDraggedTypes([
NSPasteboard.PasteboardType(kUTTypeFileURL as String),
NSPasteboard.noteType
NSPasteboard.noteType,
.URL
])

if let label = editorViewController?.vcNonSelectedLabel {
Expand Down Expand Up @@ -1617,10 +1619,9 @@ class EditTextView: NSTextView, NSTextFinderClient, NSSharingServicePickerDelega
override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
let board = sender.draggingPasteboard
let range = selectedRange
var data: Data

let dropPoint = convert(sender.draggingLocation, from: nil)
let caretLocation = characterIndexForInsertion(at: dropPoint)
var replacementRange = NSRange(location: caretLocation, length: 0)

guard let note = self.note, let storage = textStorage else { return false }

Expand Down Expand Up @@ -1649,7 +1650,8 @@ class EditTextView: NSTextView, NSTextFinderClient, NSSharingServicePickerDelega
return true
}

if let data = board.data(forType: NSPasteboard.PasteboardType.init(rawValue: "attributedText")), let attributedText = NSKeyedUnarchiver.unarchiveObject(with: data) as? NSMutableAttributedString {
if let data = board.data(forType: NSPasteboard.PasteboardType.init(rawValue: "attributedText")),
let attributedText = NSKeyedUnarchiver.unarchiveObject(with: data) as? NSMutableAttributedString {
let dropPoint = convert(sender.draggingLocation, from: nil)
let caretLocation = characterIndexForInsertion(at: dropPoint)

Expand All @@ -1665,7 +1667,7 @@ class EditTextView: NSTextView, NSTextFinderClient, NSSharingServicePickerDelega
guard let imageUrl = note.getImageUrl(imageName: path) else { return false }

let locationDiff = position > caretLocation ? caretLocation : caretLocation - 1
let attachment = NoteAttachment(editor: self, title: title, path: path, url: imageUrl, invalidateRange: NSRange(location: locationDiff, length: 1))
let attachment = NoteAttachment(editor: self, title: title, path: path, url: imageUrl)

guard let attachmentText = attachment.getAttributedString() else { return false }
guard locationDiff < storage.length else { return false }
Expand All @@ -1684,7 +1686,6 @@ class EditTextView: NSTextView, NSTextFinderClient, NSSharingServicePickerDelega
let url = urls.first,
let draggableNote = Storage.shared().getBy(url: url) {

let replacementRange = NSRange(location: caretLocation, length: 0)
let title = "[[" + draggableNote.title + "]]"
NSApp.mainWindow?.makeFirstResponder(self)

Expand All @@ -1700,56 +1701,93 @@ class EditTextView: NSTextView, NSTextFinderClient, NSSharingServicePickerDelega

if let urls = board.readObjects(forClasses: [NSURL.self], options: nil) as? [URL],
urls.count > 0 {
var offset = 0

safeSave(note: note)

for url in urls {
do {
data = try Data(contentsOf: url)
} catch {
return false
}
for (index, url) in urls.enumerated() {
fetchDataFromURL(url: url) { (data, error) in
if let error = error {
print("Error fetching data: \(error.localizedDescription)")
return
}

guard let filePath = ImagesProcessor.writeFile(data: data, url: url, note: note) else { return false }
guard let data = data else { return }

let insertRange = NSRange(location: caretLocation + offset, length: 0)
DispatchQueue.main.async {
if url.absoluteString.startsWith(string: "https://") || url.absoluteString.startsWith(string: "http://") {
let title = self.getHTMLTitle(from: data) ?? ""
self.insertText("[\(title)](\(url.absoluteString))", replacementRange: replacementRange)
return
}

if UserDefaultsManagement.liveImagesPreview {
let cleanPath = filePath.removingPercentEncoding ?? filePath
guard let url = note.getImageUrl(imageName: cleanPath) else { return false }
guard let filePath = ImagesProcessor.writeFile(data: data, url: url, note: note) else { return }

let invalidateRange = NSRange(location: caretLocation + offset, length: 1)
let attachment = NoteAttachment(editor: self, title: "", path: cleanPath, url: url, invalidateRange: invalidateRange, note: note)
if UserDefaultsManagement.liveImagesPreview {
let cleanPath = filePath.removingPercentEncoding ?? filePath
guard let url = note.getImageUrl(imageName: cleanPath) else { return }
let attachment = NoteAttachment(editor: self, title: "", path: cleanPath, url: url, note: note)

if let string = attachment.getAttributedString() {
textStorageProcessor?.shouldForceRescan = true
let newLine = urls.count > 0 && index != urls.count - 1
if let string = attachment.getAttributedString(newLine: newLine) {
self.textStorageProcessor?.shouldForceRescan = true

setSelectedRange(insertRange)
insertText(string, replacementRange: insertRange)
self.insertText(string, replacementRange: replacementRange)
replacementRange = NSRange(location: replacementRange.location + string.length, length: 0)
self.setSelectedRange(replacementRange)
}
} else {
let string = "![](\(filePath))\n"
self.insertText(string, replacementRange: replacementRange)
replacementRange = NSRange(location: replacementRange.location + string.count, length: 0)
self.setSelectedRange(replacementRange)
}

offset += 3
if let storage = self.textStorage {
NotesTextProcessor.highlightMarkdown(attributedString: storage, note: note)
self.saveTextStorageContent(to: note)
note.save()
}

self.viewDelegate?.notesTableView.reloadRow(note: note)
}
} else {
setSelectedRange(insertRange)
insertText("![](\(filePath))", replacementRange: insertRange)
}
}

if let storage = textStorage {
NotesTextProcessor.highlightMarkdown(attributedString: storage, note: note)
saveTextStorageContent(to: note)
note.save()
}

self.viewDelegate?.notesTableView.reloadRow(note: note)

return true
}

return false
}


func fetchDataFromURL(url: URL, completion: @escaping (Data?, Error?) -> Void) {
let session = URLSession.shared

let task = session.dataTask(with: url) { (data, response, error) in
if let error = error {
completion(nil, error)
return
}

completion(data, nil)
}

task.resume()
}

func getHTMLTitle(from data: Data) -> String? {
do {
let htmlString = String(data: data, encoding: .utf8)
let doc = try SwiftSoup.parse(htmlString!)
let titleElement = try doc.select("title").first()
let title = try titleElement?.text()

return title
} catch {
print("Error parsing HTML: \(error.localizedDescription)")
return nil
}
}

public func safeSave(note: Note) {
guard note.container != .encryptedTextPack else { return }

Expand Down Expand Up @@ -2198,8 +2236,7 @@ class EditTextView: NSTextView, NSTextFinderClient, NSSharingServicePickerDelega
guard let path = path.removingPercentEncoding else { return }

if let imageUrl = note.getImageUrl(imageName: path) {
let range = NSRange(location: selectedRange.location, length: 1)
let attachment = NoteAttachment(editor: self, title: "", path: path, url: imageUrl, invalidateRange: range, note: note)
let attachment = NoteAttachment(editor: self, title: "", path: path, url: imageUrl, note: note)

if let attributedString = attachment.getAttributedString() {
let newLineImage = NSMutableAttributedString(attributedString: attributedString)
Expand Down
10 changes: 6 additions & 4 deletions FSNotesCore/Shared/Business/NoteAttachment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import AVKit

class NoteAttachment {
public var title: String
public var invalidateRange: NSRange?

private var path: String
public var url: URL
Expand All @@ -27,18 +26,17 @@ class NoteAttachment {

public var editor: EditTextView?

init(editor: EditTextView, title: String, path: String, url: URL, invalidateRange: NSRange? = nil, note: Note? = nil) {
init(editor: EditTextView, title: String, path: String, url: URL, note: Note? = nil) {
self.editor = editor
self.title = title
self.url = url
self.path = path
self.invalidateRange = invalidateRange
self.note = note
}

weak var weakTimer: Timer?

public func getAttributedString() -> NSMutableAttributedString? {
public func getAttributedString(newLine: Bool = false) -> NSMutableAttributedString? {
let imageKey = NSAttributedString.Key(rawValue: "co.fluder.fsnotes.image.url")
let pathKey = NSAttributedString.Key(rawValue: "co.fluder.fsnotes.image.path")
let titleKey = NSAttributedString.Key(rawValue: "co.fluder.fsnotes.image.title")
Expand Down Expand Up @@ -74,6 +72,10 @@ class NoteAttachment {

mutableAttributedString.addAttributes(attributes, range: NSRange(0..<1))

if newLine {
mutableAttributedString.append(NSAttributedString(string: "\n"))
}

return mutableAttributedString
}

Expand Down

0 comments on commit 7d9912a

Please sign in to comment.