Models WIP: Profile

This commit is contained in:
Wilhelm Oks 2024-12-13 12:35:30 +01:00
parent 394e9a92c3
commit 9d61167e81
7 changed files with 248 additions and 5 deletions

View File

@ -78,7 +78,7 @@ extension Comment.CodingData {
name: user_username, name: user_username,
score: user_score, score: user_score,
devRantSupporter: (user_dpp ?? 0) != 0, devRantSupporter: (user_dpp ?? 0) != 0,
avatar: user_avatar.decoded, avatarSmall: user_avatar.decoded,
avatarLarge: user_avatar_lg?.decoded avatarLarge: user_avatar_lg?.decoded
), ),
created: Date(timeIntervalSince1970: TimeInterval(created_time)), created: Date(timeIntervalSince1970: TimeInterval(created_time)),

View File

@ -0,0 +1,48 @@
public extension Profile.Content {
struct Elements: Hashable {
/// The rants that the user has created.
public let rants: [Rant]
/// The rants that the user has upvoted.
public let upvotedRants: [Rant]
/// The comments that the user has created.
public let comments: [Comment]
/// The rants that the user has marked as favorite.
public let favorites: [Rant]
/// If the profile is from the logged in user, then this list contains rants that user has viewed in the past.
public let viewed: [Rant]
public init(rants: [Rant], upvotedRants: [Rant], comments: [Comment], favorites: [Rant], viewed: [Rant]) {
self.rants = rants
self.upvotedRants = upvotedRants
self.comments = comments
self.favorites = favorites
self.viewed = viewed
}
}
}
extension Profile.Content.Elements {
struct CodingData: Codable {
let rants: [Rant.CodingData]
let upvoted: [Rant.CodingData]
let comments: [Comment.CodingData]
let favorites: [Rant.CodingData]?
let viewed: [Rant.CodingData]?
}
}
extension Profile.Content.Elements.CodingData {
var decoded: Profile.Content.Elements {
.init(
rants: rants.map(\.decoded),
upvotedRants: upvoted.map(\.decoded),
comments: comments.map(\.decoded),
favorites: favorites?.map(\.decoded) ?? [],
viewed: viewed?.map(\.decoded) ?? []
)
}
}

View File

@ -0,0 +1,48 @@
public extension Profile.Content {
struct Numbers: Hashable {
/// The number of rants that the user has created.
public let rants: Int
/// The number of rants that the user has upvoted.
public let upvotedRants: Int
/// The number of the comments that the user has created.
public let comments: Int
/// The number of rants that the user has marked as favorite.
public let favorites: Int
/// The number of collaborations the user has created.
public let collaborations: Int
public init(rants: Int, upvotedRants: Int, comments: Int, favorites: Int, collaborations: Int) {
self.rants = rants
self.upvotedRants = upvotedRants
self.comments = comments
self.favorites = favorites
self.collaborations = collaborations
}
}
}
extension Profile.Content.Numbers {
struct CodingData: Codable {
let rants: Int
let upvoted: Int
let comments: Int
let favorites: Int
let collabs: Int
}
}
extension Profile.Content.Numbers.CodingData {
var decoded: Profile.Content.Numbers {
.init(
rants: rants,
upvotedRants: upvoted,
comments: comments,
favorites: favorites,
collaborations: collabs
)
}
}

View File

@ -0,0 +1,27 @@
public extension Profile {
struct Content: Hashable {
public let elements: Elements
public let numbers: Numbers
public init(elements: Profile.Content.Elements, numbers: Profile.Content.Numbers) {
self.elements = elements
self.numbers = numbers
}
}
}
extension Profile.Content {
struct CodingData: Codable {
let content: Elements.CodingData
let counts: Numbers.CodingData
}
}
extension Profile.Content.CodingData {
var decoded: Profile.Content {
.init(
elements: content.decoded,
numbers: counts.decoded
)
}
}

View File

@ -0,0 +1,119 @@
import Foundation
/// Holds information, content and the activity history of a user.
public struct Profile: Hashable {
/// The user's alias.
public let username: String
/// The number of upvotes that the user got from other users.
public let score: Int
/// The time when the user created the account.
public let created: Date
/// The description of the user.
public let about: String?
/// The description of the geographic location.
public let location: String?
/// The description of the user's skills.
public let skills: String?
/// The user's GitHub reference.
public let github: String?
/// The user's personal website.
public let website: String?
/// The user's content and activities.
public let content: Content
/// The user's large avatar, for profile views.
public let avatarLarge: User.Avatar
/// The user's small avatar, for rant views and comment views.
public let avatarSmall: User.Avatar
/// True if the user is subscribed to devRant++.
public let devRantSupporter: Bool
/// 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 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.score = score
self.created = created
self.about = about
self.location = location
self.skills = skills
self.github = github
self.website = website
self.content = content
self.avatarLarge = avatarLarge
self.avatarSmall = avatarSmall
self.devRantSupporter = devRantSupporter
self.subscribed = subscribed
}
}
public extension Profile {
enum ContentType: String {
/// All user content.
case all = "all"
/// The user's rants.
case rants = "rants"
/// The user's comments.
case comments = "comments"
/// Rants or comments upvoted by the user.
case upvoted = "upvoted"
/// The user's favorite rants.
case favorite = "favorites"
/// The rants viewd by the user.
case viewed = "viewed"
}
}
extension Profile {
struct CodingData: Codable {
let username: String
let score: Int
let created_time: Int
let about: String
let location: String
let skills: String
let github: String
let website: String
let content: Content.CodingData
let avatar: User.Avatar.CodingData
let avatar_sm: User.Avatar.CodingData
let dpp: Int?
let subscribed: Bool? //TODO: check if it exists in the json data
}
}
extension Profile.CodingData {
var decoded: Profile {
.init(
username: username,
score: score,
created: Date(timeIntervalSince1970: TimeInterval(created_time)),
about: about.isEmpty ? nil : about,
location: location.isEmpty ? nil : location,
skills: skills.isEmpty ? nil : skills,
github: github.isEmpty ? nil : github,
website: website.isEmpty ? nil : website,
content: content.decoded,
avatarLarge: avatar.decoded,
avatarSmall: avatar_sm.decoded,
devRantSupporter: (dpp ?? 0) != 0,
subscribed: subscribed ?? false
)
}
}

View File

@ -107,7 +107,7 @@ extension Rant.CodingData {
name: user_username, name: user_username,
score: user_score, score: user_score,
devRantSupporter: (user_dpp ?? 0) != 0, devRantSupporter: (user_dpp ?? 0) != 0,
avatar: user_avatar.decoded, avatarSmall: user_avatar.decoded,
avatarLarge: user_avatar_lg.decoded avatarLarge: user_avatar_lg.decoded
), ),
created: Date(timeIntervalSince1970: TimeInterval(created_time)), created: Date(timeIntervalSince1970: TimeInterval(created_time)),

View File

@ -1,3 +1,4 @@
/// Represents a user.
public struct User: Identifiable, Hashable { public struct User: Identifiable, Hashable {
public let id: Int public let id: Int
@ -10,17 +11,17 @@ public struct User: Identifiable, Hashable {
public let devRantSupporter: Bool public let devRantSupporter: Bool
/// A small avatar for the rant views and comment views. /// A small avatar for the rant views and comment views.
public let avatar: Avatar public let avatarSmall: Avatar
/// A large avatar for the profile view. /// A large avatar for the profile view.
public let avatarLarge: Avatar? public let avatarLarge: Avatar?
public init(id: Int, name: String, score: Int, devRantSupporter: Bool, avatar: User.Avatar, avatarLarge: User.Avatar?) { public init(id: Int, name: String, score: Int, devRantSupporter: Bool, avatarSmall: User.Avatar, avatarLarge: User.Avatar?) {
self.id = id self.id = id
self.name = name self.name = name
self.score = score self.score = score
self.devRantSupporter = devRantSupporter self.devRantSupporter = devRantSupporter
self.avatar = avatar self.avatarSmall = avatarSmall
self.avatarLarge = avatarLarge self.avatarLarge = avatarLarge
} }
} }