fix(detail): 콘텐츠/시리즈 상세 로딩 실패 시 자동 복귀를 적용한다
This commit is contained in:
@@ -21,6 +21,8 @@ struct ContentDetailView: View {
|
||||
@State private var isShowCommentListView = false
|
||||
@State private var isShowFollowNotifyDialog: Bool = false
|
||||
@State private var creatorId: Int = 0
|
||||
@State private var didTriggerAutoBackOnLoadFailure: Bool = false
|
||||
@State private var isViewVisible: Bool = false
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { proxy in
|
||||
@@ -28,11 +30,7 @@ struct ContentDetailView: View {
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
Button {
|
||||
if presentationMode.wrappedValue.isPresented {
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
} else {
|
||||
AppState.shared.back()
|
||||
}
|
||||
goBack()
|
||||
} label: {
|
||||
Image("ic_back")
|
||||
.resizable()
|
||||
@@ -217,9 +215,26 @@ struct ContentDetailView: View {
|
||||
.navigationTitle("")
|
||||
.navigationBarBackButtonHidden()
|
||||
.onAppear {
|
||||
isViewVisible = true
|
||||
didTriggerAutoBackOnLoadFailure = false
|
||||
viewModel.contentId = contentId
|
||||
AppState.shared.pushAudioContentId = 0
|
||||
}
|
||||
.onDisappear {
|
||||
isViewVisible = false
|
||||
}
|
||||
.onChange(of: viewModel.isShowPopup) { isShowing in
|
||||
guard isShowing else { return }
|
||||
guard viewModel.audioContent == nil else { return }
|
||||
guard !didTriggerAutoBackOnLoadFailure else { return }
|
||||
|
||||
didTriggerAutoBackOnLoadFailure = true
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
||||
guard isViewVisible else { return }
|
||||
goBack()
|
||||
}
|
||||
}
|
||||
|
||||
if let audioContent = viewModel.audioContent, isShowOrderView {
|
||||
VStack(spacing: 0) {
|
||||
@@ -423,7 +438,7 @@ struct ContentDetailView: View {
|
||||
.padding(.vertical, 13.3)
|
||||
.frame(width: screenSize().width - 66.7, alignment: .center)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.background(Color(hex: "9970ff"))
|
||||
.background(Color(hex: "3bb9f1"))
|
||||
.foregroundColor(Color.white)
|
||||
.multilineTextAlignment(.center)
|
||||
.cornerRadius(20)
|
||||
@@ -434,4 +449,12 @@ struct ContentDetailView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func goBack() {
|
||||
if presentationMode.wrappedValue.isPresented {
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
} else {
|
||||
AppState.shared.back()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ struct SeriesDetailView: View {
|
||||
|
||||
@State private var isShowFollowNotifyDialog: Bool = false
|
||||
@State private var creatorId: Int = 0
|
||||
@State private var didTriggerAutoBackOnLoadFailure: Bool = false
|
||||
@State private var isViewVisible: Bool = false
|
||||
|
||||
var body: some View {
|
||||
BaseView(isLoading: $viewModel.isLoading) {
|
||||
@@ -38,11 +40,7 @@ struct SeriesDetailView: View {
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
.onTapGesture {
|
||||
if presentationMode.wrappedValue.isPresented {
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
} else {
|
||||
AppState.shared.back()
|
||||
}
|
||||
goBack()
|
||||
}
|
||||
|
||||
Spacer()
|
||||
@@ -243,9 +241,51 @@ struct SeriesDetailView: View {
|
||||
.navigationBarBackButtonHidden()
|
||||
}
|
||||
.onAppear {
|
||||
isViewVisible = true
|
||||
didTriggerAutoBackOnLoadFailure = false
|
||||
viewModel.seriesId = seriesId
|
||||
viewModel.getSeriesDetail()
|
||||
}
|
||||
.onDisappear {
|
||||
isViewVisible = false
|
||||
}
|
||||
.onChange(of: viewModel.isShowPopup) { isShowing in
|
||||
guard isShowing else { return }
|
||||
guard viewModel.seriesDetail == nil else { return }
|
||||
guard !didTriggerAutoBackOnLoadFailure else { return }
|
||||
|
||||
didTriggerAutoBackOnLoadFailure = true
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
||||
guard isViewVisible else { return }
|
||||
goBack()
|
||||
}
|
||||
}
|
||||
.popup(isPresented: $viewModel.isShowPopup, type: .toast, position: .top, autohideIn: 2) {
|
||||
GeometryReader { geo in
|
||||
HStack {
|
||||
Spacer()
|
||||
Text(viewModel.errorMessage)
|
||||
.padding(.vertical, 13.3)
|
||||
.frame(width: screenSize().width - 66.7, alignment: .center)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.background(Color(hex: "3bb9f1"))
|
||||
.foregroundColor(Color.white)
|
||||
.multilineTextAlignment(.center)
|
||||
.cornerRadius(20)
|
||||
.padding(.top, 66.7)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func goBack() {
|
||||
if presentationMode.wrappedValue.isPresented {
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
} else {
|
||||
AppState.shared.back()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
22
docs/20260226_콘텐츠상세로딩실패시뒤로이동.md
Normal file
22
docs/20260226_콘텐츠상세로딩실패시뒤로이동.md
Normal file
@@ -0,0 +1,22 @@
|
||||
## 작업 개요
|
||||
|
||||
- 콘텐츠 상세 페이지에서 상세 데이터 로딩 실패 시 토스트만 노출되고 이전 페이지로 자동 복귀하지 않는 문제를 수정한다.
|
||||
|
||||
## 체크리스트
|
||||
|
||||
- [x] 콘텐츠 상세 로딩 실패 처리 지점 확인
|
||||
- [x] 로딩 실패 시 토스트 노출 후 이전 페이지 자동 이동 로직 추가
|
||||
- [x] 관련 상태 변수 초기화/중복 이동 방지 처리 추가
|
||||
- [x] LSP 진단 및 빌드 검증
|
||||
|
||||
## 검증 기록
|
||||
|
||||
- 무엇/왜/어떻게: `ContentDetailView`에서 로딩 실패 토스트 노출 시 `audioContent == nil` 조건을 만족하면 2초 후 자동 뒤로가기를 수행하도록 `onChange(of: viewModel.isShowPopup)`와 `goBack()` 재사용 로직을 추가했다. 중복 이동 방지를 위해 `didTriggerAutoBackOnLoadFailure`, 화면 생명주기 안전성을 위해 `isViewVisible` 상태를 함께 적용했다.
|
||||
- 실행 명령: `pod install`
|
||||
결과: 성공 (`Pod installation complete`)
|
||||
- 실행 명령: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build`
|
||||
결과: 성공 (`** BUILD SUCCEEDED **`)
|
||||
- 실행 명령: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test`
|
||||
결과: 실패 (`Scheme SodaLive is not currently configured for the test action.`)
|
||||
- 실행 도구: `lsp_diagnostics` (`ContentDetailView.swift`)
|
||||
결과: SourceKit 환경에서 `No such module 'Kingfisher'` 진단이 지속되었으나, 실제 `xcodebuild` 빌드는 성공해 코드 변경으로 인한 컴파일 오류는 없음을 확인했다.
|
||||
23
docs/20260226_콘텐츠시리즈상세로딩실패자동복귀.md
Normal file
23
docs/20260226_콘텐츠시리즈상세로딩실패자동복귀.md
Normal file
@@ -0,0 +1,23 @@
|
||||
## 작업 개요
|
||||
|
||||
- 콘텐츠 상세 토스트 색상을 지정값으로 변경하고, 시리즈 상세에서도 데이터 로딩 실패 시 토스트 노출 후 이전 페이지로 자동 복귀하도록 동작을 맞춘다.
|
||||
|
||||
## 체크리스트
|
||||
|
||||
- [x] 콘텐츠 상세/시리즈 상세 기존 오류 처리 흐름 확인
|
||||
- [x] 콘텐츠 상세 토스트 배경색 `3bb9f1` 적용
|
||||
- [x] 시리즈 상세 로딩 실패 토스트 표시 및 자동 뒤로가기 추가
|
||||
- [x] 중복 뒤로가기 방지 및 화면 생명주기 안전 처리 적용
|
||||
- [x] 빌드/테스트 검증 및 기록
|
||||
|
||||
## 검증 기록
|
||||
|
||||
- 무엇/왜/어떻게: 콘텐츠 상세 토스트 배경색을 요청값 `3bb9f1`로 변경했다. 시리즈 상세는 기존에 로딩 실패 시 `errorMessage`/`isShowPopup`만 설정되어 화면이 유지되던 상태였기 때문에, `onChange(of: viewModel.isShowPopup)`에서 `seriesDetail == nil`인 로딩 실패 케이스를 감지해 토스트 2초 노출 뒤 `goBack()`으로 자동 복귀하도록 추가했다. 또한 `didTriggerAutoBackOnLoadFailure`와 `isViewVisible`로 중복/비가시 상태 뒤로가기 호출을 방지했다.
|
||||
- 실행 도구: `lsp_diagnostics` (`ContentDetailView.swift`)
|
||||
결과: 이상 없음
|
||||
- 실행 도구: `lsp_diagnostics` (`SeriesDetailView.swift`)
|
||||
결과: SourceKit 환경에서 `No such module 'Kingfisher'` 진단 발생
|
||||
- 실행 명령: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build`
|
||||
결과: 성공 (`** BUILD SUCCEEDED **`)
|
||||
- 실행 명령: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test`
|
||||
결과: 실패 (`Scheme SodaLive is not currently configured for the test action.`)
|
||||
Reference in New Issue
Block a user