diff --git a/Projects/App/Sources/Application/AppDelegate.swift b/Projects/App/Sources/Application/AppDelegate.swift index c3c704ec6..7de90988e 100644 --- a/Projects/App/Sources/Application/AppDelegate.swift +++ b/Projects/App/Sources/Application/AppDelegate.swift @@ -24,6 +24,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { } else { LogManager.setUserID(userID: nil) } + initializeUserProperty() Analytics.logEvent(AnalyticsEventAppOpen, parameters: nil) @@ -116,6 +117,22 @@ extension AppDelegate { } } } + + private func initializeUserProperty() { + if let loginPlatform = PreferenceManager.userInfo?.platform { + LogManager.setUserProperty(property: .loginPlatform(platform: loginPlatform)) + } else { + LogManager.clearUserProperty(property: .loginPlatform(platform: "")) + } + + if let fruitTotal = PreferenceManager.userInfo?.itemCount { + LogManager.setUserProperty(property: .fruitTotal(count: fruitTotal)) + } else { + LogManager.clearUserProperty(property: .fruitTotal(count: -1)) + } + + LogManager.setUserProperty(property: .playlistSongTotal(count: PlayState.shared.count)) + } } #if DEBUG || QA diff --git a/Projects/Features/ArtistFeature/Sources/Analytics/ArtistAnalyticsLog.swift b/Projects/Features/ArtistFeature/Sources/Analytics/ArtistAnalyticsLog.swift index 3dcb12f2e..6cf400099 100644 --- a/Projects/Features/ArtistFeature/Sources/Analytics/ArtistAnalyticsLog.swift +++ b/Projects/Features/ArtistFeature/Sources/Analytics/ArtistAnalyticsLog.swift @@ -7,6 +7,4 @@ enum ArtistAnalyticsLog: AnalyticsLogType { case clickArtistSubscriptionButton(artist: String) case clickArtistPlayButton(type: String, artist: String) case clickArtistTabbarTab(tab: String, artist: String) - case selectMusicItem(id: String, location: String) - case deselectMusicItem(id: String, location: String) } diff --git a/Projects/Features/ArtistFeature/Sources/ViewControllers/ArtistDetailViewController.swift b/Projects/Features/ArtistFeature/Sources/ViewControllers/ArtistDetailViewController.swift index 9eb4b5354..bb53b06d6 100644 --- a/Projects/Features/ArtistFeature/Sources/ViewControllers/ArtistDetailViewController.swift +++ b/Projects/Features/ArtistFeature/Sources/ViewControllers/ArtistDetailViewController.swift @@ -107,13 +107,15 @@ private extension ArtistDetailViewController { .disposed(by: disposeBag) output.showLogin - .bind(with: self) { owner, _ in + .bind(with: self) { owner, entry in let viewController = owner.textPopupFactory.makeView( text: "로그인이 필요한 서비스입니다.\n로그인 하시겠습니까?", cancelButtonIsHidden: false, confirmButtonText: nil, cancelButtonText: nil, completion: { + let log = CommonAnalyticsLog.clickLoginButton(entry: entry) + LogManager.analytics(log) let loginVC = owner.signInFactory.makeView() loginVC.modalPresentationStyle = .fullScreen owner.present(loginVC, animated: true) diff --git a/Projects/Features/ArtistFeature/Sources/ViewControllers/ArtistMusicContentViewController.swift b/Projects/Features/ArtistFeature/Sources/ViewControllers/ArtistMusicContentViewController.swift index 54199e69e..489d13621 100644 --- a/Projects/Features/ArtistFeature/Sources/ViewControllers/ArtistMusicContentViewController.swift +++ b/Projects/Features/ArtistFeature/Sources/ViewControllers/ArtistMusicContentViewController.swift @@ -187,6 +187,9 @@ private extension ArtistMusicContentViewController { confirmButtonText: nil, cancelButtonText: nil, completion: { + let log = CommonAnalyticsLog.clickLoginButton(entry: .addMusics) + LogManager.analytics(log) + let loginVC = owner.signInFactory.makeView() loginVC.modalPresentationStyle = .overFullScreen owner.present(loginVC, animated: true) @@ -230,8 +233,11 @@ extension ArtistMusicContentViewController: SongCartViewDelegate { input.allSongSelected.onNext(flag) case .addSong: + let log = CommonAnalyticsLog.clickAddMusicsButton(location: .artist) + LogManager.analytics(log) + if PreferenceManager.userInfo == nil { - output.showLogin.onNext(()) + output.showLogin.onNext(.addMusics) return } guard songs.count <= limit else { diff --git a/Projects/Features/ArtistFeature/Sources/ViewModels/ArtistDetailViewModel.swift b/Projects/Features/ArtistFeature/Sources/ViewModels/ArtistDetailViewModel.swift index 71b8c47c2..391eeac53 100644 --- a/Projects/Features/ArtistFeature/Sources/ViewModels/ArtistDetailViewModel.swift +++ b/Projects/Features/ArtistFeature/Sources/ViewModels/ArtistDetailViewModel.swift @@ -36,7 +36,7 @@ public final class ArtistDetailViewModel: ViewModelType { let dataSource: BehaviorRelay = BehaviorRelay(value: nil) let isSubscription: BehaviorRelay = BehaviorRelay(value: false) let showToast: PublishSubject = PublishSubject() - let showLogin: PublishSubject = PublishSubject() + let showLogin: PublishSubject = PublishSubject() let showWarningNotification: PublishSubject = PublishSubject() let occurredError: PublishSubject = PublishSubject() } @@ -84,7 +84,7 @@ public final class ArtistDetailViewModel: ViewModelType { .withLatestFrom(PreferenceManager.$userInfo) .filter { userInfo in if userInfo == nil { - output.showLogin.onNext(()) + output.showLogin.onNext(.artistSubscribe) return false } return true diff --git a/Projects/Features/ArtistFeature/Sources/ViewModels/ArtistMusicContentViewModel.swift b/Projects/Features/ArtistFeature/Sources/ViewModels/ArtistMusicContentViewModel.swift index 21f66e9d2..bbf1f42b2 100644 --- a/Projects/Features/ArtistFeature/Sources/ViewModels/ArtistMusicContentViewModel.swift +++ b/Projects/Features/ArtistFeature/Sources/ViewModels/ArtistMusicContentViewModel.swift @@ -43,7 +43,7 @@ public final class ArtistMusicContentViewModel: ViewModelType { let indexOfSelectedSongs: BehaviorRelay<[Int]> = BehaviorRelay(value: []) let songEntityOfSelectedSongs: BehaviorRelay<[SongEntity]> = BehaviorRelay(value: []) let showToast: PublishSubject = .init() - let showLogin: PublishSubject = .init() + let showLogin: PublishSubject = .init() } public func transform(from input: Input) -> Output { @@ -81,15 +81,12 @@ public final class ArtistMusicContentViewModel: ViewModelType { .withLatestFrom(output.indexOfSelectedSongs, resultSelector: { index, selectedSongs -> [Int] in let songID: String = output.dataSource.value[index].songID if selectedSongs.contains(index) { - LogManager.analytics(ArtistAnalyticsLog.deselectMusicItem(id: songID, location: "artist")) guard let removeTargetIndex = selectedSongs.firstIndex(where: { $0 == index }) else { return selectedSongs } var newSelectedSongs = selectedSongs newSelectedSongs.remove(at: removeTargetIndex) return newSelectedSongs - } else { - LogManager.analytics(ArtistAnalyticsLog.selectMusicItem(id: songID, location: "artist")) return selectedSongs + [index] } }) diff --git a/Projects/Features/BaseFeature/Sources/Analytics/ContainSongsAnalyticsLog.swift b/Projects/Features/BaseFeature/Sources/Analytics/ContainSongsAnalyticsLog.swift index 6f815a828..2179de282 100644 --- a/Projects/Features/BaseFeature/Sources/Analytics/ContainSongsAnalyticsLog.swift +++ b/Projects/Features/BaseFeature/Sources/Analytics/ContainSongsAnalyticsLog.swift @@ -2,6 +2,7 @@ import LogManager enum ContainSongsAnalyticsLog: AnalyticsLogType { case clickCreatePlaylistButton(location: CreatePlaylistLocation) + case completeAddMusics(playlistId: String, count: Int) } enum CreatePlaylistLocation: String, AnalyticsLogEnumParametable { diff --git a/Projects/Features/BaseFeature/Sources/Etc/PlayState/PlayState.swift b/Projects/Features/BaseFeature/Sources/Etc/PlayState/PlayState.swift index 035e074fa..7a8259e67 100644 --- a/Projects/Features/BaseFeature/Sources/Etc/PlayState/PlayState.swift +++ b/Projects/Features/BaseFeature/Sources/Etc/PlayState/PlayState.swift @@ -8,6 +8,7 @@ import Combine import Foundation +import LogManager import SongsDomainInterface import Utility @@ -40,6 +41,7 @@ public final class PlayState { playlist.subscribeListChanges() .map { Array($0) } .sink { [weak self] playlistItems in + LogManager.setUserProperty(property: .playlistSongTotal(count: playlistItems.count)) self?.updatePlaylistChangesToLocalDB(playList: playlistItems) } .store(in: &subscription) diff --git a/Projects/Features/BaseFeature/Sources/ViewModels/ContainSongsViewModel.swift b/Projects/Features/BaseFeature/Sources/ViewModels/ContainSongsViewModel.swift index 355a7b40a..e8f8ca33e 100644 --- a/Projects/Features/BaseFeature/Sources/ViewModels/ContainSongsViewModel.swift +++ b/Projects/Features/BaseFeature/Sources/ViewModels/ContainSongsViewModel.swift @@ -3,6 +3,7 @@ import BaseDomainInterface import ErrorModule import Foundation import Localization +import LogManager import PlaylistDomainInterface import PriceDomainInterface import RxRelay @@ -131,6 +132,13 @@ public final class ContainSongsViewModel: ViewModelType { return self.addSongIntoPlaylistUseCase .execute(key: model.key, songs: self.songs) + .do(onSuccess: { _ in + let log = ContainSongsAnalyticsLog.completeAddMusics( + playlistId: model.key, + count: self.songs.count + ) + LogManager.analytics(log) + }) .catch { (error: Error) in let wmError = error.asWMError diff --git a/Projects/Features/ChartFeature/Sources/ViewContrillers/ChartContentViewController.swift b/Projects/Features/ChartFeature/Sources/ViewContrillers/ChartContentViewController.swift index 3b2434356..b478b4bfe 100644 --- a/Projects/Features/ChartFeature/Sources/ViewContrillers/ChartContentViewController.swift +++ b/Projects/Features/ChartFeature/Sources/ViewContrillers/ChartContentViewController.swift @@ -167,6 +167,9 @@ private extension ChartContentViewController { confirmButtonText: nil, cancelButtonText: nil, completion: { + let log = CommonAnalyticsLog.clickLoginButton(entry: .addMusics) + LogManager.analytics(log) + let loginVC = owner.signInFactory.makeView() loginVC.modalPresentationStyle = .overFullScreen owner.present(loginVC, animated: true) @@ -264,6 +267,8 @@ extension ChartContentViewController: SongCartViewDelegate { input.allSongSelected.onNext(flag) case .addSong: + let log = CommonAnalyticsLog.clickAddMusicsButton(location: .chart) + LogManager.analytics(log) if PreferenceManager.userInfo == nil { output.showLogin.onNext(()) return diff --git a/Projects/Features/CreditSongListFeature/Sources/CreditSongListTab/CreditSongListTabItemReactor.swift b/Projects/Features/CreditSongListFeature/Sources/CreditSongListTab/CreditSongListTabItemReactor.swift index 23b2e2cf9..93878d415 100644 --- a/Projects/Features/CreditSongListFeature/Sources/CreditSongListTab/CreditSongListTabItemReactor.swift +++ b/Projects/Features/CreditSongListFeature/Sources/CreditSongListTab/CreditSongListTabItemReactor.swift @@ -2,6 +2,7 @@ import BaseFeature import CreditDomainInterface import CreditSongListFeatureInterface import Localization +import LogManager import ReactorKit import RxSwift import Utility @@ -167,6 +168,9 @@ private extension CreditSongListTabItemReactor { navigateType: .textPopup( text: LocalizationStrings.needLoginWarning, completion: { [signInIsRequiredSubject] in + let log = CommonAnalyticsLog.clickLoginButton(entry: .addMusics) + LogManager.analytics(log) + signInIsRequiredSubject.onNext(()) } ) diff --git a/Projects/Features/CreditSongListFeature/Sources/CreditSongListTab/CreditSongListTabItemViewController.swift b/Projects/Features/CreditSongListFeature/Sources/CreditSongListTab/CreditSongListTabItemViewController.swift index 8fef34910..7f70a36c1 100644 --- a/Projects/Features/CreditSongListFeature/Sources/CreditSongListTab/CreditSongListTabItemViewController.swift +++ b/Projects/Features/CreditSongListFeature/Sources/CreditSongListTab/CreditSongListTabItemViewController.swift @@ -2,6 +2,7 @@ import BaseFeature import BaseFeatureInterface import CreditSongListFeatureInterface import DesignSystem +import LogManager import RxSwift import SignInFeatureInterface import Then @@ -46,6 +47,9 @@ final class CreditSongListTabItemViewController: elementKind: UICollectionView.elementKindSectionHeader ) { [reactor] headerView, _, _ in headerView.setPlayButtonHandler { + let log = CommonAnalyticsLog.clickPlayButton(location: .creditSongList, type: .random) + LogManager.analytics(log) + reactor?.action.onNext(.randomPlayButtonDidTap) } } diff --git a/Projects/Features/HomeFeature/Sources/ViewControllers/NewSongsContentViewController.swift b/Projects/Features/HomeFeature/Sources/ViewControllers/NewSongsContentViewController.swift index 980c6eb9a..558b7b935 100644 --- a/Projects/Features/HomeFeature/Sources/ViewControllers/NewSongsContentViewController.swift +++ b/Projects/Features/HomeFeature/Sources/ViewControllers/NewSongsContentViewController.swift @@ -190,6 +190,9 @@ private extension NewSongsContentViewController { confirmButtonText: nil, cancelButtonText: nil, completion: { + let log = CommonAnalyticsLog.clickLoginButton(entry: .addMusics) + LogManager.analytics(log) + let loginVC = owner.signInFactory.makeView() loginVC.modalPresentationStyle = .overFullScreen owner.present(loginVC, animated: true) @@ -274,6 +277,9 @@ extension NewSongsContentViewController: SongCartViewDelegate { input.allSongSelected.onNext(flag) case .addSong: + let log = CommonAnalyticsLog.clickAddMusicsButton(location: .recentMusic) + LogManager.analytics(log) + if PreferenceManager.userInfo == nil { output.showLogin.onNext(()) return diff --git a/Projects/Features/MainTabFeature/Sources/Analytics/NoticePopupAnalyticsLog.swift b/Projects/Features/MainTabFeature/Sources/Analytics/NoticePopupAnalyticsLog.swift new file mode 100644 index 000000000..d7e0f33fa --- /dev/null +++ b/Projects/Features/MainTabFeature/Sources/Analytics/NoticePopupAnalyticsLog.swift @@ -0,0 +1,5 @@ +import LogManager + +enum NoticePopupAnalyticsLog: AnalyticsLogType { + case clickNoticeItem(id: String, location: String = "notice_popup") +} diff --git a/Projects/Features/MainTabFeature/Sources/ViewControllers/NoticePopupViewController.swift b/Projects/Features/MainTabFeature/Sources/ViewControllers/NoticePopupViewController.swift index 6737155f4..4b4285800 100644 --- a/Projects/Features/MainTabFeature/Sources/ViewControllers/NoticePopupViewController.swift +++ b/Projects/Features/MainTabFeature/Sources/ViewControllers/NoticePopupViewController.swift @@ -8,6 +8,7 @@ import BaseFeature import DesignSystem +import LogManager import NoticeDomainInterface import RxCocoa import RxSwift @@ -44,6 +45,11 @@ public class NoticePopupViewController: UIViewController, ViewControllerFromStor inputBind() } + override public func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + LogManager.analytics(CommonAnalyticsLog.viewPage(pageName: .noticePopup)) + } + public static func viewController( viewModel: NoticePopupViewModel ) -> NoticePopupViewController { @@ -99,6 +105,9 @@ private extension NoticePopupViewController { output.dismissAndCallDelegate .bind(with: self) { owner, entity in + let log = NoticePopupAnalyticsLog.clickNoticeItem(id: "\(entity.id)", location: "notice_popup") + LogManager.analytics(log) + owner.dismiss(animated: true) { owner.delegate?.noticeTapped(model: entity) } diff --git a/Projects/Features/MusicDetailFeature/Sources/Analytics/MusicDetailAnalyticsLog.swift b/Projects/Features/MusicDetailFeature/Sources/Analytics/MusicDetailAnalyticsLog.swift index dde1fdb48..3cfd6d541 100644 --- a/Projects/Features/MusicDetailFeature/Sources/Analytics/MusicDetailAnalyticsLog.swift +++ b/Projects/Features/MusicDetailFeature/Sources/Analytics/MusicDetailAnalyticsLog.swift @@ -7,6 +7,5 @@ enum MusicDetailAnalyticsLog: AnalyticsLogType { case clickSingingRoomButton(id: String) case clickLyricsButton(id: String) case clickLikeMusicButton(id: String, like: Bool) - case clickMusicPickButton(id: String) case clickPlaylistButton(id: String) } diff --git a/Projects/Features/MusicDetailFeature/Sources/MusicDetail/MusicDetailReactor.swift b/Projects/Features/MusicDetailFeature/Sources/MusicDetail/MusicDetailReactor.swift index 2f3080059..ac741c061 100644 --- a/Projects/Features/MusicDetailFeature/Sources/MusicDetail/MusicDetailReactor.swift +++ b/Projects/Features/MusicDetailFeature/Sources/MusicDetail/MusicDetailReactor.swift @@ -349,6 +349,9 @@ private extension MusicDetailReactor { navigate: NavigateType.textPopup( text: LocalizationStrings.needLoginWarning, completion: { [signInIsRequiredSubject] in + let log = CommonAnalyticsLog.clickLoginButton(entry: .songLike) + LogManager.analytics(log) + signInIsRequiredSubject.onNext(()) } ) @@ -384,19 +387,23 @@ private extension MusicDetailReactor { } func musicPickButtonDidTap() -> Observable { + let log = CommonAnalyticsLog.clickAddMusicsButton(location: .songDetail) + LogManager.analytics(log) + guard PreferenceManager.userInfo != nil else { return navigateMutation( navigate: NavigateType.textPopup( text: LocalizationStrings.needLoginWarning, completion: { [signInIsRequiredSubject] in + let log = CommonAnalyticsLog.clickLoginButton(entry: .addMusics) + LogManager.analytics(log) + signInIsRequiredSubject.onNext(()) } ) ) } guard let song = currentState.selectedSong, !song.videoID.isEmpty else { return .empty() } - let log = Log.clickMusicPickButton(id: song.videoID) - LogManager.analytics(log) return navigateMutation(navigate: .musicPick(id: song.videoID)) } diff --git a/Projects/Features/MyInfoFeature/Sources/Analytics/FAQAnalyticsLog.swift b/Projects/Features/MyInfoFeature/Sources/Analytics/FAQAnalyticsLog.swift new file mode 100644 index 000000000..7b9897658 --- /dev/null +++ b/Projects/Features/MyInfoFeature/Sources/Analytics/FAQAnalyticsLog.swift @@ -0,0 +1,6 @@ +import LogManager + +enum FAQAnalyticsLog: AnalyticsLogType { + case selectFaqCategory(category: String) + case clickFaqItem(title: String) +} diff --git a/Projects/Features/MyInfoFeature/Sources/Analytics/InquiryAnalyticsLog.swift b/Projects/Features/MyInfoFeature/Sources/Analytics/InquiryAnalyticsLog.swift new file mode 100644 index 000000000..b36030a65 --- /dev/null +++ b/Projects/Features/MyInfoFeature/Sources/Analytics/InquiryAnalyticsLog.swift @@ -0,0 +1,33 @@ +import LogManager + +enum InquiryAnalyticsLog: AnalyticsLogType { + case clickInquirySubmitButton(type: LogInquiryType) + + enum LogInquiryType: String, AnalyticsLogEnumParametable { + case bug = "버그 제보" + case feature = "기능 제안" + case addSong = "노래 추가" + case modifySong = "노래 수정" + case weeklyChart = "주간차트 영상" + case credit = "참여 정보" + + init(mailSource: InquiryType) { + switch mailSource { + case .reportBug: + self = .bug + case .suggestFunction: + self = .feature + case .addSong: + self = .addSong + case .modifySong: + self = .modifySong + case .weeklyChart: + self = .weeklyChart + case .credit: + self = .credit + case .unknown: + self = .bug + } + } + } +} diff --git a/Projects/Features/MyInfoFeature/Sources/Analytics/MyInfoAnalyticsLog.swift b/Projects/Features/MyInfoFeature/Sources/Analytics/MyInfoAnalyticsLog.swift index ef47fc8e6..25b39e469 100644 --- a/Projects/Features/MyInfoFeature/Sources/Analytics/MyInfoAnalyticsLog.swift +++ b/Projects/Features/MyInfoFeature/Sources/Analytics/MyInfoAnalyticsLog.swift @@ -3,12 +3,14 @@ import LogManager enum MyInfoAnalyticsLog: AnalyticsLogType { case clickProfileImage case clickProfileChangeButton + case completeProfileChange case clickNicknameChangeButton + case completeNicknameChange case clickFruitDrawEntryButton(location: FruitDrawEntryLocation) case clickFruitStorageButton case clickFaqButton case clickNoticeButton - case clickQnaButton + case clickInquiryButton case clickTeamButton case clickSettingButton } diff --git a/Projects/Features/MyInfoFeature/Sources/Analytics/NoticeAnalyticsLog.swift b/Projects/Features/MyInfoFeature/Sources/Analytics/NoticeAnalyticsLog.swift new file mode 100644 index 000000000..2b06b27c1 --- /dev/null +++ b/Projects/Features/MyInfoFeature/Sources/Analytics/NoticeAnalyticsLog.swift @@ -0,0 +1,5 @@ +import LogManager + +enum NoticeAnalyticsLog: AnalyticsLogType { + case clickNoticeItem(id: String, location: String = "notice") +} diff --git a/Projects/Features/MyInfoFeature/Sources/Analytics/SettingAnalyticsLog.swift b/Projects/Features/MyInfoFeature/Sources/Analytics/SettingAnalyticsLog.swift index df7e7ded4..ff63d29e1 100644 --- a/Projects/Features/MyInfoFeature/Sources/Analytics/SettingAnalyticsLog.swift +++ b/Projects/Features/MyInfoFeature/Sources/Analytics/SettingAnalyticsLog.swift @@ -2,11 +2,14 @@ import LogManager enum SettingAnalyticsLog: AnalyticsLogType { case clickNotificationButton - case clickServiceTermsButton - case clickPrivacyButton + case clickTermsOfServiceButton + case clickPrivacyPolicyButton case clickOpensourceButton case clickRemoveCacheButton + case completeRemoveCache(size: String) case clickLogoutButton + case completeLogout case clickVersionButton case clickWithdrawButton + case completeWithdraw } diff --git a/Projects/Features/MyInfoFeature/Sources/Reactors/MyInfoReactor.swift b/Projects/Features/MyInfoFeature/Sources/Reactors/MyInfoReactor.swift index 9dc7ad2c3..f7ffbbc91 100644 --- a/Projects/Features/MyInfoFeature/Sources/Reactors/MyInfoReactor.swift +++ b/Projects/Features/MyInfoFeature/Sources/Reactors/MyInfoReactor.swift @@ -22,7 +22,7 @@ final class MyInfoReactor: Reactor { case completedFruitDraw case completedSetProfile case changeNicknameButtonDidTap(String) - case requiredLogin + case requiredLogin(CommonAnalyticsLog.LoginButtonEntry) } enum Mutation { @@ -47,7 +47,7 @@ final class MyInfoReactor: Reactor { case mail case team case setting - case login + case login(entry: CommonAnalyticsLog.LoginButtonEntry) } struct State { @@ -113,8 +113,8 @@ final class MyInfoReactor: Reactor { return teamNavigationDidTap() case .settingNavigationDidTap: return settingNavigationDidTap() - case .requiredLogin: - return navigateLogin() + case let .requiredLogin(entry): + return navigateLogin(entry: entry) case .completedFruitDraw: return mutateFetchUserInfo() case .completedSetProfile: @@ -265,8 +265,8 @@ private extension MyInfoReactor { return .just(.navigate(.setting)) } - func navigateLogin() -> Observable { - return .just(.navigate(.login)) + func navigateLogin(entry: CommonAnalyticsLog.LoginButtonEntry) -> Observable { + return .just(.navigate(.login(entry: entry))) } } diff --git a/Projects/Features/MyInfoFeature/Sources/ViewControllers/FAQ/FaqContentViewController.swift b/Projects/Features/MyInfoFeature/Sources/ViewControllers/FAQ/FaqContentViewController.swift index 08346e108..7b4c0c542 100644 --- a/Projects/Features/MyInfoFeature/Sources/ViewControllers/FAQ/FaqContentViewController.swift +++ b/Projects/Features/MyInfoFeature/Sources/ViewControllers/FAQ/FaqContentViewController.swift @@ -1,4 +1,5 @@ import BaseFeature +import LogManager import RxCocoa import RxRelay import RxSwift @@ -111,6 +112,8 @@ extension FaqContentViewController: UITableViewDelegate { if data[indexPath.section].isOpen { self.scrollToBottom(indexPath: next) + let title = data[indexPath.section].question + LogManager.analytics(FAQAnalyticsLog.clickFaqItem(title: title)) } } diff --git a/Projects/Features/MyInfoFeature/Sources/ViewControllers/FAQ/FaqViewController.swift b/Projects/Features/MyInfoFeature/Sources/ViewControllers/FAQ/FaqViewController.swift index c3d2ad10e..6c395ef6a 100644 --- a/Projects/Features/MyInfoFeature/Sources/ViewControllers/FAQ/FaqViewController.swift +++ b/Projects/Features/MyInfoFeature/Sources/ViewControllers/FAQ/FaqViewController.swift @@ -1,4 +1,5 @@ import DesignSystem +import LogManager import MyInfoFeatureInterface import NVActivityIndicatorView import Pageboy @@ -45,6 +46,25 @@ public final class FaqViewController: TabmanViewController, ViewControllerFromSt viewController.faqContentFactory = faqContentFactory return viewController } + + override public func pageboyViewController( + _ pageboyViewController: PageboyViewController, + didScrollToPageAt index: TabmanViewController.PageIndex, + direction: PageboyViewController.NavigationDirection, + animated: Bool + ) { + super.pageboyViewController( + pageboyViewController, + didScrollToPageAt: index, + direction: direction, + animated: animated + ) + + let titles = output.dataSource.value.0 + if let selectedTitle = titles[safe: index]?.trimmingCharacters(in: .whitespaces) { + LogManager.analytics(FAQAnalyticsLog.selectFaqCategory(category: selectedTitle)) + } + } } extension FaqViewController { @@ -120,7 +140,7 @@ extension FaqViewController { extension FaqViewController: PageboyViewControllerDataSource, TMBarDataSource { public func numberOfViewControllers(in pageboyViewController: Pageboy.PageboyViewController) -> Int { - DEBUG_LOG(self.viewControllers.count) + LogManager.printDebug(self.viewControllers.count) return self.viewControllers.count } diff --git a/Projects/Features/MyInfoFeature/Sources/ViewControllers/MyInfo/MyInfoViewController.swift b/Projects/Features/MyInfoFeature/Sources/ViewControllers/MyInfo/MyInfoViewController.swift index 37c44fea0..bbdae8d0a 100644 --- a/Projects/Features/MyInfoFeature/Sources/ViewControllers/MyInfo/MyInfoViewController.swift +++ b/Projects/Features/MyInfoFeature/Sources/ViewControllers/MyInfo/MyInfoViewController.swift @@ -139,6 +139,9 @@ final class MyInfoViewController: BaseReactorViewController, Edit reactor.pulse(\.$loginButtonDidTap) .compactMap { $0 } .bind(with: self) { owner, _ in + let log = CommonAnalyticsLog.clickLoginButton(entry: .mypage) + LogManager.analytics(log) + let vc = owner.signInFactory.makeView() vc.modalPresentationStyle = .fullScreen owner.present(vc, animated: true) @@ -170,14 +173,14 @@ final class MyInfoViewController: BaseReactorViewController, Edit viewController.modalPresentationStyle = .fullScreen owner.present(viewController, animated: true) } else { - reactor.action.onNext(.requiredLogin) + reactor.action.onNext(.requiredLogin(.fruitDraw)) } case .fruit: if reactor.currentState.isLoggedIn { let viewController = owner.fruitStorageFactory.makeView() owner.navigationController?.pushViewController(viewController, animated: true) } else { - reactor.action.onNext(.requiredLogin) + reactor.action.onNext(.requiredLogin(.fruitStorage)) } case .faq: let vc = owner.faqFactory.makeView() @@ -195,13 +198,25 @@ final class MyInfoViewController: BaseReactorViewController, Edit case .setting: let vc = owner.settingFactory.makeView() owner.navigationController?.pushViewController(vc, animated: true) - case .login: + case let .login(entry): let vc = owner.textPopUpFactory.makeView( text: LocalizationStrings.needLoginWarning, cancelButtonIsHidden: false, confirmButtonText: nil, cancelButtonText: nil, completion: { + switch entry { + case .fruitDraw: + let log = CommonAnalyticsLog.clickLoginButton(entry: .fruitDraw) + LogManager.analytics(log) + case .fruitStorage: + let log = CommonAnalyticsLog.clickLoginButton(entry: .fruitStorage) + LogManager.analytics(log) + default: + assertionFailure("예상치 못한 entry가 들어옴") + LogManager.printDebug("예상치 못한 entry가 들어옴") + } + let loginVC = owner.signInFactory.makeView() loginVC.modalPresentationStyle = .fullScreen owner.present(loginVC, animated: true) @@ -256,7 +271,7 @@ final class MyInfoViewController: BaseReactorViewController, Edit #warning("문의하기 mail -> qna 로 변경하기") myInfoView.rx.mailNavigationButtonDidTap - .do(onNext: { LogManager.analytics(MyInfoAnalyticsLog.clickQnaButton) }) + .do(onNext: { LogManager.analytics(MyInfoAnalyticsLog.clickInquiryButton) }) .map { MyInfoReactor.Action.mailNavigationDidTap } .bind(to: reactor.action) .disposed(by: disposeBag) @@ -297,6 +312,7 @@ extension MyInfoViewController: EditSheetViewDelegate { LogManager.analytics(MyInfoAnalyticsLog.clickProfileChangeButton) let vc = profilePopupFactory.makeView( completion: { [reactor] () in + LogManager.analytics(MyInfoAnalyticsLog.completeProfileChange) reactor?.action.onNext(.completedSetProfile) } ) @@ -308,6 +324,7 @@ extension MyInfoViewController: EditSheetViewDelegate { type: .nickname, key: "", completion: { [reactor] text in + LogManager.analytics(MyInfoAnalyticsLog.completeNicknameChange) reactor?.action.onNext(.changeNicknameButtonDidTap(text)) } ) diff --git a/Projects/Features/MyInfoFeature/Sources/ViewControllers/Notice/NoticeViewController.swift b/Projects/Features/MyInfoFeature/Sources/ViewControllers/Notice/NoticeViewController.swift index 637ce397e..6fc716562 100644 --- a/Projects/Features/MyInfoFeature/Sources/ViewControllers/Notice/NoticeViewController.swift +++ b/Projects/Features/MyInfoFeature/Sources/ViewControllers/Notice/NoticeViewController.swift @@ -1,5 +1,6 @@ import BaseFeature import DesignSystem +import LogManager import MyInfoFeatureInterface import NVActivityIndicatorView import RxCocoa @@ -85,6 +86,9 @@ private extension NoticeViewController { output.goNoticeDetailScene .bind(with: self) { owner, model in + let log = NoticeAnalyticsLog.clickNoticeItem(id: "\(model.id)", location: "notice") + LogManager.analytics(log) + let viewController = owner.noticeDetailFactory.makeView(model: model) viewController.modalPresentationStyle = .fullScreen owner.present(viewController, animated: true) diff --git a/Projects/Features/MyInfoFeature/Sources/ViewControllers/Question/QuestionViewController.swift b/Projects/Features/MyInfoFeature/Sources/ViewControllers/Question/QuestionViewController.swift index 5037ab99d..6eb0c1d90 100644 --- a/Projects/Features/MyInfoFeature/Sources/ViewControllers/Question/QuestionViewController.swift +++ b/Projects/Features/MyInfoFeature/Sources/ViewControllers/Question/QuestionViewController.swift @@ -1,6 +1,7 @@ import BaseFeature import BaseFeatureInterface import DesignSystem +import LogManager import MessageUI import RxSwift import SafariServices @@ -230,6 +231,10 @@ extension QuestionViewController { .withLatestFrom(output.mailSource) .filter { $0 != .unknown } .subscribe(onNext: { [weak self] source in + let logInquiryType: InquiryAnalyticsLog.LogInquiryType = .init(mailSource: source) + let log = InquiryAnalyticsLog.clickInquirySubmitButton(type: logInquiryType) + LogManager.analytics(log) + guard let self = self else { return } self.goToMail(source: source) }) diff --git a/Projects/Features/MyInfoFeature/Sources/ViewControllers/Setting/SettingViewController.swift b/Projects/Features/MyInfoFeature/Sources/ViewControllers/Setting/SettingViewController.swift index 6d631efc3..f52ec9311 100644 --- a/Projects/Features/MyInfoFeature/Sources/ViewControllers/Setting/SettingViewController.swift +++ b/Projects/Features/MyInfoFeature/Sources/ViewControllers/Setting/SettingViewController.swift @@ -117,6 +117,9 @@ final class SettingViewController: BaseReactorViewController { confirmButtonText: nil, cancelButtonText: nil, completion: { + let log = SettingAnalyticsLog.completeRemoveCache(size: cachSize) + LogManager.analytics(log) + owner.reactor?.action.onNext(.confirmRemoveCacheButtonDidTap) }, cancelCompletion: nil @@ -142,6 +145,9 @@ final class SettingViewController: BaseReactorViewController { text: "정말 탈퇴하시겠습니까?", cancelButtonIsHidden: false, completion: { + let log = SettingAnalyticsLog.completeWithdraw + LogManager.analytics(log) + owner.reactor?.action.onNext(.confirmWithDrawButtonDidTap) } ) @@ -216,10 +222,10 @@ extension SettingViewController: UITableViewDelegate { case .appPush: LogManager.analytics(SettingAnalyticsLog.clickNotificationButton) reactor?.action.onNext(.appPushSettingNavigationDidTap) - case .serviceTerms: LogManager.analytics(SettingAnalyticsLog.clickServiceTermsButton) + case .serviceTerms: LogManager.analytics(SettingAnalyticsLog.clickTermsOfServiceButton) reactor?.action.onNext(.serviceTermsNavigationDidTap) case .privacy: - LogManager.analytics(SettingAnalyticsLog.clickPrivacyButton) + LogManager.analytics(SettingAnalyticsLog.clickPrivacyPolicyButton) reactor?.action.onNext(.privacyNavigationDidTap) case .openSource: LogManager.analytics(SettingAnalyticsLog.clickOpensourceButton) @@ -237,6 +243,9 @@ extension SettingViewController: UITableViewDelegate { cancelButtonText: "취소", completion: { [weak self] in guard let self else { return } + let log = SettingAnalyticsLog.completeLogout + LogManager.analytics(log) + self.reactor?.action.onNext(.confirmLogoutButtonDidTap) }, cancelCompletion: {} diff --git a/Projects/Features/MyInfoFeature/Sources/ViewModels/FaqViewModel.swift b/Projects/Features/MyInfoFeature/Sources/ViewModels/FaqViewModel.swift index 2b656c350..84e330487 100644 --- a/Projects/Features/MyInfoFeature/Sources/ViewModels/FaqViewModel.swift +++ b/Projects/Features/MyInfoFeature/Sources/ViewModels/FaqViewModel.swift @@ -32,6 +32,9 @@ public final class FaqViewModel: ViewModelType { let zip1 = fetchFaqCategoriesUseCase.execute() .catchAndReturn(FaqCategoryEntity(categories: [])) .map { + /* + 탭맨의 무언가 이상함으로 인해 임시방편으로 공백을 직접 넣어줌 + */ var result: [String] = [String("전체 ")] result += $0.categories.map { $0.count < 6 ? $0 + String(repeating: " ", count: 6 - $0.count) : $0 } diff --git a/Projects/Features/MyInfoFeature/Sources/ViewModels/OpenSourceLicenseViewModel.swift b/Projects/Features/MyInfoFeature/Sources/ViewModels/OpenSourceLicenseViewModel.swift index d017dfd4e..a70d96583 100644 --- a/Projects/Features/MyInfoFeature/Sources/ViewModels/OpenSourceLicenseViewModel.swift +++ b/Projects/Features/MyInfoFeature/Sources/ViewModels/OpenSourceLicenseViewModel.swift @@ -43,6 +43,11 @@ public final class OpenSourceLicenseViewModel { description: "The MIT License\nCopyright © 2015 Krunoslav Zaher All rights reserved.", link: "https://github.com/ReactiveX/RxSwift.git" ), + OpenSourceLicense( + title: "RxGesture", + description: "The MIT License\nCopyright © 2016 RxSwiftCommunity.", + link: "https://github.com/RxSwiftCommunity/RxGesture.git" + ), OpenSourceLicense( title: "RxDataSources", description: "The MIT License\nCopyright (c) 2017 RxSwift Community", diff --git a/Projects/Features/PlaylistFeature/Sources/Reactors/UnknownPlaylistDetailReactor.swift b/Projects/Features/PlaylistFeature/Sources/Reactors/UnknownPlaylistDetailReactor.swift index d9714082f..9a071ee81 100644 --- a/Projects/Features/PlaylistFeature/Sources/Reactors/UnknownPlaylistDetailReactor.swift +++ b/Projects/Features/PlaylistFeature/Sources/Reactors/UnknownPlaylistDetailReactor.swift @@ -1,6 +1,7 @@ import AuthDomainInterface import Foundation import Localization +import LogManager import PlaylistDomainInterface import ReactorKit import RxSwift @@ -16,7 +17,11 @@ final class UnknownPlaylistDetailReactor: Reactor { case deselectAll case itemDidTap(Int) case subscriptionButtonDidTap - case requestLoginRequiredAction + case requestLoginRequiredAction(source: LoginRequiredActionSource) + + enum LoginRequiredActionSource { + case addMusics + } } enum Mutation { @@ -27,7 +32,7 @@ final class UnknownPlaylistDetailReactor: Reactor { case updateSelectingStateByIndex([SongEntity]) case updateSubscribeState(Bool) case showToast(String) - case updateLoginPopupState(Bool) + case updateLoginPopupState((Bool, CommonAnalyticsLog.LoginButtonEntry?)) case updateRefresh } @@ -38,7 +43,7 @@ final class UnknownPlaylistDetailReactor: Reactor { var selectedCount: Int var isSubscribing: Bool @Pulse var toastMessage: String? - @Pulse var showLoginPopup: Bool + @Pulse var showLoginPopup: (Bool, CommonAnalyticsLog.LoginButtonEntry?) @Pulse var refresh: Void? @Pulse var detectedNotFound: Void? } @@ -78,7 +83,7 @@ final class UnknownPlaylistDetailReactor: Reactor { isLoading: true, selectedCount: 0, isSubscribing: false, - showLoginPopup: false + showLoginPopup: (false, nil) ) } @@ -99,8 +104,12 @@ final class UnknownPlaylistDetailReactor: Reactor { case let .itemDidTap(index): return updateItemSelected(index) - case .requestLoginRequiredAction: - return .just(.updateLoginPopupState(true)) + case let .requestLoginRequiredAction(source): + switch source { + case .addMusics: + return .just(.updateLoginPopupState((true, .addMusics))) + } + return .just(.updateLoginPopupState((true, nil))) } } @@ -260,7 +269,7 @@ private extension UnknownPlaylistDetailReactor { let prev = currentState.isSubscribing if PreferenceManager.userInfo == nil { - return .just(.updateLoginPopupState(true)) + return .just(.updateLoginPopupState((true, .playlistSubscribe))) } else { return subscribePlaylistUseCase.execute(key: key, isSubscribing: prev) .andThen( diff --git a/Projects/Features/PlaylistFeature/Sources/ViewControllers/MyPlaylistDetailViewController.swift b/Projects/Features/PlaylistFeature/Sources/ViewControllers/MyPlaylistDetailViewController.swift index e25e50376..ad207286e 100644 --- a/Projects/Features/PlaylistFeature/Sources/ViewControllers/MyPlaylistDetailViewController.swift +++ b/Projects/Features/PlaylistFeature/Sources/ViewControllers/MyPlaylistDetailViewController.swift @@ -219,6 +219,9 @@ final class MyPlaylistDetailViewController: BaseReactorViewController Output { @@ -72,6 +73,13 @@ final class PlaylistViewModel: ViewModelType { input.editButtonDidTapEvent.sink { [weak self] _ in guard let self else { return } + let log = if !self.isEditing { + CommonAnalyticsLog.clickEditButton(location: .playlist) + } else { + CommonAnalyticsLog.clickEditCompleteButton(location: .playlist) + } + LogManager.analytics(log) + self.isEditing.toggle() output.editState.send(self.isEditing) }.store(in: &subscription) diff --git a/Projects/Features/SearchFeature/Sources/After/ViewControllers/SongSearchResultViewController.swift b/Projects/Features/SearchFeature/Sources/After/ViewControllers/SongSearchResultViewController.swift index 78ed1e70e..75d8784d0 100644 --- a/Projects/Features/SearchFeature/Sources/After/ViewControllers/SongSearchResultViewController.swift +++ b/Projects/Features/SearchFeature/Sources/After/ViewControllers/SongSearchResultViewController.swift @@ -247,7 +247,7 @@ final class SongSearchResultViewController: BaseReactorViewController Observable in + let log = if !editingState { + CommonAnalyticsLog.clickEditButton(location: .playlist) + } else { + CommonAnalyticsLog.clickEditCompleteButton(location: .playlist) + } + LogManager.analytics(log) + // 편집이 종료될 때 처리 if editingState == false { let new = owner.currentState.dataSource.flatMap { $0.items }.map { $0.songID } diff --git a/Projects/Features/StorageFeature/Sources/Reactors/ListStorageReactor.swift b/Projects/Features/StorageFeature/Sources/Reactors/ListStorageReactor.swift index 03a8535a0..83a0cdf1d 100644 --- a/Projects/Features/StorageFeature/Sources/Reactors/ListStorageReactor.swift +++ b/Projects/Features/StorageFeature/Sources/Reactors/ListStorageReactor.swift @@ -39,7 +39,7 @@ final class ListStorageReactor: Reactor { case switchEditingState(Bool) case updateIsLoggedIn(Bool) case updateIsShowActivityIndicator(Bool) - case showLoginAlert + case showLoginAlert(CommonAnalyticsLog.LoginButtonEntry?) case showToast(String) case showCreatePricePopup(Int) case showCreateListPopup @@ -57,7 +57,7 @@ final class ListStorageReactor: Reactor { var backupDataSource: [MyPlayListSectionModel] var selectedItemCount: Int var isShowActivityIndicator: Bool - @Pulse var showLoginAlert: Void? + @Pulse var showLoginAlert: CommonAnalyticsLog.LoginButtonEntry? @Pulse var showToast: String? @Pulse var hideSongCart: Void? @Pulse var showCreatePricePopup: Int? @@ -130,14 +130,18 @@ final class ListStorageReactor: Reactor { return tapAll(isSelecting) case .loginButtonDidTap: - return .just(.showLoginAlert) + let log = CommonAnalyticsLog.clickLoginButton(entry: .myPlaylist) + LogManager.analytics(log) + return .just(.showLoginAlert(.myPlaylist)) case .addToCurrentPlaylistButtonDidTap: return addToCurrentPlaylist() case .createListButtonDidTap: + let log = CommonAnalyticsLog.clickLoginButton(entry: .addMusics) + LogManager.analytics(log) let isLoggedIn = currentState.isLoggedIn - return isLoggedIn ? mutateFetchPlaylistCreationPrice() : .just(.showLoginAlert) + return isLoggedIn ? mutateFetchPlaylistCreationPrice() : .just(.showLoginAlert(.addMusics)) case .confirmCreatePriceButtonDidTap: return .just(.showCreateListPopup) @@ -154,7 +158,7 @@ final class ListStorageReactor: Reactor { case .drawFruitButtonDidTap: let isLoggedIn = currentState.isLoggedIn - return isLoggedIn ? .just(.showDrawFruitPopup) : .just(.showLoginAlert) + return isLoggedIn ? .just(.showDrawFruitPopup) : .just(.showLoginAlert(.fruitDraw)) case .completedFruitDraw: return completedFruitDraw() @@ -166,6 +170,13 @@ final class ListStorageReactor: Reactor { .skip(1) .withUnretained(self) .flatMap { owner, editingState -> Observable in + let log = if !editingState { + CommonAnalyticsLog.clickEditButton(location: .playlist) + } else { + CommonAnalyticsLog.clickEditCompleteButton(location: .playlist) + } + LogManager.analytics(log) + // 편집이 종료될 때 처리 if editingState == false { let new = owner.currentState.dataSource.flatMap { $0.items }.map { $0.key } @@ -233,8 +244,8 @@ final class ListStorageReactor: Reactor { newState.isEditing = flag case let .updateIsLoggedIn(isLoggedIn): newState.isLoggedIn = isLoggedIn - case .showLoginAlert: - newState.showLoginAlert = () + case let .showLoginAlert(entry): + newState.showLoginAlert = entry case let .updateIsShowActivityIndicator(isShow): newState.isShowActivityIndicator = isShow case let .showToast(message): diff --git a/Projects/Features/StorageFeature/Sources/Reactors/StorageReactor.swift b/Projects/Features/StorageFeature/Sources/Reactors/StorageReactor.swift index 5b1d0b923..9dd6afd12 100644 --- a/Projects/Features/StorageFeature/Sources/Reactors/StorageReactor.swift +++ b/Projects/Features/StorageFeature/Sources/Reactors/StorageReactor.swift @@ -1,4 +1,5 @@ import Foundation +import LogManager import ReactorKit import UserDomainInterface import Utility @@ -15,14 +16,14 @@ final class StorageReactor: Reactor { case updateIsLoggedIn(Bool) case switchTabIndex(Int) case switchEditingState(Bool) - case showLoginAlert + case showLoginAlert(CommonAnalyticsLog.LoginButtonEntry) } struct State { var isLoggedIn: Bool var isEditing: Bool var tabIndex: Int - @Pulse var showLoginAlert: Void? + @Pulse var showLoginAlert: CommonAnalyticsLog.LoginButtonEntry? } let initialState: State @@ -51,7 +52,7 @@ final class StorageReactor: Reactor { storageCommonService.isEditingState.onNext(true) return switchEditingState(true) } else { - return .just(.showLoginAlert) + return .just(.showLoginAlert(.myPlaylist)) } case .saveButtonTap: storageCommonService.isEditingState.onNext(false) @@ -84,8 +85,8 @@ final class StorageReactor: Reactor { newState.tabIndex = index case let .switchEditingState(flag): newState.isEditing = flag - case .showLoginAlert: - newState.showLoginAlert = () + case let .showLoginAlert(entry): + newState.showLoginAlert = entry case let .updateIsLoggedIn(isLoggedIn): newState.isLoggedIn = isLoggedIn } diff --git a/Projects/Features/StorageFeature/Sources/ViewControllers/LikeStorageViewController.swift b/Projects/Features/StorageFeature/Sources/ViewControllers/LikeStorageViewController.swift index 2c92b53d5..dc91d7881 100644 --- a/Projects/Features/StorageFeature/Sources/ViewControllers/LikeStorageViewController.swift +++ b/Projects/Features/StorageFeature/Sources/ViewControllers/LikeStorageViewController.swift @@ -138,6 +138,9 @@ final class LikeStorageViewController: BaseReactorViewController String { + var result = "" + var previousStringWasCapitalized = false + var previousStringWasNumber = false + + for (index, string) in self.enumerated() { + var mutableString = String(string) + + if !mutableString.isAlphabet { + if index != 0, + !previousStringWasNumber { + mutableString = "_" + mutableString + } + previousStringWasNumber = true + } else if mutableString == mutableString.uppercased() { + mutableString = mutableString.lowercased() + + // e.g. JSON으로 오면 j_s_o_n 이런식이 아닌 json 이렇게 바뀌도록 + if index != 0, + !previousStringWasCapitalized { + mutableString = "_" + mutableString + } + previousStringWasCapitalized = true + } else { + previousStringWasCapitalized = false + previousStringWasNumber = false + } + result += mutableString + } + return result + } + + var isAlphabet: Bool { + let alphabetSet = CharacterSet.uppercaseLetters.union(.lowercaseLetters).union(.whitespacesAndNewlines) + return self.rangeOfCharacter(from: alphabetSet.inverted) == nil + } +} diff --git a/Projects/Modules/LogManager/Sources/CommonAnalyticsLog.swift b/Projects/Modules/LogManager/Sources/CommonAnalyticsLog.swift index 3107bcbf9..11ae089f0 100644 --- a/Projects/Modules/LogManager/Sources/CommonAnalyticsLog.swift +++ b/Projects/Modules/LogManager/Sources/CommonAnalyticsLog.swift @@ -13,6 +13,10 @@ public enum CommonAnalyticsLog: AnalyticsLogType { case viewPage(pageName: PageName) case clickPlaylistItem(location: PlaylistItemLocation, key: String) case clickPlayButton(location: PlayButtonLocation, type: PlayButtonType) + case clickAddMusicsButton(location: AddMusicLocation) + case clickEditButton(location: EditButtonLocation) + case clickEditCompleteButton(location: EditButtonLocation) + case clickLoginButton(entry: LoginButtonEntry) } public extension CommonAnalyticsLog { @@ -37,6 +41,7 @@ public extension CommonAnalyticsLog { case login case songCredit = "song_credit" case creditSongList = "credit_song_list" + case noticePopup = "notice_popup" public var description: String { self.rawValue @@ -65,6 +70,7 @@ public extension CommonAnalyticsLog { case chart case recentMusic = "recent_music" case musicDetail = "music_detail" + case creditSongList = "credit_song_list" } enum PlayButtonType: String, AnalyticsLogEnumParametable { @@ -76,4 +82,34 @@ public extension CommonAnalyticsLog { case range50to100 case playlist } + + enum AddMusicLocation: String, AnalyticsLogEnumParametable { + case songDetail = "song_detail" + case search + case chart + case recentMusic = "recent_music" + case artist + case playlist + case playlistDetail = "playlist_detail" + case storageLike = "storage_like" + } + + enum EditButtonLocation: String, AnalyticsLogEnumParametable { + case playlistDetail = "playlist_detail" + case myPlaylist = "my_playlist" + case storageLike = "storage_like" + case playlist + } + + enum LoginButtonEntry: String, AnalyticsLogEnumParametable { + case myPlaylist = "my_playlist" + case storageLike = "storage_like" + case mypage + case fruitStorage = "fruit_storage" + case fruitDraw = "fruit_draw" + case songLike = "song_like" + case addMusics = "add_musics" + case playlistSubscribe = "playlist_subscribe" + case artistSubscribe = "artist_subscribe" + } } diff --git a/Projects/Modules/Utility/Sources/Extensions/Extension+PreferenceManager.swift b/Projects/Modules/Utility/Sources/Extensions/Extension+PreferenceManager.swift index f90c7ed51..2737f4631 100644 --- a/Projects/Modules/Utility/Sources/Extensions/Extension+PreferenceManager.swift +++ b/Projects/Modules/Utility/Sources/Extensions/Extension+PreferenceManager.swift @@ -61,10 +61,14 @@ public extension PreferenceManager { itemCount: itemCount ) Utility.PreferenceManager.userInfo = userInfo + LogManager.setUserProperty(property: .fruitTotal(count: userInfo.itemCount)) + LogManager.setUserProperty(property: .loginPlatform(platform: userInfo.platform)) } static func clearUserInfo() { LogManager.setUserID(userID: nil) PreferenceManager.userInfo = nil + LogManager.clearUserProperty(property: .fruitTotal(count: -1)) + LogManager.clearUserProperty(property: .loginPlatform(platform: "")) } }