refactor(ads): Yandex 광고 코드와 SDK 의존성을 제거한다
This commit is contained in:
@@ -15,7 +15,6 @@ import FirebaseCore
|
||||
import FirebaseAnalytics
|
||||
import FirebaseMessaging
|
||||
import LineSDK
|
||||
import YandexMobileAds
|
||||
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
@@ -33,9 +32,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
Messaging.messaging().delegate = self
|
||||
setupAppsFlyer()
|
||||
|
||||
// YandexAds 초기화
|
||||
YandexAds.initializeSDK(completionHandler: nil)
|
||||
|
||||
// For iOS 10 display notification (sent via APNS)
|
||||
UNUserNotificationCenter.current().delegate = self
|
||||
|
||||
|
||||
@@ -36,11 +36,6 @@ struct CharacterView: View {
|
||||
}
|
||||
}
|
||||
|
||||
YandexInlineBannerView(
|
||||
placement: .chatCharacterList,
|
||||
horizontalPadding: 24
|
||||
)
|
||||
.padding(.vertical, -24)
|
||||
|
||||
// 인기 캐릭터 섹션
|
||||
if !viewModel.popularCharacters.isEmpty {
|
||||
|
||||
@@ -22,10 +22,6 @@ struct OriginalTabView: View {
|
||||
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack(spacing: 12) {
|
||||
YandexInlineBannerView(
|
||||
placement: .chatOriginalTabTop,
|
||||
horizontalPadding: horizontalPadding
|
||||
)
|
||||
|
||||
LazyVGrid(
|
||||
columns: Array(
|
||||
|
||||
@@ -277,21 +277,6 @@ final class ChatRoomViewModel: ObservableObject {
|
||||
purchaseChatQuota(chargeType: .can, canOption: canOption)
|
||||
}
|
||||
|
||||
func showRewardedAdForChatQuota() {
|
||||
_Concurrency.Task {
|
||||
let isShown = await YandexRewardedAdManager.shared.showAdIfAvailable(for: .chatRoomQuota) { [weak self] in
|
||||
self?.purchaseChatQuota(chargeType: .ad, canOption: nil)
|
||||
}
|
||||
|
||||
if !isShown {
|
||||
await MainActor.run {
|
||||
errorMessage = I18n.Chat.Room.rewardedAdLoadFailed
|
||||
isShowPopup = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func purchaseChatQuota(
|
||||
chargeType: ChatRoomQuotaChargeType,
|
||||
canOption: ChatRoomQuotaCanOption?
|
||||
@@ -467,15 +452,6 @@ final class ChatRoomViewModel: ObservableObject {
|
||||
private func updateQuota(totalRemaining: Int) {
|
||||
self.totalRemaining = totalRemaining
|
||||
showQuotaNoticeView = totalRemaining <= 0
|
||||
prepareRewardedAdIfNeeded(totalRemaining: totalRemaining)
|
||||
}
|
||||
|
||||
private func prepareRewardedAdIfNeeded(totalRemaining: Int) {
|
||||
guard totalRemaining <= 1 else { return }
|
||||
|
||||
_Concurrency.Task {
|
||||
await YandexRewardedAdManager.shared.preloadAd(for: .chatRoomQuota)
|
||||
}
|
||||
}
|
||||
|
||||
private func getSavedBackgroundImageId() -> Int? {
|
||||
|
||||
@@ -21,7 +21,6 @@ struct ChatQuotaPurchaseRequest: Encodable {
|
||||
|
||||
enum ChatRoomQuotaChargeType: String, Encodable {
|
||||
case can = "CAN"
|
||||
case ad = "AD"
|
||||
}
|
||||
|
||||
enum ChatRoomQuotaCanOption: String, Encodable {
|
||||
|
||||
@@ -15,10 +15,6 @@ struct TalkView: View {
|
||||
BaseView(isLoading: $viewModel.isLoading) {
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
LazyVStack(spacing: 24) {
|
||||
YandexInlineBannerView(
|
||||
placement: .chatTalkTabTop,
|
||||
horizontalPadding: 24
|
||||
)
|
||||
|
||||
if viewModel.talkRooms.isEmpty {
|
||||
Text(I18n.Chat.Talk.emptyMessage)
|
||||
|
||||
@@ -1,316 +0,0 @@
|
||||
//
|
||||
// YandexAdSupport.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by OpenCode on 2026/04/28.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import YandexMobileAds
|
||||
|
||||
enum YandexBannerPlacement {
|
||||
case liveTab
|
||||
case liveDetail
|
||||
case creatorCommunityAll
|
||||
case seriesMainHome
|
||||
case seriesMainDayOfWeek
|
||||
case seriesMainByGenre
|
||||
case pushNotificationList
|
||||
case notificationReceiveSettings
|
||||
case chatCharacterList
|
||||
case chatOriginalTabTop
|
||||
case chatTalkTabTop
|
||||
}
|
||||
|
||||
enum YandexRewardedPlacement {
|
||||
case chatRoomQuota
|
||||
}
|
||||
|
||||
enum YandexAdUnitIdProvider {
|
||||
|
||||
static func banner(for placement: YandexBannerPlacement) -> String {
|
||||
switch placement {
|
||||
case .liveTab:
|
||||
YANDEX_LIVE_TAB_BANNER_AD_UNIT_ID
|
||||
case .liveDetail:
|
||||
YANDEX_LIVE_DETAIL_BANNER_AD_UNIT_ID
|
||||
case .creatorCommunityAll:
|
||||
YANDEX_CREATOR_COMMUNITY_ALL_BANNER_AD_UNIT_ID
|
||||
case .seriesMainHome:
|
||||
YANDEX_SERIES_MAIN_HOME_BANNER_AD_UNIT_ID
|
||||
case .seriesMainDayOfWeek:
|
||||
YANDEX_SERIES_MAIN_DAY_OF_WEEK_BANNER_AD_UNIT_ID
|
||||
case .seriesMainByGenre:
|
||||
YANDEX_SERIES_MAIN_BY_GENRE_BANNER_AD_UNIT_ID
|
||||
case .pushNotificationList:
|
||||
YANDEX_PUSH_NOTIFICATION_LIST_BANNER_AD_UNIT_ID
|
||||
case .notificationReceiveSettings:
|
||||
YANDEX_NOTIFICATION_RECEIVE_SETTINGS_BANNER_AD_UNIT_ID
|
||||
case .chatCharacterList:
|
||||
YANDEX_CHAT_CHARACTER_LIST_BANNER_AD_UNIT_ID
|
||||
case .chatOriginalTabTop:
|
||||
YANDEX_CHAT_ORIGINAL_TAB_TOP_BANNER_AD_UNIT_ID
|
||||
case .chatTalkTabTop:
|
||||
YANDEX_CHAT_TALK_TAB_TOP_BANNER_AD_UNIT_ID
|
||||
}
|
||||
}
|
||||
|
||||
static func rewarded(for placement: YandexRewardedPlacement) -> String {
|
||||
switch placement {
|
||||
case .chatRoomQuota:
|
||||
YANDEX_CHAT_ROOM_QUOTA_REWARDED_AD_UNIT_ID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct YandexInlineBannerView: View {
|
||||
|
||||
let placement: YandexBannerPlacement
|
||||
|
||||
var maxHeight: CGFloat = 90
|
||||
var horizontalPadding: CGFloat = 13.3
|
||||
|
||||
@State private var bannerHeight: CGFloat = 0
|
||||
@State private var isLoadFailed = true
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { proxy in
|
||||
let width = max(proxy.size.width - (horizontalPadding * 2), 1)
|
||||
let resolvedHeight = isLoadFailed ? 0 : (bannerHeight > 0 ? bannerHeight : maxHeight)
|
||||
|
||||
YandexInlineBannerContainer(
|
||||
placement: placement,
|
||||
width: width,
|
||||
maxHeight: maxHeight,
|
||||
bannerHeight: $bannerHeight,
|
||||
isLoadFailed: $isLoadFailed
|
||||
)
|
||||
.frame(width: width, height: resolvedHeight)
|
||||
.padding(.horizontal, horizontalPadding)
|
||||
}
|
||||
.frame(height: isLoadFailed ? 0 : (bannerHeight > 0 ? bannerHeight : maxHeight))
|
||||
}
|
||||
}
|
||||
|
||||
private struct YandexInlineBannerContainer: UIViewRepresentable {
|
||||
|
||||
let placement: YandexBannerPlacement
|
||||
|
||||
let width: CGFloat
|
||||
let maxHeight: CGFloat
|
||||
|
||||
@Binding var bannerHeight: CGFloat
|
||||
@Binding var isLoadFailed: Bool
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
Coordinator(parent: self)
|
||||
}
|
||||
|
||||
func makeUIView(context: Context) -> UIView {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .clear
|
||||
return view
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: UIView, context: Context) {
|
||||
context.coordinator.parent = self
|
||||
context.coordinator.configureIfNeeded(containerView: uiView)
|
||||
}
|
||||
|
||||
final class Coordinator: NSObject, BannerAdViewDelegate {
|
||||
|
||||
var parent: YandexInlineBannerContainer
|
||||
private weak var containerView: UIView?
|
||||
private var bannerAdView: BannerAdView?
|
||||
private var currentWidth: CGFloat = 0
|
||||
|
||||
init(parent: YandexInlineBannerContainer) {
|
||||
self.parent = parent
|
||||
}
|
||||
|
||||
func configureIfNeeded(containerView: UIView) {
|
||||
self.containerView = containerView
|
||||
|
||||
let roundedWidth = parent.width.rounded(.down)
|
||||
|
||||
guard bannerAdView == nil || abs(currentWidth - roundedWidth) > 0.5 else {
|
||||
return
|
||||
}
|
||||
|
||||
currentWidth = roundedWidth
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.parent.bannerHeight = 0
|
||||
self.parent.isLoadFailed = false
|
||||
}
|
||||
|
||||
bannerAdView?.removeFromSuperview()
|
||||
|
||||
let adSize = BannerAdSize.inline(width: roundedWidth, maxHeight: parent.maxHeight)
|
||||
let bannerAdView = BannerAdView(adSize: adSize)
|
||||
bannerAdView.translatesAutoresizingMaskIntoConstraints = false
|
||||
bannerAdView.delegate = self
|
||||
|
||||
containerView.addSubview(bannerAdView)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
bannerAdView.topAnchor.constraint(equalTo: containerView.topAnchor),
|
||||
bannerAdView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
|
||||
bannerAdView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
|
||||
bannerAdView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor)
|
||||
])
|
||||
|
||||
self.bannerAdView = bannerAdView
|
||||
bannerAdView.loadAd(with: AdRequest(adUnitID: YandexAdUnitIdProvider.banner(for: parent.placement)))
|
||||
}
|
||||
|
||||
func bannerAdViewDidLoad(_ adView: BannerAdView) {
|
||||
adView.layoutIfNeeded()
|
||||
|
||||
let measuredHeight = adView.bounds.height > 0 ? adView.bounds.height : parent.maxHeight
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.parent.bannerHeight = measuredHeight
|
||||
self.parent.isLoadFailed = false
|
||||
}
|
||||
}
|
||||
|
||||
func bannerAdViewDidFailLoading(_ adView: BannerAdView, error: Error) {
|
||||
DispatchQueue.main.async {
|
||||
self.parent.bannerHeight = 0
|
||||
self.parent.isLoadFailed = true
|
||||
}
|
||||
}
|
||||
|
||||
func bannerAdViewDidClick(_ adView: BannerAdView) {
|
||||
}
|
||||
|
||||
func bannerAdView(_ adView: BannerAdView, didTrackImpression impressionData: ImpressionData?) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
final class YandexRewardedAdManager: NSObject {
|
||||
|
||||
static let shared = YandexRewardedAdManager()
|
||||
|
||||
private var rewardedAd: RewardedAd?
|
||||
private var rewardedAdLoader: RewardedAdLoader?
|
||||
private var currentPlacement: YandexRewardedPlacement?
|
||||
private var pendingRewardAction: (@MainActor () -> Void)?
|
||||
private var rewardedPlacement: YandexRewardedPlacement?
|
||||
private var isLoading = false
|
||||
|
||||
func preloadAd(for placement: YandexRewardedPlacement) {
|
||||
guard !isLoading else {
|
||||
return
|
||||
}
|
||||
|
||||
if currentPlacement == placement, rewardedAd != nil {
|
||||
return
|
||||
}
|
||||
|
||||
let loader = RewardedAdLoader()
|
||||
rewardedAdLoader = loader
|
||||
rewardedAd = nil
|
||||
currentPlacement = placement
|
||||
isLoading = true
|
||||
|
||||
Task {
|
||||
do {
|
||||
let loadedAd = try await loader.loadAd(with: AdRequest(adUnitID: YandexAdUnitIdProvider.rewarded(for: placement)))
|
||||
guard currentPlacement == placement else {
|
||||
isLoading = false
|
||||
return
|
||||
}
|
||||
|
||||
loadedAd.delegate = self
|
||||
rewardedAd = loadedAd
|
||||
} catch {
|
||||
if currentPlacement == placement {
|
||||
rewardedAd = nil
|
||||
}
|
||||
}
|
||||
|
||||
if currentPlacement == placement {
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func showAdIfAvailable(for placement: YandexRewardedPlacement, onReward: @escaping @MainActor () -> Void) -> Bool {
|
||||
guard let presenter = presentingViewController(), let rewardedAd, currentPlacement == placement else {
|
||||
preloadAd(for: placement)
|
||||
return false
|
||||
}
|
||||
|
||||
pendingRewardAction = onReward
|
||||
rewardedPlacement = placement
|
||||
rewardedAd.show(from: presenter)
|
||||
return true
|
||||
}
|
||||
|
||||
private func completeRewardIfNeeded() {
|
||||
let action = pendingRewardAction
|
||||
pendingRewardAction = nil
|
||||
action?()
|
||||
}
|
||||
|
||||
private func resetAndPreload() {
|
||||
pendingRewardAction = nil
|
||||
rewardedAd = nil
|
||||
|
||||
if let rewardedPlacement {
|
||||
self.rewardedPlacement = nil
|
||||
preloadAd(for: rewardedPlacement)
|
||||
}
|
||||
}
|
||||
|
||||
private func presentingViewController() -> UIViewController? {
|
||||
guard
|
||||
let rootViewController = UIApplication.shared.connectedScenes
|
||||
.compactMap({ $0 as? UIWindowScene })
|
||||
.flatMap({ $0.windows })
|
||||
.first(where: { $0.isKeyWindow })?
|
||||
.rootViewController
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
var topViewController = rootViewController
|
||||
|
||||
while let presentedViewController = topViewController.presentedViewController {
|
||||
topViewController = presentedViewController
|
||||
}
|
||||
|
||||
return topViewController
|
||||
}
|
||||
}
|
||||
|
||||
extension YandexRewardedAdManager: RewardedAdDelegate {
|
||||
|
||||
func rewardedAd(_ rewardedAd: RewardedAd, didReward reward: Reward) {
|
||||
DEBUG_LOG("리워드 광고 보상 받기 성공")
|
||||
completeRewardIfNeeded()
|
||||
}
|
||||
|
||||
func rewardedAd(_ rewardedAd: RewardedAd, didFailToShow error: Error) {
|
||||
DEBUG_LOG("리워드 광고 에러")
|
||||
resetAndPreload()
|
||||
}
|
||||
|
||||
func rewardedAdDidShow(_ rewardedAd: RewardedAd) {
|
||||
}
|
||||
|
||||
func rewardedAdDidDismiss(_ rewardedAd: RewardedAd) {
|
||||
DEBUG_LOG("리워드 광고 닫기")
|
||||
resetAndPreload()
|
||||
}
|
||||
|
||||
func rewardedAdDidClick(_ rewardedAd: RewardedAd) {
|
||||
}
|
||||
|
||||
func rewardedAd(_ rewardedAd: RewardedAd, didTrackImpression impressionData: ImpressionData?) {
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,6 @@ struct SeriesMainByGenreView: View {
|
||||
let width = (screenSize().width - (horizontalPadding * 2) - gridSpacing) / 2
|
||||
|
||||
VStack(spacing: 16) {
|
||||
if !viewModel.genreList.isEmpty {
|
||||
YandexInlineBannerView(placement: .seriesMainByGenre, horizontalPadding: 24)
|
||||
}
|
||||
|
||||
LazyVGrid(
|
||||
columns: Array(
|
||||
|
||||
@@ -62,7 +62,6 @@ struct SeriesMainDayOfWeekView: View {
|
||||
let width = (screenSize().width - (horizontalPadding * 2) - gridSpacing) / 2
|
||||
|
||||
VStack(spacing: 16) {
|
||||
YandexInlineBannerView(placement: .seriesMainDayOfWeek, horizontalPadding: 24)
|
||||
|
||||
LazyVGrid(
|
||||
columns: Array(
|
||||
|
||||
@@ -55,7 +55,6 @@ struct SeriesMainHomeView: View {
|
||||
}
|
||||
}
|
||||
|
||||
YandexInlineBannerView(placement: .seriesMainHome, horizontalPadding: 24)
|
||||
|
||||
if !viewModel.recommendSeriesList.isEmpty {
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
|
||||
@@ -11,7 +11,6 @@ let BASE_URL = "https://test-api.sodalive.net"
|
||||
let APPLY_SODALIVE_CREATOR = "https://forms.gle/mmhJKmijjVRnwtdZ7"
|
||||
|
||||
let AGORA_APP_ID = "b96574e191a9430fa54c605528aa3ef7"
|
||||
let AGORA_APP_CERTIFICATE = "ae18ade3afcf4086bd4397726eb0654c"
|
||||
|
||||
let BOOTPAY_APP_ID = "6242a7772701800023f68b2f"
|
||||
let BOOTPAY_APP_HECTO_ID = "667fca5d3bab7404f831c3e5"
|
||||
@@ -32,18 +31,3 @@ let LINE_CHANNEL_ID = "2008995582"
|
||||
|
||||
let AGORA_CUSTOMER_ID = "de5dd9ea151f4a43ba1ad8411817b169"
|
||||
let AGORA_CUSTOMER_SECRET = "3855da8bc5ae4743af8bf4f87408b515"
|
||||
|
||||
let YANDEX_LIVE_TAB_BANNER_AD_UNIT_ID = "R-M-19140297-3"
|
||||
let YANDEX_LIVE_DETAIL_BANNER_AD_UNIT_ID = "R-M-19140297-4"
|
||||
let YANDEX_CONTENT_DETAIL_BANNER_AD_UNIT_ID = "R-M-19140297-5"
|
||||
let YANDEX_CONTENT_DETAIL_INTERSTITIAL_AD_UNIT_ID = "R-M-19140297-6"
|
||||
let YANDEX_CREATOR_COMMUNITY_ALL_BANNER_AD_UNIT_ID = "R-M-19140297-7"
|
||||
let YANDEX_SERIES_MAIN_HOME_BANNER_AD_UNIT_ID = "R-M-19140297-8"
|
||||
let YANDEX_SERIES_MAIN_DAY_OF_WEEK_BANNER_AD_UNIT_ID = "R-M-19140297-9"
|
||||
let YANDEX_SERIES_MAIN_BY_GENRE_BANNER_AD_UNIT_ID = "R-M-19140297-10"
|
||||
let YANDEX_PUSH_NOTIFICATION_LIST_BANNER_AD_UNIT_ID = "R-M-19140297-11"
|
||||
let YANDEX_NOTIFICATION_RECEIVE_SETTINGS_BANNER_AD_UNIT_ID = "R-M-19140297-12"
|
||||
let YANDEX_CHAT_CHARACTER_LIST_BANNER_AD_UNIT_ID = "R-M-19140297-13"
|
||||
let YANDEX_CHAT_ORIGINAL_TAB_TOP_BANNER_AD_UNIT_ID = "R-M-19140297-14"
|
||||
let YANDEX_CHAT_TALK_TAB_TOP_BANNER_AD_UNIT_ID = "R-M-19140297-15"
|
||||
let YANDEX_CHAT_ROOM_QUOTA_REWARDED_AD_UNIT_ID = "R-M-19140297-16"
|
||||
|
||||
@@ -47,7 +47,6 @@ struct CreatorCommunityAllView: View {
|
||||
|
||||
communityViewTypeTabView
|
||||
|
||||
YandexInlineBannerView(placement: .creatorCommunityAll)
|
||||
|
||||
if isGridMode {
|
||||
gridContentView
|
||||
|
||||
@@ -326,14 +326,6 @@ enum I18n {
|
||||
pick(ko: "입력 중", en: "Typing", ja: "入力中")
|
||||
}
|
||||
|
||||
static func quotaAdAction(chatCount: Int) -> String {
|
||||
pick(
|
||||
ko: "광고 / \(chatCount)채팅",
|
||||
en: "Ad / \(chatCount) chats",
|
||||
ja: "広告 / \(chatCount)チャット"
|
||||
)
|
||||
}
|
||||
|
||||
static func quotaChatCount(_ chatCount: Int) -> String {
|
||||
pick(
|
||||
ko: "\(chatCount)채팅",
|
||||
@@ -342,14 +334,6 @@ enum I18n {
|
||||
)
|
||||
}
|
||||
|
||||
static var rewardedAdLoadFailed: String {
|
||||
pick(
|
||||
ko: "광고를 불러오지 못했어요\n잠시 후 다시 시도해 주세요.",
|
||||
en: "Could not load the ad.\nPlease try again later.",
|
||||
ja: "広告を読み込めませんでした。\nしばらくしてからもう一度お試しください。"
|
||||
)
|
||||
}
|
||||
|
||||
static var backgroundSelectionTitle: String {
|
||||
pick(ko: "배경 이미지 선택", en: "Select background image", ja: "背景画像を選択")
|
||||
}
|
||||
|
||||
@@ -91,8 +91,6 @@ struct LiveView: View {
|
||||
SectionLatestFinishedLiveView(items: viewModel.latestFinishedLiveItems)
|
||||
}
|
||||
|
||||
YandexInlineBannerView(placement: .liveTab)
|
||||
.padding(.vertical, -24)
|
||||
|
||||
if viewModel.replayLiveItems.count > 0 {
|
||||
LiveReplayListView(contentList: viewModel.replayLiveItems)
|
||||
|
||||
@@ -129,9 +129,6 @@ struct LiveDetailView: View {
|
||||
.frame(width: proxy.size.width - 26.7)
|
||||
}
|
||||
|
||||
YandexInlineBannerView(placement: .liveDetail, horizontalPadding: 0)
|
||||
.frame(width: proxy.size.width - 26.7)
|
||||
.padding(.top, 13.3)
|
||||
|
||||
Rectangle()
|
||||
.frame(height: 1)
|
||||
|
||||
@@ -17,7 +17,6 @@ struct PushNotificationListView: View {
|
||||
selectedTheme: $viewModel.selectedCategory
|
||||
)
|
||||
|
||||
YandexInlineBannerView(placement: .pushNotificationList)
|
||||
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
LazyVStack(spacing: 0) {
|
||||
|
||||
@@ -158,8 +158,6 @@ struct NotificationReceiveSettingsView: View {
|
||||
.padding(.top, 13.3)
|
||||
.padding(.horizontal, 13.3)
|
||||
|
||||
YandexInlineBannerView(placement: .notificationReceiveSettings)
|
||||
.padding(.top, 26.7)
|
||||
|
||||
Text(I18n.Settings.Notification.followingChannels)
|
||||
.appFont(size: 16.7, weight: .bold)
|
||||
|
||||
@@ -11,7 +11,6 @@ let BASE_URL = "https://api.sodalive.net"
|
||||
let APPLY_SODALIVE_CREATOR = "https://forms.gle/mmhJKmijjVRnwtdZ7"
|
||||
|
||||
let AGORA_APP_ID = "e34e40046e9847baba3adfe2b8ffb4f6"
|
||||
let AGORA_APP_CERTIFICATE = "15cadeea4ba94ff7b091c9a10f4bf4a6"
|
||||
|
||||
let BOOTPAY_APP_ID = "64c35be1d25985001dc50c88"
|
||||
let BOOTPAY_APP_HECTO_ID = "664c1707b18b225deca4b42a"
|
||||
@@ -32,18 +31,3 @@ let LINE_CHANNEL_ID = "2008995539"
|
||||
|
||||
let AGORA_CUSTOMER_ID = "de5dd9ea151f4a43ba1ad8411817b169"
|
||||
let AGORA_CUSTOMER_SECRET = "3855da8bc5ae4743af8bf4f87408b515"
|
||||
|
||||
let YANDEX_LIVE_TAB_BANNER_AD_UNIT_ID = "R-M-19157621-1"
|
||||
let YANDEX_LIVE_DETAIL_BANNER_AD_UNIT_ID = "R-M-19157621-2"
|
||||
let YANDEX_CONTENT_DETAIL_BANNER_AD_UNIT_ID = "R-M-19157621-3"
|
||||
let YANDEX_CONTENT_DETAIL_INTERSTITIAL_AD_UNIT_ID = "R-M-19157621-4"
|
||||
let YANDEX_CREATOR_COMMUNITY_ALL_BANNER_AD_UNIT_ID = "R-M-19157621-5"
|
||||
let YANDEX_SERIES_MAIN_HOME_BANNER_AD_UNIT_ID = "R-M-19157621-6"
|
||||
let YANDEX_SERIES_MAIN_DAY_OF_WEEK_BANNER_AD_UNIT_ID = "R-M-19157621-7"
|
||||
let YANDEX_SERIES_MAIN_BY_GENRE_BANNER_AD_UNIT_ID = "R-M-19157621-8"
|
||||
let YANDEX_PUSH_NOTIFICATION_LIST_BANNER_AD_UNIT_ID = "R-M-19157621-9"
|
||||
let YANDEX_NOTIFICATION_RECEIVE_SETTINGS_BANNER_AD_UNIT_ID = "R-M-19157621-10"
|
||||
let YANDEX_CHAT_CHARACTER_LIST_BANNER_AD_UNIT_ID = "R-M-19157621-11"
|
||||
let YANDEX_CHAT_ORIGINAL_TAB_TOP_BANNER_AD_UNIT_ID = "R-M-19157621-12"
|
||||
let YANDEX_CHAT_TALK_TAB_TOP_BANNER_AD_UNIT_ID = "R-M-19157621-13"
|
||||
let YANDEX_CHAT_ROOM_QUOTA_REWARDED_AD_UNIT_ID = "R-M-19157621-14"
|
||||
|
||||
Reference in New Issue
Block a user