added Sendable and other corrections
This commit is contained in:
parent
d782a2fcf5
commit
3824735fe1
@ -1,6 +1,6 @@
|
|||||||
/// Represents an error coming directly from the devrant API.
|
/// Represents an error coming directly from the devrant API.
|
||||||
public struct DevRantApiError: Swift.Error {
|
public struct DevRantApiError: Swift.Error {
|
||||||
let message: String
|
public let message: String
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension DevRantApiError {
|
public extension DevRantApiError {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/// An image that the user has uploaded for his rant or comment.
|
/// An image that the user has uploaded for his rant or comment.
|
||||||
public struct AttachedImage: Hashable {
|
public struct AttachedImage: Hashable, Sendable {
|
||||||
public let url: String
|
public let url: String
|
||||||
public let width: Int
|
public let width: Int
|
||||||
public let height: Int
|
public let height: Int
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public struct AuthToken: Hashable {
|
public struct AuthToken: Hashable, Sendable {
|
||||||
public let id: Int
|
public let id: Int
|
||||||
public let key: String
|
public let key: String
|
||||||
public let expireTime: Date
|
public let expireTime: Date
|
||||||
@ -18,21 +18,21 @@ public struct AuthToken: Hashable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AuthToken {
|
public extension AuthToken {
|
||||||
struct CodingData: Codable {
|
public struct CodingData: Codable {
|
||||||
struct Container: Codable {
|
public struct Container: Codable {
|
||||||
let auth_token: AuthToken.CodingData
|
let auth_token: AuthToken.CodingData
|
||||||
}
|
}
|
||||||
|
|
||||||
let id: Int
|
public let id: Int
|
||||||
let key: String
|
public let key: String
|
||||||
let expire_time: Int
|
public let expire_time: Int
|
||||||
let user_id: Int
|
public let user_id: Int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AuthToken.CodingData {
|
public extension AuthToken.CodingData {
|
||||||
var decoded: AuthToken {
|
public var decoded: AuthToken {
|
||||||
.init(
|
.init(
|
||||||
id: id,
|
id: id,
|
||||||
key: key,
|
key: key,
|
||||||
@ -41,3 +41,14 @@ extension AuthToken.CodingData {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public extension AuthToken {
|
||||||
|
public var encoded: AuthToken.CodingData {
|
||||||
|
.init(
|
||||||
|
id: id,
|
||||||
|
key: key,
|
||||||
|
expire_time: Int(expireTime.timeIntervalSince1970),
|
||||||
|
user_id: userId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
public struct Collaboration: Hashable {
|
public struct Collaboration: Hashable, Sendable {
|
||||||
public enum Kind: Int {
|
public enum Kind: Int, Sendable {
|
||||||
case openSourceIdea = 1
|
case openSourceIdea = 1
|
||||||
case existingOpenSourceProject = 2
|
case existingOpenSourceProject = 2
|
||||||
case projectIdea = 3
|
case projectIdea = 3
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
/// A comment posted by a user inside of a rant.
|
/// A comment posted by a user inside of a rant.
|
||||||
public struct Comment: Identifiable, Hashable {
|
public struct Comment: Identifiable, Hashable, Sendable {
|
||||||
/// The id of this comment.
|
/// The id of this comment.
|
||||||
public let id: Int
|
public let id: Int
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/// Represents the reason for downvoting.
|
/// Represents the reason for downvoting.
|
||||||
public enum DownvoteReason: Int, Hashable {
|
public enum DownvoteReason: Int, Hashable, Sendable {
|
||||||
case notForMe = 0
|
case notForMe = 0
|
||||||
case repost = 1
|
case repost = 1
|
||||||
case offensiveOrSpam = 2
|
case offensiveOrSpam = 2
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/// A URL or a user mention link in a rant or comment.
|
/// A URL or a user mention link in a rant or comment.
|
||||||
public struct Link: Hashable {
|
public struct Link: Hashable, Sendable {
|
||||||
public enum Kind {
|
public enum Kind: String, Sendable {
|
||||||
case url
|
case url = "url"
|
||||||
case userMention
|
case userMention = "mention"
|
||||||
}
|
}
|
||||||
|
|
||||||
public let kind: Kind
|
public let kind: Kind
|
||||||
@ -47,7 +47,7 @@ extension Link {
|
|||||||
extension Link.CodingData {
|
extension Link.CodingData {
|
||||||
var decoded: Link {
|
var decoded: Link {
|
||||||
.init(
|
.init(
|
||||||
kind: type == "mention" ? .userMention : .url,
|
kind: .init(rawValue: type) ?? .url,
|
||||||
url: url,
|
url: url,
|
||||||
shortURL: short_url,
|
shortURL: short_url,
|
||||||
title: title,
|
title: title,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
/// A notification about activities in a rant or a comment.
|
/// A notification about activities in a rant or a comment.
|
||||||
public struct Notification: Hashable, Identifiable {
|
public struct Notification: Hashable, Identifiable, Sendable {
|
||||||
public enum Kind: String {
|
public enum Kind: String, Sendable {
|
||||||
/// An upvote for a rant.
|
/// An upvote for a rant.
|
||||||
case rantUpvote = "content_vote"
|
case rantUpvote = "content_vote"
|
||||||
|
|
||||||
|
57
Sources/SwiftDevRant/Models/NotificationFeed+Mapping.swift
Normal file
57
Sources/SwiftDevRant/Models/NotificationFeed+Mapping.swift
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
public extension NotificationFeed {
|
||||||
|
public struct MappedNotificationItem: Hashable, Sendable {
|
||||||
|
public let rantId: Rant.ID
|
||||||
|
public let commentId: Comment.ID?
|
||||||
|
public let userId: Int
|
||||||
|
public let userAvatar: User.Avatar
|
||||||
|
public let userName: String
|
||||||
|
public let notificationKind: Notification.Kind
|
||||||
|
public let created: Date
|
||||||
|
public let isRead: Bool
|
||||||
|
|
||||||
|
public init(rantId: Rant.ID, commentId: Comment.ID?, userId: Int, userAvatar: User.Avatar, userName: String, notificationKind: Notification.Kind, created: Date, isRead: Bool) {
|
||||||
|
self.rantId = rantId
|
||||||
|
self.commentId = commentId
|
||||||
|
self.userId = userId
|
||||||
|
self.userAvatar = userAvatar
|
||||||
|
self.userName = userName
|
||||||
|
self.notificationKind = notificationKind
|
||||||
|
self.created = created
|
||||||
|
self.isRead = isRead
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var mappedItems: [MappedNotificationItem] {
|
||||||
|
notifications.map { notification in
|
||||||
|
let rantId = notification.rantId
|
||||||
|
let commentId = notification.commentId
|
||||||
|
let userId = notification.userId
|
||||||
|
let userInfo = userInfos.first { $0.userId == String(userId) }
|
||||||
|
let userAvatar = userInfo?.avatar ?? .init(colorHex: "cccccc", imageUrlPath: nil)
|
||||||
|
let userName = userInfo?.username ?? ""
|
||||||
|
|
||||||
|
return MappedNotificationItem(
|
||||||
|
rantId: rantId,
|
||||||
|
commentId: commentId,
|
||||||
|
userId: userId,
|
||||||
|
userAvatar: userAvatar,
|
||||||
|
userName: userName,
|
||||||
|
notificationKind: notification.kind,
|
||||||
|
created: notification.created,
|
||||||
|
isRead: notification.read
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var unreadByCategory: [NotificationFeed.Category: Int] {
|
||||||
|
[
|
||||||
|
.all: unreadNumbers.all,
|
||||||
|
.upvotes: unreadNumbers.upvotes,
|
||||||
|
.mentions: unreadNumbers.mentions,
|
||||||
|
.comments: unreadNumbers.comments,
|
||||||
|
.subscriptions: unreadNumbers.subscriptions,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
public extension NotificationFeed {
|
public extension NotificationFeed {
|
||||||
/// Holds numbers of unread notifications for each type of notification.
|
/// Holds numbers of unread notifications for each type of notification.
|
||||||
struct UnreadNumbers: Decodable, Hashable {
|
struct UnreadNumbers: Decodable, Hashable, Sendable {
|
||||||
/// The total number of unread notifications
|
/// The total number of unread notifications
|
||||||
public let all: Int
|
public let all: Int
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
public extension NotificationFeed {
|
public extension NotificationFeed {
|
||||||
struct UserInfo: Hashable {
|
struct UserInfo: Hashable, Sendable {
|
||||||
public let avatar: User.Avatar
|
public let avatar: User.Avatar
|
||||||
public let username: String
|
public let username: String
|
||||||
public let userId: String //TODO: why is this String? The other user ids are Int.
|
public let userId: String //TODO: why is this String? The other user ids are Int.
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
/// Contains a list of all notifications for the logged in user and the numbers of unread notifications.
|
/// Contains a list of all notifications for the logged in user and the numbers of unread notifications.
|
||||||
public struct NotificationFeed: Hashable {
|
public struct NotificationFeed: Hashable, Sendable {
|
||||||
public enum Category: String, CaseIterable {
|
public enum Category: String, CaseIterable, Sendable {
|
||||||
case all = ""
|
case all = ""
|
||||||
case upvotes = "upvotes"
|
case upvotes = "upvotes"
|
||||||
case mentions = "mentions"
|
case mentions = "mentions"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
public extension Profile.Content {
|
public extension Profile.Content {
|
||||||
struct Elements: Hashable {
|
struct Elements: Hashable, Sendable {
|
||||||
/// The rants that the user has created.
|
/// The rants that the user has created.
|
||||||
public let rants: [Rant]
|
public let rants: [Rant]
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
public extension Profile.Content {
|
public extension Profile.Content {
|
||||||
struct Numbers: Hashable {
|
struct Numbers: Hashable, Sendable {
|
||||||
/// The number of rants that the user has created.
|
/// The number of rants that the user has created.
|
||||||
public let rants: Int
|
public let rants: Int
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
public extension Profile {
|
public extension Profile {
|
||||||
struct Content: Hashable {
|
struct Content: Hashable, Sendable {
|
||||||
public let elements: Elements
|
public let elements: Elements
|
||||||
public let numbers: Numbers
|
public let numbers: Numbers
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
/// Holds information, content and the activity history of a user.
|
/// Holds information, content and the activity history of a user.
|
||||||
public struct Profile: Hashable {
|
public struct Profile: Hashable, Sendable {
|
||||||
/// The user's alias.
|
/// The user's alias.
|
||||||
public let username: String
|
public let username: String
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ public struct Profile: Hashable {
|
|||||||
public let devRantSupporter: Bool
|
public let devRantSupporter: Bool
|
||||||
|
|
||||||
/// True if the logged in user is subscribed to the user of this profile.
|
/// True if the logged in user is subscribed to the user of this profile.
|
||||||
public let subscribed: Bool //TODO: where is this set? It's not in the json data of the profile
|
public var subscribed: Bool //TODO: where is this set? It's not in the json data of the profile
|
||||||
|
|
||||||
public init(username: String, score: Int, created: Date, about: String?, location: String?, skills: String?, github: String?, website: String?, content: Profile.Content, avatarLarge: User.Avatar, avatarSmall: User.Avatar, devRantSupporter: Bool, subscribed: Bool) {
|
public init(username: String, score: Int, created: Date, about: String?, location: String?, skills: String?, github: String?, website: String?, content: Profile.Content, avatarLarge: User.Avatar, avatarSmall: User.Avatar, devRantSupporter: Bool, subscribed: Bool) {
|
||||||
self.username = username
|
self.username = username
|
||||||
@ -59,7 +59,7 @@ public struct Profile: Hashable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public extension Profile {
|
public extension Profile {
|
||||||
enum ContentType: String {
|
enum ContentType: String, Sendable {
|
||||||
/// All user content.
|
/// All user content.
|
||||||
case all = "all"
|
case all = "all"
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
public extension Rant {
|
public extension Rant {
|
||||||
public enum Kind: Int {
|
public enum Kind: Int, Sendable {
|
||||||
case rant = 1
|
case rant = 1
|
||||||
case collaboration = 2
|
case collaboration = 2
|
||||||
case meme = 3
|
case meme = 3
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
public extension Rant {
|
public extension Rant {
|
||||||
/// Holds information about a specific weekly group rant.
|
/// Holds information about a specific weekly group rant.
|
||||||
struct Weekly: Hashable {
|
struct Weekly: Hashable, Sendable {
|
||||||
public let week: Int
|
public let week: Int
|
||||||
public let topic: String
|
public let topic: String
|
||||||
public let date: String
|
public let date: String
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public struct Rant: Identifiable, Hashable {
|
public struct Rant: Identifiable, Hashable, Sendable {
|
||||||
/// The id of this rant.
|
/// The id of this rant.
|
||||||
public let id: Int
|
public let id: Int
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ public struct Rant: Identifiable, Hashable {
|
|||||||
public let isEdited: Bool
|
public let isEdited: Bool
|
||||||
|
|
||||||
/// True if this rant has been marked as a favorite by the logged in user.
|
/// True if this rant has been marked as a favorite by the logged in user.
|
||||||
public let isFavorite: Bool
|
public var isFavorite: Bool
|
||||||
|
|
||||||
/// The text contents of this rant.
|
/// The text contents of this rant.
|
||||||
public let text: String
|
public let text: String
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
public extension RantFeed {
|
public extension RantFeed {
|
||||||
/// Contains information about news given in rant feeds.
|
/// Contains information about news given in rant feeds.
|
||||||
/// - note: This is mostly used for weekly group rants.
|
/// - note: This is mostly used for weekly group rants.
|
||||||
struct News: Hashable, Identifiable {
|
struct News: Hashable, Identifiable, Sendable {
|
||||||
public enum Action: String {
|
public enum Action: String, Sendable {
|
||||||
case groupRant = "grouprant"
|
case groupRant = "grouprant"
|
||||||
case none = "none"
|
case none = "none"
|
||||||
case rant = "rant"
|
case rant = "rant"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/// Contains the list of rants for the logged in user and other random things.
|
/// Contains the list of rants for the logged in user and other random things.
|
||||||
public struct RantFeed: Hashable {
|
public struct RantFeed: Hashable, Sendable {
|
||||||
public let rants: [Rant]
|
public let rants: [Rant]
|
||||||
|
|
||||||
public let sessionHash: String?
|
public let sessionHash: String?
|
||||||
@ -25,7 +25,7 @@ public struct RantFeed: Hashable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public extension RantFeed {
|
public extension RantFeed {
|
||||||
enum Sort {
|
enum Sort: Sendable {
|
||||||
/// The devRant algorithm decides what rants appear in the feed.
|
/// The devRant algorithm decides what rants appear in the feed.
|
||||||
case algorithm
|
case algorithm
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ public extension RantFeed {
|
|||||||
case top(range: Range)
|
case top(range: Range)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Range {
|
enum Range: Sendable {
|
||||||
/// Rants from the one day.
|
/// Rants from the one day.
|
||||||
case day
|
case day
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
public extension User {
|
public extension User {
|
||||||
struct Avatar: Hashable {
|
struct Avatar: Hashable, Sendable {
|
||||||
public let colorHex: String
|
public let colorHex: String
|
||||||
|
|
||||||
public let imageUrlPath: String?
|
public let imageUrlPath: String?
|
||||||
|
|
||||||
public var imageUrl: String? {
|
public var imageUrl: URL? {
|
||||||
imageUrlPath.flatMap { "https://avatars.devrant.com/\($0)" }
|
imageUrlPath.flatMap { URL(string: "https://avatars.devrant.com/\($0)") }
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(colorHex: String, imageUrlPath: String?) {
|
public init(colorHex: String, imageUrlPath: String?) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/// Represents a user.
|
/// Represents a user.
|
||||||
public struct User: Identifiable, Hashable {
|
public struct User: Identifiable, Hashable, Sendable {
|
||||||
public let id: Int
|
public let id: Int
|
||||||
|
|
||||||
public let name: String
|
public let name: String
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/// Represents the different kinds of votes that a rant or comment can have.
|
/// Represents the different kinds of votes that a rant or comment can have.
|
||||||
public enum VoteState: Int, Hashable {
|
public enum VoteState: Int, Hashable, Sendable {
|
||||||
/// A given ++ vote.
|
/// A given ++ vote.
|
||||||
case upvoted = 1
|
case upvoted = 1
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/// The weekly item data for the list of weeklies.
|
/// The weekly item data for the list of weeklies.
|
||||||
public struct Weekly: Hashable, Identifiable {
|
public struct Weekly: Hashable, Identifiable, Sendable {
|
||||||
/// The number of the week. The first week starts with 1.
|
/// The number of the week. The first week starts with 1.
|
||||||
public let week: Int
|
public let week: Int
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import KreeRequest
|
import KreeRequest
|
||||||
|
|
||||||
public struct SwiftDevRant {
|
public struct SwiftDevRant { //TODO: rename to something else to not collide with the module name
|
||||||
let request: KreeRequest
|
let request: KreeRequest
|
||||||
let backend = DevRantBackend()
|
let backend = DevRantBackend()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user