Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion today-s-sound/Core/Network/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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" // 운영 서버
Expand Down
2 changes: 2 additions & 0 deletions today-s-sound/Data/Models/Feed.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -57,6 +58,7 @@ struct FeedItemResponse: Codable, Identifiable {
enum CodingKeys: String, CodingKey {
case subscriptionId
case alias
case summaryTitle
case summaryContent
case url
case timeAgo
Expand Down
72 changes: 3 additions & 69 deletions today-s-sound/Presentation/Features/Feed/FeedModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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시간 전" 등)

Expand All @@ -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시간 전
)
]
}
12 changes: 6 additions & 6 deletions today-s-sound/Presentation/Features/Feed/FeedView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -19,7 +19,7 @@ struct FeedView: View {
if selectedFilter == "전체" {
viewModel.items
} else {
viewModel.items.filter { $0.source == selectedFilter }
viewModel.items.filter { $0.alias == selectedFilter }
}
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)"
)
}
}
Expand Down
10 changes: 4 additions & 6 deletions today-s-sound/Presentation/Features/Feed/FeedViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down Expand Up @@ -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
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,4 @@ class HomeViewModel: ObservableObject {
)
.store(in: &cancellables)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -204,5 +204,4 @@ class MainViewModel: ObservableObject {

currentItemIndex += 1
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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모든 데이터가 삭제되고 앱이 종료됩니다.")
}
}
}
Expand All @@ -54,4 +58,3 @@ struct SettingsView_Previews: PreviewProvider {
.environmentObject(SessionStore.preview)
}
}