From f145de87aa68ebe8c6cffab8ef4bd021774b38d8 Mon Sep 17 00:00:00 2001 From: Yu Sung Date: Fri, 6 Mar 2026 14:25:04 +0900 Subject: [PATCH] =?UTF-8?q?feat(community):=20=EC=BB=A4=EB=AE=A4=EB=8B=88?= =?UTF-8?q?=ED=8B=B0=20=EB=B3=B4=EA=B8=B0=20=EC=A0=84=ED=99=98=20=ED=83=AD?= =?UTF-8?q?=EA=B3=BC=20=EC=95=84=EC=9D=B4=EC=BD=98=EC=9D=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ic_community_grid.imageset/Contents.json | 21 ++ .../ic_community_grid.png | Bin 0 -> 702 bytes .../Contents.json | 21 ++ .../ic_community_grid_selected.png | Bin 0 -> 594 bytes .../ic_community_list.imageset/Contents.json | 21 ++ .../ic_community_list.png | Bin 0 -> 600 bytes .../Contents.json | 21 ++ .../ic_community_list_selected.png | Bin 0 -> 517 bytes .../All/CreatorCommunityAllView.swift | 286 +++++++++++++++--- ...—์ดํ„ฐ์ปค๋ฎค๋‹ˆํ‹ฐ์ „์ฒด๋ณด๊ธฐ๊ทธ๋ฆฌ๋“œ๋ฆฌ์ŠคํŠธ์ „ํ™˜๊ตฌํ˜„.md | 124 ++++++++ 10 files changed, 452 insertions(+), 42 deletions(-) create mode 100644 SodaLive/Resources/Assets.xcassets/ic_community_grid.imageset/Contents.json create mode 100644 SodaLive/Resources/Assets.xcassets/ic_community_grid.imageset/ic_community_grid.png create mode 100644 SodaLive/Resources/Assets.xcassets/ic_community_grid_selected.imageset/Contents.json create mode 100644 SodaLive/Resources/Assets.xcassets/ic_community_grid_selected.imageset/ic_community_grid_selected.png create mode 100644 SodaLive/Resources/Assets.xcassets/ic_community_list.imageset/Contents.json create mode 100644 SodaLive/Resources/Assets.xcassets/ic_community_list.imageset/ic_community_list.png create mode 100644 SodaLive/Resources/Assets.xcassets/ic_community_list_selected.imageset/Contents.json create mode 100644 SodaLive/Resources/Assets.xcassets/ic_community_list_selected.imageset/ic_community_list_selected.png create mode 100644 docs/20260305_ํฌ๋ฆฌ์—์ดํ„ฐ์ปค๋ฎค๋‹ˆํ‹ฐ์ „์ฒด๋ณด๊ธฐ๊ทธ๋ฆฌ๋“œ๋ฆฌ์ŠคํŠธ์ „ํ™˜๊ตฌํ˜„.md diff --git a/SodaLive/Resources/Assets.xcassets/ic_community_grid.imageset/Contents.json b/SodaLive/Resources/Assets.xcassets/ic_community_grid.imageset/Contents.json new file mode 100644 index 0000000..d48b431 --- /dev/null +++ b/SodaLive/Resources/Assets.xcassets/ic_community_grid.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "ic_community_grid.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SodaLive/Resources/Assets.xcassets/ic_community_grid.imageset/ic_community_grid.png b/SodaLive/Resources/Assets.xcassets/ic_community_grid.imageset/ic_community_grid.png new file mode 100644 index 0000000000000000000000000000000000000000..eb54f310ecd57dbb42c302bc2378c6f8d99ffc74 GIT binary patch literal 702 zcmV;v0zv(WP)6vjUw2*z@Q9D(jgrDHdGg0?3p3u1+V z0a)k>;0SPn(uJ9B-AcEPj3EA`?};p>b`paqBz`~10@?3D{MmW2qh~-61i@lbQ4Oor z>Qz3UuWU9O7Z*$_m6~#Cx7)Kw_F)F~dflauK9w@!#ehmPOo%`MYPDK1old{f*DJ)6 z*>=0V?{>RWoq<*Wf8@FIF5=Cc%C&ALq;+1N=QR-j&NDoF`?^Nu4Dd()6A5CuTo!u0 z-h98_Q5nrcRrcB#pn@*q3l~n0HUl~rTvrtvHz_^VgM{h1c2q32EouhIdiV}0U`cM zj0A|fCqL)=0G+=Mi2<-25dfAW0>E-)A!K4K+hN%bCl3(-mLpFAm?7I?*$yWR5dfAW z0>E-a09cNZ0Q7vl_?%(R6*RI}RnlVOkvgkOFCB!X%bjZ_=ns%8M-YzVR9dap=uf@M zc(qy$bGe*O02T)aa<=yY>-G9wRj=%cpHn+Vau^tAixW@SrJBc`8I`84Q7Zr|M)%yU z{{wMl&IcxfPK{)OyeE^%cd1kwd7f9G=vqX)7*o0HbUGhFMv)Iq@fiZnBIkk&CX>m` k7K_DDbv8f{1VPy22Wr|3%2z`~zyJUM07*qoM6N<$f@~isaR2}S literal 0 HcmV?d00001 diff --git a/SodaLive/Resources/Assets.xcassets/ic_community_grid_selected.imageset/Contents.json b/SodaLive/Resources/Assets.xcassets/ic_community_grid_selected.imageset/Contents.json new file mode 100644 index 0000000..a9241df --- /dev/null +++ b/SodaLive/Resources/Assets.xcassets/ic_community_grid_selected.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "ic_community_grid_selected.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SodaLive/Resources/Assets.xcassets/ic_community_grid_selected.imageset/ic_community_grid_selected.png b/SodaLive/Resources/Assets.xcassets/ic_community_grid_selected.imageset/ic_community_grid_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..f527036d3d0888d561c497115f47a1a8fda6a9da GIT binary patch literal 594 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBK3|DzL`iUdT1k0gQ7VI5W_oVoyp7Y6fx6Cm zx;TbZFutArF!zvwKx@3fe{b^w^98~zW*WjJE$a?&yk)t-yNmH9OKS5n;VHbAHha`J z)cCDo=zRR$bGb*S{0V*W<9+8C6kAk$u5C*U4K=p3@s!}1y|-8Av{ww%%N-MMgnryO z(ZKibX(=oF>4*K2+AK6x!zS@ouWih7csuXy9>+T}Dso%hlO74K6Rdx(YgTQ3%Qc&QIk?(~oG&sLc?HTxUyHdkpC=4-c3+zQ;k zZ`rnM``ccqb3A50yj;`TpTjhv<5|7W*2$K-)FA*^(`jB_uljG4GOl$;fC<3J8>wl-y!p? zs3HVp^nE6d#SGIAU%y&xS(BUrF$74dUulrYYV-9-&Q*)hdLEzRRM`HkXy?9t>^G#B zh05i9p`Kg}>*aIq3)ZdFHIUmDwY4I6=N{kL5#PD~1bgW;pMIKsQ0P~M z0JGWT@O^KM?`?P3d->3;4}Cv03hroZ{BFv1(@Ze@PYsU literal 0 HcmV?d00001 diff --git a/SodaLive/Resources/Assets.xcassets/ic_community_list.imageset/Contents.json b/SodaLive/Resources/Assets.xcassets/ic_community_list.imageset/Contents.json new file mode 100644 index 0000000..447f334 --- /dev/null +++ b/SodaLive/Resources/Assets.xcassets/ic_community_list.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "ic_community_list.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SodaLive/Resources/Assets.xcassets/ic_community_list.imageset/ic_community_list.png b/SodaLive/Resources/Assets.xcassets/ic_community_list.imageset/ic_community_list.png new file mode 100644 index 0000000000000000000000000000000000000000..7a559d741d9f7521168ac22803e57839856f9e08 GIT binary patch literal 600 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBK3|DzL`iUdT1k0gQ7VI5W_oVoyp7Y6fx0ex zx;TbZFut8_U3ADmpsoJ)!;7qW50od&Q_{RVQCP*2F;8OqLKdkaCJQD@#}ygQyGjao zP0>rNuvmT2SK{OYzohT8Z#GW6#{4fVXe$$oqkzQYxw9o)0~g1wFE862%hCPOCVyp; zfrLu>)A?QbljL>LUUgA`!}{ylKllCjigu*#-xsrRy1+h3@( zHiq8{*VJkGSM2d|#q8A~TCy^H$Lgnu8Z6x_axf|5>#9d3rojvK?pLtASa9n9fud9E z&IK{)2?{bi>tHZ&XKAohVmKqnn9#?;Q0&4mLz(G-3_+>oQyA`lU;AD%Y;RNQr}aFK zI}`UvAOE;@?c1Wt#x1>*u4a98HeV;Y;buZoxvr2wrcDQ5^r@`P~2j literal 0 HcmV?d00001 diff --git a/SodaLive/Resources/Assets.xcassets/ic_community_list_selected.imageset/Contents.json b/SodaLive/Resources/Assets.xcassets/ic_community_list_selected.imageset/Contents.json new file mode 100644 index 0000000..e693ea5 --- /dev/null +++ b/SodaLive/Resources/Assets.xcassets/ic_community_list_selected.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "ic_community_list_selected.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SodaLive/Resources/Assets.xcassets/ic_community_list_selected.imageset/ic_community_list_selected.png b/SodaLive/Resources/Assets.xcassets/ic_community_list_selected.imageset/ic_community_list_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..9ff608251d06aac4d66ec7e5c33f6991f13c41cb GIT binary patch literal 517 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBK3|DzL`iUdT1k0gQ7VI5W_oVoyp7Y6fw~$z zT^vIy7~jsm=zG{epzXiHJx%Euyr($sHuxRjNM#92XlmoVvEXh)j>C+Gyo7gCJ_!93 z()oJu+~4^nT`ATR|NNY^=MH0wz@r(@_H!rqNbj`qWSQc-{Gy3(f3|`&ztHjsdH2o@ zTlS|VevaNbN5yQ#1q(HvCcAvt!{`_E)-Y{+{8hW}IO2 zSAR`+^~t8wB_FOu>}fqK-L^$*qQb|VGcV=W%;kH=m2vbDH<#O{aQ^2LW^k?iT717j z|is>6e)o(~YZkKp0drEiuW#&y> zs`kOnVJp|zyrXwMee23C?GNty8&B&^m(Ra(@Soh3 zhO|$0>uS@!=^K<`IjP;8mNxqri1rrUc~ SC0+!^5`(9!pUXO@geCwcI??F> literal 0 HcmV?d00001 diff --git a/SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllView.swift b/SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllView.swift index b67120d..883409c 100644 --- a/SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllView.swift +++ b/SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllView.swift @@ -8,57 +8,49 @@ import SwiftUI struct CreatorCommunityAllView: View { - + let creatorId: Int - + @StateObject var viewModel = CreatorCommunityAllViewModel() @StateObject var playerManager = CreatorCommunityMediaPlayerManager.shared - + + @State private var isGridMode = false + @State private var isListFromGridTap = false + @State private var selectedListIndex = 0 + @State private var listAnchorIndex = 0 + @State private var pendingGridAnchorIndex: Int? + + private let gridColumns = [ + GridItem(.flexible(), spacing: 1), + GridItem(.flexible(), spacing: 1), + GridItem(.flexible(), spacing: 1) + ] + var body: some View { GeometryReader { proxy in BaseView(isLoading: $viewModel.isLoading) { VStack(spacing: 0) { - DetailNavigationBar(title: "์ปค๋ฎค๋‹ˆํ‹ฐ") - - ScrollView(.vertical, showsIndicators: false) { - LazyVStack(spacing: 26.7) { - ForEach(0.. 0 && item.existOrdered && item.creatorId != UserDefaults.int(forKey: .userId) - viewModel.isShowCommentListView = true - }, - onClickWriteComment: { comment, isSecret in - viewModel.createCommunityPostComment( - comment: comment, - postId: item.postId, - isSecret: isSecret - ) - }, - onClickShowReportMenu: { - viewModel.postId = item.postId - viewModel.isShowReportMenu = true - }, - onClickPurchaseContent: { - viewModel.postId = item.postId - viewModel.postPrice = item.price - viewModel.postIndex = index - viewModel.isShowPostPurchaseView = true - } - ) - .onAppear { - if index == viewModel.communityPostList.count - 1 { - viewModel.getCommunityPostList() - } + DetailNavigationBar( + title: "์ปค๋ฎค๋‹ˆํ‹ฐ", + backAction: { + if isGridMode { + AppState.shared.back() + } else { + if isListFromGridTap { + returnToGridMode() + } else { + AppState.shared.back() } } } + ) + + communityViewTypeTabView + + if isGridMode { + gridContentView + } else { + listContentView } } .sheet( @@ -188,12 +180,222 @@ struct CreatorCommunityAllView: View { } } } - + + private var gridContentView: some View { + ScrollViewReader { scrollProxy in + ScrollView(.vertical, showsIndicators: false) { + LazyVGrid(columns: gridColumns, spacing: 1) { + ForEach(0.. some View { + CreatorCommunityAllItemView( + item: item, + onClickLike: { + viewModel.communityPostLike(postId: item.postId) + }, + onClickComment: { + viewModel.postId = item.postId + viewModel.isShowSecret = item.price > 0 && item.existOrdered && item.creatorId != UserDefaults.int(forKey: .userId) + viewModel.isShowCommentListView = true + }, + onClickWriteComment: { comment, isSecret in + viewModel.createCommunityPostComment( + comment: comment, + postId: item.postId, + isSecret: isSecret + ) + }, + onClickShowReportMenu: { + viewModel.postId = item.postId + viewModel.isShowReportMenu = true + }, + onClickPurchaseContent: { + viewModel.postId = item.postId + viewModel.postPrice = item.price + viewModel.postIndex = index + viewModel.isShowPostPurchaseView = true + } + ) + } + + private func returnToGridMode() { + pendingGridAnchorIndex = listAnchorIndex + isListFromGridTap = false + isGridMode = true + } + + private var communityViewTypeTabView: some View { + VStack(spacing: 0) { + HStack(spacing: 0) { + Button { + isGridMode = false + isListFromGridTap = false + } label: { + Image(isGridMode ? "ic_community_list" : "ic_community_list_selected") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .frame(maxWidth: .infinity) + .frame(height: 44) + } + + Button { + isGridMode = true + isListFromGridTap = false + } label: { + Image(isGridMode ? "ic_community_grid_selected" : "ic_community_grid") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .frame(maxWidth: .infinity) + .frame(height: 44) + } + } + .background(Color.black) + + ZStack(alignment: .bottomLeading) { + Rectangle() + .foregroundColor(Color(hex: "909090")) + .frame(height: 1) + + HStack(spacing: 0) { + Rectangle() + .foregroundColor(isGridMode ? Color.clear : Color.white) + .frame(maxWidth: .infinity) + + Rectangle() + .foregroundColor(isGridMode ? Color.white : Color.clear) + .frame(maxWidth: .infinity) + } + .frame(height: 2) + } + .frame(height: 2) + } + } + private func creatorCommunityModifySuccess() { viewModel.getCommunityPostList() } } +private struct CreatorCommunityAllGridItemView: View { + let item: GetCommunityPostListResponse + + var body: some View { + ZStack { + if isPaidLocked { + Color.gray33 + + Image("ic_lock_bb") + .resizable() + .scaledToFit() + .frame(width: 24, height: 24) + } else if let imageUrl = item.imageUrl, !imageUrl.isEmpty { + AsyncImage(url: URL(string: imageUrl)) { phase in + switch phase { + case .empty: + Color.gray33 + case .success(let image): + image + .resizable() + .scaledToFill() + case .failure: + Color(hex: "263238") + @unknown default: + Color.gray33 + } + } + } else { + Color(hex: "263238") + + Text(fallbackText) + .appFont(size: 12, weight: .medium) + .foregroundColor(Color.grayee) + .multilineTextAlignment(.center) + .lineLimit(3) + .padding(8) + } + } + .aspectRatio(1, contentMode: .fit) + .clipped() + } + + private var isPaidLocked: Bool { + item.price > 0 && !item.existOrdered + } + + private var fallbackText: String { + let content = item.content.trimmingCharacters(in: .whitespacesAndNewlines) + if content.isEmpty { + return "-" + } + + return String(content.prefix(18)) + } +} + struct CreatorCommunityAllView_Previews: PreviewProvider { static var previews: some View { CreatorCommunityAllView(creatorId: 0) diff --git a/docs/20260305_ํฌ๋ฆฌ์—์ดํ„ฐ์ปค๋ฎค๋‹ˆํ‹ฐ์ „์ฒด๋ณด๊ธฐ๊ทธ๋ฆฌ๋“œ๋ฆฌ์ŠคํŠธ์ „ํ™˜๊ตฌํ˜„.md b/docs/20260305_ํฌ๋ฆฌ์—์ดํ„ฐ์ปค๋ฎค๋‹ˆํ‹ฐ์ „์ฒด๋ณด๊ธฐ๊ทธ๋ฆฌ๋“œ๋ฆฌ์ŠคํŠธ์ „ํ™˜๊ตฌํ˜„.md new file mode 100644 index 0000000..236a6cf --- /dev/null +++ b/docs/20260305_ํฌ๋ฆฌ์—์ดํ„ฐ์ปค๋ฎค๋‹ˆํ‹ฐ์ „์ฒด๋ณด๊ธฐ๊ทธ๋ฆฌ๋“œ๋ฆฌ์ŠคํŠธ์ „ํ™˜๊ตฌํ˜„.md @@ -0,0 +1,124 @@ +# 20260305 ํฌ๋ฆฌ์—์ดํ„ฐ ์ปค๋ฎค๋‹ˆํ‹ฐ ์ „์ฒด๋ณด๊ธฐ ๊ทธ๋ฆฌ๋“œ ๋ฆฌ์ŠคํŠธ ์ „ํ™˜ ๊ตฌํ˜„ + +## ๊ตฌํ˜„ ๋ชฉํ‘œ +- `CreatorCommunityAllView`๋ฅผ ์ธ์Šคํƒ€๊ทธ๋žจ๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ๊ธฐ๋ณธ `Grid` ํ™”๋ฉด์œผ๋กœ ๋…ธ์ถœํ•œ๋‹ค. +- ๊ทธ๋ฆฌ๋“œ ์•„์ดํ…œ ํƒญ ์‹œ `List` ํ™”๋ฉด์œผ๋กœ ์ „ํ™˜ํ•˜๊ณ , ํƒญํ•œ ์•„์ดํ…œ ์œ„์น˜์—์„œ ๋ฆฌ์ŠคํŠธ๋ฅผ ์‹œ์ž‘ํ•œ๋‹ค. +- ๊ทธ๋ฆฌ๋“œ ์ธ๋„ค์ผ ๊ทœ์น™์„ ๋ฐ˜์˜ํ•œ๋‹ค: ์ด๋ฏธ์ง€ ์žˆ์Œ(์ด๋ฏธ์ง€), ์ด๋ฏธ์ง€ ์—†์Œ(ํ…์ŠคํŠธ ์ผ๋ถ€), ์œ ๋ฃŒ ๋ฏธ๊ตฌ๋งค(์ž๋ฌผ์‡  ์ด๋ฏธ์ง€). +- ๋ฆฌ์ŠคํŠธ ํ™”๋ฉด์—์„œ ๋’ค๋กœ๊ฐ€๊ธฐ ๋ฒ„ํŠผ ๋ฐ ํˆด๋ฐ”๋ฅผ ์ œ๊ณตํ•˜๊ณ , ๋’ค๋กœ๊ฐ€๊ธฐ ์‹œ ๋‹ค์‹œ ๊ทธ๋ฆฌ๋“œ๋กœ ๋ณต๊ท€ํ•œ๋‹ค. +- ๋ฆฌ์ŠคํŠธ์—์„œ ๋’ค๋กœ๊ฐ€๊ธฐ ์‹œ ๋งˆ์ง€๋ง‰ ๋ฆฌ์ŠคํŠธ ์•ต์ปค ์•„์ดํ…œ์ด ๊ทธ๋ฆฌ๋“œ์—์„œ ๋ณด์ด๋„๋ก ์Šคํฌ๋กค ์œ„์น˜๋ฅผ ๋ณต์›ํ•œ๋‹ค. + +## ์ฒดํฌ๋ฆฌ์ŠคํŠธ +- [x] ๊ธฐ์กด `CreatorCommunity` ํ™”๋ฉด/๋ชจ๋ธ/๋‚ด๋น„๊ฒŒ์ด์…˜ ํŒจํ„ด ํƒ์ƒ‰ +- [x] `CreatorCommunityAllView` ๊ธฐ๋ณธ ๋ ˆ์ด์•„์›ƒ์„ Grid ์ค‘์‹ฌ์œผ๋กœ ์ „ํ™˜ +- [x] Grid ์•„์ดํ…œ ์ธ๋„ค์ผ ๊ทœ์น™(์ด๋ฏธ์ง€/ํ…์ŠคํŠธ/์œ ๋ฃŒ ์ž๋ฌผ์‡ ) ๊ตฌํ˜„ +- [x] ์•„์ดํ…œ ํƒญ ์‹œ List ์ „ํ™˜ + ํƒญ ์•„์ดํ…œ ์•ต์ปค ์ด๋™ ๊ตฌํ˜„ +- [x] ๋ฆฌ์ŠคํŠธ ์ƒํƒœ ํˆด๋ฐ”/๋’ค๋กœ๊ฐ€๊ธฐ ๊ตฌํ˜„ ๋ฐ ๊ทธ๋ฆฌ๋“œ ๋ณต๊ท€ ๋™์ž‘ ์—ฐ๊ฒฐ +- [x] ๋ฆฌ์ŠคํŠธ ์Šคํฌ๋กค ์ค‘ ์•ต์ปค ์ธ๋ฑ์Šค ์ถ”์  ๋ฐ ๊ทธ๋ฆฌ๋“œ ๋ณต๊ท€ ์‹œ ์œ„์น˜ ๋ณต์› +- [x] LSP/๋นŒ๋“œ/ํ…Œ์ŠคํŠธ ๊ฒ€์ฆ ๋ฐ ๊ฒฐ๊ณผ ๊ธฐ๋ก + +## ๊ฒ€์ฆ ๊ธฐ๋ก +- 2026-03-05 + - ๋ฌด์—‡: ์ž‘์—… ์‹œ์ž‘ ๋ฐ ์š”๊ตฌ์‚ฌํ•ญ ๋ถ„์„/ํŒจํ„ด ํƒ์ƒ‰ + - ์™œ: ๊ธฐ์กด ์•„ํ‚คํ…์ฒ˜์™€ ์ถฉ๋Œ ์—†์ด `Grid -> List -> Grid` UX๋ฅผ ์ •ํ™•ํžˆ ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•ด + - ์–ด๋–ป๊ฒŒ: `CreatorCommunityAllView`, `CreatorCommunityAllItemView`, `DetailNavigationBar`, ์‘๋‹ต ๋ชจ๋ธ์„ ํ™•์ธํ•ด ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ/ํƒ์ƒ‰ ํŒจํ„ด์„ ์ถ”์ถœ + - ๊ฒฐ๊ณผ: ์™„๋ฃŒ + +- 2026-03-05 (๊ตฌํ˜„/๊ฒ€์ฆ ์™„๋ฃŒ) + - ๋ฌด์—‡: `CreatorCommunityAllView`๋ฅผ ๊ธฐ๋ณธ Grid(ํ•œ ์ค„ 3๊ฐœ) ๋…ธ์ถœ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ , ์•„์ดํ…œ ํƒญ ์‹œ List ์ „ํ™˜/๋’ค๋กœ๊ฐ€๊ธฐ ๋ณต๊ท€/์•ต์ปค ๋ณต์›์„ ๊ตฌํ˜„ํ–ˆ๋‹ค. + - ์™œ: ์ธ์Šคํƒ€๊ทธ๋žจ๊ณผ ์œ ์‚ฌํ•œ ํƒ์ƒ‰ UX(๊ทธ๋ฆฌ๋“œ ์ง„์ž…, ๊ฒŒ์‹œ๋ฌผ ๋ฆฌ์ŠคํŠธ ํƒ์ƒ‰, ์›์œ„์น˜ ๋ณต๊ท€)๋ฅผ ์š”๊ตฌ์‚ฌํ•ญ๋Œ€๋กœ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด. + - ์–ด๋–ป๊ฒŒ: + - ์ˆ˜์ • ํŒŒ์ผ + - `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllView.swift` + - ์ ์šฉ ๋‚ด์šฉ + - `LazyVGrid` 3์—ด ๊ณ ์ •(`GridItem` 3๊ฐœ)์œผ๋กœ ๊ทธ๋ฆฌ๋“œ ๊ธฐ๋ณธ ํ™”๋ฉด ๊ตฌ์„ฑ + - ์ธ๋„ค์ผ ๊ทœ์น™ ๋ฐ˜์˜: ์œ ๋ฃŒ ๋ฏธ๊ตฌ๋งค(`price > 0 && !existOrdered`)๋Š” `ic_lock_bb`, ์ด๋ฏธ์ง€ ์—†์œผ๋ฉด ํ…์ŠคํŠธ ์•ž 18์ž, ๊ทธ ์™ธ `AsyncImage` + - `DetailNavigationBar`์˜ `backAction` ๋ถ„๊ธฐ๋กœ Grid ๋ชจ๋“œ์—์„œ๋Š” ํ™”๋ฉด ๋’ค๋กœ๊ฐ€๊ธฐ, List ๋ชจ๋“œ์—์„œ๋Š” Grid ๋ณต๊ท€ + - Grid ํƒญ ์‹œ `selectedListIndex`๋กœ List ์Šคํฌ๋กค ์‹œ์ž‘์  ์ด๋™, List ์Šคํฌ๋กค ์ค‘ `listAnchorIndex` ์ถ”์  + - List์—์„œ ๋’ค๋กœ๊ฐ€๊ธฐ ์‹œ `pendingGridAnchorIndex`๋ฅผ ์‚ฌ์šฉํ•ด Grid์—์„œ ํ•ด๋‹น ์•ต์ปค ์•„์ดํ…œ์œผ๋กœ `scrollTo` + - ์‹คํ–‰ ๋ช…๋ น + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test` + - `lsp_diagnostics` (`CreatorCommunityAllView.swift`) + - ๊ฒฐ๊ณผ: + - ๋นŒ๋“œ: `SodaLive`, `SodaLive-dev` ๋ชจ๋‘ `** BUILD SUCCEEDED **` ํ™•์ธ. + - ํ…Œ์ŠคํŠธ: ๋‘ ์Šคํ‚ด ๋ชจ๋‘ `Scheme ... is not currently configured for the test action.`๋กœ ์‹คํ–‰ ๋ถˆ๊ฐ€. + - LSP: SourceKit ๋‹จ๋… ์ง„๋‹จ์—์„œ ํ”„๋กœ์ ํŠธ ์‹ฌ๋ณผ ๋ฏธํ•ด๊ฒฐ ์—๋Ÿฌ๊ฐ€ ๋‹ค์ˆ˜ ๋ฐœ์ƒํ–ˆ์œผ๋‚˜, ์‹ค์ œ xcodebuild ์ปดํŒŒ์ผ์€ ์„ฑ๊ณต. + +- 2026-03-05 (์š”๊ตฌ์‚ฌํ•ญ ๋ณด๊ฐ•: ๊ทธ๋ฆฌ๋“œ 3์—ด/์•ต์ปค ๋ณต์› ํƒ€์ด๋ฐ ์•ˆ์ •ํ™”) + - ๋ฌด์—‡: `Grid`๋ฅผ ํ•œ ์ค„ 3๊ฐœ ๊ณ ์ • ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๊ณ , List -> Grid ๋ณต๊ท€ ์‹œ ์•ต์ปค ์Šคํฌ๋กค์ด ์ƒํƒœ ์ „ํ™˜ ํƒ€์ด๋ฐ์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋„๋ก `onAppear` ๋ณต์› ๋กœ์ง์„ ์ถ”๊ฐ€ํ–ˆ๋‹ค. + - ์™œ: "๊ทธ๋ฆฌ๋“œ ๋ฆฌ์ŠคํŠธ ํ•œ ์ค„์— 3๊ฐœ ํ‘œ์‹œ" ๋ฐ "๋ฆฌ์ŠคํŠธ ์•ต์ปค ์•„์ดํ…œ ๋ณต๊ท€" ์š”๊ตฌ๋ฅผ ๋” ์•ˆ์ •์ ์œผ๋กœ ์ถฉ์กฑํ•˜๊ธฐ ์œ„ํ•ด. + - ์–ด๋–ป๊ฒŒ: + - `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllView.swift` + - `gridColumns` 3๊ฐœ ๊ณ ์ • ์œ ์ง€ + - `gridContentView`์— `pendingGridAnchorIndex` ์ฒ˜๋ฆฌ์šฉ `.onAppear` ์ถ”๊ฐ€ + - ์‹คํ–‰ ๋ช…๋ น + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test` + - ๊ฒฐ๊ณผ: + - ๋นŒ๋“œ: ๋‘ ์Šคํ‚ด ๋ชจ๋‘ `** BUILD SUCCEEDED **`. + - ํ…Œ์ŠคํŠธ: ๋‘ ์Šคํ‚ด ๋ชจ๋‘ `Scheme ... is not currently configured for the test action.`. + +- 2026-03-05 (ํผํฌ๋จผ์Šค ๊ฐœ์„ : List -> Grid ์ „ํ™˜ ์ง€์—ฐ ์™„ํ™”) + - ๋ฌด์—‡: ๋ฆฌ์ŠคํŠธ์—์„œ ๊ทธ๋ฆฌ๋“œ๋กœ ๋Œ์•„๊ฐˆ ๋•Œ ์ „ํ™˜์ด ๋А๋ฆฐ ๋ฌธ์ œ๋ฅผ ์™„ํ™”ํ•˜๋„๋ก ๋ณต๊ท€ ๊ฒฝ๋กœ๋ฅผ ๋ฌด์• ๋‹ˆ๋ฉ”์ด์…˜/๋‹จ์ผ ๋ณต์›์œผ๋กœ ์ตœ์ ํ™”ํ–ˆ๋‹ค. + - ์™œ: ๋ณต๊ท€ ์‹œ ๋ชจ๋“œ ์ „ํ™˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ + ์•ต์ปค ๋ณต์› ์• ๋‹ˆ๋ฉ”์ด์…˜ + ์ค‘๋ณต ๋ณต์› ํŠธ๋ฆฌ๊ฑฐ๊ฐ€ ๊ฒน์น˜๋ฉด ์ฒด๊ฐ ์ง€์—ฐ์ด ์ปค์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ. + - ์–ด๋–ป๊ฒŒ: + - `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllView.swift` + - `returnToGridMode()`์—์„œ `withAnimation` ์ œ๊ฑฐ ํ›„ ์ฆ‰์‹œ `isGridMode = true`๋กœ ์ „ํ™˜ + - `gridContentView`์˜ `pendingGridAnchorIndex` ๋ณต์›์„ `onAppear` ๋‹จ์ผ ๊ฒฝ๋กœ๋กœ ํ†ตํ•ฉ + - ์•ต์ปค ๋ณต์› `scrollTo`๋ฅผ ๋ฌด์• ๋‹ˆ๋ฉ”์ด์…˜์œผ๋กœ ๋ณ€๊ฒฝํ•ด ๋ Œ๋”๋ง ๋ถ€ํ•˜ ๊ฐ์†Œ + - ์‹คํ–‰ ๋ช…๋ น + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test` + - `lsp_diagnostics` (`CreatorCommunityAllView.swift`) + - ๊ฒฐ๊ณผ: + - ๋นŒ๋“œ: `SodaLive`๋Š” `** BUILD SUCCEEDED **`, `SodaLive-dev`๋Š” ๋ณ‘๋ ฌ ๋นŒ๋“œ ์ค‘ `build.db locked` 1ํšŒ ๋ฐœ์ƒ ํ›„ ์ˆœ์ฐจ ์žฌ์‹คํ–‰์—์„œ `** BUILD SUCCEEDED **`. + - ํ…Œ์ŠคํŠธ: ๋‘ ์Šคํ‚ด ๋ชจ๋‘ `Scheme ... is not currently configured for the test action.`. + - LSP: SourceKit ๋‹จ๋… ์ง„๋‹จ์—์„œ ํ”„๋กœ์ ํŠธ ์‹ฌ๋ณผ ๋ฏธํ•ด๊ฒฐ ์—๋Ÿฌ๊ฐ€ ๋‹ค์ˆ˜ ๋ฐœ์ƒํ–ˆ์œผ๋‚˜, ์‹ค์ œ xcodebuild ์ปดํŒŒ์ผ์€ ์„ฑ๊ณต. + +- 2026-03-06 (UI ๋ณ€๊ฒฝ: Toolbar ์•„๋ž˜ List/Grid ํƒญ ๋ฐ ๊ธฐ๋ณธ List ์ง„์ž…) + - ๋ฌด์—‡: Toolbar ์•„๋ž˜์— ์ขŒ์ธก List/์šฐ์ธก Grid ํƒญ์„ ์ถ”๊ฐ€ํ•˜๊ณ , ๊ธฐ๋ณธ ํ‘œ์‹œ๋ฅผ Grid์—์„œ List๋กœ ๋ณ€๊ฒฝํ–ˆ๋‹ค. + - ์™œ: ์š”์ฒญ๋œ UI ๋ณ€๊ฒฝ(ํƒญ 2๊ฐœ, ๊ธฐ๋ณธ List, ๋’ค๋กœ๊ฐ€๊ธฐ ๋ถ„๊ธฐ)์„ ์ •ํ™•ํžˆ ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•ด. + - ์–ด๋–ป๊ฒŒ: + - `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllView.swift` + - `communityViewTypeTabView` ์ถ”๊ฐ€: ์ขŒ `ic_community_list(_selected)`, ์šฐ `ic_community_grid(_selected)`, ๊ฐ ๋ฒ„ํŠผ `maxWidth: .infinity`๋กœ ๊ฐ€๋กœ ๊ฝ‰์ฐฌ ํƒญ ๊ตฌ์„ฑ + - ๊ธฐ๋ณธ ๋ชจ๋“œ `isGridMode = false`๋กœ ๋ณ€๊ฒฝ + - `isListFromGridTap` ์ƒํƒœ ์ถ”๊ฐ€ + - Grid ์•„์ดํ…œ ํƒญ์œผ๋กœ List ์ง„์ž… ์‹œ `isListFromGridTap = true` + - List ์ƒํƒœ ๋’ค๋กœ๊ฐ€๊ธฐ ๋ถ„๊ธฐ: + - `isListFromGridTap == true`๋ฉด Grid ๋ณต๊ท€ + - ์ดˆ๊ธฐ List(๋˜๋Š” ํƒญ ์ „ํ™˜ List)๋Š” ๊ธฐ๋ณธ ๋’ค๋กœ๊ฐ€๊ธฐ ์ˆ˜ํ–‰ + - ์‹คํ–‰ ๋ช…๋ น + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test` + - `lsp_diagnostics` (`CreatorCommunityAllView.swift`) + - ๊ฒฐ๊ณผ: + - ๋นŒ๋“œ: `SodaLive`, `SodaLive-dev` ๋ชจ๋‘ `** BUILD SUCCEEDED **`. + - ํ…Œ์ŠคํŠธ: ๋‘ ์Šคํ‚ด ๋ชจ๋‘ `Scheme ... is not currently configured for the test action.`. + - LSP: SourceKit ๋‹จ๋… ์ง„๋‹จ์—์„œ๋Š” ํ”„๋กœ์ ํŠธ ์‹ฌ๋ณผ ๋ฏธํ•ด๊ฒฐ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋‚˜, ์‹ค์ œ xcodebuild๋Š” ์„ฑ๊ณต. + +- 2026-03-06 (ํƒญ ๋””ํ…Œ์ผ ์กฐ์ •: ๋ฐฐ๊ฒฝ/ํ•˜๋‹จ ๋ผ์ธ/์„ ํƒ ์ธ๋””์ผ€์ดํ„ฐ) + - ๋ฌด์—‡: ์ปค๋ฎค๋‹ˆํ‹ฐ ์ „์ฒด๋ณด๊ธฐ ํƒญ์˜ ์‹œ๊ฐ ๋””ํ…Œ์ผ์„ ์š”์ฒญ ์‚ฌ์–‘์œผ๋กœ ์กฐ์ •ํ–ˆ๋‹ค. + - ์™œ: ํƒญ ๋ฐฐ๊ฒฝ์ƒ‰, ํ•˜๋‹จ ๊ตฌ๋ถ„์„ , ์„ ํƒ ์ธ๋””์ผ€์ดํ„ฐ๋ฅผ ๋ช…์‹œํ•œ ์ตœ์‹  UI ์š”๊ตฌ๋ฅผ ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•ด. + - ์–ด๋–ป๊ฒŒ: + - `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllView.swift` + - ํƒญ ๋ฐฐ๊ฒฝ์ƒ‰์„ `#777777`๋กœ ๋ณ€๊ฒฝ + - ํƒญ ํ•˜๋‹จ์— ์ „์ฒด ํญ ๊ตฌ๋ถ„์„ (`height: 1`, `#909090`) ์ถ”๊ฐ€ + - ์„ ํƒ ํƒญ ํ•˜๋‹จ ์ธ๋””์ผ€์ดํ„ฐ(`height: 2`, `#ffffff`) ์ถ”๊ฐ€ + - ์‹คํ–‰ ๋ช…๋ น + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test` + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test` + - `lsp_diagnostics` (`CreatorCommunityAllView.swift`) + - ๊ฒฐ๊ณผ: + - ๋นŒ๋“œ: `SodaLive`, `SodaLive-dev` ๋ชจ๋‘ `** BUILD SUCCEEDED **`. + - ํ…Œ์ŠคํŠธ: ๋‘ ์Šคํ‚ด ๋ชจ๋‘ `Scheme ... is not currently configured for the test action.`. + - LSP: SourceKit ๋‹จ๋… ์ง„๋‹จ์—์„œ๋Š” ํ”„๋กœ์ ํŠธ ์‹ฌ๋ณผ ๋ฏธํ•ด๊ฒฐ ๋ฐ ํ™•์žฅ ํƒ€์ž… ํ•ด์„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋‚˜, ์‹ค์ œ xcodebuild๋Š” ์„ฑ๊ณต.