aboutsummaryrefslogtreecommitdiff
path: root/Hotline/Utility
diff options
context:
space:
mode:
authorRuben Beltran del Rio <git@r.bdr.sh>2025-02-05 22:27:17 +0100
committerRuben Beltran del Rio <git@r.bdr.sh>2025-02-05 22:27:17 +0100
commit45829daa856b376b1ab04d415917110b71b1dec5 (patch)
tree8e52daed6897b6f489d455736fe256cb9bd90fef /Hotline/Utility
parent5c3ea897d062a47bc8cd6255fb8c36bad2f0733f (diff)
Apply formatting
Diffstat (limited to 'Hotline/Utility')
-rw-r--r--Hotline/Utility/BookmarkDocument.swift14
-rw-r--r--Hotline/Utility/DAKeychain.swift23
-rw-r--r--Hotline/Utility/FoundationExtensions.swift28
-rw-r--r--Hotline/Utility/NSWindowBridge.swift22
-rw-r--r--Hotline/Utility/ObservableScrollView.swift28
-rw-r--r--Hotline/Utility/RegularExpressions.swift6
-rw-r--r--Hotline/Utility/SoundEffects.swift22
-rw-r--r--Hotline/Utility/SwiftUIExtensions.swift4
-rw-r--r--Hotline/Utility/TextDocument.swift12
9 files changed, 83 insertions, 76 deletions
diff --git a/Hotline/Utility/BookmarkDocument.swift b/Hotline/Utility/BookmarkDocument.swift
index 47fa442..43f251c 100644
--- a/Hotline/Utility/BookmarkDocument.swift
+++ b/Hotline/Utility/BookmarkDocument.swift
@@ -1,5 +1,5 @@
-import SwiftUI
import Foundation
+import SwiftUI
import UniformTypeIdentifiers
struct BookmarkDocument: FileDocument {
@@ -7,22 +7,22 @@ struct BookmarkDocument: FileDocument {
static var writableContentTypes: [UTType] { [.data, UTType(filenameExtension: "hlbm")!] }
var bookmark: Bookmark
-
+
init(bookmark: Bookmark) {
self.bookmark = bookmark
}
-
+
init(configuration: ReadConfiguration) throws {
guard configuration.file.isRegularFile,
- let data = configuration.file.regularFileContents,
- let fileName = configuration.file.preferredFilename,
- let bookmark = Bookmark(fileData: data, name: (fileName as NSString).deletingPathExtension)
+ let data = configuration.file.regularFileContents,
+ let fileName = configuration.file.preferredFilename,
+ let bookmark = Bookmark(fileData: data, name: (fileName as NSString).deletingPathExtension)
else {
throw CocoaError(.fileReadCorruptFile)
}
self.bookmark = bookmark
}
-
+
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
let wrapper = FileWrapper(regularFileWithContents: self.bookmark.bookmarkFileData()!)
wrapper.fileAttributes[FileAttributeKey.hfsCreatorCode.rawValue] = "HTLC".fourCharCode()
diff --git a/Hotline/Utility/DAKeychain.swift b/Hotline/Utility/DAKeychain.swift
index 8031886..aa71508 100644
--- a/Hotline/Utility/DAKeychain.swift
+++ b/Hotline/Utility/DAKeychain.swift
@@ -9,26 +9,27 @@
import Foundation
open class DAKeychain {
-
+
open var loggingEnabled = false
-
+
private init() {}
public static let shared = DAKeychain()
-
+
open subscript(key: String) -> String? {
get {
return load(withKey: key)
- } set {
+ }
+ set {
DispatchQueue.global().sync(flags: .barrier) {
self.save(newValue, forKey: key)
}
}
}
-
+
private func save(_ string: String?, forKey key: String) {
let query = keychainQuery(withKey: key)
let objectData: Data? = string?.data(using: .utf8, allowLossyConversion: false)
-
+
if SecItemCopyMatching(query, nil) == noErr {
if let dictData = objectData {
let status = SecItemUpdate(query, NSDictionary(dictionary: [kSecValueData: dictData]))
@@ -45,15 +46,15 @@ open class DAKeychain {
}
}
}
-
+
private func load(withKey key: String) -> String? {
let query = keychainQuery(withKey: key)
query.setValue(kCFBooleanTrue, forKey: kSecReturnData as String)
query.setValue(kCFBooleanTrue, forKey: kSecReturnAttributes as String)
-
+
var result: CFTypeRef?
let status = SecItemCopyMatching(query, &result)
-
+
guard
let resultsDict = result as? NSDictionary,
let resultsData = resultsDict.value(forKey: kSecValueData as String) as? Data,
@@ -64,7 +65,7 @@ open class DAKeychain {
}
return String(data: resultsData, encoding: .utf8)
}
-
+
private func keychainQuery(withKey key: String) -> NSMutableDictionary {
let result = NSMutableDictionary()
result.setValue(kSecClassGenericPassword, forKey: kSecClass as String)
@@ -72,7 +73,7 @@ open class DAKeychain {
result.setValue(kSecAttrAccessibleWhenUnlocked, forKey: kSecAttrAccessible as String)
return result
}
-
+
private func logPrint(_ items: Any...) {
if loggingEnabled {
print(items)
diff --git a/Hotline/Utility/FoundationExtensions.swift b/Hotline/Utility/FoundationExtensions.swift
index 9fc9ae7..b1cd1b9 100644
--- a/Hotline/Utility/FoundationExtensions.swift
+++ b/Hotline/Utility/FoundationExtensions.swift
@@ -7,27 +7,27 @@ enum Endianness {
}
extension String {
-
+
func convertToAttributedStringWithLinks() -> AttributedString {
let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: self)
let matches = self.ranges(of: RegularExpressions.relaxedLink)
for match in matches {
let matchString = String(self[match])
if matchString.isEmailAddress() {
- attributedString.addAttribute(.link, value: "mailto:\(matchString)", range: NSRange(match, in: self))
- }
- else {
+ attributedString.addAttribute(
+ .link, value: "mailto:\(matchString)", range: NSRange(match, in: self))
+ } else {
attributedString.addAttribute(.link, value: matchString, range: NSRange(match, in: self))
}
-// attributedString.addAttribute(.underlineStyle, value: 1, range: NSRange(match, in: self))
+ // attributedString.addAttribute(.underlineStyle, value: 1, range: NSRange(match, in: self))
}
return AttributedString(attributedString)
}
-
+
func isEmailAddress() -> Bool {
self.wholeMatch(of: RegularExpressions.emailAddress) != nil
}
-
+
func isWebURL() -> Bool {
guard let url = URL(string: self) else {
return false
@@ -39,12 +39,12 @@ extension String {
return false
}
}
-
+
func isImageURL() -> Bool {
guard let url = URL(string: self) else {
return false
}
-
+
switch url.pathExtension.lowercased() {
case "jpg", "jpeg", "png", "gif":
return true
@@ -52,29 +52,27 @@ extension String {
return false
}
}
-
+
func convertingLinksToMarkdown() -> String {
var cp = String(self)
cp.replace(RegularExpressions.relaxedLink) { match -> String in
let linkText = self[match.range]
var injectedScheme = "https://"
- if let _ = try? RegularExpressions.supportedLinkScheme.prefixMatch(in: linkText) {
+ if (try? RegularExpressions.supportedLinkScheme.prefixMatch(in: linkText)) != nil {
injectedScheme = ""
}
-
+
return "[\(linkText)](\(injectedScheme)\(linkText))"
}
return cp
}
}
-
-
extension Binding where Value: OptionSet, Value == Value.Element {
func bindedValue(_ options: Value) -> Bool {
return wrappedValue.contains(options)
}
-
+
func bind(_ options: Value) -> Binding<Bool> {
return .init { () -> Bool in
self.wrappedValue.contains(options)
diff --git a/Hotline/Utility/NSWindowBridge.swift b/Hotline/Utility/NSWindowBridge.swift
index 5cd7197..ad56105 100644
--- a/Hotline/Utility/NSWindowBridge.swift
+++ b/Hotline/Utility/NSWindowBridge.swift
@@ -1,25 +1,25 @@
import SwiftUI
-fileprivate class NSWindowAccessorView: NSView {
- let executeBlock: (_ window: NSWindow? ) -> ()
-
- init(_ inConfigFunction: @escaping (_ window: NSWindow? ) -> () ) {
+private class NSWindowAccessorView: NSView {
+ let executeBlock: (_ window: NSWindow?) -> Void
+
+ init(_ inConfigFunction: @escaping (_ window: NSWindow?) -> Void) {
executeBlock = inConfigFunction
- super.init( frame: NSRect() )
+ super.init(frame: NSRect())
}
-
+
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
-
+
public override func viewDidMoveToWindow() {
super.viewDidMoveToWindow()
- executeBlock( self.window ) // We pass it through even if it is nil.
+ executeBlock(self.window) // We pass it through even if it is nil.
}
}
public struct NSWindowAccessor: NSViewRepresentable {
- var configCode: (_ window: NSWindow? ) -> ()
-
+ var configCode: (_ window: NSWindow?) -> Void
+
public init(_ configCode: @escaping (_: NSWindow?) -> Void) { self.configCode = configCode }
- public func makeNSView(context: Context) -> NSView { return NSWindowAccessorView( configCode ) }
+ public func makeNSView(context: Context) -> NSView { return NSWindowAccessorView(configCode) }
public func updateNSView(_ nsView: NSView, context: Context) {}
}
diff --git a/Hotline/Utility/ObservableScrollView.swift b/Hotline/Utility/ObservableScrollView.swift
index a6f46cc..05688f1 100644
--- a/Hotline/Utility/ObservableScrollView.swift
+++ b/Hotline/Utility/ObservableScrollView.swift
@@ -8,27 +8,31 @@ struct ScrollViewOffsetPreferenceKey: PreferenceKey {
}
}
-struct ObservableScrollView<Content>: View where Content : View {
+struct ObservableScrollView<Content>: View where Content: View {
@Namespace var scrollSpace
@Binding var scrollOffset: CGFloat
let content: () -> Content
-
- init(scrollOffset: Binding<CGFloat>,
- @ViewBuilder content: @escaping () -> Content) {
+
+ init(
+ scrollOffset: Binding<CGFloat>,
+ @ViewBuilder content: @escaping () -> Content
+ ) {
_scrollOffset = scrollOffset
self.content = content
}
-
+
var body: some View {
ScrollView {
content()
- .background(GeometryReader { geo in
- let offset = -geo.frame(in: .named(scrollSpace)).minY
- Color.clear
- .preference(key: ScrollViewOffsetPreferenceKey.self,
- value: offset)
- })
-
+ .background(
+ GeometryReader { geo in
+ let offset = -geo.frame(in: .named(scrollSpace)).minY
+ Color.clear
+ .preference(
+ key: ScrollViewOffsetPreferenceKey.self,
+ value: offset)
+ })
+
}
.coordinateSpace(name: scrollSpace)
.onPreferenceChange(ScrollViewOffsetPreferenceKey.self) { value in
diff --git a/Hotline/Utility/RegularExpressions.swift b/Hotline/Utility/RegularExpressions.swift
index c1f2a18..db705ae 100644
--- a/Hotline/Utility/RegularExpressions.swift
+++ b/Hotline/Utility/RegularExpressions.swift
@@ -20,7 +20,7 @@ struct RegularExpressions {
}
}
}
-
+
static let supportedLinkScheme = Regex {
Anchor.startOfLine
ChoiceOf {
@@ -30,7 +30,7 @@ struct RegularExpressions {
}
"://"
}.ignoresCase().anchorsMatchLineEndings()
-
+
static let relaxedLink = Regex {
ChoiceOf {
Anchor.startOfLine
@@ -138,7 +138,7 @@ struct RegularExpressions {
}
.anchorsMatchLineEndings()
.ignoresCase()
-
+
static let emailAddress = Regex {
ChoiceOf {
Anchor.startOfLine
diff --git a/Hotline/Utility/SoundEffects.swift b/Hotline/Utility/SoundEffects.swift
index 93f8b9a..74314e4 100644
--- a/Hotline/Utility/SoundEffects.swift
+++ b/Hotline/Utility/SoundEffects.swift
@@ -1,5 +1,5 @@
-import Foundation
import AVFAudio
+import Foundation
enum SoundEffects: String {
case loggedIn = "logged-in"
@@ -15,28 +15,30 @@ enum SoundEffects: String {
@Observable
class SoundEffectPlayer: NSObject, AVAudioPlayerDelegate {
static let shared = SoundEffectPlayer()
-
+
private var activeSounds: [AVAudioPlayer] = []
-
+
func playSoundEffect(_ name: SoundEffects) {
// Load a local sound file
- guard let soundFileURL = Bundle.main.url(
- forResource: name.rawValue,
- withExtension: "aiff"
- ) else {
+ guard
+ let soundFileURL = Bundle.main.url(
+ forResource: name.rawValue,
+ withExtension: "aiff"
+ )
+ else {
return
}
-
+
DispatchQueue.main.async { [weak self] in
guard let self = self else {
return
}
-
+
if let soundEffect = try? AVAudioPlayer(contentsOf: soundFileURL) {
soundEffect.delegate = self
soundEffect.volume = 0.75
soundEffect.play()
-
+
self.activeSounds.append(soundEffect)
}
}
diff --git a/Hotline/Utility/SwiftUIExtensions.swift b/Hotline/Utility/SwiftUIExtensions.swift
index 3b850e0..27697f8 100644
--- a/Hotline/Utility/SwiftUIExtensions.swift
+++ b/Hotline/Utility/SwiftUIExtensions.swift
@@ -2,6 +2,8 @@ import SwiftUI
extension Color {
init(hex: Int, opacity: Double = 1.0) {
- self.init(red: Double((hex >> 16) & 0xFF) / 255.0, green: Double((hex >> 8) & 0xFF) / 255.0, blue: Double(hex & 0xFF) / 255.0, opacity: opacity)
+ self.init(
+ red: Double((hex >> 16) & 0xFF) / 255.0, green: Double((hex >> 8) & 0xFF) / 255.0,
+ blue: Double(hex & 0xFF) / 255.0, opacity: opacity)
}
}
diff --git a/Hotline/Utility/TextDocument.swift b/Hotline/Utility/TextDocument.swift
index 82727de..a3591fd 100644
--- a/Hotline/Utility/TextDocument.swift
+++ b/Hotline/Utility/TextDocument.swift
@@ -1,29 +1,29 @@
import Foundation
-import UniformTypeIdentifiers
import SwiftUI
+import UniformTypeIdentifiers
struct TextFile: FileDocument {
// tell the system we support only plain text
static var readableContentTypes = [UTType.plainText, UTType.utf8PlainText]
-
+
// by default our document is empty
var text = ""
-
+
// a simple initializer that creates new, empty documents
init(initialText: String = "") {
text = initialText
}
-
+
// this initializer loads data that has been saved previously
init(configuration: ReadConfiguration) throws {
-
+
if let data = configuration.file.regularFileContents {
if let str = String(data: data, encoding: .utf8) {
self.text = str
}
}
}
-
+
// this will be called when the system wants to write our data to disk
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
return FileWrapper(regularFileWithContents: self.text.data(using: .utf8)!)