diff --git a/Projects/Core/PPACAnalytics/Sources/PPACAnalytics.swift b/Projects/Core/PPACAnalytics/Sources/PPACAnalytics.swift index efadd16..183be39 100644 --- a/Projects/Core/PPACAnalytics/Sources/PPACAnalytics.swift +++ b/Projects/Core/PPACAnalytics/Sources/PPACAnalytics.swift @@ -27,6 +27,7 @@ final public class PPACAnalytics { case searchDetail = "search_detail" case myPage = "my_page" case settings + case uploadMeme = "upload_meme" } public enum UserEvent: String { @@ -42,6 +43,9 @@ final public class PPACAnalytics { case meme case settings case appUpdate = "app_update" + case back + case upload + case tab } private init() { diff --git a/Projects/Core/PPACData/Sources/Endpoint/MemeEditEndPoint.swift b/Projects/Core/PPACData/Sources/Endpoint/MemeEditEndPoint.swift index 8fe7859..5ff6990 100644 --- a/Projects/Core/PPACData/Sources/Endpoint/MemeEditEndPoint.swift +++ b/Projects/Core/PPACData/Sources/Endpoint/MemeEditEndPoint.swift @@ -22,7 +22,7 @@ enum MemeEditEndPoint: MultipartRequestable { var path: String? { switch self { case .registerMeme: - return "meme" + return "/meme" } } diff --git a/Projects/Core/PPACNetwork/Sources/Requestable.swift b/Projects/Core/PPACNetwork/Sources/Requestable.swift index af8acbc..90f7592 100644 --- a/Projects/Core/PPACNetwork/Sources/Requestable.swift +++ b/Projects/Core/PPACNetwork/Sources/Requestable.swift @@ -33,8 +33,8 @@ public protocol Requestable { extension Requestable { private var baseUrl: String { - return "http://ppac-server.run.goorm.io/api" // 개발 서버 - //return "https://ppac-server-goorm.run.goorm.site/api" // 운영 서버 + //return "http://ppac-server.run.goorm.io/api" // 개발 서버 + return "https://ppac-server-goorm.run.goorm.site/api" // 운영 서버 } public func makeURL() -> URL? { @@ -47,7 +47,7 @@ extension Requestable { urlRequest.httpMethod = httpMethod.rawValue.uppercased() var defaultHeaders = [ - "x-device-id": UserInfo.shared.testDeviceId, + "x-device-id": UserInfo.shared.deviceId, "accept": "application/json", "Content-Type": "application/json" ] diff --git a/Projects/Features/MemeEditor/Sources/MemeEditorView.swift b/Projects/Features/MemeEditor/Sources/MemeEditorView.swift index ed7dc02..2f5f01f 100644 --- a/Projects/Features/MemeEditor/Sources/MemeEditorView.swift +++ b/Projects/Features/MemeEditor/Sources/MemeEditorView.swift @@ -25,20 +25,18 @@ struct MemeEditorView: View { .foregroundStyle(Color.Background.assistive) .padding(.top, 50) ScrollView { - VStack { - ImageEditView( - imageUrl: viewModel.state.memeImageUrl, - onImageSelectionCompleted: { selectedImage in - viewModel.state.selectedImage = selectedImage - } - ) - memeTitleInputView - memeSourceInputView - divider - memeCategoriesTitleView - memeCategoriesView - } - .padding(.bottom, 48) + ImageEditView( + imageUrl: viewModel.state.memeImageUrl, + onImageSelectionCompleted: { selectedImage in + viewModel.state.selectedImage = selectedImage + } + ) + memeTitleInputView + memeSourceInputView + divider + memeCategoriesTitleView + memeCategoriesView + Spacer(minLength: 48) } if !viewModel.state.isVisibleKeyboard { diff --git a/Projects/Features/MemeEditor/Sources/MemeEditorViewModel.swift b/Projects/Features/MemeEditor/Sources/MemeEditorViewModel.swift index 6a7aeb7..8dd82bb 100644 --- a/Projects/Features/MemeEditor/Sources/MemeEditorViewModel.swift +++ b/Projects/Features/MemeEditor/Sources/MemeEditorViewModel.swift @@ -11,6 +11,7 @@ import PPACUtil import PPACModels import PPACDomain import PPACNetwork +import PPACAnalytics @MainActor public protocol MemeEditorRouting: AnyObject { @@ -86,15 +87,11 @@ final public class MemeEditorViewModel: ViewModelType, ObservableObject { await fetchMemeCategories() case .naviBackButtonTapped: router?.popView() + self.logUploadMeme(event: .back) case .memeKeywordTapped(let keyword): await self.updateSelectedMemeKeyword(keyword) case .registerButtonTapped: - print("===============================") - print("selectedImage = \(state.selectedImage)") - print("title = \(state.memeTitle)") - print("source = \(state.memeSource)") - print("keywords = \(state.selectedMemeKeywords)") - print("===============================") + self.logUploadMeme(event: .upload) await self.registMeme() case .alertConfirmButtonTapped: router?.popView() @@ -141,6 +138,12 @@ final public class MemeEditorViewModel: ViewModelType, ObservableObject { @MainActor private func registMeme() async { do { + print("===============================") + print("selectedImage = \(state.selectedImage)") + print("title = \(state.memeTitle)") + print("source = \(state.memeSource)") + print("keywords = \(state.selectedMemeKeywords)") + print("===============================") let imageFormData = try self.getImageFormData() self.state.needLoadingIndicator = true try await self.registerMemeUserCase @@ -181,4 +184,13 @@ final public class MemeEditorViewModel: ViewModelType, ObservableObject { self.state.contentOfPopup = text self.state.isActivePopup = true } + + private func logUploadMeme(event: PPACAnalytics.UserEvent) { + PPACAnalytics.shared + .log( + interaction: .click, + event: event, + page: .uploadMeme + ) + } } diff --git a/Projects/Features/MemeEditor/Sources/RequiredInputTextFieldView.swift b/Projects/Features/MemeEditor/Sources/RequiredInputTextFieldView.swift index 14bc7aa..ceff976 100644 --- a/Projects/Features/MemeEditor/Sources/RequiredInputTextFieldView.swift +++ b/Projects/Features/MemeEditor/Sources/RequiredInputTextFieldView.swift @@ -22,6 +22,7 @@ struct RequiredTitleView: View { .padding(.leading, -4) .padding(.bottom, 10) } + .frame(height: 20) } } @@ -37,9 +38,9 @@ struct RequiredInputTextFieldView: View { } var body: some View { - VStack(alignment: .leading) { + VStack(alignment: .leading, spacing: 0) { RequiredTitleView(title: title) - .padding(.bottom, 8) + .padding(.bottom, 12) textFieldWithTextCountView } .padding(.horizontal, 20) @@ -60,12 +61,12 @@ struct RequiredInputTextFieldView: View { .foregroundStyle(content.isEmpty ? Color.Text.assistive : Color.clear) .font(Font.Body.Large.medium) .padding(.horizontal, 16) - .padding(.top, 12) + .padding(.top, 14) TextEditor(text: $content) .scrollContentBackground(.hidden) .scrollIndicators(.hidden) .padding(.horizontal, 12) - .padding(.top, 4) + .padding(.top, 6) .font(Font.Body.Large.medium) .foregroundStyle(Color.Text.primary) .onChange(of: content) { _ , newValue in diff --git a/Projects/Features/MyPage/Sources/MyPageView.swift b/Projects/Features/MyPage/Sources/MyPageView.swift index d5b3197..15f14ee 100644 --- a/Projects/Features/MyPage/Sources/MyPageView.swift +++ b/Projects/Features/MyPage/Sources/MyPageView.swift @@ -51,19 +51,6 @@ public struct MyPageView: View { ) .padding(.horizontal, 20) .padding(.bottom, 138) -// SavedMemeListView( -// memeDetailList: $viewModel.state.currentMyMemeList, -// memeClickHandler: { meme in -// viewModel.dispatch(type: .onTappedSavedMeme(meme: meme)) -// }, -// memeCopyHandler: { meme in -// viewModel.dispatch(type: .onTappedCopyButton(meme: meme)) -// }, -// onAppearLastMemeHandler: { -// viewModel.dispatch(type: .onAppearLastMeme) -// } -// ) -// .padding(.bottom, 138) } .onAppear { viewModel.dispatch(type: .onAppearMyPageView) diff --git a/Projects/Features/MyPage/Sources/MyPageViewModel.swift b/Projects/Features/MyPage/Sources/MyPageViewModel.swift index 607e652..d326648 100644 --- a/Projects/Features/MyPage/Sources/MyPageViewModel.swift +++ b/Projects/Features/MyPage/Sources/MyPageViewModel.swift @@ -24,6 +24,7 @@ final public class MyPageViewModel: ViewModelType, ObservableObject { enum MyMemeType: String { case recentMeme = "my_recent_meme" case savedMeme = "my_saved_meme" + case uploadedMeme = "my_uploaded_meme" } enum MyPageSegmentedTitle: String { @@ -159,15 +160,14 @@ final public class MyPageViewModel: ViewModelType, ObservableObject { self.logMyPage(event: .settings) case .onTappedRecentMeme(let meme): self.router?.showMemeDetail(memeDetail: meme) - self.logMyPage(event: .meme, type: .recentMeme) + self.logMyPage(event: .meme, meme: meme, type: .recentMeme) case .onTappedSavedMeme(let meme): self.router?.showMemeDetail(memeDetail: meme) - self.logMyPage(event: .meme, type: .savedMeme) + self.logMyPageClickMeme(meme: meme) case .onTappedCopyButton(let meme): await self.copyMemeImage(with: meme) case .onTappedSegmentedTitleItem(let title): - self.updateSegmentedTitleItems(selectedTitle: title) - self.updateCurrentMyMemeList(selectedTitle: MyPageSegmentedTitle(rawValue: title)) + self.selectedSegmentedTitle(title: title) case .onAppearLastMeme: await self.fetchNextPageMemes() } @@ -275,6 +275,19 @@ final public class MyPageViewModel: ViewModelType, ObservableObject { } } + @MainActor + private func selectedSegmentedTitle(title: String) { + let segmentedTitle = MyPageSegmentedTitle(rawValue: title) + self.updateSegmentedTitleItems(selectedTitle: title) + self.updateCurrentMyMemeList(selectedTitle: segmentedTitle) + + if segmentedTitle == .myRegisteredMeme { + self.logMyPage(event: .tab, type: .uploadedMeme) + } else { + self.logMyPage(event: .tab, type: .savedMeme) + } + } + @MainActor private func updateSegmentedTitleItems(selectedTitle: String) { guard let selectedItem = self.state.segmentedTitleItems @@ -301,6 +314,14 @@ final public class MyPageViewModel: ViewModelType, ObservableObject { } } + private func logMyPageClickMeme(meme: MemeDetail?) { + if self.state.currentSegmentedTitle == .myRegisteredMeme { + self.logMyPage(event: .meme, meme: meme, type: .uploadedMeme) + } else { + self.logMyPage(event: .meme, meme: meme, type: .savedMeme) + } + } + func logMyPage( interaction: PPACAnalytics.UserInteraction = .click, event: PPACAnalytics.UserEvent, diff --git a/Projects/Features/Recommend/Sources/Presentation/RecommendViewModel.swift b/Projects/Features/Recommend/Sources/Presentation/RecommendViewModel.swift index 7226069..ba64ec4 100644 --- a/Projects/Features/Recommend/Sources/Presentation/RecommendViewModel.swift +++ b/Projects/Features/Recommend/Sources/Presentation/RecommendViewModel.swift @@ -38,7 +38,6 @@ public final class RecommendViewModel: ViewModelType, ObservableObject { var userLevel: Int var memeRecommendWatchCount: Int var isSuccessFetch: Bool - var isSuccessMemeUpload: Bool = false } weak var router: RecommendRouting? @@ -103,6 +102,7 @@ public final class RecommendViewModel: ViewModelType, ObservableObject { await saveMeme(meme: meme) case .memeUploadButtonTapped: router?.showMemeUploadView() + self.logRecommend(event: .upload) } } } @@ -110,7 +110,7 @@ public final class RecommendViewModel: ViewModelType, ObservableObject { public func logRecommend( interaction: PPACAnalytics.UserInteraction = .click, event: PPACAnalytics.UserEvent, - meme: MemeDetail? + meme: MemeDetail? = nil ) { PPACAnalytics.shared .log( diff --git a/Tuist/Package.resolved b/Tuist/Package.resolved index 617030d..aea908d 100644 --- a/Tuist/Package.resolved +++ b/Tuist/Package.resolved @@ -9,15 +9,6 @@ "version" : "1.2024011602.0" } }, - { - "identity" : "alamofire", - "kind" : "remoteSourceControl", - "location" : "https://github.com/Alamofire/Alamofire.git", - "state" : { - "revision" : "f455c2975872ccd2d9c81594c658af65716e9b9a", - "version" : "5.9.1" - } - }, { "identity" : "app-check", "kind" : "remoteSourceControl",