diff --git a/ByeBoo-iOS/ByeBoo-iOS.xcodeproj/project.pbxproj b/ByeBoo-iOS/ByeBoo-iOS.xcodeproj/project.pbxproj index de2d12b6..cebb8afe 100644 --- a/ByeBoo-iOS/ByeBoo-iOS.xcodeproj/project.pbxproj +++ b/ByeBoo-iOS/ByeBoo-iOS.xcodeproj/project.pbxproj @@ -328,7 +328,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.3.0; + MARKETING_VERSION = 1.2.4; PRODUCT_BUNDLE_IDENTIFIER = "com.heartz.ByeBoo-iOS"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -352,7 +352,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = "ByeBoo-iOS/ByeBoo-Prod.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 18; DEVELOPMENT_TEAM = ""; @@ -371,11 +371,11 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.3.0; + MARKETING_VERSION = 1.2.4; PRODUCT_BUNDLE_IDENTIFIER = "com.heartz.ByeBoo-iOS"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.heartz.ByeBoo-iOS"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.heartz.ByeBoo-iOS"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Home/ViewController/NotificationsViewController.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Home/ViewController/NotificationsViewController.swift index e4281a55..dff7321c 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Home/ViewController/NotificationsViewController.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Home/ViewController/NotificationsViewController.swift @@ -8,6 +8,8 @@ import Combine import UIKit +import Mixpanel + final class NotificationsViewController: BaseViewController { private let rootView = NoticesView() @@ -30,6 +32,8 @@ final class NotificationsViewController: BaseViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) viewModel.action(.viewWillAppear) + + Mixpanel.mainInstance().track(event: AlarmEvents.Name.alarmMain) } override func viewDidLoad() { diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestHistoryViewController.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestHistoryViewController.swift index aa56c93d..6fbe4710 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestHistoryViewController.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestHistoryViewController.swift @@ -270,7 +270,7 @@ extension CommonQuestHistoryViewController { rootView.configure( answerID: answerID, question: entity.question, - writtenAt: ServerDateFormatter.shared.relativeTimeString(from: answer.writtenAt) ?? "", //TODO: ViewModel로 수정 + writtenAt: ServerDateFormatter.shared.relativeTimeString(from: answer.writtenAt) ?? "", profileIcon: ProfileIcon.image(for: answer.profileIcon) ?? .relievedBadge, nickname: answer.writer, content: answer.content, @@ -303,6 +303,10 @@ extension CommonQuestHistoryViewController { case .success(let result): let entity = result.entity self?.rootView.questContentView.updateUI(likeCount: entity.likeCount, isLiked: entity.isLiked) + + if entity.isLiked { + Mixpanel.mainInstance().track(event: CommonJourneyEvents.Name.commonJourneyLike) + } case .failure(let error): ByeBooLogger.error(error) } @@ -319,6 +323,8 @@ extension CommonQuestHistoryViewController { case .success: ByeBooLogger.debug("댓글 입력 성공") self.scrollToComment() + + Mixpanel.mainInstance().track(event: CommonJourneyEvents.Name.commonJourneyComment) case .failure(let error): ByeBooLogger.debug(error) } diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestMyAnswersViewController.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestMyAnswersViewController.swift index 67697919..a14ef3d8 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestMyAnswersViewController.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestMyAnswersViewController.swift @@ -8,6 +8,8 @@ import Combine import UIKit +import Mixpanel + final class CommonQuestMyAnswersViewController: BaseViewController { private let rootView = CommonQuestMyAnswersView() @@ -112,6 +114,10 @@ extension CommonQuestMyAnswersViewController { likeCount: entity.likeCount, isLiked: entity.isLiked ) + + if entity.isLiked { + Mixpanel.mainInstance().track(event: CommonJourneyEvents.Name.commonJourneyLike) + } case .failure(let error): ByeBooLogger.error(error) } diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestReplyViewController.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestReplyViewController.swift index f852d994..991471e9 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestReplyViewController.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestReplyViewController.swift @@ -8,6 +8,8 @@ import Combine import UIKit +import Mixpanel + final class CommonQuestReplyViewController: BaseViewController { private let rootView = CommonQuestReplyView() @@ -106,6 +108,8 @@ extension CommonQuestReplyViewController { case .success: ByeBooLogger.debug("답글 입력 성공") self.scrollToComment() + + Mixpanel.mainInstance().track(event: CommonJourneyEvents.Name.commonJourneyComment) case .failure(let error): ByeBooLogger.debug(error) } diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestViewController.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestViewController.swift index 5c322839..3c450872 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestViewController.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestViewController.swift @@ -94,6 +94,10 @@ extension CommonQuestViewController { case .success(let result): let entity = result.entity self?.updateLikeCount(answerID: result.answerID, likeCount: entity.likeCount, isLiked: entity.isLiked) + + if entity.isLiked { + Mixpanel.mainInstance().track(event: CommonJourneyEvents.Name.commonJourneyLike) + } case .failure(let error): ByeBooLogger.error(error) } diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Mixpanel/AlarmEvents.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Mixpanel/AlarmEvents.swift new file mode 100644 index 00000000..8f98f554 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Mixpanel/AlarmEvents.swift @@ -0,0 +1,14 @@ +// +// AlarmEvents.swift +// ByeBoo-iOS +// +// Created by 이나연 on 8/18/26. +// + +import Mixpanel + +struct AlarmEvents { + enum Name { + static let alarmMain = "alarm_main" + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Mixpanel/CommonJourneyEvents.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Mixpanel/CommonJourneyEvents.swift index c58985cf..fc6e0445 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Mixpanel/CommonJourneyEvents.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Mixpanel/CommonJourneyEvents.swift @@ -13,5 +13,7 @@ struct CommonJourneyEvents { static let commonJourneyWriteClick = "common_journey_write_click" static let commonJourneyWriteSuccess = "common_journey_write_success" static let commonJourneyOthersAnswerPageview = "common_journey_others_answer_pageview" + static let commonJourneyComment = "common_journey_comment" + static let commonJourneyLike = "common_journey_like" } } diff --git a/ByeBoo-iOS/fastlane/Fastfile b/ByeBoo-iOS/fastlane/Fastfile index 339399e2..0f9ecf6f 100644 --- a/ByeBoo-iOS/fastlane/Fastfile +++ b/ByeBoo-iOS/fastlane/Fastfile @@ -22,6 +22,20 @@ XCODEPROJ = "ByeBoo-iOS.xcodeproj" SCHEME = "ByeBoo-iOS" platform :ios do + def prepare_ci_and_signing + app_store_connect_api_key( + key_id: ENV['APP_STORE_CONNECT_API_KEY_KEY_ID'], + issuer_id: ENV['APP_STORE_CONNECT_API_KEY_ISSUER_ID'], + key_content: ENV['APP_STORE_CONNECT_API_KEY_CONTENT'], + is_key_content_base64: true + ) + setup_ci + match(type: "appstore") + update_project_team( + path: XCODEPROJ, + teamid: ENV['TEAM_ID'] + ) + end def notify_discord_success(lane_name, build_number) version = get_version_number(xcodeproj: XCODEPROJ) @@ -41,21 +55,10 @@ platform :ios do ) end - def prepare_ci_and_signing - setup_ci - match(type: "appstore") - update_project_team( - path: XCODEPROJ, - teamid: ENV['TEAM_ID'] - ) - end - + # 날짜+시간 기반 빌드 번호 (예: 2026081815 -> 2026년 08월 18일 15시) + # 재배포 시에도 항상 이전보다 큰 값이 되도록 YYMMDDHM으로 사용 def next_build_number - latest_build = latest_testflight_build_number( - app_identifier: ENV['APP_IDENTIFIER'], - initial_build_number: 0 - ) - latest_build + 1 + Time.now.getlocal("+09:00").strftime("%Y%m%d%H%M").to_i # 한국시간 기준 end desc "Push a new beta build to TestFlight" @@ -103,10 +106,11 @@ platform :ios do upload_to_app_store( skip_screenshots: true, - skip_metadata: true, + skip_metadata: false, + skip_app_version_update: true, force: true, submit_for_review: true, # 자동으로 심사 제출 - automatic_release: true, # 심사 통과 후 자동 출시 + automatic_release: false, precheck_include_in_app_purchases: false, submission_information: { add_id_info_uses_idfa: false, # AdMob 추가 시 true로 변경 diff --git a/ByeBoo-iOS/fastlane/metadata/ko/release_notes.txt b/ByeBoo-iOS/fastlane/metadata/ko/release_notes.txt new file mode 100644 index 00000000..4cb41473 --- /dev/null +++ b/ByeBoo-iOS/fastlane/metadata/ko/release_notes.txt @@ -0,0 +1,2 @@ +- 공통 여정 커뮤니티에서 댓글과 좋아요를 남기며 이별의 아픔을 공유하고, 서로 위로할 수 있어요! +- 메인페이지에 알림함이 추가됐어요! 이제 보리를 더 자주 만날 수 있어요!