From 2781bf4bdd3f9492d71c618fef9ed8ca91b14e52 Mon Sep 17 00:00:00 2001 From: Wilhelm Oks Date: Tue, 10 Dec 2024 19:12:13 +0100 Subject: [PATCH] Models WIP --- .../SwiftDevRant/Models/Collaboration.swift | 7 ++ Sources/SwiftDevRant/Models/Rant.swift | 113 ++++++++++++++++++ Sources/SwiftDevRant/Models/User.swift | 12 ++ Sources/SwiftDevRant/Models/VoteState.swift | 14 +++ 4 files changed, 146 insertions(+) create mode 100644 Sources/SwiftDevRant/Models/Collaboration.swift create mode 100644 Sources/SwiftDevRant/Models/Rant.swift create mode 100644 Sources/SwiftDevRant/Models/User.swift create mode 100644 Sources/SwiftDevRant/Models/VoteState.swift diff --git a/Sources/SwiftDevRant/Models/Collaboration.swift b/Sources/SwiftDevRant/Models/Collaboration.swift new file mode 100644 index 0000000..b64ed1d --- /dev/null +++ b/Sources/SwiftDevRant/Models/Collaboration.swift @@ -0,0 +1,7 @@ +public struct Collaboration: Hashable { + public let type: String //TODO: check if this is a kind of enum or some arbitrary text entered by the user. + public let description: String + public let techStack: String + public let teamSize: String + public let url: String +} diff --git a/Sources/SwiftDevRant/Models/Rant.swift b/Sources/SwiftDevRant/Models/Rant.swift new file mode 100644 index 0000000..51151c4 --- /dev/null +++ b/Sources/SwiftDevRant/Models/Rant.swift @@ -0,0 +1,113 @@ +import Foundation + +public struct Rant: Identifiable, Hashable { + //TODO: public let weekly: Weekly? + + /// The id of this rant. + public let id: Int + + /// The text contents of this rant. + public let text: String + + /// The number of upvotes from other users. + public let score: Int + + /// The time when this rant was created. + public let created: Date + + /// If the rant has an image attached to it, a URL of the image will be stored in this. + //TODO: public let attachedImage: AttachedImage? + + /// The number of comments that this rant has. + public let numberOfComments: Int + + /// The tags for this rant. + public let tags: [String] + + /// The current logged in user's vote on this rant. + public let voteState: VoteState + + /// True if this rant is edited by the author. + public let isEdited: Bool + + /// True if this rant has been marked as a favorite by the logged in user. + public var isFavorite: Bool + + /// A url link to this rant. + public let link: String? + + /// If the rant includes URLs in the text, those that were successfully parsed by the server will be in this array. + //TODO: public var links: [Link]? + + /// Holds information about the collaboration project if this rant is of type collaboration. + let collaboration: Collaboration? + + /// The user who wrote this rant. + let author: User +} + +extension Rant { + struct CodingData: Codable { + let id: Int + let text: String + let score: Int + let created_time: Int + //TODO: let attachedImage: AttachedImage? + let num_comments: Int + let tags: [String] + let vote_state: Int + //TODO: let weekly: Weekly? + let edited: Bool + let favorited: Int? + let link: String? + //TODO: let links: [Link] + let c_type_long: String? + let c_description: String? + let c_tech_stack: String? + let c_team_size: String? + let c_url: String? + let user_id: Int + let user_username: String + let user_score: Int + //TODO: let user_avatar: UserAvatar + //TODO: let user_avatar_lg: UserAvatar + let user_dpp: Int? + } +} + +extension Rant.CodingData { + var decoded: Rant { + .init( + id: id, + text: text, + score: score, + created: Date(timeIntervalSince1970: TimeInterval(created_time)), + numberOfComments: num_comments, + tags: tags, + voteState: .init(rawValue: vote_state) ?? .unvoted, + isEdited: edited, + isFavorite: (favorited ?? 0) != 0, + link: link, + collaboration: decodedCollaboration, + author: .init( + id: user_id, + name: user_username, + score: user_score, + devRantSupporter: (user_dpp ?? 0) != 0 + ) + ) + } + + private var decodedCollaboration: Collaboration? { + let collaborationProperties = [c_type_long, c_description, c_tech_stack, c_team_size, c_url] + let nonNilProperties = collaborationProperties.compactMap { $0 } + guard !nonNilProperties.isEmpty else { return nil } + return .init( + type: c_type_long ?? "", + description: c_description ?? "", + techStack: c_tech_stack ?? "", + teamSize: c_team_size ?? "", + url: c_url ?? "" + ) + } +} diff --git a/Sources/SwiftDevRant/Models/User.swift b/Sources/SwiftDevRant/Models/User.swift new file mode 100644 index 0000000..2b3568e --- /dev/null +++ b/Sources/SwiftDevRant/Models/User.swift @@ -0,0 +1,12 @@ +public struct User: Identifiable, Hashable { + public let id: Int + public let name: String + public let score: Int + public let devRantSupporter: Bool + + /// The author's avatar, can be used optimally for small portraits of the user. + //TODO: public let userAvatar: UserAvatar + + /// A larger version of the author's avatar, can be used optimally for profile screens. + //TODO: public let userAvatarLarge: UserAvatar +} diff --git a/Sources/SwiftDevRant/Models/VoteState.swift b/Sources/SwiftDevRant/Models/VoteState.swift new file mode 100644 index 0000000..829c5a1 --- /dev/null +++ b/Sources/SwiftDevRant/Models/VoteState.swift @@ -0,0 +1,14 @@ +/// Represents the different kinds of votes that a rant or comment can have. +public enum VoteState: Int, Hashable { + /// A given ++ vote. + case upvoted = 1 + + /// No votes given. + case unvoted = 0 + + /// A given -- vote. + case downvoted = -1 + + /// Not able to vote (if the rant or comment belongs to the logged in user). + case unvotable = -2 +}