Skip to content

Commit

Permalink
Merge pull request #1943 from CruGlobal/GT-2214-UnDownload-Language-B…
Browse files Browse the repository at this point in the history
…utton

GT-2214 Undownload language button
  • Loading branch information
rachaelblue authored Feb 16, 2024
2 parents 2fb9121 + 3cd8829 commit ad4e63e
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ struct DownloadableLanguagesView: View {

DownloadableLanguageItemView(downloadableLanguage: downloadableLanguage) {

viewModel.downloadableLanguageTapped(downloadableLanguage: downloadableLanguage)
downloadableLanguageTapped(downloadableLanguage: downloadableLanguage)
}
.listRowBackground(Color.clear)
}
Expand All @@ -41,4 +41,18 @@ struct DownloadableLanguagesView: View {
.navigationTitle(viewModel.navTitle)
.environment(\.layoutDirection, ApplicationLayout.shared.layoutDirection)
}

private func downloadableLanguageTapped(downloadableLanguage: DownloadableLanguageListItemDomainModel) {

switch downloadableLanguage.downloadStatus {
case .notDownloaded:
viewModel.downloadLanguage(downloadableLanguage)

case .downloading:
break

case .downloaded:
viewModel.removeDownloadedLanguage(downloadableLanguage)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,50 +116,42 @@ extension DownloadableLanguagesViewModel {
return SearchBarViewModel(getCurrentAppLanguageUseCase: getCurrentAppLanguageUseCase, viewSearchBarUseCase: viewSearchBarUseCase)
}

func downloadableLanguageTapped(downloadableLanguage: DownloadableLanguageListItemDomainModel) {
func downloadLanguage(_ downloadableLanguage: DownloadableLanguageListItemDomainModel) {

let languageId = downloadableLanguage.languageId

activeDownloads[languageId] = .downloading(progress: 0)

switch downloadableLanguage.downloadStatus {

case .notDownloaded:

activeDownloads[languageId] = .downloading(progress: 0)

downloadToolLanguageUseCase.downloadToolLanguage(languageId: downloadableLanguage.languageId, languageCode: downloadableLanguage.languageCode)
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { [weak self] completed in
downloadToolLanguageUseCase.downloadToolLanguage(languageId: downloadableLanguage.languageId, languageCode: downloadableLanguage.languageCode)
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { [weak self] completed in

switch completed {
case .finished:

switch completed {
case .finished:

self?.activeDownloads.removeValue(forKey: languageId)

case .failure(let error):

// TODO: - what happens during a failure?

self?.activeDownloads[languageId] = .notDownloaded
self?.flowDelegate?.navigate(step: .showLanguageDownloadErrorAlert(error: error))
}
}, receiveValue: { [weak self] progress in
self?.activeDownloads.removeValue(forKey: languageId)

self?.activeDownloads[languageId] = .downloading(progress: progress)
})
.store(in: &DownloadableLanguagesViewModel.backgrounDownloadCancellables)

case .downloaded:

removeDownloadedToolLanguageUseCase.removeDownloadedToolLanguage(downloadableLanguage.languageId)
.sink { _ in
case .failure(let error):

// TODO: - what happens during a failure?

self?.activeDownloads[languageId] = .notDownloaded
self?.flowDelegate?.navigate(step: .showLanguageDownloadErrorAlert(error: error))
}
.store(in: &DownloadableLanguagesViewModel.backgrounDownloadCancellables)

case .downloading:

break
}
}, receiveValue: { [weak self] progress in

self?.activeDownloads[languageId] = .downloading(progress: progress)
})
.store(in: &DownloadableLanguagesViewModel.backgrounDownloadCancellables)
}

func removeDownloadedLanguage(_ downloadableLanguage: DownloadableLanguageListItemDomainModel) {

removeDownloadedToolLanguageUseCase.removeDownloadedToolLanguage(downloadableLanguage.languageId)
.sink { _ in

}
.store(in: &DownloadableLanguagesViewModel.backgrounDownloadCancellables)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,18 @@ struct DownloadableLanguageItemView: View {

@State private var animationDownloadProgress: Double?
@State private var downloadProgressTarget: Double?
@State private var timer: Timer?
@State private var progressAnimationTimer: Timer?
@State private var removeDownloadTimer: Timer?
@State private var isVisible: Bool = false
@State private var shouldConfirmDownloadRemoval: Bool = false

private var isAnimatingDownload: Bool {
guard let animationDownloadProgress = animationDownloadProgress else {
return false
}

return animationDownloadProgress < 1
}

init(downloadableLanguage: DownloadableLanguageListItemDomainModel, tappedClosure: (() -> Void)?) {

Expand Down Expand Up @@ -52,11 +62,11 @@ struct DownloadableLanguageItemView: View {

Button {

tappedClosure?()
didTapItem()

} label: {

LanguageDownloadIcon(languageDownloadStatus: downloadableLanguage.downloadStatus, animationDownloadProgress: animationDownloadProgress)
LanguageDownloadIcon(languageDownloadStatus: downloadableLanguage.downloadStatus, animationDownloadProgress: animationDownloadProgress, shouldConfirmDownloadRemoval: shouldConfirmDownloadRemoval)
}
}
.onChange(of: downloadableLanguage.downloadStatus, perform: { newDownloadStatus in
Expand All @@ -65,6 +75,7 @@ struct DownloadableLanguageItemView: View {
case .notDownloaded:
self.downloadProgressTarget = nil
self.animationDownloadProgress = nil
self.shouldConfirmDownloadRemoval = false

case .downloading(let progress):
self.downloadProgressTarget = progress
Expand All @@ -76,16 +87,18 @@ struct DownloadableLanguageItemView: View {
self.downloadProgressTarget = 1
}

if timer == nil {
startAnimationTimer()
if progressAnimationTimer == nil {
startProgressAnimationTimer()
}
})
.animation(.default, value: downloadableLanguage.downloadStatus)
.animation(.default, value: animationDownloadProgress)
.animation(.default, value: shouldConfirmDownloadRemoval)
.onDisappear {

isVisible = false
stopAnimationTimer()
stopProgressAnimationTimer()
cancelDownloadRemovalConfirmation()
}
.onAppear {

Expand All @@ -94,17 +107,63 @@ struct DownloadableLanguageItemView: View {
}
.onAppBackgrounded {

stopAnimationTimer()
stopProgressAnimationTimer()
}
.onAppForegrounded {

continueDownloadProgressAnimationIfNeeded()
}
}

private func startAnimationTimer() {
private func didTapItem() {

switch downloadableLanguage.downloadStatus {
case .downloaded:

if isAnimatingDownload {
return

} else if shouldConfirmDownloadRemoval == false {

shouldConfirmDownloadRemoval = true
startRemoveDownloadTimer()

return

} else {
stopRemoveDownloadTimer()
tappedClosure?()
}

default:

tappedClosure?()
}
}

private func startRemoveDownloadTimer() {

removeDownloadTimer = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false, block: { timer in

self.cancelDownloadRemovalConfirmation()
})
}

private func cancelDownloadRemovalConfirmation() {

shouldConfirmDownloadRemoval = false
stopRemoveDownloadTimer()
}

private func stopRemoveDownloadTimer() {

removeDownloadTimer?.invalidate()
removeDownloadTimer = nil
}

private func startProgressAnimationTimer() {

timer = Timer.scheduledTimer(withTimeInterval: 0.2, repeats: true, block: { timer in
progressAnimationTimer = Timer.scheduledTimer(withTimeInterval: 0.2, repeats: true, block: { timer in
guard let downloadProgress = self.animationDownloadProgress,
let progressTarget = self.downloadProgressTarget
else { return }
Expand All @@ -115,21 +174,21 @@ struct DownloadableLanguageItemView: View {

} else if progressTarget >= 1 && downloadProgress >= 1 {

self.stopAnimationTimer()
self.stopProgressAnimationTimer()
}
})
}

private func stopAnimationTimer() {
guard timer != nil else { return }
private func stopProgressAnimationTimer() {
guard progressAnimationTimer != nil else { return }

timer?.invalidate()
timer = nil
progressAnimationTimer?.invalidate()
progressAnimationTimer = nil
}

private func continueDownloadProgressAnimationIfNeeded() {
if shouldContinueDownloadProgressAnimation() {
startAnimationTimer()
startProgressAnimationTimer()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ struct LanguageDownloadIcon: View {

private let languageDownloadStatus: LanguageDownloadStatusDomainModel
private let animationDownloadProgress: Double?
private let shouldConfirmDownloadRemoval: Bool

init(languageDownloadStatus: LanguageDownloadStatusDomainModel, animationDownloadProgress: Double?) {
init(languageDownloadStatus: LanguageDownloadStatusDomainModel, animationDownloadProgress: Double?, shouldConfirmDownloadRemoval: Bool) {
self.languageDownloadStatus = languageDownloadStatus
self.animationDownloadProgress = animationDownloadProgress
self.shouldConfirmDownloadRemoval = shouldConfirmDownloadRemoval
}

var body: some View {
Expand Down Expand Up @@ -53,7 +55,12 @@ struct LanguageDownloadIcon: View {

case .downloaded:

if shouldFinishAnimatingDownloadProgress(), let animationDownloadProgress = animationDownloadProgress {
if shouldConfirmDownloadRemoval {

Image(systemName: "xmark")
.imageScale(.small)

} else if shouldFinishAnimatingDownloadProgress(), let animationDownloadProgress = animationDownloadProgress {

drawProgressInCircle(progress: animationDownloadProgress)

Expand Down Expand Up @@ -113,7 +120,12 @@ struct LanguageDownloadIcon: View {
}

case .downloaded:
return ColorPalette.gtBlue.color

if shouldConfirmDownloadRemoval {
return Color(.sRGB, red: 229 / 255, green: 91 / 255, blue: 54 / 255, opacity: 1.0)
} else {
return ColorPalette.gtBlue.color
}
}
}

Expand Down

0 comments on commit ad4e63e

Please sign in to comment.