import Foundation struct HomeFollowingTabResponse: Decodable { let isLoginRequired: Bool let followingCreators: [FollowingCreatorResponse] let onAirLives: [FollowingLiveResponse] let recentChats: [ChatRoomListItemResponse] let monthlySchedules: [FollowingScheduleResponse] let recentNews: [FollowingNewsResponse] } struct FollowingCreatorResponse: Decodable, Identifiable { let creatorId: Int let creatorNickname: String let creatorProfileImageUrl: String var id: Int { creatorId } } struct FollowingLiveResponse: Decodable, Identifiable { let liveId: Int let creatorProfileImageUrl: String let creatorNickname: String let title: String let startedAtUtc: String var id: Int { liveId } } struct ChatRoomListItemResponse: Decodable, Identifiable { let roomId: Int let chatType: String let targetName: String let targetImageUrl: String let lastMessage: String let lastMessageAt: String var id: Int { roomId } } struct FollowingScheduleResponse: Decodable, Identifiable { let scheduleId: String let creatorId: Int let creatorProfileImageUrl: String let creatorNickname: String let title: String let type: CreatorActivityType let targetId: Int let scheduledAtUtc: String let isOnAir: Bool var id: String { scheduleId } } enum CreatorActivityType: Decodable, Hashable { case live case audio case community case liveReplay case unknown(String) init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let code = try container.decode(String.self) switch code { case "LIVE": self = .live case "AUDIO": self = .audio case "COMMUNITY": self = .community case "LIVE_REPLAY": self = .liveReplay default: self = .unknown(code) } } } struct FollowingNewsResponse: Decodable, Identifiable { let newsId: String let type: FollowingNewsType let visibleFromAtUtc: String let creatorRanking: FollowingCreatorRankingNewsResponse? let audioContent: FollowingContentNewsResponse? let photoContent: FollowingContentNewsResponse? let contentRanking: FollowingContentRankingNewsResponse? let communityPost: FollowingCommunityPostNewsResponse? var id: String { newsId } } struct FollowingCreatorRankingNewsResponse: Decodable { let rank: Int let creatorId: Int let nickname: String let profileImageUrl: String } struct FollowingContentNewsResponse: Decodable { let contentId: Int let contentImageUrl: String? let title: String let creatorProfileImageUrl: String let creatorNickname: String } struct FollowingContentRankingNewsResponse: Decodable { let rank: Int let contentId: Int let contentImageUrl: String? let title: String } struct FollowingCommunityPostNewsResponse: Decodable { let postId: Int let creatorProfileImage: String let creatorNickname: String let imageUrl: String? let content: String let createdAt: String let likeCount: Int let commentCount: Int } enum FollowingNewsType: Decodable, Hashable { case creatorRanking case contentRanking case communityPost case audioContent case photoContent case unknown(String) init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let code = try container.decode(String.self) switch code { case "CREATOR_RANKING": self = .creatorRanking case "CONTENT_RANKING": self = .contentRanking case "COMMUNITY_POST": self = .communityPost case "AUDIO_CONTENT": self = .audioContent case "PHOTO_CONTENT": self = .photoContent default: self = .unknown(code) } } }