Skip to content

Commit

Permalink
Update translations logic
Browse files Browse the repository at this point in the history
  • Loading branch information
erolburak committed Nov 8, 2024
1 parent ceb0175 commit b2c4c19
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 68 deletions.
6 changes: 3 additions & 3 deletions BobbysNews/Presentation/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,11 @@ struct ContentView: View {
}
.onChange(of: viewModel.translate) {
Task {
await viewModel.translateConfiguration()
await viewModel.configureTranslations()
}
}
.translationTask(viewModel.translationSessionConfiguration) { translateSession in
await viewModel.translate(translateSession: translateSession)
await viewModel.fetchTranslations(translateSession: translateSession)
}
}
}
Expand Down Expand Up @@ -258,7 +258,7 @@ private struct ListItem: View {

Spacer()

Text((article.titleTranslated ?? article.title) ?? String(localized: "EmptyArticleTitle"))
Text((article.showTranslations ? article.titleTranslated : article.title) ?? String(localized: "EmptyArticleTitle"))
.font(.system(.subheadline,
weight: .semibold))
.lineLimit(2)
Expand Down
126 changes: 63 additions & 63 deletions BobbysNews/Presentation/ContentViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ final class ContentViewModel {
}
}

var articles: [Article] = []
var countries: [String] = []
var articles = [Article]()
var countries = [String]()
var listDisabled: Bool { stateTopHeadlines != .loaded }
var listOpacity: Double { stateTopHeadlines == .loaded ? 1 : 0.3 }
var selectedCountry = "" {
Expand Down Expand Up @@ -116,6 +116,21 @@ final class ContentViewModel {
await fetchSources()
}

@MainActor
func configureTranslations() async {
guard await checkNetworkConnection() == true else {
translate = false
return
}
if translate, translationSessionConfiguration == nil {
translationSessionConfiguration = TranslationSession.Configuration()
} else if translate {
translationSessionConfiguration?.invalidate()
} else {
showArticlesTranslations(show: false)
}
}

@MainActor
func fetchSources(sensoryFeedback: Bool? = nil) async {
if sensoryFeedback == true {
Expand Down Expand Up @@ -159,95 +174,79 @@ final class ContentViewModel {
}

@MainActor
func reset() async {
do {
/// Delete all persisted sources
try deleteSourcesUseCase.delete()
/// Delete all persisted topHeadlines
try deleteTopHeadlinesUseCase.delete()
apiKeyVersion = 1
articles.removeAll()
countries.removeAll()
selectedCountry = ""
stateSources = .emptyRead
stateTopHeadlines = .emptyRead
translate = false
translateDisabled = true
await MainActor.run {
sensoryFeedbackTrigger(feedback: .success)
}
} catch {
await MainActor.run {
showAlert(error: .reset)
}
}
}

func showSettingsTip() throws {
SettingsTip.show = true
}

@MainActor
func translate(translateSession: TranslationSession) async {
func fetchTranslations(translateSession: TranslationSession) async {
stateTopHeadlines = .isTranslating
var contentRequests: [TranslationSession.Request]? = []
var titleRequests: [TranslationSession.Request]? = []
var contentRequests = [TranslationSession.Request]()
var titleRequests = [TranslationSession.Request]()
for (index, article) in articles.enumerated() {
if let content = article.content,
article.contentTranslated == nil
{
contentRequests?.append(TranslationSession.Request(sourceText: content,
clientIdentifier: "\(index)"))
contentRequests.append(TranslationSession.Request(sourceText: content,
clientIdentifier: "\(index)"))
}
if let title = article.title,
article.titleTranslated == nil
{
titleRequests?.append(TranslationSession.Request(sourceText: title,
clientIdentifier: "\(index)"))
titleRequests.append(TranslationSession.Request(sourceText: title,
clientIdentifier: "\(index)"))
}
}
do {
if let contentRequests,
!contentRequests.isEmpty
{
if !contentRequests.isEmpty {
for try await response in translateSession.translate(batch: contentRequests) {
guard let index = Int(response.clientIdentifier ?? "") else {
continue
}
articles[index].contentTranslated = response.targetText
}
}
if let titleRequests,
!titleRequests.isEmpty
{
if !titleRequests.isEmpty {
for try await response in translateSession.translate(batch: titleRequests) {
guard let index = Int(response.clientIdentifier ?? "") else {
continue
}
articles[index].titleTranslated = response.targetText
}
}
updateStateTopHeadlines(state: contentRequests?.isEmpty == true && titleRequests?.isEmpty == true ? .emptyTranslate : .loaded)
guard !articles.compactMap(\.contentTranslated).isEmpty,
!articles.compactMap(\.titleTranslated).isEmpty else {

Check warning on line 213 in BobbysNews/Presentation/ContentViewModel.swift

View workflow job for this annotation

GitHub Actions / tests (iPhone 16 Pro)

Place else, catch or while keyword in accordance with current style (same or next line). (elseOnSameLine)

Check warning on line 213 in BobbysNews/Presentation/ContentViewModel.swift

View workflow job for this annotation

GitHub Actions / tests (iPhone 16 Pro)

Wrap the opening brace of multiline statements. (wrapMultilineStatementBraces)

Check warning on line 213 in BobbysNews/Presentation/ContentViewModel.swift

View workflow job for this annotation

GitHub Actions / tests (iPad Pro 13-inch (M4))

Place else, catch or while keyword in accordance with current style (same or next line). (elseOnSameLine)

Check warning on line 213 in BobbysNews/Presentation/ContentViewModel.swift

View workflow job for this annotation

GitHub Actions / tests (iPad Pro 13-inch (M4))

Wrap the opening brace of multiline statements. (wrapMultilineStatementBraces)
return updateStateTopHeadlines(state: .emptyTranslate)
}
showArticlesTranslations(show: true)
} catch {
updateStateTopHeadlines(error: error,
state: .emptyTranslate)
}
}

@MainActor
func translateConfiguration() async {
guard await checkNetworkConnection() == true else {
func reset() async {
do {
/// Delete all persisted sources
try deleteSourcesUseCase.delete()
/// Delete all persisted topHeadlines
try deleteTopHeadlinesUseCase.delete()
apiKeyVersion = 1
articles.removeAll()
countries.removeAll()
selectedCountry = ""
stateSources = .emptyRead
stateTopHeadlines = .emptyRead
translate = false
return
}
if translate, translationSessionConfiguration == nil {
translationSessionConfiguration = TranslationSession.Configuration()
} else if translate {
translationSessionConfiguration?.invalidate()
} else {
deleteTranslations()
translateDisabled = true
await MainActor.run {
sensoryFeedbackTrigger(feedback: .success)
}
} catch {
await MainActor.run {
showAlert(error: .reset)
}
}
sensoryFeedbackTrigger(feedback: .success)
}

func showSettingsTip() throws {
SettingsTip.show = true
}

@MainActor
Expand All @@ -268,13 +267,6 @@ final class ContentViewModel {
.datastoreLocation(.groupContainer(identifier: "com.burakerol.BobbysNews"))])
}

private func deleteTranslations() {
for index in articles.indices {
articles[index].contentTranslated = nil
articles[index].titleTranslated = nil
}
}

private func readSources() {
do {
guard let sources = try readSourcesUseCase.read().sources else {
Expand Down Expand Up @@ -318,6 +310,14 @@ final class ContentViewModel {
sensoryFeedbackTrigger(feedback: .error)
}

private func showArticlesTranslations(show: Bool) {
for index in articles.indices {
articles[index].showTranslations = show
}
sensoryFeedbackTrigger(feedback: .success)
updateStateTopHeadlines(state: articles.isEmpty ? stateTopHeadlines == .emptyFetch ? .emptyFetch : .emptyRead : .loaded)
}

private func updateStateSources(error: Error? = nil,
state: StatesSources)
{
Expand Down
4 changes: 2 additions & 2 deletions BobbysNews/Presentation/DetailViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ final class DetailViewModel {

var article: Article
var articleContent: String {
article.contentTranslated ?? article.content ?? String(localized: "EmptyArticleContent")
(article.showTranslations ? article.contentTranslated : article.content) ?? String(localized: "EmptyArticleContent")
}

var articleImage: Image?

var articleTitle: String {
article.titleTranslated ?? article.title ?? String(localized: "EmptyArticleTitle")
(article.showTranslations ? article.titleTranslated : article.title) ?? String(localized: "EmptyArticleTitle")
}

var navigationTitleOpacity: Double {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public struct Article: Hashable, Identifiable, Sendable {
public let url: URL?
public let urlToImage: URL?
public var contentTranslated: String?
public var showTranslations = false
public var titleTranslated: String?

// MARK: - Lifecycles
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct ArticleTests {
article?.content == "Test" &&
article?.contentTranslated == nil &&
article?.publishedAt == .distantPast &&
!article?.showTranslations &&
article?.source?.category == "Test" &&
article?.source?.country == "uk" &&
article?.source?.id == "Test" &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct ArticleExtensionTests {
article.content == "Test" &&
article.contentTranslated == nil &&
article.publishedAt == .distantPast &&
!article.showTranslations &&
article.source?.category == "Test" &&
article.source?.country == "uk" &&
article.source?.id == "Test" &&
Expand Down
1 change: 1 addition & 0 deletions BobbysNewsTests/Presentation/DetailViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ struct DetailViewModelTests {
sut.article.content == article.content &&
sut.article.contentTranslated == nil &&
sut.article.publishedAt == article.publishedAt &&
sut.article.showTranslations == article.showTranslations &&
sut.article.source?.category == article.source?.category &&
sut.article.source?.country == article.source?.country &&
sut.article.source?.id == article.source?.id &&
Expand Down

0 comments on commit b2c4c19

Please sign in to comment.