This commit brings key local notification logic into the notification extension target to allow the extension to reuse much of the functionality surrounding the processing and formatting of notifications. More specifically, the functions `process_local_notification` and `create_local_notification` were brought into the extension target. This will enable us to reuse much of the pre-existing notification logic (and avoid having to reimplement all of that) However, those functions had high dependencies on other parts of the code, so significant refactorings were needed to make this happen: - `create_local_notification` and `process_local_notification` had its function signatures changed to avoid the need to `DamusState` (which pulls too many other dependecies) - Other necessary dependencies, such as `Profiles`, `UserSettingsStore` had to be pulled into the extension target. Subsequently, sub-dependencies of those items had to be pulled in as well - In several cases, files were split to avoid pulling too many dependencies (e.g. Some Model files depended on some functions in View files, so in those cases I moved those functions into their own separate file to avoid pulling in view logic into the extension target) - Notification processing logic was changed a bit to remove dependency on `EventCache` in favor of using ndb directly (As instructed in a TODO comment in EventCache, and because EventCache has too many other dependencies) tldr: A LOT of things were moved around, a bit of logic was changed around local notifications to avoid using `EventCache`, but otherwise this commit is meant to be a no-op without any new features or user-facing functional changes. Testing ------- Device: iPhone 15 Pro iOS: 17.0.1 Damus: This commit Coverage: 1. Ran unit tests to check for regressions (none detected) 2. Launched the app and navigated around and did some interactions to perform a quick functional smoke test (no regressions found) 3. Sent a few push notifications to check they still work as expected (PASS) Signed-off-by: Daniel D’Aquino <daniel@daquino.me> Signed-off-by: William Casarin <jb55@jb55.com>
114 lines
3.6 KiB
Swift
114 lines
3.6 KiB
Swift
//
|
|
// CompatibleAttribute.swift
|
|
// damus
|
|
//
|
|
// Created by William Casarin on 2023-04-06.
|
|
//
|
|
|
|
import Foundation
|
|
import SwiftUI
|
|
|
|
// Concatening too many `Text` objects can cause crashes (See https://github.com/damus-io/damus/issues/1826)
|
|
fileprivate let MAX_TEXT_ITEMS = 100
|
|
|
|
class CompatibleText: Equatable {
|
|
var text: some View {
|
|
if items.count > MAX_TEXT_ITEMS {
|
|
return AnyView(
|
|
VStack {
|
|
Image("warning")
|
|
Text(NSLocalizedString("This note contains too many items and cannot be rendered", comment: "Error message indicating that a note is too big and cannot be rendered"))
|
|
.multilineTextAlignment(.center)
|
|
}
|
|
.foregroundColor(.secondary)
|
|
)
|
|
}
|
|
return AnyView(
|
|
items.reduce(Text(""), { (accumulated, item) in
|
|
return accumulated + item.render_to_text()
|
|
})
|
|
)
|
|
}
|
|
var attributed: AttributedString {
|
|
return items.reduce(AttributedString(stringLiteral: ""), { (accumulated, item) in
|
|
guard let item_attributed_string = item.attributed_string() else { return accumulated }
|
|
return accumulated + item_attributed_string
|
|
})
|
|
}
|
|
var items: [Item]
|
|
|
|
init() {
|
|
self.items = [.attributed_string(AttributedString(stringLiteral: ""))]
|
|
}
|
|
|
|
init(stringLiteral: String) {
|
|
self.items = [.attributed_string(AttributedString(stringLiteral: stringLiteral))]
|
|
}
|
|
|
|
init(attributed: AttributedString) {
|
|
self.items = [.attributed_string(attributed)]
|
|
}
|
|
|
|
init(items: [Item]) {
|
|
self.items = items
|
|
}
|
|
|
|
static func == (lhs: CompatibleText, rhs: CompatibleText) -> Bool {
|
|
return lhs.items == rhs.items
|
|
}
|
|
|
|
static func +(lhs: CompatibleText, rhs: CompatibleText) -> CompatibleText {
|
|
if case .attributed_string(let las) = lhs.items.last,
|
|
case .attributed_string(let ras) = rhs.items.first
|
|
{
|
|
// Concatenate attributed strings whenever possible to reduce item count
|
|
let combined_attributed_string = las + ras
|
|
return CompatibleText(items:
|
|
Array(lhs.items.prefix(upTo: lhs.items.count - 1)) +
|
|
[.attributed_string(combined_attributed_string)] +
|
|
Array(rhs.items.suffix(from: 1))
|
|
)
|
|
}
|
|
else {
|
|
return CompatibleText(items: lhs.items + rhs.items)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension CompatibleText {
|
|
enum Item: Equatable {
|
|
case attributed_string(AttributedString)
|
|
case icon(named: String, offset: CGFloat)
|
|
|
|
func render_to_text() -> Text {
|
|
switch self {
|
|
case .attributed_string(let attributed_string):
|
|
return Text(attributed_string)
|
|
case .icon(named: let image_name, offset: let offset):
|
|
return Text(Image(image_name)).baselineOffset(offset)
|
|
}
|
|
}
|
|
|
|
func attributed_string() -> AttributedString? {
|
|
switch self {
|
|
case .attributed_string(let attributed_string):
|
|
return attributed_string
|
|
case .icon(named: let name, offset: _):
|
|
guard let img = UIImage(named: name) else { return nil }
|
|
return icon_attributed_string(img: img)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
func icon_attributed_string(img: UIImage) -> AttributedString {
|
|
let attachment = NSTextAttachment()
|
|
attachment.image = img
|
|
let attachmentString = NSAttributedString(attachment: attachment)
|
|
return AttributedString(attachmentString)
|
|
}
|
|
|
|
|