WIP activity view, french, optimizations
This commit is contained in:
parent
c58c35fa37
commit
0073cfa4d1
|
@ -41,6 +41,10 @@
|
|||
B9BED51A2B5D662D00C9B715 /* ShareSheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9BED5192B5D662D00C9B715 /* ShareSheetController.swift */; };
|
||||
B9CC45B82B40A2D6001E4FA5 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9CC45B72B40A2D6001E4FA5 /* AboutView.swift */; };
|
||||
B9CFC43B2B4F08C9004CFCB7 /* LaunchStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B9CFC43A2B4F08C9004CFCB7 /* LaunchStoryboard.storyboard */; };
|
||||
B9D9C6C12B6A56E000C26A41 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9D9C6C02B6A56E000C26A41 /* Notification.swift */; };
|
||||
B9D9C6C32B6A576C00C26A41 /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9D9C6C22B6A576C00C26A41 /* NotificationsView.swift */; };
|
||||
B9D9C6C52B6A587700C26A41 /* NotificationRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9D9C6C42B6A587700C26A41 /* NotificationRow.swift */; };
|
||||
B9D9C6C72B6A590F00C26A41 /* ProfilePicture.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9D9C6C62B6A590F00C26A41 /* ProfilePicture.swift */; };
|
||||
B9EBE8562B47256900FB594D /* PostAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9EBE8552B47256900FB594D /* PostAttachment.swift */; };
|
||||
B9EBE8582B474FD600FB594D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9EBE8572B474FD600FB594D /* AppDelegate.swift */; };
|
||||
B9F8FA162B5D3AC30044DAB4 /* SafariView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F8FA152B5D3AC30044DAB4 /* SafariView.swift */; };
|
||||
|
@ -130,6 +134,10 @@
|
|||
B9CC45B72B40A2D6001E4FA5 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
|
||||
B9CC45B92B40AA1E001E4FA5 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
B9CFC43A2B4F08C9004CFCB7 /* LaunchStoryboard.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchStoryboard.storyboard; sourceTree = "<group>"; };
|
||||
B9D9C6C02B6A56E000C26A41 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
|
||||
B9D9C6C22B6A576C00C26A41 /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = "<group>"; };
|
||||
B9D9C6C42B6A587700C26A41 /* NotificationRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationRow.swift; sourceTree = "<group>"; };
|
||||
B9D9C6C62B6A590F00C26A41 /* ProfilePicture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfilePicture.swift; sourceTree = "<group>"; };
|
||||
B9EBE8552B47256900FB594D /* PostAttachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostAttachment.swift; sourceTree = "<group>"; };
|
||||
B9EBE8572B474FD600FB594D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
B9F8FA152B5D3AC30044DAB4 /* SafariView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariView.swift; sourceTree = "<group>"; };
|
||||
|
@ -220,6 +228,14 @@
|
|||
path = Post;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B9D9C6BF2B6A56D500C26A41 /* Notifications */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B9D9C6C02B6A56E000C26A41 /* Notification.swift */,
|
||||
);
|
||||
path = Notifications;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B9FB944E2B2DEECE00D81C07 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -270,6 +286,7 @@
|
|||
B9FB946C2B2DF3A600D81C07 /* Data */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B9D9C6BF2B6A56D500C26A41 /* Notifications */,
|
||||
B93BCC3F2B5E38E5008EEA19 /* Content */,
|
||||
B9FB94BD2B2F038D00D81C07 /* Accounts */,
|
||||
B9FB946F2B2DF3CD00D81C07 /* Navigator.swift */,
|
||||
|
@ -296,6 +313,7 @@
|
|||
B98BC7462B46CE6300595441 /* PostDetailsView.swift */,
|
||||
B93B677B2B433A6E000892E9 /* PostingView.swift */,
|
||||
B9F8FA152B5D3AC30044DAB4 /* SafariView.swift */,
|
||||
B9D9C6C22B6A576C00C26A41 /* NotificationsView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
|
@ -312,6 +330,8 @@
|
|||
B9B63B202B442D1500BBC82D /* DynamicTextEditor.swift */,
|
||||
B98BC74A2B46CF0400595441 /* ListStyle.swift */,
|
||||
B9BED5192B5D662D00C9B715 /* ShareSheetController.swift */,
|
||||
B9D9C6C42B6A587700C26A41 /* NotificationRow.swift */,
|
||||
B9D9C6C62B6A590F00C26A41 /* ProfilePicture.swift */,
|
||||
);
|
||||
path = Components;
|
||||
sourceTree = "<group>";
|
||||
|
@ -429,6 +449,7 @@
|
|||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
fr,
|
||||
);
|
||||
mainGroup = B9FB944E2B2DEECE00D81C07;
|
||||
packageReferences = (
|
||||
|
@ -488,6 +509,7 @@
|
|||
B98F47982B64670F0092000F /* ShopView.swift in Sources */,
|
||||
B9842C0E2B2F21B700D9F3C1 /* CompactPostView.swift in Sources */,
|
||||
B98BC7492B46CEDA00595441 /* AppearenceView.swift in Sources */,
|
||||
B9D9C6C52B6A587700C26A41 /* NotificationRow.swift in Sources */,
|
||||
B9FB94992B2EEB9400D81C07 /* AddInstanceView.swift in Sources */,
|
||||
B9FB94972B2EDABF00D81C07 /* PrivacyView.swift in Sources */,
|
||||
B9F8FA162B5D3AC30044DAB4 /* SafariView.swift in Sources */,
|
||||
|
@ -496,8 +518,10 @@
|
|||
B9B63B232B447B8000BBC82D /* PostCardView.swift in Sources */,
|
||||
B9FB949B2B2EF09A00D81C07 /* Client.swift in Sources */,
|
||||
B9FB949D2B2EF0D600D81C07 /* Instance.swift in Sources */,
|
||||
B9D9C6C72B6A590F00C26A41 /* ProfilePicture.swift in Sources */,
|
||||
B9842C102B2F228C00D9F3C1 /* Status.swift in Sources */,
|
||||
B93B677A2B42EC51000892E9 /* MetaPicker.swift in Sources */,
|
||||
B9D9C6C32B6A576C00C26A41 /* NotificationsView.swift in Sources */,
|
||||
B9FB94722B2DF49700D81C07 /* ConnectView.swift in Sources */,
|
||||
B9FB945B2B2DEECE00D81C07 /* ThreadedApp.swift in Sources */,
|
||||
B9FB94862B2E211200D81C07 /* Account+Elms.swift in Sources */,
|
||||
|
@ -525,6 +549,7 @@
|
|||
B9FB948E2B2E28E800D81C07 /* MediaTransferables.swift in Sources */,
|
||||
B98BC74D2B46CFCE00595441 /* UserPreferences.swift in Sources */,
|
||||
B9FB94A22B2EF24A00D81C07 /* AppInfo.swift in Sources */,
|
||||
B9D9C6C12B6A56E000C26A41 /* Notification.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
//Made by Lumaa
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct NotificationRow: View {
|
||||
var notif: Notification = .placeholder()
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
HStack(spacing: 5) {
|
||||
ProfilePicture(url: notif.account.avatar)
|
||||
.padding(.trailing)
|
||||
.overlay(alignment: .bottomTrailing) {
|
||||
notifIcon()
|
||||
.offset(x: -5, y: 5)
|
||||
}
|
||||
.padding()
|
||||
Text(localizedString())
|
||||
}
|
||||
.padding(.horizontal)
|
||||
}
|
||||
}
|
||||
|
||||
private func localizedString() -> String {
|
||||
switch (notif.supportedType) {
|
||||
case .favourite:
|
||||
return String(localized: "activity.favorite.%@").replacingOccurrences(of: "%@", with: "@\(notif.account.username)")
|
||||
case .follow:
|
||||
return String(localized: "activity.followed.%@").replacingOccurrences(of: "%@", with: "@\(notif.account.username)")
|
||||
case .mention:
|
||||
return String(localized: "activity.mentionned.%@").replacingOccurrences(of: "%@", with: "@\(notif.account.username)")
|
||||
case .reblog:
|
||||
return String(localized: "activity.reblogged.%@").replacingOccurrences(of: "%@", with: "@\(notif.account.username)")
|
||||
case .status:
|
||||
return String(localized: "activity.status.%@").replacingOccurrences(of: "%@", with: "@\(notif.account.username)")
|
||||
default:
|
||||
return String(localized: "activity.unknown")
|
||||
}
|
||||
}
|
||||
|
||||
private func notifColor() -> Color {
|
||||
switch (notif.supportedType) {
|
||||
case .favourite:
|
||||
return Color.red
|
||||
case .follow:
|
||||
return Color.purple
|
||||
case .mention:
|
||||
return Color.blue
|
||||
case .reblog:
|
||||
return Color.pink
|
||||
case .status:
|
||||
return Color.yellow
|
||||
default:
|
||||
return Color.gray
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func notifIcon() -> some View {
|
||||
ZStack {
|
||||
switch (notif.supportedType) {
|
||||
case .favourite:
|
||||
Image(systemName: "heart.fill")
|
||||
.font(.caption)
|
||||
case .follow:
|
||||
Image(systemName: "person.fill.badge.plus")
|
||||
.font(.caption)
|
||||
case .mention:
|
||||
Image(systemName: "tag.fill")
|
||||
.font(.caption)
|
||||
case .reblog:
|
||||
Image(systemName: "bolt.horizontal.fill")
|
||||
.font(.caption)
|
||||
case .status:
|
||||
Image(systemName: "text.badge.plus")
|
||||
.font(.caption)
|
||||
default:
|
||||
Image(systemName: "questionmark")
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
.padding(5)
|
||||
.background(notifColor())
|
||||
.clipShape(.circle)
|
||||
.overlay {
|
||||
Circle()
|
||||
.stroke(Color.appBackground, lineWidth: 3)
|
||||
}
|
||||
.fixedSize()
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
NotificationRow()
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
//Made by Lumaa
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ProfilePicture: View {
|
||||
@Environment(UserPreferences.self) private var pref
|
||||
var url: URL
|
||||
var cornerRadius: CGFloat {
|
||||
return pref.profilePictureShape == .circle ? (50 / 2) : 15.0
|
||||
}
|
||||
|
||||
init(url: URL) {
|
||||
self.url = url
|
||||
}
|
||||
|
||||
init(url: String) {
|
||||
self.url = .init(string: url)!
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
OnlineImage(url: url, size: 50, useNuke: true)
|
||||
.frame(width: 40, height: 40)
|
||||
.clipShape(RoundedRectangle(cornerRadius: cornerRadius))
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
//TODO: Change this to SwiftData
|
||||
|
||||
@Observable
|
||||
public class AccountManager {
|
||||
private var client: Client?
|
||||
|
@ -46,7 +48,6 @@ public class AccountManager {
|
|||
}
|
||||
}
|
||||
|
||||
//TODO: Change this to SwiftData
|
||||
public struct AppAccount: Codable, Identifiable, Hashable {
|
||||
public let server: String
|
||||
public var accountName: String?
|
||||
|
|
|
@ -26,7 +26,7 @@ struct FetchTimeline {
|
|||
}
|
||||
|
||||
public mutating func addStatuses(lastStatusIndex: Int) async -> [Status] {
|
||||
print("i: \(lastStatusIndex)\ndatasource-6: \(self.datasource.count - 6)")
|
||||
// print("i: \(lastStatusIndex)\ndatasource-6: \(self.datasource.count - 6)")
|
||||
guard client != nil && lastStatusIndex >= self.datasource.count - 6 else { return self.datasource }
|
||||
|
||||
self.statusesState = .loading
|
||||
|
|
|
@ -572,3 +572,39 @@ public struct MediaDescriptionData: Encodable, Sendable {
|
|||
self.description = description
|
||||
}
|
||||
}
|
||||
|
||||
public enum Notifications: Endpoint {
|
||||
case notifications(minId: String?,
|
||||
maxId: String?,
|
||||
types: [String]?,
|
||||
limit: Int)
|
||||
case notification(id: String)
|
||||
case clear
|
||||
|
||||
public func path() -> String {
|
||||
switch self {
|
||||
case .notifications:
|
||||
"notifications"
|
||||
case let .notification(id):
|
||||
"notifications/\(id)"
|
||||
case .clear:
|
||||
"notifications/clear"
|
||||
}
|
||||
}
|
||||
|
||||
public func queryItems() -> [URLQueryItem]? {
|
||||
switch self {
|
||||
case let .notifications(mindId, maxId, types, limit):
|
||||
var params = makePaginationParam(sinceId: nil, maxId: maxId, mindId: mindId) ?? []
|
||||
params.append(.init(name: "limit", value: String(limit)))
|
||||
if let types {
|
||||
for type in types {
|
||||
params.append(.init(name: "exclude_types[]", value: type))
|
||||
}
|
||||
}
|
||||
return params
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
//Made by Lumaa
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct Notification: Decodable, Identifiable, Equatable {
|
||||
public enum NotificationType: String, CaseIterable {
|
||||
case follow, follow_request, mention, reblog, status, favourite, poll, update
|
||||
}
|
||||
|
||||
public let id: String
|
||||
public let type: String
|
||||
public let createdAt: ServerDate
|
||||
public let account: Account
|
||||
public let status: Status?
|
||||
|
||||
public var supportedType: NotificationType? {
|
||||
.init(rawValue: type)
|
||||
}
|
||||
|
||||
public static func placeholder() -> Notification {
|
||||
.init(id: UUID().uuidString,
|
||||
type: NotificationType.favourite.rawValue,
|
||||
createdAt: ServerDate(),
|
||||
account: .placeholder(),
|
||||
status: .placeholder())
|
||||
}
|
||||
}
|
||||
|
||||
extension Notification: Sendable {}
|
||||
extension Notification.NotificationType: Sendable {}
|
|
@ -20,6 +20,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "About"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "À propos"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -30,6 +36,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "About Threaded"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "À propos de Threaded"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -71,6 +83,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "An audio file"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Un fichier audio"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -82,6 +100,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "An animated GIF"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Un GIF animé"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -93,6 +117,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "An image"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Une image"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -104,6 +134,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "A video"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Une vidéo"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -114,6 +150,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Follow"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Suivre"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -124,6 +166,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Follow back"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Suivre en retour"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -156,6 +204,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Mention"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Mentionner"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -166,6 +220,118 @@
|
|||
"state" : "translated",
|
||||
"value" : "Unfollow"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Ne plus suivre"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"activity.favorite.%@" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ liked your post"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"activity.followed.%@" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ followed you"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ vous a suivi(e)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"activity.mentionned.%@" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ mentionned you "
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ vous a mentionné(e)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"activity.no-notifications" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "No notifications"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Pas de notifications"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"activity.reblogged.%@" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ reposted your post"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ a republié votre publication"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"activity.status.%@" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ posted"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ a publié une publication"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"activity.unknown" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Unknown activity"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Activité inconnue"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -176,6 +342,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Image Error"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Erreur Image"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -186,6 +358,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Experimental"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Expérimental"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -196,6 +374,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Rules"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Règles"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -206,6 +390,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Log in using Mastodon"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Connexion avec Mastodon"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -216,6 +406,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Log in your Mastodon account using its instance URL. You cannot create an account using Threaded."
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Connectez-vous à l'aide de votre compte Mastodon en utilisant l'URL de votre instance. Vous ne pouvez pas créer de compte via Threaded"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -226,6 +422,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Enter the instance's URL"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Entrez l'URL de l'instance"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -236,6 +438,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Log in"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Connexion"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -246,6 +454,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Verify"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Vérifier"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -256,6 +470,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "This might not be a Mastodon instance."
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Ce n'est sûrement pas une instance Mastodon"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -266,6 +486,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Stay anonymous"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Rester anonyme"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -276,6 +502,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Without an account, you cannot interact with posts, users and instances. You can only read posts and users' public data."
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Sans compte, vous ne pouvez pas interagir avec les publications, les utilisateurs et instances. Vous pouvez seulement lire données publiques des publications et des utilisateurs."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -286,6 +518,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Welcome to Threaded!"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Bienvenue sur Threaded !"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -296,6 +534,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Log out"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Déconnexion"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -306,6 +550,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Appearence"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Apparence"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -316,6 +566,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Open links"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Ouvrir les liens"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -326,6 +582,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "In-app"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Dans l'application"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -336,6 +598,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "In a browser"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "En dehors de l'application"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -346,6 +614,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Displayed Name"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Nom affiché"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -356,6 +630,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Both"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Les deux"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -366,6 +646,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Display Name"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Le nom d'affichage"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -376,6 +662,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Username"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Le nom d'utilisateur"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -386,6 +678,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Shape of Profile Pictures"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Forme de la photo de profil"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -396,6 +694,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Circle"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Circulaire"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -406,6 +710,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Rounded Rectangle"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Rectangulaire"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -416,6 +726,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Show Reply Symbols"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Afficher les symboles de réponses"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -426,6 +742,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Show experimental features"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Afficher les fonctionnalités expérimentales"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -436,6 +758,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Privacy"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Confidentialité"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -446,6 +774,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Settings"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Paramètres"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -456,6 +790,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Cancel"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Annuler"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -466,6 +806,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Done"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Terminé"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -476,6 +822,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Cancel"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Annuler"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -496,6 +848,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Editing post"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Modification d'une publication"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -518,6 +876,24 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"variations" : {
|
||||
"plural" : {
|
||||
"one" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%lld likes"
|
||||
}
|
||||
},
|
||||
"other" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "%lld likes"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -528,6 +904,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Copy text"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Copier le texte"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -538,6 +920,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Delete"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Supprimer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -548,6 +936,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Edit"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Modifier"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -558,6 +952,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Share"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Partager"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -568,6 +968,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Share as image"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Partager en tant qu'image"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -578,6 +984,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Share as link"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Partager le lien"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -588,6 +1000,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Pinned"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Épinglé"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -598,6 +1016,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "New post"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Nouvelle publication "
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -608,6 +1032,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Cancel"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Annuler"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -618,6 +1048,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "No custom emojis"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Pas d'emojis personnalisés"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -628,6 +1064,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "What's new?"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Quoi de neuf ?"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -638,6 +1080,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Post"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Publier"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -648,6 +1096,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Visibility"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Visibilité"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -658,6 +1112,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Direct Message"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Message privé"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -668,6 +1128,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Private"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Privé"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -678,6 +1144,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Public"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Public"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -688,6 +1160,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Unlisted"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Non répertorié"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -698,6 +1176,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "Replied to @%@"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "A répondu à %@"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -720,6 +1204,24 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"variations" : {
|
||||
"plural" : {
|
||||
"one" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%lld réponse"
|
||||
}
|
||||
},
|
||||
"other" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%lld réponses"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -730,6 +1232,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "%@ reposted"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ a republié"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -740,6 +1248,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "No posts"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Pas de publications"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -750,6 +1264,12 @@
|
|||
"state" : "translated",
|
||||
"value" : "You don't have posts in your home timeline. Follow users or change timelines to see posts!"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Vous n'avez pas de publications dans votre chronologie. Suivez des utilisateurs ou changez de chronologie pour voir des publications !"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -770,4 +1290,4 @@
|
|||
}
|
||||
},
|
||||
"version" : "1.0"
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ struct ContentView: View {
|
|||
.tag(TabDestination.search)
|
||||
|
||||
//TODO: Messaging UI in Activity tab
|
||||
Text(String("Activity"))
|
||||
NotificationsView()
|
||||
.background(Color.appBackground)
|
||||
.tag(TabDestination.activity)
|
||||
|
||||
|
@ -62,6 +62,7 @@ struct ContentView: View {
|
|||
.environment(accountManager)
|
||||
.environment(navigator)
|
||||
.environment(appDelegate)
|
||||
.environment(preferences)
|
||||
.onAppear {
|
||||
do {
|
||||
preferences = try UserPreferences.loadAsCurrent() ?? .defaultPreferences
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
//Made by Lumaa
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct NotificationsView: View {
|
||||
@Environment(AccountManager.self) private var accountManager
|
||||
|
||||
@State private var navigator: Navigator = Navigator()
|
||||
@State private var notifications: [Notification] = []
|
||||
@State private var loadingNotifs: Bool = false
|
||||
@State private var lastId: Int? = nil
|
||||
private let notifLimit = 50
|
||||
|
||||
|
||||
var body: some View {
|
||||
NavigationStack(path: $navigator.path) {
|
||||
if !notifications.isEmpty {
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
LazyVStack(alignment: .leading) {
|
||||
ForEach(notifications) { notif in
|
||||
NotificationRow(notif: notif)
|
||||
.onDisappear() {
|
||||
guard !notifications.isEmpty else { return }
|
||||
lastId = notifications.firstIndex(where: { $0.id == notif.id })
|
||||
}
|
||||
}
|
||||
}
|
||||
.refreshable {
|
||||
notifications = []
|
||||
await fetchNotifications(lastId: nil)
|
||||
}
|
||||
.onChange(of: lastId ?? 0) { _, new in
|
||||
guard !loadingNotifs else { return }
|
||||
Task {
|
||||
loadingNotifs = true
|
||||
await fetchNotifications(lastId: new)
|
||||
loadingNotifs = false
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if loadingNotifs == false && notifications.isEmpty {
|
||||
ZStack {
|
||||
Color.appBackground
|
||||
.ignoresSafeArea()
|
||||
|
||||
ContentUnavailableView("activity.no-notifications", systemImage: "bolt.heart")
|
||||
}
|
||||
} else if loadingNotifs == true && notifications.isEmpty {
|
||||
ZStack {
|
||||
Color.appBackground
|
||||
.ignoresSafeArea()
|
||||
|
||||
ProgressView()
|
||||
.progressViewStyle(.circular)
|
||||
}
|
||||
}
|
||||
}
|
||||
.task {
|
||||
loadingNotifs = true
|
||||
await fetchNotifications(lastId: nil)
|
||||
loadingNotifs = false
|
||||
}
|
||||
}
|
||||
|
||||
func fetchNotifications(lastId: Int? = nil) async {
|
||||
guard let client = accountManager.getClient() else { return }
|
||||
|
||||
if lastId != nil {
|
||||
guard lastId! >= notifications.count - 6 else { return }
|
||||
}
|
||||
|
||||
do {
|
||||
let allCases = Notification.NotificationType.allCases.map({ $0.rawValue })
|
||||
let notifs: [Notification] = try await client.get(endpoint: Notifications.notifications(minId: nil, maxId: nil, types: nil, limit: lastId != nil ? notifLimit : 30))
|
||||
guard !notifs.isEmpty else { return }
|
||||
|
||||
if notifications.isEmpty {
|
||||
notifications = notifs
|
||||
} else {
|
||||
notifications.append(contentsOf: notifs)
|
||||
}
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue