Skip to content

Commit

Permalink
Merge pull request #151 from JORDYMA-Link/FEATURE/#150
Browse files Browse the repository at this point in the history
[FEATURE] 링크 AI 요약 시 Google Ads 전면 광고 연결
  • Loading branch information
kimkyuchul authored Dec 9, 2024
2 parents 7103b36 + 3c7e7ae commit 0aaf61e
Show file tree
Hide file tree
Showing 32 changed files with 325 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ public enum ExternalDependency: String {
case composableArchitecture = "ComposableArchitecture"
case kakaoSDK = "KakaoSDK"
case FSCalendar = "FSCalendar"
case googleMobileAds = "GoogleMobileAds"
}
6 changes: 6 additions & 0 deletions Projects/App/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>GADApplicationIdentifier</key>
<string>$(GOOGLE_ADS_KEY)</string>
<key>FirebaseAppDelegateProxyEnabled</key>
<false/>
<key>BASE_URL</key>
Expand Down Expand Up @@ -39,6 +41,8 @@
<false/>
<key>KAKAO_NATIVE_APP_KEY</key>
<string>$(KAKAO_NATIVE_APP_KEY)</string>
<key>GOOGLE_AD_UNITID</key>
<string>$(GOOGLE_AD_UNITID)</string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>LSApplicationQueriesSchemes</key>
Expand All @@ -59,5 +63,7 @@
</array>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>NSUserTrackingUsageDescription</key>
<string>Blink에서 사용자에게 맞춤 광고를 위해 추적 권한을 요청합니다</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion Projects/App/Project.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ProjectDescription
@preconcurrency import ProjectDescription
import ProjectDescriptionHelpers
import DependencyPlugin

Expand Down
2 changes: 0 additions & 2 deletions Projects/App/Sources/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import SwiftUI
import Feature

import ComposableArchitecture
import FirebaseCore
import FirebaseMessaging

final class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
let store = StoreOf<AppDelegateFeature>.init(
Expand Down
13 changes: 12 additions & 1 deletion Projects/App/Sources/AppDelegateFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import Foundation
import Services

import ComposableArchitecture
import FirebaseCore
import FirebaseMessaging
import FirebaseCore

@Reducer
struct AppDelegateFeature {
Expand All @@ -27,6 +27,7 @@ struct AppDelegateFeature {
case initKakaoSDK
case setUpNotificationCenter
case setUpFirebase
case setUpGoogleAds

case setUserNotificationCenterDelegate
case setUserNotificationCenterAuthorization
Expand All @@ -41,6 +42,8 @@ struct AppDelegateFeature {
@Dependency(\.userDefaultsClient) private var userDefault
@Dependency(\.socialLogin) private var socialLogin
@Dependency(\.userNotificationClient) private var userNotificationClient
@Dependency(ATTrackingManagerClient.self) private var attrackingManagerClient
@Dependency(GoogleMobileAdsClient.self) private var googleMobileAdsClient

var body: some ReducerOf<Self> {
Reduce { state, action in
Expand All @@ -53,6 +56,8 @@ struct AppDelegateFeature {
await send(.setUpNotificationCenter)
/// Firebase 설정
await send(.setUpFirebase)
/// Google Ads 설정
await send(.setUpGoogleAds)
}

case let .didRegisterForRemoteNotificationsWithDeviceToken(deviceToken):
Expand All @@ -79,6 +84,12 @@ struct AppDelegateFeature {
await send(.setFirebaseIsAutoInitEnabled)
}

case .setUpGoogleAds:
return .run { send in
await attrackingManagerClient.requestTrackingAuthorization()
await googleMobileAdsClient.start()
}

case .setUserNotificationCenterDelegate:
return .run { send in
for await event in self.userNotificationClient.delegate() {
Expand Down
2 changes: 1 addition & 1 deletion Projects/Core/Analytics/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by kyuchul on 11/1/24.
//

import ProjectDescription
@preconcurrency import ProjectDescription
import ProjectDescriptionHelpers
import DependencyPlugin

Expand Down
2 changes: 1 addition & 1 deletion Projects/Core/Models/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by kyuchul on 6/14/24.
//

import ProjectDescription
@preconcurrency import ProjectDescription
import ProjectDescriptionHelpers
import DependencyPlugin

Expand Down
2 changes: 1 addition & 1 deletion Projects/Core/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by kyuchul on 6/14/24.
//

import ProjectDescription
@preconcurrency import ProjectDescription
import ProjectDescriptionHelpers
import DependencyPlugin

Expand Down
2 changes: 1 addition & 1 deletion Projects/Core/Services/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by kyuchul on 6/14/24.
//

import ProjectDescription
@preconcurrency import ProjectDescription
import ProjectDescriptionHelpers
import DependencyPlugin

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// ATTTrackingManagerClient.swift
// Services
//
// Created by kyuchul on 11/30/24.
// Copyright © 2024 com.kyuchul.blink. All rights reserved.
//

import Foundation
import AppTrackingTransparency

import Dependencies
import DependenciesMacros

@DependencyClient
public struct ATTrackingManagerClient {
public var requestTrackingAuthorization: @Sendable () async -> Void
}

extension ATTrackingManagerClient: DependencyKey {
public static var liveValue: ATTrackingManagerClient = live()
private static func live() -> ATTrackingManagerClient {

return ATTrackingManagerClient(
requestTrackingAuthorization: { @MainActor in
return await withCheckedContinuation { continuation in
ATTrackingManager.requestTrackingAuthorization { _ in
continuation.resume()
}
}
}
)
}
}
51 changes: 51 additions & 0 deletions Projects/Core/Services/Sources/GoogleAds/GoogleAdsClient.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// GoogleAdsClient.swift
// Services
//
// Created by kyuchul on 11/30/24.
// Copyright © 2024 com.kyuchul.blink. All rights reserved.
//

import Foundation
import GoogleMobileAds

import Dependencies
import DependenciesMacros

@DependencyClient
public struct GoogleMobileAdsClient {
public var start: @Sendable () async -> Void
public var load: @Sendable () async throws -> GoogleAd
}

extension GoogleMobileAdsClient: DependencyKey {
public static var liveValue: GoogleMobileAdsClient = live()
private static func live() -> GoogleMobileAdsClient {
return GoogleMobileAdsClient(
start: {
await GADMobileAds.sharedInstance().start()
},
load: {
var adUnitID: String {
#if DEBUG
return "ca-app-pub-3940256099942544/4411468910"
#else
return APIKey.googleAdUnitID
#endif
}

let ad = try await GADInterstitialAd.load(withAdUnitID: adUnitID, request: GADRequest())

return GoogleAd(ad: ad)
}
)
}
}

public struct GoogleAd: Equatable {
public var ad: GADInterstitialAd

public init(ad: GADInterstitialAd) {
self.ad = ad
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import Foundation

import Models



struct FeedResponse: Decodable {
let feedId: Int
let thumbnailImage: String
Expand Down
17 changes: 0 additions & 17 deletions Projects/Core/Services/Sources/SocialLogin/Util/APIKey.swift

This file was deleted.

22 changes: 22 additions & 0 deletions Projects/Core/Services/Sources/Util/APIKey.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// APIKey.swift
// CoreKit
//
// Created by kyuchul on 6/17/24.
// Copyright © 2024 com.jordyma.blink. All rights reserved.
//

import Foundation

enum APIKey {
static let kakao = getInfoValue(for: "KAKAO_NATIVE_APP_KEY")
static let googleAdUnitID = getInfoValue(for: "GOOGLE_AD_UNITID")

private static func getInfoValue(for key: String) -> String {
guard let infoDictionary = Bundle.main.infoDictionary,
let value = infoDictionary[key] as? String else {
fatalError("Wrong \(key)")
}
return value
}
}
2 changes: 1 addition & 1 deletion Projects/Domain/Folder/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by kyuchul on 10/18/24.
//

import ProjectDescription
@preconcurrency import ProjectDescription
import ProjectDescriptionHelpers
import DependencyPlugin

Expand Down
2 changes: 1 addition & 1 deletion Projects/Domain/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by kyuchul on 10/18/24.
//

import ProjectDescription
@preconcurrency import ProjectDescription
import ProjectDescriptionHelpers
import DependencyPlugin

Expand Down
2 changes: 1 addition & 1 deletion Projects/Feature/Project.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ProjectDescription
@preconcurrency import ProjectDescription
import ProjectDescriptionHelpers
import DependencyPlugin

Expand Down
63 changes: 63 additions & 0 deletions Projects/Feature/Scene/Common/BKGoogleAdView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// BKGoogleAdView.swift
// Feature
//
// Created by kyuchul on 11/30/24.
// Copyright © 2024 com.kyuchul.blink. All rights reserved.
//

import SwiftUI

import Services

import GoogleMobileAds

struct BKGoogleAdView: UIViewControllerRepresentable {
@Binding private var isPresented: Bool
@Binding private var interstitialAd: GoogleAd?
private let dismissAdScreen: () -> Void
private let viewController: UIViewController

init(isPresented: Binding<Bool>,
interstitialAd: Binding<GoogleAd?>,
dismissAdScreen: @escaping () -> Void
) {
self._isPresented = isPresented
self._interstitialAd = interstitialAd
self.dismissAdScreen = dismissAdScreen
self.viewController = UIViewController()
}

func makeUIViewController(context: Context) -> UIViewController {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1)) {
if let interstitialAd {
interstitialAd.ad.present(fromRootViewController: viewController)
}
}

return viewController
}

func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}

func makeCoordinator() -> Coordinator {
Coordinator(parent: self)
}
}

extension BKGoogleAdView {
final class Coordinator: NSObject, GADFullScreenContentDelegate {
private let parent: BKGoogleAdView

init(parent: BKGoogleAdView) {
self.parent = parent
super.init()
parent.interstitialAd?.ad.fullScreenContentDelegate = self
}

func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
parent.isPresented.toggle()
parent.dismissAdScreen()
}
}
}
Loading

0 comments on commit 0aaf61e

Please sign in to comment.