feat(community): 크리에이터 커뮤니티 게시물 고정 기능을 추가한다
This commit is contained in:
@@ -2506,6 +2506,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"고정 해제" : {
|
||||
|
||||
},
|
||||
"공개 설정" : {
|
||||
"localizations" : {
|
||||
@@ -4142,6 +4145,22 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"목" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Thu"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "木"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"모집완료" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@@ -4174,22 +4193,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"목" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Thu"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "木"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"무료" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@@ -8406,6 +8409,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"최상단에 고정" : {
|
||||
|
||||
},
|
||||
"최신 콘텐츠" : {
|
||||
"localizations" : {
|
||||
@@ -8647,22 +8653,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"캐릭터 정보" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Character info"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "キャラクター情報"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"캔" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@@ -8679,6 +8669,22 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"캐릭터 정보" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Character info"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "キャラクター情報"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"캔 충전" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
|
||||
@@ -257,6 +257,7 @@ struct CreatorCommunityAllItemView_Previews: PreviewProvider {
|
||||
isCommentAvailable: false,
|
||||
isAdult: false,
|
||||
isLike: true,
|
||||
isFixed: false,
|
||||
existOrdered: false,
|
||||
likeCount: 10,
|
||||
commentCount: 0,
|
||||
|
||||
@@ -74,6 +74,12 @@ struct CreatorCommunityAllView: View {
|
||||
CreatorCommunityMenuView(
|
||||
isShowing: $viewModel.isShowReportMenu,
|
||||
isShowCreatorMenu: creatorId == UserDefaults.int(forKey: .userId),
|
||||
isFixed: viewModel.isPostFixed,
|
||||
fixedAction: {
|
||||
if creatorId == UserDefaults.int(forKey: .userId) {
|
||||
viewModel.updateCommunityPostFixed()
|
||||
}
|
||||
},
|
||||
modifyAction: {
|
||||
let postId = viewModel.postId
|
||||
AppState.shared
|
||||
@@ -165,6 +171,7 @@ struct CreatorCommunityAllView: View {
|
||||
let item = viewModel.communityPostList[index]
|
||||
CreatorCommunityAllGridItemView(item: item)
|
||||
.id(index)
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.onTapGesture {
|
||||
selectedListIndex = index
|
||||
listAnchorIndex = index
|
||||
@@ -173,6 +180,9 @@ struct CreatorCommunityAllView: View {
|
||||
isGridMode = false
|
||||
}
|
||||
}
|
||||
.onLongPressGesture(minimumDuration: 0.5) {
|
||||
viewModel.openReportMenu(item: item)
|
||||
}
|
||||
.onAppear {
|
||||
if index == viewModel.communityPostList.count - 1 {
|
||||
viewModel.getCommunityPostList()
|
||||
@@ -243,8 +253,7 @@ struct CreatorCommunityAllView: View {
|
||||
)
|
||||
},
|
||||
onClickShowReportMenu: {
|
||||
viewModel.postId = item.postId
|
||||
viewModel.isShowReportMenu = true
|
||||
viewModel.openReportMenu(item: item)
|
||||
},
|
||||
onClickPurchaseContent: {
|
||||
viewModel.postId = item.postId
|
||||
@@ -328,20 +337,27 @@ private struct CreatorCommunityAllGridItemView: View {
|
||||
.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
|
||||
Rectangle()
|
||||
.fill(Color.clear)
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.overlay {
|
||||
AsyncImage(url: URL(string: imageUrl)) { phase in
|
||||
switch phase {
|
||||
case .empty:
|
||||
Color.gray33
|
||||
case .success(let image):
|
||||
image
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
case .failure:
|
||||
Color(hex: "263238")
|
||||
@unknown default:
|
||||
Color.gray33
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.clipped()
|
||||
} else {
|
||||
Color(hex: "263238")
|
||||
|
||||
@@ -355,6 +371,17 @@ private struct CreatorCommunityAllGridItemView: View {
|
||||
}
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.clipped()
|
||||
.overlay(alignment: .topTrailing) {
|
||||
if item.isFixed == true {
|
||||
Image("ic_pin")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 14, height: 14)
|
||||
.padding(8)
|
||||
.shadow(color: .black.opacity(0.45), radius: 2, x: 0, y: 1)
|
||||
.allowsHitTesting(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var isPaidLocked: Bool {
|
||||
|
||||
@@ -21,6 +21,7 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
@Published private(set) var communityPostList = [GetCommunityPostListResponse]()
|
||||
|
||||
@Published var postId = 0
|
||||
@Published var isPostFixed = false
|
||||
@Published var postPrice = 0
|
||||
@Published var postIndex = -1
|
||||
@Published var isShowSecret = false
|
||||
@@ -124,6 +125,12 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
isShowCommentListView = true
|
||||
}
|
||||
|
||||
func openReportMenu(item: GetCommunityPostListResponse) {
|
||||
postId = item.postId
|
||||
isPostFixed = item.isFixed == true
|
||||
isShowReportMenu = true
|
||||
}
|
||||
|
||||
func openCommentListForDeepLink(postId: Int) {
|
||||
guard postId > 0 else {
|
||||
return
|
||||
@@ -290,6 +297,56 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func updateCommunityPostFixed() {
|
||||
let postId = postId
|
||||
let nextIsFixed = !isPostFixed
|
||||
|
||||
guard postId > 0 else {
|
||||
return
|
||||
}
|
||||
|
||||
isLoading = true
|
||||
|
||||
let request = UpdateCommunityPostFixedRequest(postId: postId, isFixed: nextIsFixed)
|
||||
repository.updateCommunityPostFixed(request: request)
|
||||
.sink { result in
|
||||
switch result {
|
||||
case .finished:
|
||||
DEBUG_LOG("finish")
|
||||
case .failure(let error):
|
||||
ERROR_LOG(error.localizedDescription)
|
||||
}
|
||||
} receiveValue: { [unowned self] response in
|
||||
let responseData = response.data
|
||||
|
||||
do {
|
||||
let jsonDecoder = JSONDecoder()
|
||||
let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: responseData)
|
||||
|
||||
if decoded.success {
|
||||
self.isPostFixed = nextIsFixed
|
||||
DispatchQueue.main.async {
|
||||
self.refreshCommunityPostListKeepingLoadedCount()
|
||||
}
|
||||
} else {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.isShowPopup = true
|
||||
}
|
||||
|
||||
self.isLoading = false
|
||||
}
|
||||
.store(in: &subscription)
|
||||
}
|
||||
|
||||
func purchaseCommunityPost() {
|
||||
let postId = postId
|
||||
let postIndex = postIndex
|
||||
@@ -337,6 +394,13 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
private func refreshCommunityPostListKeepingLoadedCount() {
|
||||
pageSize = max(communityPostList.count, 10)
|
||||
page = 1
|
||||
isLast = false
|
||||
getCommunityPostList()
|
||||
}
|
||||
|
||||
private func shouldShowSecretCommentOption(item: GetCommunityPostListResponse) -> Bool {
|
||||
item.price > 0 && item.existOrdered && item.creatorId != UserDefaults.int(forKey: .userId)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,9 @@ struct CreatorCommunityMenuView: View {
|
||||
@Binding var isShowing: Bool
|
||||
|
||||
let isShowCreatorMenu: Bool
|
||||
let isFixed: Bool
|
||||
|
||||
let fixedAction: () -> Void
|
||||
let modifyAction: () -> Void
|
||||
let deleteAction: () -> Void
|
||||
let reportAction: () -> Void
|
||||
@@ -28,6 +30,23 @@ struct CreatorCommunityMenuView: View {
|
||||
|
||||
VStack(spacing: 13.3) {
|
||||
if isShowCreatorMenu {
|
||||
HStack(spacing: 13.3) {
|
||||
Image(isFixed ? "ic_pin_cancel" : "ic_pin")
|
||||
|
||||
Text(isFixed ? "고정 해제" : "최상단에 고정")
|
||||
.appFont(size: 16.7, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.vertical, 8)
|
||||
.padding(.horizontal, 26.7)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
isShowing = false
|
||||
fixedAction()
|
||||
}
|
||||
|
||||
HStack(spacing: 13.3) {
|
||||
Image("ic_make_message")
|
||||
|
||||
@@ -90,6 +109,8 @@ struct CreatorCommunityMenuView: View {
|
||||
CreatorCommunityMenuView(
|
||||
isShowing: .constant(true),
|
||||
isShowCreatorMenu: true,
|
||||
isFixed: false,
|
||||
fixedAction: {},
|
||||
modifyAction: {},
|
||||
deleteAction: {},
|
||||
reportAction: {}
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
import Foundation
|
||||
import Moya
|
||||
|
||||
struct UpdateCommunityPostFixedRequest: Encodable {
|
||||
let postId: Int
|
||||
let isFixed: Bool
|
||||
}
|
||||
|
||||
enum CreatorCommunityApi {
|
||||
case createCommunityPost(parameters: [MultipartFormData])
|
||||
case modifyCommunityPost(parameters: [MultipartFormData])
|
||||
@@ -20,6 +25,7 @@ enum CreatorCommunityApi {
|
||||
case modifyComment(request: ModifyCommunityPostCommentRequest)
|
||||
case getLatestPostListFromCreatorsYouFollow
|
||||
case purchaseCommunityPost(postId: Int)
|
||||
case updateCommunityPostFixed(request: UpdateCommunityPostFixedRequest)
|
||||
}
|
||||
|
||||
extension CreatorCommunityApi: TargetType {
|
||||
@@ -52,6 +58,9 @@ extension CreatorCommunityApi: TargetType {
|
||||
|
||||
case .purchaseCommunityPost:
|
||||
return "/creator-community/purchase"
|
||||
|
||||
case .updateCommunityPostFixed:
|
||||
return "/creator-community/fixed"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +72,7 @@ extension CreatorCommunityApi: TargetType {
|
||||
case .getCommunityPostList, .getCommunityPostCommentList, .getCommentReplyList, .getCommunityPostDetail, .getLatestPostListFromCreatorsYouFollow:
|
||||
return .get
|
||||
|
||||
case .modifyComment, .modifyCommunityPost:
|
||||
case .modifyComment, .modifyCommunityPost, .updateCommunityPostFixed:
|
||||
return .put
|
||||
}
|
||||
}
|
||||
@@ -122,6 +131,9 @@ extension CreatorCommunityApi: TargetType {
|
||||
|
||||
case .purchaseCommunityPost(let postId):
|
||||
return .requestJSONEncodable(PurchasePostRequest(postId: postId))
|
||||
|
||||
case .updateCommunityPostFixed(let request):
|
||||
return .requestJSONEncodable(request)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ struct CreatorCommunityItemView_Previews: PreviewProvider {
|
||||
isCommentAvailable: false,
|
||||
isAdult: false,
|
||||
isLike: false,
|
||||
isFixed: false,
|
||||
existOrdered: false,
|
||||
likeCount: 10,
|
||||
commentCount: 0,
|
||||
|
||||
@@ -56,4 +56,8 @@ class CreatorCommunityRepository {
|
||||
func purchaseCommunityPost(postId: Int) -> AnyPublisher<Response, MoyaError> {
|
||||
return api.requestPublisher(.purchaseCommunityPost(postId: postId))
|
||||
}
|
||||
|
||||
func updateCommunityPostFixed(request: UpdateCommunityPostFixedRequest) -> AnyPublisher<Response, MoyaError> {
|
||||
return api.requestPublisher(.updateCommunityPostFixed(request: request))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ struct GetCommunityPostListResponse: Decodable {
|
||||
let isCommentAvailable: Bool
|
||||
let isAdult: Bool
|
||||
let isLike: Bool
|
||||
var isFixed: Bool?
|
||||
let existOrdered: Bool
|
||||
let likeCount: Int
|
||||
let commentCount: Int
|
||||
|
||||
@@ -58,6 +58,7 @@ struct SectionCommunityPostView_Previews: PreviewProvider {
|
||||
isCommentAvailable: false,
|
||||
isAdult: false,
|
||||
isLike: true,
|
||||
isFixed: false,
|
||||
existOrdered: false,
|
||||
likeCount: 10,
|
||||
commentCount: 0,
|
||||
@@ -77,6 +78,7 @@ struct SectionCommunityPostView_Previews: PreviewProvider {
|
||||
isCommentAvailable: false,
|
||||
isAdult: false,
|
||||
isLike: true,
|
||||
isFixed: false,
|
||||
existOrdered: false,
|
||||
likeCount: 20,
|
||||
commentCount: 0,
|
||||
|
||||
39
docs/20260316_크리에이터커뮤니티게시물고정기능.md
Normal file
39
docs/20260316_크리에이터커뮤니티게시물고정기능.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# 크리에이터 커뮤니티 게시물 고정 기능 구현
|
||||
|
||||
- [x] API `/creator-community/fixed` (`PUT`) 추가
|
||||
- [x] `UpdateCommunityPostFixedRequest` DTO 추가 및 Repository 연결
|
||||
- [x] 리스트 모드 보조 메뉴에 고정/해제 항목 추가
|
||||
- [x] 그리드 모드 길게 터치 시 보조 메뉴 표시 연결
|
||||
- [x] 보조 메뉴를 BottomSheet 형태로 표시
|
||||
- [x] 고정 상태에 따라 문구 분기 (`최상단에 고정` / `고정 해제`)
|
||||
- [x] 고정 게시물 우측 상단 핀 표시를 그리드 모드에만 적용
|
||||
- [x] 그리드 모드 게시물 이미지를 1:1 비율로 표시
|
||||
- [x] 진단/빌드/테스트 수행 및 결과 기록
|
||||
|
||||
---
|
||||
|
||||
## 검증 기록
|
||||
|
||||
- `lsp_diagnostics` (수정 파일 전체): SourceKit 환경에서 외부 모듈(`Moya`, `Kingfisher`) 인식 오류가 지속되어 진단 신뢰성이 낮아 빌드 결과로 최종 검증함.
|
||||
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build`: 성공 (`** BUILD SUCCEEDED **`).
|
||||
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`: 성공 (`** BUILD SUCCEEDED **`).
|
||||
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test`: 실패 (`Scheme SodaLive is not currently configured for the test action.`).
|
||||
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test`: 실패 (`Scheme SodaLive-dev is not currently configured for the test action.`).
|
||||
- (추가 반영) `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build && xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`: 성공 (`** BUILD SUCCEEDED **` 2회).
|
||||
- (추가 반영) `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test; xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test`: 두 스킴 모두 test action 미구성으로 실패.
|
||||
- (요구사항 조정) 리스트 모드 핀 오버레이 제거, 그리드 모드(`CreatorCommunityAllGridItemView`)만 핀 표시 유지.
|
||||
- (요구사항 조정) 그리드 모드 셀 내부 콘텐츠에 `frame(maxWidth: .infinity, maxHeight: .infinity)`를 적용해 1:1 비율 셀에서 이미지가 항상 정사각형 기준으로 표시되도록 고정.
|
||||
- (요구사항 조정) `gridContentView`에서 셀 프레임을 `width = (containerWidth - 2) / 3`, `height = width`로 직접 지정해 긴 이미지여도 세로가 가로를 넘지 않도록 고정.
|
||||
- (추가 반영) `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build && xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`: 성공 (`** BUILD SUCCEEDED **` 2회).
|
||||
- (추가 반영) `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test; xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test`: 두 스킴 모두 test action 미구성으로 실패.
|
||||
- (요구사항 조정) 그리드 셀의 `aspectRatio` 기반 계산을 제거하고, `CreatorCommunityAllGridItemView` 호출부에서 정사각형 고정 프레임을 직접 부여.
|
||||
- (추가 반영) `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build && xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`: 성공 (`** BUILD SUCCEEDED **` 2회).
|
||||
- (추가 반영) `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test; xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test`: 두 스킴 모두 test action 미구성으로 실패.
|
||||
- (요구사항 조정) 바깥 폭(`containerWidth`) 기반 고정 계산을 제거하고, `LazyVGrid` 컬럼 폭에 맞춰 `CreatorCommunityAllGridItemView` 내부 `aspectRatio(1, .fit)`로 정사각형을 강제해 옆 셀 침범을 방지.
|
||||
- (요구사항 조정) 정사각형은 `LazyVGrid` 컬럼 자체 폭 기준으로만 계산되도록 `gridContentView(containerWidth:)`와 `gridItemLength`를 제거해 긴 원본 비율 이미지의 옆 셀 침범을 차단.
|
||||
- (추가 반영) `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build && xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`: 성공 (`** BUILD SUCCEEDED **` 2회).
|
||||
- (추가 반영) `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test; xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test`: 두 스킴 모두 test action 미구성으로 실패.
|
||||
- (요구사항 조정) `GeometryReader` 내부 실제 그리드 폭 기준으로 `gridItemLength = (width - 2) / 3`를 계산하고 각 아이템에 `frame(width: gridItemLength, height: gridItemLength)`를 적용해 1:1을 강제.
|
||||
- (요구사항 조정) 아이템 내부 중복 비율 제약(`aspectRatio`)을 제거해 부모 고정 프레임과 충돌하지 않도록 정리.
|
||||
- (추가 반영) `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build && xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`: 성공 (`** BUILD SUCCEEDED **` 2회).
|
||||
- (추가 반영) `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test; xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test`: 두 스킴 모두 test action 미구성으로 실패.
|
||||
15
docs/20260317_현재변경사항안전커밋.md
Normal file
15
docs/20260317_현재변경사항안전커밋.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# 현재 변경사항 안전 커밋
|
||||
|
||||
- [x] `commit-policy` 스킬을 로드한다.
|
||||
- [x] 작업 트리 상태(`git status`, `git diff --cached`, `git diff`, `git log -5 --oneline`)를 확인한다.
|
||||
- [x] 커밋 대상 파일만 스테이징하고 민감정보 파일 제외 여부를 점검한다.
|
||||
- [x] 커밋 메시지 규칙(``<type>(scope): <description>`` + 한글 description)을 만족하는 메시지를 확정한다.
|
||||
- [x] 커밋 전 메시지 검증 스크립트를 실행해 PASS를 확인한다.
|
||||
- [ ] 커밋을 수행한다.
|
||||
- [ ] 커밋 후 메시지 검증 스크립트를 실행해 PASS를 확인한다.
|
||||
|
||||
---
|
||||
|
||||
## 검증 기록
|
||||
|
||||
- (진행 중) 커밋 실행 이후 명령/결과를 누적 기록한다.
|
||||
Reference in New Issue
Block a user