diff --git a/today-s-sound/Core/Network/Config.swift b/today-s-sound/Core/Network/Config.swift index 2e27503..b476640 100644 --- a/today-s-sound/Core/Network/Config.swift +++ b/today-s-sound/Core/Network/Config.swift @@ -3,7 +3,7 @@ import Foundation enum Config { static var baseURL: String { #if DEBUG - return "https://www.today-sound.com" + return "https://www.today-sound.com" // return "http://localhost:8080" // 개발 서버 #else return "https://api.todays-sound.com" // 운영 서버 diff --git a/today-s-sound/Data/Models/Feed.swift b/today-s-sound/Data/Models/Feed.swift index d058128..4cc7d1d 100644 --- a/today-s-sound/Data/Models/Feed.swift +++ b/today-s-sound/Data/Models/Feed.swift @@ -46,6 +46,7 @@ extension FeedListResponse { struct FeedItemResponse: Codable, Identifiable { let subscriptionId: Int64 let alias: String + let summaryTitle: String let summaryContent: String let url: String let timeAgo: String @@ -57,6 +58,7 @@ struct FeedItemResponse: Codable, Identifiable { enum CodingKeys: String, CodingKey { case subscriptionId case alias + case summaryTitle case summaryContent case url case timeAgo diff --git a/today-s-sound/Presentation/Features/Feed/FeedModel.swift b/today-s-sound/Presentation/Features/Feed/FeedModel.swift index 1ef3d0d..1ad5c79 100644 --- a/today-s-sound/Presentation/Features/Feed/FeedModel.swift +++ b/today-s-sound/Presentation/Features/Feed/FeedModel.swift @@ -4,7 +4,7 @@ struct FeedItem: Identifiable, Hashable { let id: UUID let alias: String let summary: String - let source: String + let summaryTitle: String let publishedAt: Date let timeAgo: String // 서버에서 받은 시간 문자열 ("2시간 전" 등) @@ -20,81 +20,15 @@ struct FeedItem: Identifiable, Hashable { id: UUID = UUID(), alias: String, summary: String, - source: String, + summaryTitle: String, publishedAt: Date, timeAgo: String = "" ) { self.id = id self.alias = alias self.summary = summary - self.source = source + self.summaryTitle = summaryTitle self.publishedAt = publishedAt self.timeAgo = timeAgo } } - -enum FeedSampleData { - /// 스크롤 테스트용 데모 데이터 (여러 사이트 섞어서 충분히 길게) - static let items: [FeedItem] = [ - FeedItem( - alias: "교육부, 시각장애 학생을 위한 AI 오디오 교재 배포", - summary: "전국 특수학교를 대상으로 접근성 강화 음성 교재를 순차적으로 배포합니다.", - source: "교육부 보도자료", - publishedAt: Date().addingTimeInterval(-60 * 20) // 20분 전 - ), - FeedItem( - alias: "서울시청, 공공 서비스 음성 지원 확대 발표", - summary: "서울시는 민원 앱에 보이스오버 전용 모드를 도입해 정보 접근성을 높인다고 밝혔습니다.", - source: "서울시청 뉴스룸", - publishedAt: Date().addingTimeInterval(-60 * 60) // 1시간 전 - ), - FeedItem( - alias: "오늘의 소리 베타 사용자 인터뷰", - summary: "베타 사용자들이 직접 전한 알림 읽기 경험과 개선 아이디어를 정리했습니다.", - source: "오늘의 소리 팀", - publishedAt: Date().addingTimeInterval(-60 * 60 * 2) // 2시간 전 - ), - FeedItem( - alias: "접근성 블로그: iOS 18 보이스오버 변경점 정리", - summary: "새 버전에서 달라진 제스처와 읽기 옵션을 한 번에 확인해 보세요.", - source: "접근성 블로그", - publishedAt: Date().addingTimeInterval(-60 * 60 * 3) // 3시간 전 - ), - FeedItem( - alias: "접근성 블로그: 시각장애인을 위한 키보드 단축키 모음", - summary: "웹 브라우저, 문서 편집기, 메신저 앱에서 유용한 단축키를 정리했습니다.", - source: "접근성 블로그", - publishedAt: Date().addingTimeInterval(-60 * 60 * 5) // 5시간 전 - ), - FeedItem( - alias: "서울시청, 버스 정류장 음성 안내 고도화", - summary: "버스 도착 정보에 노선 혼잡도와 환승 정보까지 음성으로 추가 안내합니다.", - source: "서울시청 뉴스룸", - publishedAt: Date().addingTimeInterval(-60 * 60 * 7) // 7시간 전 - ), - FeedItem( - alias: "교육부, 대학 온라인 강의 자막·음성 안내 의무화 추진", - summary: "강의 동영상에 자막과 음성 설명을 의무화하는 지침을 마련 중입니다.", - source: "교육부 보도자료", - publishedAt: Date().addingTimeInterval(-60 * 60 * 9) // 9시간 전 - ), - FeedItem( - alias: "오늘의 소리: 이번 주 서비스 업데이트 안내", - summary: "알림 필터 기능과 음성 재생 속도 조절 기능이 추가되었습니다.", - source: "오늘의 소리 팀", - publishedAt: Date().addingTimeInterval(-60 * 60 * 12) // 12시간 전 - ), - FeedItem( - alias: "오늘의 소리: 새로 구독 가능한 웹사이트 소개", - summary: "시각장애인 관련 단체, 공공기관, 접근성 블로그 등 5개 웹사이트를 새로 추가했습니다.", - source: "오늘의 소리 팀", - publishedAt: Date().addingTimeInterval(-60 * 60 * 24) // 1일 전 - ), - FeedItem( - alias: "접근성 블로그: 화면 낭독기와 함께 쓰기 좋은 브라우저 설정", - summary: "페이지 자동 스크롤, 탭 이동, 포커스 표시 옵션을 함께 조정해 보세요.", - source: "접근성 블로그", - publishedAt: Date().addingTimeInterval(-60 * 60 * 30) // 1일 6시간 전 - ) - ] -} diff --git a/today-s-sound/Presentation/Features/Feed/FeedView.swift b/today-s-sound/Presentation/Features/Feed/FeedView.swift index 32a5755..e1d452f 100644 --- a/today-s-sound/Presentation/Features/Feed/FeedView.swift +++ b/today-s-sound/Presentation/Features/Feed/FeedView.swift @@ -9,8 +9,8 @@ struct FeedView: View { /// 필터 옵션 목록: ["전체", "교육부 보도자료", "서울시청 뉴스룸", "오늘의 소리 팀", ...] private var filterOptions: [String] { - let sources = Set(viewModel.items.map(\.source)) - let sorted = Array(sources).sorted() + let alias = Set(viewModel.items.map(\.alias)) + let sorted = Array(alias).sorted() return ["전체"] + sorted } @@ -19,7 +19,7 @@ struct FeedView: View { if selectedFilter == "전체" { viewModel.items } else { - viewModel.items.filter { $0.source == selectedFilter } + viewModel.items.filter { $0.alias == selectedFilter } } } @@ -204,12 +204,12 @@ private struct FeedCard: View { var body: some View { VStack(alignment: .leading, spacing: 12) { // 페이지 이름 (작은 회색 텍스트) - Text(item.source) + Text(item.alias) .font(.KoddiRegular16) .foregroundColor(Color.secondaryText(colorScheme)) // 제목 (큰 볼드 텍스트, 두 줄 가능) - Text(item.alias) + Text(item.summaryTitle) .font(.KoddiBold28) .foregroundColor(Color.text(colorScheme)) .multilineTextAlignment(.leading) @@ -239,7 +239,7 @@ private struct FeedCard: View { ) .accessibilityElement(children: .combine) .accessibilityLabel( - "\(item.source) 새 글, \(item.alias), \(item.summary), \(item.timeAgo)" + "\(item.summaryTitle) 새 글, \(item.alias), \(item.summary), \(item.timeAgo)" ) } } diff --git a/today-s-sound/Presentation/Features/Feed/FeedViewModel.swift b/today-s-sound/Presentation/Features/Feed/FeedViewModel.swift index 7231a7c..4da450a 100644 --- a/today-s-sound/Presentation/Features/Feed/FeedViewModel.swift +++ b/today-s-sound/Presentation/Features/Feed/FeedViewModel.swift @@ -85,12 +85,11 @@ final class FeedViewModel: ObservableObject { // FeedItemResponse를 FeedItem으로 변환 let newItems = feedItems.map { response -> FeedItem in - // summaryContent를 제목으로 사용 (디자인에 맞춰 제목만 표시) FeedItem( id: UUID(), alias: response.alias, - summary: response.summaryContent, // 내용도 동일하게 사용 - source: response.alias, + summary: response.summaryContent, + summaryTitle: response.summaryTitle, publishedAt: self.parseTimeAgo(response.timeAgo), timeAgo: response.timeAgo ) @@ -182,12 +181,11 @@ final class FeedViewModel: ObservableObject { let feedItems = response.feeds let newItems = feedItems.map { response -> FeedItem in - // summaryContent를 제목으로 사용 (디자인에 맞춰 제목만 표시) FeedItem( id: UUID(), alias: response.alias, - summary: response.summaryContent, // 내용도 동일하게 사용 - source: response.alias, + summary: response.summaryContent, + summaryTitle: response.summaryTitle, publishedAt: self.parseTimeAgo(response.timeAgo), timeAgo: response.timeAgo ) diff --git a/today-s-sound/Presentation/Features/Main/Home/HomeViewModel.swift b/today-s-sound/Presentation/Features/Main/Home/HomeViewModel.swift index 40f71e7..5544486 100644 --- a/today-s-sound/Presentation/Features/Main/Home/HomeViewModel.swift +++ b/today-s-sound/Presentation/Features/Main/Home/HomeViewModel.swift @@ -95,5 +95,4 @@ class HomeViewModel: ObservableObject { ) .store(in: &cancellables) } - } diff --git a/today-s-sound/Presentation/Features/Main/MainViewModel.swift b/today-s-sound/Presentation/Features/Main/MainViewModel.swift index 0efa0cc..1d19ebd 100644 --- a/today-s-sound/Presentation/Features/Main/MainViewModel.swift +++ b/today-s-sound/Presentation/Features/Main/MainViewModel.swift @@ -204,5 +204,4 @@ class MainViewModel: ObservableObject { currentItemIndex += 1 } - } diff --git a/today-s-sound/Presentation/Features/Settings/SettingsView.swift b/today-s-sound/Presentation/Features/Settings/SettingsView.swift index 5c2bf8e..3fcec06 100644 --- a/today-s-sound/Presentation/Features/Settings/SettingsView.swift +++ b/today-s-sound/Presentation/Features/Settings/SettingsView.swift @@ -40,9 +40,13 @@ struct SettingsView: View { Button("취소", role: .cancel) {} Button("탈퇴하기", role: .destructive) { session.logout() + // 앱 종료 + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + exit(0) + } } } message: { - Text("정말 회원탈퇴를 하시겠습니까?\n모든 데이터가 삭제됩니다.") + Text("정말 회원탈퇴를 하시겠습니까?\n모든 데이터가 삭제되고 앱이 종료됩니다.") } } } @@ -54,4 +58,3 @@ struct SettingsView_Previews: PreviewProvider { .environmentObject(SessionStore.preview) } } -