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 Projects/App/Configs/app.debug.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ CODE_SIGN_STYLE=Automatic
CURRENT_PROJECT_VERSION=1
DEVELOPMENT_TEAM=M29A6H95KD
INFOPLIST_FILE=talktrans/Info.plist
MARKETING_VERSION=2.2.0
MARKETING_VERSION=2.2.1
PRODUCT_BUNDLE_IDENTIFIER=com.credif.talktrans
PRODUCT_NAME=$(TARGET_NAME)
PROVISIONING_PROFILE=
Expand Down
2 changes: 1 addition & 1 deletion Projects/App/Configs/app.release.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ CODE_SIGN_STYLE=Automatic
CURRENT_PROJECT_VERSION=1
DEVELOPMENT_TEAM=M29A6H95KD
INFOPLIST_FILE=talktrans/Info.plist
MARKETING_VERSION=2.2.0
MARKETING_VERSION=2.2.1
PRODUCT_BUNDLE_IDENTIFIER=com.credif.talktrans
PRODUCT_NAME=$(TARGET_NAME)
PROVISIONING_PROFILE=
Expand Down
4 changes: 4 additions & 0 deletions Projects/App/Resources/Strings/Base.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ Translate="Translate";
"No favorites yet"="No favorites yet";
"Detail"="Detail";
"Filter"="Filter";
"Send Feedback"="Send Feedback";
"Unable to Open Link"="Unable to Open Link";
"Copy Link"="Copy Link";
"Please copy and open the feedback link manually."="Please copy and open the feedback link manually.";
4 changes: 4 additions & 0 deletions Projects/App/Resources/Strings/de.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ Translate="Übersetzen";
"No favorites yet"="Keine Favoriten";
"Detail"="Detail";
"Filter"="Filter";
"Send Feedback"="Feedback senden";
"Unable to Open Link"="Link kann nicht geöffnet werden";
"Copy Link"="Link kopieren";
"Please copy and open the feedback link manually."="Bitte kopieren Sie den Feedback-Link und öffnen Sie ihn manuell.";
4 changes: 4 additions & 0 deletions Projects/App/Resources/Strings/es.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ Translate="Traducir";
"No favorites yet"="Sin favoritos";
"Detail"="Detalle";
"Filter"="Filtro";
"Send Feedback"="Enviar comentarios";
"Unable to Open Link"="No se puede abrir el enlace";
"Copy Link"="Copiar enlace";
"Please copy and open the feedback link manually."="Copie y abra manualmente el enlace de comentarios.";
4 changes: 4 additions & 0 deletions Projects/App/Resources/Strings/fr.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ Translate="Traduire";
"No favorites yet"="Aucun favori";
"Detail"="Détail";
"Filter"="Filtre";
"Send Feedback"="Envoyer des commentaires";
"Unable to Open Link"="Impossible d’ouvrir le lien";
"Copy Link"="Copier le lien";
"Please copy and open the feedback link manually."="Veuillez copier et ouvrir manuellement le lien de commentaires.";
4 changes: 4 additions & 0 deletions Projects/App/Resources/Strings/id.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ Translate="Menterjemahkan";
"No favorites yet"="Belum ada favorit";
"Detail"="Detail";
"Filter"="Filter";
"Send Feedback"="Kirim masukan";
"Unable to Open Link"="Tidak dapat membuka tautan";
"Copy Link"="Salin tautan";
"Please copy and open the feedback link manually."="Silakan salin dan buka tautan masukan secara manual.";
4 changes: 4 additions & 0 deletions Projects/App/Resources/Strings/it.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ Translate="Tradurre";
"No favorites yet"="Nessun preferito";
"Detail"="Dettaglio";
"Filter"="Filtro";
"Send Feedback"="Invia feedback";
"Unable to Open Link"="Impossibile aprire il link";
"Copy Link"="Copia link";
"Please copy and open the feedback link manually."="Copia e apri manualmente il link di feedback.";
4 changes: 4 additions & 0 deletions Projects/App/Resources/Strings/ja.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ Translate="翻訳";
"No favorites yet"="お気に入りがありません";
"Detail"="詳細";
"Filter"="フィルター";
"Send Feedback"="フィードバックを送信";
"Unable to Open Link"="リンクを開けません";
"Copy Link"="リンクをコピー";
"Please copy and open the feedback link manually."="フィードバックリンクをコピーして手動で開いてください。";
4 changes: 4 additions & 0 deletions Projects/App/Resources/Strings/ko.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,7 @@ Translate="번역";
"No favorites yet"="즐겨찾기가 없습니다";
"Detail"="상세";
"Filter"="필터";
"Send Feedback"="피드백 보내기";
"Unable to Open Link"="링크를 열 수 없습니다";
"Copy Link"="링크 복사";
"Please copy and open the feedback link manually."="피드백 링크를 복사해 직접 열어주세요.";
4 changes: 4 additions & 0 deletions Projects/App/Resources/Strings/ru.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ Translate="Переведите";
"No favorites yet"="Нет избранного";
"Detail"="Подробности";
"Filter"="Фильтр";
"Send Feedback"="Отправить отзыв";
"Unable to Open Link"="Не удалось открыть ссылку";
"Copy Link"="Копировать ссылку";
"Please copy and open the feedback link manually."="Скопируйте ссылку обратной связи и откройте ее вручную.";
4 changes: 4 additions & 0 deletions Projects/App/Resources/Strings/th.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ Translate="แปลความ";
"No favorites yet"="ยังไม่มีรายการโปรด";
"Detail"="รายละเอียด";
"Filter"="กรอง";
"Send Feedback"="ส่งข้อเสนอแนะ";
"Unable to Open Link"="ไม่สามารถเปิดลิงก์ได้";
"Copy Link"="คัดลอกลิงก์";
"Please copy and open the feedback link manually."="โปรดคัดลอกและเปิดลิงก์ข้อเสนอแนะด้วยตนเอง";
4 changes: 4 additions & 0 deletions Projects/App/Resources/Strings/vi.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,8 @@ Translate="Dịch";
"No favorites yet"="Chưa có mục yêu thích";
"Detail"="Chi tiết";
"Filter"="Lọc";
"Send Feedback"="Gửi phản hồi";
"Unable to Open Link"="Không thể mở liên kết";
"Copy Link"="Sao chép liên kết";
"Please copy and open the feedback link manually."="Vui lòng sao chép và mở liên kết phản hồi theo cách thủ công.";

Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ Translate="翻译";
"No favorites yet"="暂无收藏";
"Detail"="详情";
"Filter"="筛选";
"Send Feedback"="发送反馈";
"Unable to Open Link"="无法打开链接";
"Copy Link"="复制链接";
"Please copy and open the feedback link manually."="请复制并手动打开反馈链接。";
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ Translate="翻譯";
"No favorites yet"="尚無收藏";
"Detail"="詳情";
"Filter"="篩選";
"Send Feedback"="傳送回饋";
"Unable to Open Link"="無法開啟連結";
"Copy Link"="複製連結";
"Please copy and open the feedback link manually."="請複製並手動開啟回饋連結。";
32 changes: 18 additions & 14 deletions Projects/App/Sources/App.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,26 @@ struct SendadvApp: App {
}
}

private func handleAppDidBecomeActive() {
print("scene become active")
Task {
defer {
LSDefaults.increaseLaunchCount()
}
private func handleAppDidBecomeActive() {
print("scene become active")
Task { @MainActor in
defer {
LSDefaults.increaseLaunchCount()
}

guard !SwiftUIAdManager.isDisabled else {
checkPendingReview()
return
}
guard !SwiftUIAdManager.isDisabled else {
checkPendingReview()
return
}

await adManager.show(unit: .launch)
checkPendingReview()
}
}
adManager.refreshAdFreeStatus()

if !adManager.isAdFree {
await adManager.show(unit: .launch)
}
checkPendingReview()
}
}

private func checkPendingReview() {
guard LSDefaults.pendingReviewRequest else { return }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct BannerAdSwiftUIView: View {

var body: some View {
Group {
if SwiftUIAdManager.isDisabled {
if SwiftUIAdManager.isDisabled || adManager.isAdFree {
EmptyView()
} else if let bannerView = coordinator.bannerView {
BannerAdRepresentable(bannerView: bannerView)
Expand All @@ -24,8 +24,16 @@ struct BannerAdSwiftUIView: View {
}
.onChange(of: adManager.isReady, initial: true) { _, isReady in
guard isReady else { return }
guard !adManager.isAdFree else { return }
coordinator.load(withAdManager: adManager)
}
.onChange(of: adManager.isAdFree, initial: true) { _, isAdFree in
if isAdFree {
coordinator.reset()
} else if adManager.isReady {
coordinator.load(withAdManager: adManager)
}
}
}
}

Expand All @@ -44,6 +52,11 @@ final class BannerAdCoordinator {
banner.load(request)
}
}

func reset() {
bannerView = nil
hasLoaded = false
}
}

private struct BannerAdRepresentable: UIViewRepresentable {
Expand Down
42 changes: 38 additions & 4 deletions Projects/App/Sources/Managers/SwiftUIAdManager.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Foundation
import Firebase
import GADManager
import GoogleMobileAds
Expand Down Expand Up @@ -34,7 +35,14 @@ class SwiftUIAdManager: NSObject, ObservableObject {

// 싱글톤 패턴으로 전역 접근 지원
static var shared: SwiftUIAdManager?
@Published var isReady: Bool = false
@Published var isReady: Bool = false
@Published private(set) var isAdFree: Bool = LSDefaults.isAdFree

private var adFreeStatusTask: Task<Void, Never>?

deinit {
adFreeStatusTask?.cancel()
}

func setup() {
guard !SwiftUIAdManager.isDisabled else { return }
Expand All @@ -49,6 +57,10 @@ class SwiftUIAdManager: NSObject, ObservableObject {
// 싱글톤 인스턴스 설정
SwiftUIAdManager.shared = self
self.isReady = true
Task { @MainActor in
self.refreshAdFreeStatus()
self.startAdFreeStatusTimer()
}
}

func prepare(interstitialUnit unit: GADUnitName, interval: TimeInterval) {
Expand All @@ -74,7 +86,7 @@ class SwiftUIAdManager: NSObject, ObservableObject {
@discardableResult
func show(unit: GADUnitName) async -> Bool {
guard !SwiftUIAdManager.isDisabled else { return false }
guard !LSDefaults.isAdFree else { return false }
guard !isAdFree else { return false }

return await withCheckedContinuation { continuation in
guard let gadManager else {
Expand All @@ -94,7 +106,9 @@ class SwiftUIAdManager: NSObject, ObservableObject {
guard let gadManager else { completion(false); return }

gadManager.show(unit: .rewarded, needToWait: true, isTesting: isTesting(unit: .rewarded)) { _, _, rewarded in
completion(rewarded)
Task { @MainActor in
completion(rewarded)
}
}
}

Expand All @@ -105,10 +119,30 @@ class SwiftUIAdManager: NSObject, ObservableObject {

func createBannerAdView(withAdSize size: AdSize, forUnit unit: GADUnitName) -> BannerView? {
guard !SwiftUIAdManager.isDisabled else { return nil }
guard !LSDefaults.isAdFree else { return nil }
guard !isAdFree else { return nil }
return gadManager?.prepare(bannerUnit: unit, isTesting: self.isTesting(unit: unit), size: size)
}

@MainActor
func refreshAdFreeStatus() {
let latestState = LSDefaults.isAdFree
guard latestState != isAdFree else { return }
isAdFree = latestState
}

@MainActor
private func startAdFreeStatusTimer() {
adFreeStatusTask?.cancel()

adFreeStatusTask = Task { [weak self] in
while !Task.isCancelled {
try? await Task.sleep(for: .seconds(30))
guard !Task.isCancelled else { return }
self?.refreshAdFreeStatus()
}
}
}

// MARK: - Testing Flags
func isTesting(unit: GADUnitName) -> Bool {
return testUnits.contains(unit)
Expand Down
32 changes: 32 additions & 0 deletions Projects/App/Sources/Screens/HistoryScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,23 @@

import SwiftUI
import SwiftData
import UIKit

// MARK: - HistoryScreen

struct HistoryScreen: View {
/// Called when user taps Re-translate on a detail sheet.
let onRetranslate: (String, String, String, String) -> Void

static let feedbackIssueURLString = "https://github.com/2sem/talktrans/issues/new/choose"

@Environment(\.dismiss) private var dismiss
@Environment(\.openURL) private var openURL
@Environment(\.modelContext) private var modelContext

@State private var filterMode: HistoryFilter = .all
@State private var selectedEntry: TranslationEntry?
@State private var showFeedbackFallbackAlert = false

var body: some View {
NavigationStack {
Expand Down Expand Up @@ -52,12 +57,26 @@ struct HistoryScreen: View {
.navigationTitle("History".localized())
.navigationBarTitleDisplayMode(.large)
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button(action: openFeedbackIssue) {
Image(systemName: "bubble.left.and.text.bubble.right")
}
.accessibilityLabel("Send Feedback".localized())
}
ToolbarItem(placement: .topBarTrailing) {
Button("Done".localized()) {
dismiss()
}
}
}
.alert("Unable to Open Link".localized(), isPresented: $showFeedbackFallbackAlert) {
Button("Copy Link".localized()) {
UIPasteboard.general.string = Self.feedbackIssueURLString
}
Button("OK".localized(), role: .cancel) { }
} message: {
Text("Please copy and open the feedback link manually.".localized())
}
.sheet(item: $selectedEntry) { entry in
HistoryDetailSheet(entry: entry) { sourceText, translatedText, sourceLang, targetLang in
dismiss()
Expand All @@ -69,6 +88,19 @@ struct HistoryScreen: View {
}
}

private func openFeedbackIssue() {
guard let issueURL = URL(string: Self.feedbackIssueURLString) else {
showFeedbackFallbackAlert = true
return
}

openURL(issueURL) { accepted in
if !accepted {
showFeedbackFallbackAlert = true
}
}
}

private func toggleFavorite(_ entry: TranslationEntry) {
entry.isFavorited.toggle()
}
Expand Down
Loading
Loading