Skip to content

Commit

Permalink
Merge pull request #240 from Team-Smeme/feat/#239-amplitude
Browse files Browse the repository at this point in the history
[Feat] #239 - Coahing, Detail Diary Amplitude 연결
  • Loading branch information
cchanmi authored Dec 12, 2024
2 parents dae00ac + 8ad8e0f commit 537cc7c
Show file tree
Hide file tree
Showing 15 changed files with 151 additions and 91 deletions.
70 changes: 22 additions & 48 deletions Smeem-iOS/Smeem-iOS.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

38 changes: 35 additions & 3 deletions Smeem-iOS/Smeem-iOS/Global/Constants/AmplitudeConstant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,24 @@ enum AmplitudeConstant {
}

enum diaryDetail {
case toggle_click(String)
case mydiary_click
case mydiary_edit
case mydiary_view(Bool)
case mydiary_edit(Bool)
case mydiary_edit_complete_click(Bool)

var event: BaseEvent {
switch self {
case .toggle_click(let toggle):
return BaseEvent(eventType: "toggle_click", eventProperties: ["toggle": toggle])
case .mydiary_click:
return BaseEvent(eventType: "mydiary_click", eventProperties: nil)
case .mydiary_edit:
return BaseEvent(eventType: "mydiary_edit", eventProperties: nil)
case .mydiary_view(let hasCoaching):
return BaseEvent(eventType: "mydiary_view", eventProperties: ["has_coaching": hasCoaching])
case .mydiary_edit(let hasCoaching):
return BaseEvent(eventType: "mydiary_edit", eventProperties: ["has_coaching": hasCoaching])
case .mydiary_edit_complete_click(let hasCoaching):
return BaseEvent(eventType: "mydiary_edit_complete_click", eventProperties: ["has_coaching": hasCoaching])
}
}
}
Expand Down Expand Up @@ -175,4 +184,27 @@ enum AmplitudeConstant {
}
}
}

enum coaching {
case coaching_try_click(Bool)
case coaching_exit_click(Bool)
case coaching_load_view
case coaching_result_view
case coaching_feedback_view(Int)

var event: BaseEvent {
switch self {
case .coaching_try_click(let isActive):
return BaseEvent(eventType: "coaching_try_click", eventProperties: ["active": isActive])
case .coaching_exit_click(let isActive):
return BaseEvent(eventType: "coaching_exit_click", eventProperties: ["active": isActive])
case .coaching_load_view:
return BaseEvent(eventType: "coaching_load_view", eventProperties: nil)
case .coaching_result_view:
return BaseEvent(eventType: "coaching_result_view", eventProperties: nil)
case .coaching_feedback_view(let index):
return BaseEvent(eventType: "badge_bottom_sheet_view", eventProperties: ["Index": index])
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct SegmentButton: View {
.foregroundColor(foregroundColor)
.font(Font(UIFont.c5))
// .lineLimit(1)
// .minimumScaleFactor(0.9)
.minimumScaleFactor(0.9)
.overlay(
Group {
if isSelected && isFirstButton {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ extension DetailDiaryEndPoint {
"content": "일기 내용입니다",
"createdAt": "2024년 5월 18일",
"username": "찬미",
"isUpdated": true,
"corrections": [
{
"originalSentence": "original text",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ struct DetailDiaryResponse: Codable, Equatable {
}
}

//struct CorrentionsData: Codable {
// let correntionId: Int
// let before: String
// let after: String
//}

extension DetailDiaryResponse {
static let empty = DetailDiaryResponse(diaryId: 0, topic: "", content: "테스트임?", createdAt: "그래", username: "그래", isUpdated: true, corrections: [CoachingResponse(originalSentence: "I have went to the park yesterdayI have went to the park yesterdayI have went to the park yesterdayI have went to the park yesterday",
correctedSentence: "I went to the park yesterdayI went to the park yesterdayI went to the park yesterdayI went to the park yesterdayI went to the park yesterday",
Expand All @@ -37,17 +31,3 @@ extension DetailDiaryResponse {
reason: "이러 이러한 이유로 이건 맞습니다",
isCorrected: true)], correctionCount: 0, correctionMaxCount: 0)
}

//struct CoachingResponse: Codable, Equatable {
// let originalSentence: String
// let correctedSentence: String
// let reason: String
// let isCorrected: Bool
//
// enum CodingKeys: String, CodingKey {
// case originalSentence = "originalSentence"
// case correctedSentence = "correctedSentence"
// case reason
// case isCorrected = "isCorrected"
// }
//}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import SwiftUI
struct CoachingCompleteView: View {

@Binding var coachingAppData: CoachingAppData
@State var currentIndex = 0

var body: some View {

Expand All @@ -31,7 +30,7 @@ struct CoachingCompleteView: View {
.modifier(HighlightModifier(
diaryText: coachingAppData.diaryText,
corrections: coachingAppData.corrections,
highlightIndex: currentIndex
highlightIndex: coachingAppData.currentIndex
))
.font(Font.custom("Pretendard", size: 16))
.foregroundColor(coachingAppData.corrections.isEmpty
Expand All @@ -54,7 +53,7 @@ struct CoachingCompleteView: View {
Rectangle()
.frame(height: 8)
.foregroundStyle(Color(UIColor.gray100))
TabView(selection: $currentIndex) {
TabView(selection: $coachingAppData.currentIndex) {
ForEach(coachingAppData.corrections.indices, id: \.self) { item in
ScrollView {
VStack(spacing: 8) {
Expand All @@ -68,7 +67,7 @@ struct CoachingCompleteView: View {
.frame(width: screenWidth, height: screenHeight * (326/screenHeight), alignment: .top)
.tabViewStyle(.page(indexDisplayMode: .never))

PageControl(currentPage: $currentIndex,
PageControl(currentPage: $coachingAppData.currentIndex,
coachingResponse: $coachingAppData.corrections)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,20 @@
import Foundation

struct CoachingAppData {
var currentIndex: Int
var diaryText: String
var corrections: [CoachingResponse]
var correctResultText: String
}

enum CoachingAmplitude {
case coachingButtonTapped(Bool)
case exitButtonTapped(Bool)
case coachingLoading
case coachingResult
case coachingSwipe(Int)
}

final class CoachingStore: Store, ObservableObject {

var service: CoachingServiceProtocol
Expand All @@ -27,11 +36,13 @@ final class CoachingStore: Store, ObservableObject {
enum Action {
case detailDiaryAPI(diaryID: Int)
case coachingButton(diaryID: Int)
case amplitudeInput(type: CoachingAmplitude)
}

struct State {
var detailDiaryResponse = DetailDiaryResponse.empty
var coachingAppData = CoachingAppData(diaryText: "",
var coachingAppData = CoachingAppData(currentIndex: 0,
diaryText: "",
corrections: CoachingsResponse.sample.corrections,
correctResultText: "첨삭 중이에요")
var toastErrorMessage: SmeemError? = nil
Expand Down Expand Up @@ -63,7 +74,8 @@ final class CoachingStore: Store, ObservableObject {
do {
state.hiddenIndex += 1
let coachingResponse = try await service.coachingPostAPI(diaryID: ID)
state.coachingAppData = CoachingAppData(diaryText: combineCorrectionText(coachingResponse.corrections),
state.coachingAppData = CoachingAppData(currentIndex: 0,
diaryText: combineCorrectionText(coachingResponse.corrections),
corrections: filiterCorrection(coachingResponse.corrections) ?? [],
correctResultText: correctTextResult(filiterCorrection(coachingResponse.corrections) ?? []))
state.hiddenIndex += 1
Expand All @@ -73,6 +85,19 @@ final class CoachingStore: Store, ObservableObject {
state.hiddenIndex = 0
}
}
case .amplitudeInput(let type):
switch type {
case .coachingButtonTapped(let isActive):
AmplitudeManager.shared.track(event: AmplitudeConstant.coaching.coaching_try_click(isActive).event)
case .exitButtonTapped(let isActive):
AmplitudeManager.shared.track(event: AmplitudeConstant.coaching.coaching_exit_click(isActive).event)
case .coachingLoading:
AmplitudeManager.shared.track(event: AmplitudeConstant.coaching.coaching_load_view.event)
case .coachingResult:
AmplitudeManager.shared.track(event: AmplitudeConstant.coaching.coaching_result_view.event)
case .coachingSwipe(let index):
AmplitudeManager.shared.track(event: AmplitudeConstant.coaching.coaching_feedback_view(index+1).event)
}
}
}

Expand Down
12 changes: 12 additions & 0 deletions Smeem-iOS/Smeem-iOS/Presentation/Coaching/View/CoachingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct CoachingView: View {
HStack() {
Spacer()
Button(action: {
store.send(action: .amplitudeInput(type: .exitButtonTapped(store.state.isEnabled)))
let homeVC = HomeViewController()
homeVC.handlePostDiaryAPI(with: store.state.diaryResponse)
changeRootViewController(homeVC)
Expand All @@ -37,6 +38,7 @@ struct CoachingView: View {
Button(action: {
if store.state.isEnabled {
store.send(action: .coachingButton(diaryID: store.state.diaryResponse.diaryID))
store.send(action: .amplitudeInput(type: .coachingButtonTapped(store.state.isEnabled)))
}
}) {
HStack {
Expand Down Expand Up @@ -77,6 +79,9 @@ struct CoachingView: View {
LottieView("smeemLoading")
.loopMode(.loop)
.frame(width: screenWidth, height: 164, alignment: .center)
.onAppear {
store.send(action: .amplitudeInput(type: .coachingLoading))
}

Text("AI 코치가 내 일기를 분석하고 있어요\n잠시만 기다려주세요")
.font(Font.custom("Pretendard", size: 16))
Expand All @@ -87,6 +92,13 @@ struct CoachingView: View {
// MARK: 첨삭 화면
} else {
CoachingCompleteView(coachingAppData: $store.state.coachingAppData)
.onAppear {
store.send(action: .amplitudeInput(type: .coachingResult))
store.send(action: .amplitudeInput(type: .coachingSwipe(1)))
}
.onChange(of: store.state.coachingAppData.currentIndex) { index in
store.send(action: .amplitudeInput(type: .coachingSwipe(index)))
}
}

// MARK: 첫 진입시 토스트뷰 실행
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ struct DetailDiaryCoachedView: View {

@State private var toastErrorMessage: SmeemError? = nil
var toastMessage: SmeemToast? = .completed
var hasCorrections: Bool {
return !(response?.corrections.isEmpty ?? true)
}
@Environment(\.dismiss) private var dismiss

private let detailDiaryService = DetailDiaryService.shared
Expand Down Expand Up @@ -67,6 +70,9 @@ struct DetailDiaryCoachedView: View {
navigateToEditDiary()
}
}
.onTapGesture {
AmplitudeManager.shared.track(event: AmplitudeConstant.diaryDetail.mydiary_edit(hasCorrections).event)
}

Button("삭제하기", role: .destructive) {
deleteDiaryWithAPI(diaryID: diaryID ?? 0)
Expand Down Expand Up @@ -115,10 +121,15 @@ struct DetailDiaryCoachedView: View {
}
}
.onAppear {
AmplitudeManager.shared.track(event: AmplitudeConstant.diaryDetail.mydiary_view(hasCorrections).event)
Task {
await fetchCoachingData(diaryID: diaryID ?? 0)
}
}
.onChange(of: selectedIndex) { newValue in
AmplitudeManager.shared.track(event: AmplitudeConstant.diaryDetail.toggle_click(convertSelectedIndexToString(newValue)).event
)
}
.overlay {
if isLoading {
SmemeEmptyView()
Expand Down Expand Up @@ -154,10 +165,15 @@ extension DetailDiaryCoachedView {
editVC.diaryID = self.diaryID ?? 0
editVC.randomContent = self.randomTopic
editVC.diaryTextView.text = self.diaryContent
editVC.hasCoached = self.hasCorrections
editVC.randomSubjectView.setData(contentText: self.randomTopic)
self.pushToUIKitView(editVC)
}

private func convertSelectedIndexToString(_ index: Int) -> String {
return index == 0 ? "코칭 OFF" : "코칭 ON"
}

@MainActor
private func fetchCoachingData(diaryID: Int) async {
isLoading = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ extension DetailDiaryViewController {
@objc func showActionSheet() {
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let modifyAction = UIAlertAction (title: "수정", style: .default, handler: { (action) in
AmplitudeManager.shared.track(event: AmplitudeConstant.diaryDetail.mydiary_edit.event)
let editVC = EditDiaryViewController()
editVC.diaryID = self.diaryId
editVC.randomContent = self.isRandomTopic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ final class EditDiaryViewController: BaseViewController {

var diaryID = Int()
var randomContent = String()
var hasCoached = Bool()

// MARK: - UI Property

Expand Down Expand Up @@ -169,6 +170,7 @@ extension EditDiaryViewController {
func patchDiaryAPI() {
PostDiaryAPI.shared.patchDiary(param: PatchDiaryRequest(content: diaryTextView.text), diaryID: diaryID) { response in
DispatchQueue.main.async {
AmplitudeConstant.diaryDetail.mydiary_edit_complete_click(self.hasCoached).event
self.changeRootViewControllerAndPresent(HomeViewController())
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Combine

final class SplashViewModel: ViewModel {

private let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String

struct Input {
let checkUpdatePopup: PassthroughSubject<Void, Never>
Expand Down Expand Up @@ -52,7 +52,6 @@ final class SplashViewModel: ViewModel {
switch result {
case .success(let response):
if self.checkVersion(client: self.appVersion,
now: response.iosVersion.version,
force: response.iosVersion.forceVersion) {

promise(.success(UpdateTextModel(title: response.title,
Expand Down Expand Up @@ -133,7 +132,24 @@ final class SplashViewModel: ViewModel {
}

extension SplashViewModel {
func checkVersion(client: String, now: String, force: String) -> Bool {
func checkVersion(client: String, force: String) -> Bool {
let clientVersion = client.split(separator: ".").map{$0}
let forceVersion = force.split(separator: ".").map{$0}

// x 버전이 더 크면 강제 업데이트
if forceVersion[0] > clientVersion[0] {
return true
// x 버전이 같고, y 버전이 더 크면 강제 업데이트
} else if forceVersion[0] == clientVersion[0] && forceVersion[1] > clientVersion[1] {
return true
// x, y 버전이 같고, z버전이 더 크면 강제 업데이트
} else if (forceVersion[0] == clientVersion[0] && forceVersion[1] > clientVersion[1]) && forceVersion[2] > clientVersion[2] {
return true
}
return false
}

func checkVersion2(client: String, now: String, force: String) -> Bool {
let clientVersion = client.split(separator: ".").map{$0}
let nowVersion = now.split(separator: ".").map{$0}
let forceVersion = force.split(separator: ".").map{$0}
Expand All @@ -147,5 +163,6 @@ extension SplashViewModel {
return false
}
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ extension CoachingServiceTest {
content: "일기 내용입니다",
createdAt: "2024년 5월 18일",
username: "찬미",
isUpdated: true,
corrections: [CoachingResponse(originalSentence: "original text",
correctedSentence: "corrected text",
reason: "수정된 문구입니다.",
Expand Down
Loading

0 comments on commit 537cc7c

Please sign in to comment.