feat(home): 홈 탭 shell을 연결한다
This commit is contained in:
@@ -195,11 +195,24 @@
|
|||||||
401A3FA02FEEAFA000A5BBA3 /* FollowRecommendedCreatorsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F962FEEAFA000A5BBA3 /* FollowRecommendedCreatorsRequest.swift */; };
|
401A3FA02FEEAFA000A5BBA3 /* FollowRecommendedCreatorsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F962FEEAFA000A5BBA3 /* FollowRecommendedCreatorsRequest.swift */; };
|
||||||
401A3FA12FEEAFA000A5BBA3 /* MainHomeRecommendationRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F9B2FEEAFA000A5BBA3 /* MainHomeRecommendationRepository.swift */; };
|
401A3FA12FEEAFA000A5BBA3 /* MainHomeRecommendationRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F9B2FEEAFA000A5BBA3 /* MainHomeRecommendationRepository.swift */; };
|
||||||
401A3FA22FEEAFA000A5BBA3 /* RecommendedActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F982FEEAFA000A5BBA3 /* RecommendedActivityType.swift */; };
|
401A3FA22FEEAFA000A5BBA3 /* RecommendedActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F982FEEAFA000A5BBA3 /* RecommendedActivityType.swift */; };
|
||||||
|
401A3FBA2FEEAFA000A5BBA3 /* MainHomeRecommendationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76506E56D017236824FE9B8F /* MainHomeRecommendationViewModel.swift */; };
|
||||||
|
401A3FA82FEEAFA000A5BBA3 /* MainHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3FB42FEEAFA000A5BBA3 /* MainHomeView.swift */; };
|
||||||
|
401A3FA92FEEAFA000A5BBA3 /* MainHomeRecommendationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3FB52FEEAFA000A5BBA3 /* MainHomeRecommendationView.swift */; };
|
||||||
|
401A3FAA2FEEAFA000A5BBA3 /* MainHomeRankingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3FB62FEEAFA000A5BBA3 /* MainHomeRankingView.swift */; };
|
||||||
|
401A3FAB2FEEAFA000A5BBA3 /* MainHomeFollowingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3FB72FEEAFA000A5BBA3 /* MainHomeFollowingView.swift */; };
|
||||||
401A3FA32FEEAFA000A5BBA3 /* MainHomeRecommendationApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F9A2FEEAFA000A5BBA3 /* MainHomeRecommendationApi.swift */; };
|
401A3FA32FEEAFA000A5BBA3 /* MainHomeRecommendationApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F9A2FEEAFA000A5BBA3 /* MainHomeRecommendationApi.swift */; };
|
||||||
401A3FA42FEEAFA000A5BBA3 /* MainHomeRecommendationResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F972FEEAFA000A5BBA3 /* MainHomeRecommendationResponse.swift */; };
|
401A3FA42FEEAFA000A5BBA3 /* MainHomeRecommendationResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F972FEEAFA000A5BBA3 /* MainHomeRecommendationResponse.swift */; };
|
||||||
401A3FA52FEEAFA000A5BBA3 /* FollowRecommendedCreatorsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F962FEEAFA000A5BBA3 /* FollowRecommendedCreatorsRequest.swift */; };
|
401A3FA52FEEAFA000A5BBA3 /* FollowRecommendedCreatorsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F962FEEAFA000A5BBA3 /* FollowRecommendedCreatorsRequest.swift */; };
|
||||||
401A3FA62FEEAFA000A5BBA3 /* MainHomeRecommendationRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F9B2FEEAFA000A5BBA3 /* MainHomeRecommendationRepository.swift */; };
|
401A3FA62FEEAFA000A5BBA3 /* MainHomeRecommendationRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F9B2FEEAFA000A5BBA3 /* MainHomeRecommendationRepository.swift */; };
|
||||||
401A3FA72FEEAFA000A5BBA3 /* RecommendedActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F982FEEAFA000A5BBA3 /* RecommendedActivityType.swift */; };
|
401A3FA72FEEAFA000A5BBA3 /* RecommendedActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3F982FEEAFA000A5BBA3 /* RecommendedActivityType.swift */; };
|
||||||
|
401A3FAC2FEEAFA000A5BBA3 /* MainHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3FB42FEEAFA000A5BBA3 /* MainHomeView.swift */; };
|
||||||
|
401A3FAD2FEEAFA000A5BBA3 /* MainHomeRecommendationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3FB52FEEAFA000A5BBA3 /* MainHomeRecommendationView.swift */; };
|
||||||
|
401A3FAE2FEEAFA000A5BBA3 /* MainHomeRankingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3FB62FEEAFA000A5BBA3 /* MainHomeRankingView.swift */; };
|
||||||
|
401A3FAF2FEEAFA000A5BBA3 /* MainHomeFollowingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3FB72FEEAFA000A5BBA3 /* MainHomeFollowingView.swift */; };
|
||||||
|
401A3FB02FEEAFA000A5BBA3 /* MainHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3FB42FEEAFA000A5BBA3 /* MainHomeView.swift */; };
|
||||||
|
401A3FB12FEEAFA000A5BBA3 /* MainHomeRecommendationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3FB52FEEAFA000A5BBA3 /* MainHomeRecommendationView.swift */; };
|
||||||
|
401A3FB22FEEAFA000A5BBA3 /* MainHomeRankingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3FB62FEEAFA000A5BBA3 /* MainHomeRankingView.swift */; };
|
||||||
|
401A3FB32FEEAFA000A5BBA3 /* MainHomeFollowingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A3FB72FEEAFA000A5BBA3 /* MainHomeFollowingView.swift */; };
|
||||||
40235DED2E3797EB00B09A87 /* RecentContent+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40235DEC2E3797EB00B09A87 /* RecentContent+CoreDataClass.swift */; };
|
40235DED2E3797EB00B09A87 /* RecentContent+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40235DEC2E3797EB00B09A87 /* RecentContent+CoreDataClass.swift */; };
|
||||||
40235DEE2E3797EB00B09A87 /* RecentContent+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40235DEC2E3797EB00B09A87 /* RecentContent+CoreDataClass.swift */; };
|
40235DEE2E3797EB00B09A87 /* RecentContent+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40235DEC2E3797EB00B09A87 /* RecentContent+CoreDataClass.swift */; };
|
||||||
40235DF02E37983D00B09A87 /* PersistenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40235DEF2E37983D00B09A87 /* PersistenceController.swift */; };
|
40235DF02E37983D00B09A87 /* PersistenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40235DEF2E37983D00B09A87 /* PersistenceController.swift */; };
|
||||||
@@ -1565,7 +1578,7 @@
|
|||||||
A376733CDBF21EBAF81C8BE2 /* SocialLoginRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D0050039EBD24D2FF6D0BD0 /* SocialLoginRequest.swift */; };
|
A376733CDBF21EBAF81C8BE2 /* SocialLoginRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D0050039EBD24D2FF6D0BD0 /* SocialLoginRequest.swift */; };
|
||||||
A3BDD0D3E14CD72B022AF6A7 /* FollowButtonImageAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC033E531A9420363D017CE /* FollowButtonImageAsset.swift */; };
|
A3BDD0D3E14CD72B022AF6A7 /* FollowButtonImageAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC033E531A9420363D017CE /* FollowButtonImageAsset.swift */; };
|
||||||
A3EB81FD727C63FE034048B9 /* Spacing.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6B18C00DE256DCC53030630 /* Spacing.swift */; };
|
A3EB81FD727C63FE034048B9 /* Spacing.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6B18C00DE256DCC53030630 /* Spacing.swift */; };
|
||||||
A4EB669DFFFB64681E045EF3 /* MainHomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76506E56D017236824FE9B8F /* MainHomeViewModel.swift */; };
|
A4EB669DFFFB64681E045EF3 /* MainHomeRecommendationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76506E56D017236824FE9B8F /* MainHomeRecommendationViewModel.swift */; };
|
||||||
A840136779D6CC95F94CB681 /* HomeTitleBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA81E8424A575A0F8546D31 /* HomeTitleBar.swift */; };
|
A840136779D6CC95F94CB681 /* HomeTitleBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAA81E8424A575A0F8546D31 /* HomeTitleBar.swift */; };
|
||||||
ACD71056E97E13E48941ABBB /* MainPlaceholderTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7900EA9FD1150BABE64CF1B3 /* MainPlaceholderTabView.swift */; };
|
ACD71056E97E13E48941ABBB /* MainPlaceholderTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7900EA9FD1150BABE64CF1B3 /* MainPlaceholderTabView.swift */; };
|
||||||
AD6424211AA898794BBE8470 /* SectionTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D16C12DFB83FE164B38CC066 /* SectionTitle.swift */; };
|
AD6424211AA898794BBE8470 /* SectionTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D16C12DFB83FE164B38CC066 /* SectionTitle.swift */; };
|
||||||
@@ -1573,7 +1586,7 @@
|
|||||||
B11681AC02BF51C6E2FA6FF3 /* MainTabBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F49E8BB9BACFCA8878B70D /* MainTabBarButton.swift */; };
|
B11681AC02BF51C6E2FA6FF3 /* MainTabBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F49E8BB9BACFCA8878B70D /* MainTabBarButton.swift */; };
|
||||||
B3AF650899B8FC84E0C0CDA0 /* MainPlaceholderTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7900EA9FD1150BABE64CF1B3 /* MainPlaceholderTabView.swift */; };
|
B3AF650899B8FC84E0C0CDA0 /* MainPlaceholderTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7900EA9FD1150BABE64CF1B3 /* MainPlaceholderTabView.swift */; };
|
||||||
B5E9FA82CF4238F640702D4A /* CreatorDetailDialogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7406AE69F7667FAA2E6DD23 /* CreatorDetailDialogView.swift */; };
|
B5E9FA82CF4238F640702D4A /* CreatorDetailDialogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7406AE69F7667FAA2E6DD23 /* CreatorDetailDialogView.swift */; };
|
||||||
BA2B76FDCAF81D15E2D4E258 /* MainHomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76506E56D017236824FE9B8F /* MainHomeViewModel.swift */; };
|
BA2B76FDCAF81D15E2D4E258 /* MainHomeRecommendationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76506E56D017236824FE9B8F /* MainHomeRecommendationViewModel.swift */; };
|
||||||
BA511503C1E037162697D771 /* DonationRankingPeriod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44A42B63A1021DD9F8AA3F30 /* DonationRankingPeriod.swift */; };
|
BA511503C1E037162697D771 /* DonationRankingPeriod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44A42B63A1021DD9F8AA3F30 /* DonationRankingPeriod.swift */; };
|
||||||
BCA6CD9E57528C5F4203F1A5 /* CapsuleTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74990A0798E64A97237DD113 /* CapsuleTabBar.swift */; };
|
BCA6CD9E57528C5F4203F1A5 /* CapsuleTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74990A0798E64A97237DD113 /* CapsuleTabBar.swift */; };
|
||||||
BEAAA523CAD3198065A557BC /* EntityInfo-SodaLive-dev.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0ED95AC08C6481751AE9D97 /* EntityInfo-SodaLive-dev.generated.swift */; };
|
BEAAA523CAD3198065A557BC /* EntityInfo-SodaLive-dev.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0ED95AC08C6481751AE9D97 /* EntityInfo-SodaLive-dev.generated.swift */; };
|
||||||
@@ -1709,6 +1722,10 @@
|
|||||||
401A3F982FEEAFA000A5BBA3 /* RecommendedActivityType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecommendedActivityType.swift; sourceTree = "<group>"; };
|
401A3F982FEEAFA000A5BBA3 /* RecommendedActivityType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecommendedActivityType.swift; sourceTree = "<group>"; };
|
||||||
401A3F9A2FEEAFA000A5BBA3 /* MainHomeRecommendationApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainHomeRecommendationApi.swift; sourceTree = "<group>"; };
|
401A3F9A2FEEAFA000A5BBA3 /* MainHomeRecommendationApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainHomeRecommendationApi.swift; sourceTree = "<group>"; };
|
||||||
401A3F9B2FEEAFA000A5BBA3 /* MainHomeRecommendationRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainHomeRecommendationRepository.swift; sourceTree = "<group>"; };
|
401A3F9B2FEEAFA000A5BBA3 /* MainHomeRecommendationRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainHomeRecommendationRepository.swift; sourceTree = "<group>"; };
|
||||||
|
401A3FB42FEEAFA000A5BBA3 /* MainHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainHomeView.swift; sourceTree = "<group>"; };
|
||||||
|
401A3FB52FEEAFA000A5BBA3 /* MainHomeRecommendationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainHomeRecommendationView.swift; sourceTree = "<group>"; };
|
||||||
|
401A3FB62FEEAFA000A5BBA3 /* MainHomeRankingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainHomeRankingView.swift; sourceTree = "<group>"; };
|
||||||
|
401A3FB72FEEAFA000A5BBA3 /* MainHomeFollowingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainHomeFollowingView.swift; sourceTree = "<group>"; };
|
||||||
40235DEC2E3797EB00B09A87 /* RecentContent+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RecentContent+CoreDataClass.swift"; sourceTree = "<group>"; };
|
40235DEC2E3797EB00B09A87 /* RecentContent+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RecentContent+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||||
40235DEF2E37983D00B09A87 /* PersistenceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceController.swift; sourceTree = "<group>"; };
|
40235DEF2E37983D00B09A87 /* PersistenceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceController.swift; sourceTree = "<group>"; };
|
||||||
40235DF22E37987300B09A87 /* RecentContentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentContentService.swift; sourceTree = "<group>"; };
|
40235DF22E37987300B09A87 /* RecentContentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentContentService.swift; sourceTree = "<group>"; };
|
||||||
@@ -2369,7 +2386,7 @@
|
|||||||
716260E8214A329EE07CAAFA /* LanguageSettingsViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LanguageSettingsViewModel.swift; sourceTree = "<group>"; };
|
716260E8214A329EE07CAAFA /* LanguageSettingsViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LanguageSettingsViewModel.swift; sourceTree = "<group>"; };
|
||||||
72CD656CAEE376701F2B563E /* MainView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
|
72CD656CAEE376701F2B563E /* MainView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
|
||||||
74990A0798E64A97237DD113 /* CapsuleTabBar.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CapsuleTabBar.swift; sourceTree = "<group>"; };
|
74990A0798E64A97237DD113 /* CapsuleTabBar.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CapsuleTabBar.swift; sourceTree = "<group>"; };
|
||||||
76506E56D017236824FE9B8F /* MainHomeViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MainHomeViewModel.swift; sourceTree = "<group>"; };
|
76506E56D017236824FE9B8F /* MainHomeRecommendationViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MainHomeRecommendationViewModel.swift; sourceTree = "<group>"; };
|
||||||
7900EA9FD1150BABE64CF1B3 /* MainPlaceholderTabView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MainPlaceholderTabView.swift; sourceTree = "<group>"; };
|
7900EA9FD1150BABE64CF1B3 /* MainPlaceholderTabView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MainPlaceholderTabView.swift; sourceTree = "<group>"; };
|
||||||
7C21D69F717F8D80644F6AEE /* PushNotificationListView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PushNotificationListView.swift; sourceTree = "<group>"; };
|
7C21D69F717F8D80644F6AEE /* PushNotificationListView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PushNotificationListView.swift; sourceTree = "<group>"; };
|
||||||
7C22ACAC456B3BCB2D9C568D /* AcceptLanguageDebugLogger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AcceptLanguageDebugLogger.swift; sourceTree = "<group>"; };
|
7C22ACAC456B3BCB2D9C568D /* AcceptLanguageDebugLogger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AcceptLanguageDebugLogger.swift; sourceTree = "<group>"; };
|
||||||
@@ -2516,7 +2533,9 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
401A3F9D2FEEAFA000A5BBA3 /* Recommendation */,
|
401A3F9D2FEEAFA000A5BBA3 /* Recommendation */,
|
||||||
76506E56D017236824FE9B8F /* MainHomeViewModel.swift */,
|
401A3FB82FEEAFA000A5BBA3 /* Ranking */,
|
||||||
|
401A3FB92FEEAFA000A5BBA3 /* Following */,
|
||||||
|
401A3FB42FEEAFA000A5BBA3 /* MainHomeView.swift */,
|
||||||
);
|
);
|
||||||
path = Home;
|
path = Home;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -2680,10 +2699,28 @@
|
|||||||
children = (
|
children = (
|
||||||
401A3F992FEEAFA000A5BBA3 /* Models */,
|
401A3F992FEEAFA000A5BBA3 /* Models */,
|
||||||
401A3F9C2FEEAFA000A5BBA3 /* Repository */,
|
401A3F9C2FEEAFA000A5BBA3 /* Repository */,
|
||||||
|
401A3FB52FEEAFA000A5BBA3 /* MainHomeRecommendationView.swift */,
|
||||||
|
76506E56D017236824FE9B8F /* MainHomeRecommendationViewModel.swift */,
|
||||||
);
|
);
|
||||||
path = Recommendation;
|
path = Recommendation;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
401A3FB82FEEAFA000A5BBA3 /* Ranking */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
401A3FB62FEEAFA000A5BBA3 /* MainHomeRankingView.swift */,
|
||||||
|
);
|
||||||
|
path = Ranking;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
401A3FB92FEEAFA000A5BBA3 /* Following */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
401A3FB72FEEAFA000A5BBA3 /* MainHomeFollowingView.swift */,
|
||||||
|
);
|
||||||
|
path = Following;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
40235DEA2E3797B000B09A87 /* Recent */ = {
|
40235DEA2E3797B000B09A87 /* Recent */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -5274,6 +5311,11 @@
|
|||||||
401A3FA02FEEAFA000A5BBA3 /* FollowRecommendedCreatorsRequest.swift in Sources */,
|
401A3FA02FEEAFA000A5BBA3 /* FollowRecommendedCreatorsRequest.swift in Sources */,
|
||||||
401A3FA12FEEAFA000A5BBA3 /* MainHomeRecommendationRepository.swift in Sources */,
|
401A3FA12FEEAFA000A5BBA3 /* MainHomeRecommendationRepository.swift in Sources */,
|
||||||
401A3FA22FEEAFA000A5BBA3 /* RecommendedActivityType.swift in Sources */,
|
401A3FA22FEEAFA000A5BBA3 /* RecommendedActivityType.swift in Sources */,
|
||||||
|
401A3FBA2FEEAFA000A5BBA3 /* MainHomeRecommendationViewModel.swift in Sources */,
|
||||||
|
401A3FA82FEEAFA000A5BBA3 /* MainHomeView.swift in Sources */,
|
||||||
|
401A3FA92FEEAFA000A5BBA3 /* MainHomeRecommendationView.swift in Sources */,
|
||||||
|
401A3FAA2FEEAFA000A5BBA3 /* MainHomeRankingView.swift in Sources */,
|
||||||
|
401A3FAB2FEEAFA000A5BBA3 /* MainHomeFollowingView.swift in Sources */,
|
||||||
409143302A85652F00EEBFB1 /* CanChargeView.swift in Sources */,
|
409143302A85652F00EEBFB1 /* CanChargeView.swift in Sources */,
|
||||||
40975CA32B572298004E2F1B /* LiveRoomOverlayStrokeTextButton.swift in Sources */,
|
40975CA32B572298004E2F1B /* LiveRoomOverlayStrokeTextButton.swift in Sources */,
|
||||||
40235DED2E3797EB00B09A87 /* RecentContent+CoreDataClass.swift in Sources */,
|
40235DED2E3797EB00B09A87 /* RecentContent+CoreDataClass.swift in Sources */,
|
||||||
@@ -6015,7 +6057,11 @@
|
|||||||
AD6424211AA898794BBE8470 /* SectionTitle.swift in Sources */,
|
AD6424211AA898794BBE8470 /* SectionTitle.swift in Sources */,
|
||||||
38D73A7B6BFB9A984834984B /* TextTabBar.swift in Sources */,
|
38D73A7B6BFB9A984834984B /* TextTabBar.swift in Sources */,
|
||||||
372837FE9857C16B6B5087FF /* TitleBar.swift in Sources */,
|
372837FE9857C16B6B5087FF /* TitleBar.swift in Sources */,
|
||||||
BA2B76FDCAF81D15E2D4E258 /* MainHomeViewModel.swift in Sources */,
|
BA2B76FDCAF81D15E2D4E258 /* MainHomeRecommendationViewModel.swift in Sources */,
|
||||||
|
401A3FAC2FEEAFA000A5BBA3 /* MainHomeView.swift in Sources */,
|
||||||
|
401A3FAD2FEEAFA000A5BBA3 /* MainHomeRecommendationView.swift in Sources */,
|
||||||
|
401A3FAE2FEEAFA000A5BBA3 /* MainHomeRankingView.swift in Sources */,
|
||||||
|
401A3FAF2FEEAFA000A5BBA3 /* MainHomeFollowingView.swift in Sources */,
|
||||||
B3AF650899B8FC84E0C0CDA0 /* MainPlaceholderTabView.swift in Sources */,
|
B3AF650899B8FC84E0C0CDA0 /* MainPlaceholderTabView.swift in Sources */,
|
||||||
CA65AD0D677B4A8E9CAC0E15 /* MainTab.swift in Sources */,
|
CA65AD0D677B4A8E9CAC0E15 /* MainTab.swift in Sources */,
|
||||||
A0643C829BE7377DC09112CB /* MainTabBarButton.swift in Sources */,
|
A0643C829BE7377DC09112CB /* MainTabBarButton.swift in Sources */,
|
||||||
@@ -6784,7 +6830,11 @@
|
|||||||
32595EDE75871A7B2FDCC5AB /* SectionTitle.swift in Sources */,
|
32595EDE75871A7B2FDCC5AB /* SectionTitle.swift in Sources */,
|
||||||
7A1DDAAE227BF176BDEF1CB9 /* TextTabBar.swift in Sources */,
|
7A1DDAAE227BF176BDEF1CB9 /* TextTabBar.swift in Sources */,
|
||||||
5EEE98FE0EC4039761C604EE /* TitleBar.swift in Sources */,
|
5EEE98FE0EC4039761C604EE /* TitleBar.swift in Sources */,
|
||||||
A4EB669DFFFB64681E045EF3 /* MainHomeViewModel.swift in Sources */,
|
A4EB669DFFFB64681E045EF3 /* MainHomeRecommendationViewModel.swift in Sources */,
|
||||||
|
401A3FB02FEEAFA000A5BBA3 /* MainHomeView.swift in Sources */,
|
||||||
|
401A3FB12FEEAFA000A5BBA3 /* MainHomeRecommendationView.swift in Sources */,
|
||||||
|
401A3FB22FEEAFA000A5BBA3 /* MainHomeRankingView.swift in Sources */,
|
||||||
|
401A3FB32FEEAFA000A5BBA3 /* MainHomeFollowingView.swift in Sources */,
|
||||||
ACD71056E97E13E48941ABBB /* MainPlaceholderTabView.swift in Sources */,
|
ACD71056E97E13E48941ABBB /* MainPlaceholderTabView.swift in Sources */,
|
||||||
33BA3AB731849284E62AE04B /* MainTab.swift in Sources */,
|
33BA3AB731849284E62AE04B /* MainTab.swift in Sources */,
|
||||||
B11681AC02BF51C6E2FA6FF3 /* MainTabBarButton.swift in Sources */,
|
B11681AC02BF51C6E2FA6FF3 /* MainTabBarButton.swift in Sources */,
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct MainHomeFollowingView: View {
|
||||||
|
var body: some View {
|
||||||
|
MainPlaceholderTabView(title: "팔로잉")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MainHomeFollowingView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
MainHomeFollowingView()
|
||||||
|
}
|
||||||
|
}
|
||||||
91
SodaLive/Sources/V2/Main/Home/MainHomeView.swift
Normal file
91
SodaLive/Sources/V2/Main/Home/MainHomeView.swift
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct MainHomeView: View {
|
||||||
|
let onTapCanCharge: () -> Void
|
||||||
|
let onTapSearch: () -> Void
|
||||||
|
let onTapNotificationList: () -> Void
|
||||||
|
let onTapLive: (Int) -> Void
|
||||||
|
let onTapCreator: (Int) -> Void
|
||||||
|
let onTapContent: (Int) -> Void
|
||||||
|
let onTapCharacter: (Int) -> Void
|
||||||
|
let onTapCommunity: (Int) -> Void
|
||||||
|
|
||||||
|
@State private var selectedTab: MainHomeTab = .recommendation
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
HomeTitleBar {
|
||||||
|
HStack(spacing: 14) {
|
||||||
|
Image("ic_bar_cash")
|
||||||
|
.onTapGesture { onTapCanCharge() }
|
||||||
|
|
||||||
|
Image("ic_bar_search")
|
||||||
|
.onTapGesture { onTapSearch() }
|
||||||
|
|
||||||
|
Image("ic_bar_bell")
|
||||||
|
.onTapGesture { onTapNotificationList() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextTabBar(
|
||||||
|
items: MainHomeTab.allCases,
|
||||||
|
selectedItem: $selectedTab,
|
||||||
|
title: { $0.title }
|
||||||
|
)
|
||||||
|
|
||||||
|
tabContent
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
}
|
||||||
|
.background(Color.black.ignoresSafeArea())
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private var tabContent: some View {
|
||||||
|
switch selectedTab {
|
||||||
|
case .recommendation:
|
||||||
|
MainHomeRecommendationView(
|
||||||
|
onTapLive: onTapLive,
|
||||||
|
onTapCreator: onTapCreator,
|
||||||
|
onTapContent: onTapContent,
|
||||||
|
onTapCharacter: onTapCharacter,
|
||||||
|
onTapCommunity: onTapCommunity
|
||||||
|
)
|
||||||
|
case .ranking:
|
||||||
|
MainHomeRankingView()
|
||||||
|
case .following:
|
||||||
|
MainHomeFollowingView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum MainHomeTab: CaseIterable, Hashable {
|
||||||
|
case recommendation
|
||||||
|
case ranking
|
||||||
|
case following
|
||||||
|
|
||||||
|
var title: String {
|
||||||
|
switch self {
|
||||||
|
case .recommendation:
|
||||||
|
return "추천"
|
||||||
|
case .ranking:
|
||||||
|
return "랭킹"
|
||||||
|
case .following:
|
||||||
|
return "팔로잉"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MainHomeView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
MainHomeView(
|
||||||
|
onTapCanCharge: {},
|
||||||
|
onTapSearch: {},
|
||||||
|
onTapNotificationList: {},
|
||||||
|
onTapLive: { _ in },
|
||||||
|
onTapCreator: { _ in },
|
||||||
|
onTapContent: { _ in },
|
||||||
|
onTapCharacter: { _ in },
|
||||||
|
onTapCommunity: { _ in }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct MainHomeRankingView: View {
|
||||||
|
var body: some View {
|
||||||
|
MainPlaceholderTabView(title: "랭킹")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MainHomeRankingView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
MainHomeRankingView()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct MainHomeRecommendationView: View {
|
||||||
|
let onTapLive: (Int) -> Void
|
||||||
|
let onTapCreator: (Int) -> Void
|
||||||
|
let onTapContent: (Int) -> Void
|
||||||
|
let onTapCharacter: (Int) -> Void
|
||||||
|
let onTapCommunity: (Int) -> Void
|
||||||
|
|
||||||
|
@StateObject private var viewModel = MainHomeRecommendationViewModel()
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ZStack {
|
||||||
|
Color.black
|
||||||
|
.ignoresSafeArea()
|
||||||
|
|
||||||
|
if viewModel.isLoading && viewModel.recommendations == nil {
|
||||||
|
ProgressView()
|
||||||
|
.progressViewStyle(CircularProgressViewStyle(tint: .white))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
if viewModel.recommendations == nil {
|
||||||
|
viewModel.fetchRecommendations()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sodaToast(
|
||||||
|
isPresented: $viewModel.isShowPopup,
|
||||||
|
message: viewModel.errorMessage,
|
||||||
|
autohideIn: 2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MainHomeRecommendationView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
MainHomeRecommendationView(
|
||||||
|
onTapLive: { _ in },
|
||||||
|
onTapCreator: { _ in },
|
||||||
|
onTapContent: { _ in },
|
||||||
|
onTapCharacter: { _ in },
|
||||||
|
onTapCommunity: { _ in }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
final class MainHomeViewModel: ObservableObject {
|
final class MainHomeRecommendationViewModel: ObservableObject {
|
||||||
private let repository = MainHomeRecommendationRepository()
|
private let repository = MainHomeRecommendationRepository()
|
||||||
private var subscription = Set<AnyCancellable>()
|
private var subscription = Set<AnyCancellable>()
|
||||||
|
|
||||||
@@ -153,7 +153,16 @@ struct MainView: View {
|
|||||||
private var contentView: some View {
|
private var contentView: some View {
|
||||||
switch viewModel.currentTab {
|
switch viewModel.currentTab {
|
||||||
case .home:
|
case .home:
|
||||||
MainPlaceholderTabView(title: MainTab.home.title)
|
MainHomeView(
|
||||||
|
onTapCanCharge: handleHomeCanChargeTap,
|
||||||
|
onTapSearch: handleHomeSearchTap,
|
||||||
|
onTapNotificationList: handleHomeNotificationListTap,
|
||||||
|
onTapLive: handleRecommendationLiveTap,
|
||||||
|
onTapCreator: handleRecommendationCreatorTap,
|
||||||
|
onTapContent: handleRecommendationContentTap,
|
||||||
|
onTapCharacter: handleRecommendationCharacterTap,
|
||||||
|
onTapCommunity: handleRecommendationCommunityTap
|
||||||
|
)
|
||||||
case .content:
|
case .content:
|
||||||
MainPlaceholderTabView(title: MainTab.content.title)
|
MainPlaceholderTabView(title: MainTab.content.title)
|
||||||
case .chat:
|
case .chat:
|
||||||
@@ -416,6 +425,106 @@ struct MainView: View {
|
|||||||
navigationAction()
|
navigationAction()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func handleHomeCanChargeTap() {
|
||||||
|
appState.setAppStep(step: .canCharge(refresh: {}))
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleHomeSearchTap() {
|
||||||
|
appState.setAppStep(step: .search)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleHomeNotificationListTap() {
|
||||||
|
appState.setAppStep(step: .notificationList)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleRecommendationLiveTap(roomId: Int) {
|
||||||
|
guard roomId > 0 else { return }
|
||||||
|
performRecommendationDetailAction {
|
||||||
|
openLiveDetail(roomId: roomId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleRecommendationCreatorTap(creatorId: Int) {
|
||||||
|
guard creatorId > 0 else { return }
|
||||||
|
performRecommendationDetailAction {
|
||||||
|
appState.setAppStep(step: .creatorDetail(userId: creatorId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleRecommendationContentTap(contentId: Int) {
|
||||||
|
guard contentId > 0 else { return }
|
||||||
|
performRecommendationDetailAction {
|
||||||
|
appState.setAppStep(step: .contentDetail(contentId: contentId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleRecommendationCharacterTap(characterId: Int) {
|
||||||
|
guard characterId > 0 else { return }
|
||||||
|
performRecommendationDetailAction {
|
||||||
|
appState.setAppStep(step: .characterDetail(characterId: characterId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleRecommendationCommunityTap(creatorId: Int) {
|
||||||
|
guard creatorId > 0 else { return }
|
||||||
|
performRecommendationDetailAction {
|
||||||
|
appState.setAppStep(step: .creatorCommunityAll(creatorId: creatorId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func performRecommendationDetailAction(
|
||||||
|
requiresAdultContent: Bool = false,
|
||||||
|
action: @escaping () -> Void
|
||||||
|
) {
|
||||||
|
let trimmed = token.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
guard !trimmed.isEmpty else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if requiresAdultContent {
|
||||||
|
let normalizedCountryCode = UserDefaults
|
||||||
|
.string(forKey: .countryCode)
|
||||||
|
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
.uppercased()
|
||||||
|
let isKoreanCountry = normalizedCountryCode.isEmpty || normalizedCountryCode == "KR"
|
||||||
|
|
||||||
|
if isKoreanCountry && auth == false {
|
||||||
|
pendingAction = action
|
||||||
|
isShowAuthConfirmView = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !UserDefaults.isAdultContentVisible() {
|
||||||
|
pendingAction = nil
|
||||||
|
moveToContentSettingsWithGuideToast()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
action()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func openLiveDetail(roomId: Int) {
|
||||||
|
appState.setAppStep(
|
||||||
|
step: .liveDetail(
|
||||||
|
roomId: roomId,
|
||||||
|
onClickParticipant: {
|
||||||
|
appState.isShowPlayer = false
|
||||||
|
liveViewModel.enterLiveRoom(roomId: roomId)
|
||||||
|
},
|
||||||
|
onClickReservation: {},
|
||||||
|
onClickStart: {},
|
||||||
|
onClickCancel: {}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func moveToContentSettingsWithGuideToast() {
|
||||||
|
AppState.shared.setPendingContentSettingsGuideMessage(I18n.Settings.adultContentEnableGuide)
|
||||||
|
AppState.shared.setAppStep(step: .contentViewSettings)
|
||||||
|
}
|
||||||
|
|
||||||
private func confirmExternalNavigation() {
|
private func confirmExternalNavigation() {
|
||||||
guard pendingExternalNavigationAction != nil else {
|
guard pendingExternalNavigationAction != nil else {
|
||||||
isShowLeaveLiveNavigationDialog = false
|
isShowLeaveLiveNavigationDialog = false
|
||||||
|
|||||||
@@ -135,7 +135,7 @@
|
|||||||
|
|
||||||
### Phase 4: 추천 데이터 상태 계층 정리
|
### Phase 4: 추천 데이터 상태 계층 정리
|
||||||
|
|
||||||
- [ ] **Task 4.1: 추천 ViewModel 데이터 로딩 계층 정리**
|
- [x] **Task 4.1: 추천 ViewModel 데이터 로딩 계층 정리**
|
||||||
- 대상 파일:
|
- 대상 파일:
|
||||||
- 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationViewModel.swift`
|
- 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationViewModel.swift`
|
||||||
- 이동/정리: `SodaLive/Sources/V2/Main/Home/MainHomeViewModel.swift`
|
- 이동/정리: `SodaLive/Sources/V2/Main/Home/MainHomeViewModel.swift`
|
||||||
@@ -151,7 +151,7 @@
|
|||||||
|
|
||||||
### Phase 5: 추천 상세 진입 데이터/라우팅 guard
|
### Phase 5: 추천 상세 진입 데이터/라우팅 guard
|
||||||
|
|
||||||
- [ ] **Task 5.1: 추천 탭 상세 진입 guard 적용**
|
- [x] **Task 5.1: 추천 탭 상세 진입 guard 적용**
|
||||||
- 대상 파일:
|
- 대상 파일:
|
||||||
- 수정: `SodaLive/Sources/V2/Main/MainView.swift`
|
- 수정: `SodaLive/Sources/V2/Main/MainView.swift`
|
||||||
- 생성/보완: `SodaLive/Sources/V2/Main/Home/MainHomeView.swift`
|
- 생성/보완: `SodaLive/Sources/V2/Main/Home/MainHomeView.swift`
|
||||||
@@ -174,7 +174,7 @@
|
|||||||
|
|
||||||
### Phase 6: 홈 탭 shell과 탭별 루트 연결
|
### Phase 6: 홈 탭 shell과 탭별 루트 연결
|
||||||
|
|
||||||
- [ ] **Task 6.1: 추천/랭킹/팔로잉 하위 폴더와 루트 View 준비**
|
- [x] **Task 6.1: 추천/랭킹/팔로잉 하위 폴더와 루트 View 준비**
|
||||||
- 대상 파일:
|
- 대상 파일:
|
||||||
- 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift`
|
- 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift`
|
||||||
- 생성/보완: `SodaLive/Sources/V2/Main/Home/Ranking/MainHomeRankingView.swift`
|
- 생성/보완: `SodaLive/Sources/V2/Main/Home/Ranking/MainHomeRankingView.swift`
|
||||||
@@ -187,7 +187,7 @@
|
|||||||
- 실행 명령: `find SodaLive/Sources/V2/Main/Home -maxdepth 3 -type f | sort`
|
- 실행 명령: `find SodaLive/Sources/V2/Main/Home -maxdepth 3 -type f | sort`
|
||||||
- 기대 결과: `Recommendation`, `Ranking`, `Following` 하위 폴더의 루트 View 파일이 확인된다.
|
- 기대 결과: `Recommendation`, `Ranking`, `Following` 하위 폴더의 루트 View 파일이 확인된다.
|
||||||
|
|
||||||
- [ ] **Task 6.2: MainHomeView 탭 shell 작성/보완**
|
- [x] **Task 6.2: MainHomeView 탭 shell 작성/보완**
|
||||||
- 대상 파일:
|
- 대상 파일:
|
||||||
- 생성/보완: `SodaLive/Sources/V2/Main/Home/MainHomeView.swift`
|
- 생성/보완: `SodaLive/Sources/V2/Main/Home/MainHomeView.swift`
|
||||||
- 확인: `SodaLive/Sources/V2/Component/HomeTitleBar.swift`
|
- 확인: `SodaLive/Sources/V2/Component/HomeTitleBar.swift`
|
||||||
@@ -199,7 +199,7 @@
|
|||||||
- 실행 명령: `rg "struct MainHomeView|HomeTitleBar|MainHomeRecommendationView|MainHomeRankingView|MainHomeFollowingView|MainTabBarView|fetchRecommendations" SodaLive/Sources/V2/Main/Home/MainHomeView.swift SodaLive/Sources/V2/Main/MainView.swift`
|
- 실행 명령: `rg "struct MainHomeView|HomeTitleBar|MainHomeRecommendationView|MainHomeRankingView|MainHomeFollowingView|MainTabBarView|fetchRecommendations" SodaLive/Sources/V2/Main/Home/MainHomeView.swift SodaLive/Sources/V2/Main/MainView.swift`
|
||||||
- 기대 결과: `MainHomeView`는 탭별 루트 View를 조합하고, `fetchRecommendations`를 직접 호출하지 않으며, 탭바 중복 생성은 없어야 한다.
|
- 기대 결과: `MainHomeView`는 탭별 루트 View를 조합하고, `fetchRecommendations`를 직접 호출하지 않으며, 탭바 중복 생성은 없어야 한다.
|
||||||
|
|
||||||
- [ ] **Task 6.3: MainView 홈 탭 연결**
|
- [x] **Task 6.3: MainView 홈 탭 연결**
|
||||||
- 대상 파일:
|
- 대상 파일:
|
||||||
- 수정: `SodaLive/Sources/V2/Main/MainView.swift`
|
- 수정: `SodaLive/Sources/V2/Main/MainView.swift`
|
||||||
- 작업 내용:
|
- 작업 내용:
|
||||||
@@ -442,6 +442,26 @@
|
|||||||
|
|
||||||
## 검증 기록
|
## 검증 기록
|
||||||
|
|
||||||
|
### 2026-06-26 Phase 4~6 구현 완료
|
||||||
|
|
||||||
|
- 목적: 추천 ViewModel 데이터 로딩 계층을 `Recommendation` 하위로 정리하고, 추천 탭 상세 진입 callback guard와 홈 탭 shell/루트 View를 연결
|
||||||
|
- 수행 내용:
|
||||||
|
- `MainHomeViewModel.swift`를 `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationViewModel.swift`로 이동하고 `MainHomeRecommendationViewModel`로 이름 변경
|
||||||
|
- `MainHomeRecommendationView`를 추가해 추천 API 로딩/에러 toast 상태를 추천 탭 루트에서 관리하도록 구성
|
||||||
|
- `MainHomeView`를 추가해 `HomeTitleBar`, 추천/랭킹/팔로잉 `TextTabBar`, 탭별 루트 View 조합만 담당하도록 구성
|
||||||
|
- `MainHomeRankingView`, `MainHomeFollowingView`는 이번 추천 API 범위 밖이므로 최소 placeholder 루트 View만 추가
|
||||||
|
- `MainView`의 `.home` 분기를 `MainHomeView`로 교체하고, 추천 상세 진입 callback을 기존 `token`, `auth`, `pendingAction`, `isShowAuthConfirmView`, `authView` 인프라를 재사용하는 guard helper에 연결
|
||||||
|
- `HomeLiveItem`에 성인 여부 필드가 없어 라이브 항목 성인 여부는 임의 판단하지 않고, 향후 성인 여부가 명확한 호출에서 `requiresAdultContent`를 사용할 수 있게 중앙 helper만 준비
|
||||||
|
- 신규/이동 Swift 파일을 `SodaLive.xcodeproj/project.pbxproj` 빌드 대상에 포함
|
||||||
|
- 검증:
|
||||||
|
- `rg "final class MainHomeRecommendationViewModel|fetchRecommendations|HomeRecommendationResponse|MainHomeRecommendationRepository|isLoading|errorMessage" SodaLive/Sources/V2/Main/Home` 실행, 추천 API 로딩/에러/응답 상태가 `MainHomeRecommendationViewModel` 중심으로 검색됨 확인
|
||||||
|
- `rg "pendingAction|isShowAuthConfirmView|setPendingContentSettingsGuideMessage|adultContentEnableGuide|contentViewSettings|MainHomeView\(|MainHomeRecommendationView\(" SodaLive/Sources/V2/Main/MainView.swift SodaLive/Sources/V2/Main/Home` 실행, 신규 추천 탭 callback이 `MainView` guard 인프라를 재사용함 확인
|
||||||
|
- `find SodaLive/Sources/V2/Main/Home -maxdepth 3 -type f | sort` 실행, `Recommendation`, `Ranking`, `Following` 하위 루트 파일 확인
|
||||||
|
- `rg "struct MainHomeView|HomeTitleBar|MainHomeRecommendationView|MainHomeRankingView|MainHomeFollowingView|MainTabBarView|fetchRecommendations" SodaLive/Sources/V2/Main/Home/MainHomeView.swift SodaLive/Sources/V2/Main/MainView.swift` 실행, `MainHomeView`가 탭별 루트 View를 조합하고 `fetchRecommendations`를 직접 호출하지 않음 확인
|
||||||
|
- `rg "case \\.home|MainHomeView|MainPlaceholderTabView" SodaLive/Sources/V2/Main/MainView.swift` 실행, `.home`이 `MainHomeView`를 표시하고 다른 placeholder 탭은 유지됨 확인
|
||||||
|
- `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인
|
||||||
|
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인
|
||||||
|
|
||||||
### 2026-06-26 Phase 1~3 코드 리뷰 보완
|
### 2026-06-26 Phase 1~3 코드 리뷰 보완
|
||||||
|
|
||||||
- 목적: Phase 2.2 리뷰에서 지적된 과거 추정 응답 필드 혼재를 제거하고, 추천 전용 request 모델 위치를 `Recommendation/Models` 구조로 일치
|
- 목적: Phase 2.2 리뷰에서 지적된 과거 추정 응답 필드 혼재를 제거하고, 추천 전용 request 모델 위치를 `Recommendation/Models` 구조로 일치
|
||||||
|
|||||||
Reference in New Issue
Block a user