feat: 최근 들은 콘텐츠 로컬 DB 추가

This commit is contained in:
Yu Sung
2025-07-28 22:34:34 +09:00
parent a73cafa08c
commit 70af4cb3dd
10 changed files with 306 additions and 67 deletions

View File

@@ -16,6 +16,7 @@ import RefreshableScrollView
struct MyPageView: View {
@StateObject var viewModel = MyPageViewModel()
@StateObject var recentContentViewModel = RecentContentViewModel()
@State private var payload = Payload()
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
@@ -68,6 +69,7 @@ struct MyPageView: View {
) {
viewModel.getMypage()
}
.padding(.horizontal, 24)
} else {
HStack {
Text("LOGIN")
@@ -78,6 +80,7 @@ struct MyPageView: View {
.frame(maxWidth: .infinity)
.background(Color.gray22)
.cornerRadius(16)
.padding(.horizontal, 24)
.onTapGesture {
AppState.shared
.setAppStep(step: .login)
@@ -91,6 +94,7 @@ struct MyPageView: View {
token: token,
refresh: { viewModel.getMypage() }
)
.padding(.horizontal, 24)
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
// Category Buttons
@@ -105,23 +109,24 @@ struct MyPageView: View {
viewModel.getMypage()
}
)
.padding(.horizontal, 24)
}
if let url = URL(string: "https://blog.naver.com/sodalive_official"),
UIApplication.shared.canOpenURL(url) {
// Voice On Banner
Image("img_introduce_voiceon")
.padding(.horizontal, 24)
.onTapGesture {
UIApplication.shared.open(url)
}
}
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && !viewModel.recentContentList.isEmpty {
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && !recentContentViewModel.recentContents.isEmpty {
// Recent 10 Section
RecentContentSection(recentContentList: viewModel.recentContentList)
RecentContentSection(recentContents: recentContentViewModel.recentContents)
}
}
.padding(.horizontal, 24)
.padding(.vertical, 32)
}
}
@@ -129,6 +134,7 @@ struct MyPageView: View {
.onAppear {
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
viewModel.getMypage()
recentContentViewModel.fetchRecentContents()
}
viewModel.getLatestNotice()
}
@@ -442,24 +448,25 @@ struct CategoryButtonItem: View {
// MARK: - Recent 10 Content Section
struct RecentContentSection: View {
let recentContentList: [AudioContentMainItem]
let recentContents: [RecentContent]
var body: some View {
VStack(alignment: .leading, spacing: 14) {
HStack(spacing: 0) {
Text("최근 들은 ")
.font(.system(size: 16, weight: .bold))
.foregroundColor(.white)
.font(.custom(Font.preBold.rawValue, size: 16))
.foregroundColor(Color(hex: "B0BEC5"))
Text("\(recentContentList.count)")
.font(.system(size: 16, weight: .bold))
.foregroundColor(.white)
Text("\(recentContents.count)")
.font(.custom(Font.preBold.rawValue, size: 16))
.foregroundColor(Color(hex: "FDC118"))
}
.padding(.horizontal, 24)
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 16) {
ForEach(0..<recentContentList.count, id: \.self) { index in
RecentItemView()
ForEach(0..<recentContents.count, id: \.self) { index in
RecentItemView(content: recentContents[index])
}
}
.padding(.horizontal, 24)
@@ -469,67 +476,41 @@ struct RecentContentSection: View {
}
struct RecentItemView: View {
let content: RecentContent
var body: some View {
VStack(spacing: 8) {
// Thumbnail placeholder
RoundedRectangle(cornerRadius: 16)
.fill(Color.gray)
.frame(width: 168, height: 168)
.overlay(
VStack {
Spacer()
HStack {
Spacer()
Text("00:12:33")
.font(.system(size: 12))
.foregroundColor(.white)
.padding(.horizontal, 10)
.padding(.vertical, 3)
.background(Color.black.opacity(0.7))
.cornerRadius(39)
}
.padding(8)
}
)
.overlay(
VStack {
HStack {
Text("신작")
.font(.system(size: 12))
.foregroundColor(.white)
.padding(.horizontal, 10)
.padding(.vertical, 3)
.background(LinearGradient(
gradient: Gradient(colors: [Color(hex: "0001B1"), Color(hex: "3B5FF1")]),
startPoint: .leading,
endPoint: .trailing
))
.cornerRadius(12)
Spacer()
Image(systemName: "shield.fill")
.foregroundColor(.red)
.frame(width: 20, height: 20)
}
.padding(8)
Spacer()
}
)
VStack(alignment: .leading, spacing: 4) {
Text("우디(Woody)")
.font(.system(size: 18))
.foregroundColor(.white)
VStack(alignment: .leading, spacing: 0) {
KFImage(URL(string: content.coverImageUrl))
.cancelOnDisappear(true)
.resizable()
.scaledToFill()
.frame(width: 160, height: 160, alignment: .top)
.cornerRadius(16)
Text("우기라스")
.font(.system(size: 14))
Text(content.title)
.font(.custom(Font.preRegular.rawValue, size: 18))
.foregroundColor(.white)
.multilineTextAlignment(.leading)
.fixedSize(horizontal: false, vertical: true)
.lineLimit(1)
.padding(.horizontal, 6)
.padding(.top, 8)
Text(content.creatorNickname)
.font(.custom(Font.preRegular.rawValue, size: 14))
.foregroundColor(Color(hex: "78909C"))
.lineLimit(1)
.padding(.horizontal, 6)
.padding(.top, 4)
}
.frame(width: 160)
.onTapGesture {
AppState.shared.setAppStep(step: .contentDetail(contentId: Int(content.contentId)))
}
.padding(.leading, 6)
}
.frame(width: 168)
}
}