feat(i18n): 탐색 프로필 하드코딩 문구를 I18n 키로 통일한다
This commit is contained in:
@@ -51,7 +51,7 @@ struct ExplorerSectionView: View {
|
||||
.appFont(size: 14.7, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Text("※ 인기 크리에이터의 순위는 매주 업데이트됩니다.")
|
||||
Text(I18n.Explorer.rankingWeeklyUpdateNotice)
|
||||
.appFont(size: 13.3, weight: .light)
|
||||
.foregroundColor(Color(hex: "bbbbbb"))
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ struct ExplorerView: View {
|
||||
HStack(spacing: 0) {
|
||||
Image("ic_title_search_black")
|
||||
|
||||
TextField("채널명을 입력해 보세요", text: $viewModel.channel)
|
||||
TextField(I18n.Explorer.searchChannelPlaceholder, text: $viewModel.channel)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
@@ -72,7 +72,7 @@ struct ExplorerView: View {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text("검색 결과가 없습니다.")
|
||||
Text(I18n.Explorer.searchEmptyResult)
|
||||
.appFont(size: 18.3, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
.padding(.top, 40)
|
||||
|
||||
@@ -62,13 +62,13 @@ final class ExplorerViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
@@ -98,13 +98,13 @@ final class ExplorerViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,11 +115,15 @@ private extension ChannelDonationItemView {
|
||||
}
|
||||
|
||||
func highlightedMessageText(_ message: String) -> Text {
|
||||
let plainCanToken = "\(item.can)캔"
|
||||
let commaCanToken = "\(item.can.comma())캔"
|
||||
let plainCanToken = "\(item.can)\(I18n.Explorer.canUnitCompact)"
|
||||
let commaCanToken = "\(item.can.comma())\(I18n.Explorer.canUnitCompact)"
|
||||
let plainCanTokenWithSpace = "\(item.can)\(I18n.Explorer.canUnitWithSpace)"
|
||||
let commaCanTokenWithSpace = "\(item.can.comma())\(I18n.Explorer.canUnitWithSpace)"
|
||||
|
||||
let range = message.range(of: commaCanToken)
|
||||
?? message.range(of: plainCanToken)
|
||||
?? message.range(of: commaCanTokenWithSpace)
|
||||
?? message.range(of: plainCanTokenWithSpace)
|
||||
|
||||
guard let range else {
|
||||
return Text(message).foregroundColor(Color(hex: "CFD8DC"))
|
||||
|
||||
@@ -45,7 +45,7 @@ struct CreatorCommunityCommentItemView: View {
|
||||
.foregroundColor(Color.gray90)
|
||||
|
||||
if commentItem.isSecret {
|
||||
Text("비밀댓글")
|
||||
Text(I18n.Explorer.secretComment)
|
||||
.appFont(size: 11, weight: .medium)
|
||||
.foregroundColor(Color.grayee)
|
||||
.padding(.horizontal, 4)
|
||||
@@ -72,7 +72,7 @@ struct CreatorCommunityCommentItemView: View {
|
||||
HStack(spacing: 0) {
|
||||
if isModeModify {
|
||||
HStack(spacing: 0) {
|
||||
TextField("댓글을 입력해 보세요.", text: $comment)
|
||||
TextField(I18n.Explorer.commentInputPlaceholder, text: $comment)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
@@ -119,7 +119,7 @@ struct CreatorCommunityCommentItemView: View {
|
||||
parentComment: commentItem
|
||||
)
|
||||
) {
|
||||
Text(commentItem.replyCount > 0 ? "답글 \(commentItem.replyCount)개" : "답글 쓰기")
|
||||
Text(commentItem.replyCount > 0 ? I18n.Explorer.replyCount(commentItem.replyCount) : I18n.Explorer.replyWrite)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color.button)
|
||||
}
|
||||
@@ -140,7 +140,7 @@ struct CreatorCommunityCommentItemView: View {
|
||||
if isShowPopupMenu {
|
||||
VStack(spacing: 10) {
|
||||
if commentItem.writerId == UserDefaults.int(forKey: .userId) {
|
||||
Text("수정")
|
||||
Text(I18n.Explorer.edit)
|
||||
.appFont(size: 14, weight: .medium)
|
||||
.foregroundColor(Color(hex: "777777"))
|
||||
.onTapGesture {
|
||||
@@ -152,7 +152,7 @@ struct CreatorCommunityCommentItemView: View {
|
||||
if creatorId == UserDefaults.int(forKey: .userId) ||
|
||||
commentItem.writerId == UserDefaults.int(forKey: .userId)
|
||||
{
|
||||
Text("삭제")
|
||||
Text(I18n.Common.delete)
|
||||
.appFont(size: 14, weight: .medium)
|
||||
.foregroundColor(Color(hex: "777777"))
|
||||
.onTapGesture {
|
||||
|
||||
@@ -29,7 +29,7 @@ struct CreatorCommunityCommentListView: View {
|
||||
ZStack {
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
Text("댓글")
|
||||
Text(I18n.RankingSort.comments)
|
||||
.appFont(size: 14.7, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
.padding(.leading, 13.3)
|
||||
@@ -65,7 +65,7 @@ struct CreatorCommunityCommentListView: View {
|
||||
viewModel.isSecret.toggle()
|
||||
}
|
||||
|
||||
Text("비밀댓글")
|
||||
Text(I18n.Explorer.secretComment)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(viewModel.isSecret ? Color.button : Color.grayee)
|
||||
.onTapGesture {
|
||||
@@ -84,7 +84,7 @@ struct CreatorCommunityCommentListView: View {
|
||||
.clipShape(Circle())
|
||||
|
||||
HStack(spacing: 0) {
|
||||
TextField("댓글을 입력해 보세요.", text: $viewModel.comment)
|
||||
TextField(I18n.Explorer.commentInputPlaceholder, text: $viewModel.comment)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
|
||||
@@ -60,13 +60,13 @@ final class CreatorCommunityCommentListViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
|
||||
@@ -108,13 +108,13 @@ final class CreatorCommunityCommentListViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
@@ -129,13 +129,13 @@ final class CreatorCommunityCommentListViewModel: ObservableObject {
|
||||
isActive: Bool? = nil
|
||||
) {
|
||||
if comment == nil && isActive == nil {
|
||||
errorMessage = "변경사항이 없습니다."
|
||||
errorMessage = I18n.Explorer.noChanges
|
||||
isShowPopup = true
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if let comment = comment, comment.trimmingCharacters(in: .whitespaces).isEmpty {
|
||||
errorMessage = "내용을 입력하세요."
|
||||
errorMessage = I18n.Explorer.inputContentWithPeriod
|
||||
isShowPopup = true
|
||||
return
|
||||
}
|
||||
@@ -181,14 +181,14 @@ final class CreatorCommunityCommentListViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.isLoading = false
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ struct CreatorCommunityCommentReplyView: View {
|
||||
HStack(spacing: 6.7) {
|
||||
Image("ic_back")
|
||||
|
||||
Text("답글")
|
||||
Text(I18n.Explorer.replyTitle)
|
||||
.appFont(size: 14.7, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
|
||||
@@ -55,7 +55,7 @@ struct CreatorCommunityCommentReplyView: View {
|
||||
.clipShape(Circle())
|
||||
|
||||
HStack(spacing: 0) {
|
||||
TextField("댓글을 입력해 보세요.", text: $viewModel.comment)
|
||||
TextField(I18n.Explorer.commentInputPlaceholder, text: $viewModel.comment)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
|
||||
@@ -61,13 +61,13 @@ final class CreatorCommunityCommentReplyViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
|
||||
@@ -108,13 +108,13 @@ final class CreatorCommunityCommentReplyViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
@@ -129,13 +129,13 @@ final class CreatorCommunityCommentReplyViewModel: ObservableObject {
|
||||
isActive: Bool? = nil
|
||||
) {
|
||||
if comment == nil && isActive == nil {
|
||||
errorMessage = "변경사항이 없습니다."
|
||||
errorMessage = I18n.Explorer.noChanges
|
||||
isShowPopup = true
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if let comment = comment, comment.trimmingCharacters(in: .whitespaces).isEmpty {
|
||||
errorMessage = "내용을 입력하세요."
|
||||
errorMessage = I18n.Explorer.inputContentWithPeriod
|
||||
isShowPopup = true
|
||||
return
|
||||
}
|
||||
@@ -181,14 +181,14 @@ final class CreatorCommunityCommentReplyViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.isLoading = false
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ struct CreatorCommunityCommentView: View {
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 11) {
|
||||
HStack(spacing: 5.3) {
|
||||
Text("댓글")
|
||||
Text(I18n.RankingSort.comments)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
|
||||
@@ -39,7 +39,7 @@ struct CreatorCommunityCommentView: View {
|
||||
isSecret.toggle()
|
||||
}
|
||||
|
||||
Text("비밀댓글")
|
||||
Text(I18n.Explorer.secretComment)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(isSecret ? Color.button : Color.grayee)
|
||||
.onTapGesture {
|
||||
@@ -81,7 +81,7 @@ struct CreatorCommunityCommentView: View {
|
||||
.clipShape(Circle())
|
||||
|
||||
HStack(spacing: 0) {
|
||||
TextField("댓글을 입력해 보세요.", text: $comment)
|
||||
TextField(I18n.Explorer.commentInputPlaceholder, text: $comment)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
|
||||
@@ -16,7 +16,7 @@ struct CreatorCommunityAllItemLockView: View {
|
||||
VStack(spacing: 26.7) {
|
||||
Image("ic_lock_bb")
|
||||
|
||||
Text("\(price)캔으로 게시글 보기")
|
||||
Text(I18n.Explorer.viewPostWithCans(price))
|
||||
.appFont(size: 12, weight: .bold)
|
||||
.foregroundColor(Color.button)
|
||||
.padding(.horizontal, 21)
|
||||
|
||||
@@ -31,7 +31,7 @@ struct CreatorCommunityAllView: View {
|
||||
BaseView(isLoading: $viewModel.isLoading) {
|
||||
VStack(spacing: 0) {
|
||||
DetailNavigationBar(
|
||||
title: "커뮤니티",
|
||||
title: I18n.Explorer.communityTitle,
|
||||
backAction: {
|
||||
if isGridMode {
|
||||
AppState.shared.back()
|
||||
|
||||
@@ -103,13 +103,13 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
|
||||
@@ -189,13 +189,13 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
|
||||
@@ -227,12 +227,12 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
@@ -269,7 +269,7 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: responseData)
|
||||
|
||||
if decoded.success {
|
||||
self.errorMessage = "삭제되었습니다"
|
||||
self.errorMessage = I18n.Explorer.deleted
|
||||
self.isShowPopup = true
|
||||
|
||||
self.page = 1
|
||||
@@ -279,19 +279,19 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
.store(in: &subscription)
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
self.isLoading = false
|
||||
}
|
||||
@@ -332,13 +332,13 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
|
||||
@@ -378,13 +378,13 @@ class CreatorCommunityAllViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ struct CreatorCommunityMenuView: View {
|
||||
HStack(spacing: 13.3) {
|
||||
Image(isFixed ? "ic_pin_cancel" : "ic_pin")
|
||||
|
||||
Text(isFixed ? "고정 해제" : "최상단에 고정")
|
||||
Text(isFixed ? I18n.Explorer.pinRelease : I18n.Explorer.pinToTop)
|
||||
.appFont(size: 16.7, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
|
||||
@@ -50,7 +50,7 @@ struct CreatorCommunityMenuView: View {
|
||||
HStack(spacing: 13.3) {
|
||||
Image("ic_make_message")
|
||||
|
||||
Text("수정")
|
||||
Text(I18n.Explorer.edit)
|
||||
.appFont(size: 16.7, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
|
||||
@@ -67,7 +67,7 @@ struct CreatorCommunityMenuView: View {
|
||||
HStack(spacing: 13.3) {
|
||||
Image("ic_trash_can")
|
||||
|
||||
Text("삭제")
|
||||
Text(I18n.Common.delete)
|
||||
.appFont(size: 16.7, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
|
||||
@@ -82,7 +82,7 @@ struct CreatorCommunityMenuView: View {
|
||||
}
|
||||
} else {
|
||||
HStack(spacing: 0) {
|
||||
Text("신고")
|
||||
Text(I18n.Explorer.report)
|
||||
.appFont(size: 16.7, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ final class CreatorCommunityMediaPlayerManager: NSObject, ObservableObject {
|
||||
}
|
||||
|
||||
private func showError() {
|
||||
self.errorMessage = "오류가 발생했습니다. 다시 시도해 주세요."
|
||||
self.errorMessage = I18n.Message.Voice.Sound.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ struct CreatorCommunityMoreItemView: View {
|
||||
.resizable()
|
||||
.frame(width: 40, height: 40)
|
||||
|
||||
Text("더보기")
|
||||
Text(I18n.Explorer.viewMore)
|
||||
.appFont(size: 11, weight: .light)
|
||||
.foregroundColor(Color(hex: "bbbbbb"))
|
||||
}
|
||||
|
||||
@@ -15,11 +15,11 @@ struct CreatorCommunityNoPostsItemView: View {
|
||||
VStack(spacing: 10.3) {
|
||||
CreatorCommunityWriteItemView()
|
||||
|
||||
Text("게시물 등록")
|
||||
Text(I18n.Explorer.postRegister)
|
||||
.appFont(size: 14.7, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Text("게시 후에 게시물이 여기에 표시되고\n커뮤니티에 공개됩니다.")
|
||||
|
||||
Text(I18n.Explorer.postRegisterDescription)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(Color(hex: "777777"))
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
|
||||
@@ -24,12 +24,12 @@ struct CreatorCommunityModifyView: View {
|
||||
GeometryReader { proxy in
|
||||
ZStack {
|
||||
VStack(spacing: 0) {
|
||||
DetailNavigationBar(title: "게시글 수정")
|
||||
DetailNavigationBar(title: I18n.Explorer.postModifyTitle)
|
||||
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 13.3) {
|
||||
Text("이미지")
|
||||
Text(I18n.Explorer.imageTitle)
|
||||
.appFont(size: 16.7, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
@@ -81,7 +81,7 @@ struct CreatorCommunityModifyView: View {
|
||||
viewModel.postImageData = data
|
||||
}
|
||||
} catch {
|
||||
viewModel.errorMessage = "이미지를 로드하지 못했습니다."
|
||||
viewModel.errorMessage = I18n.Explorer.imageLoadFailed
|
||||
viewModel.isShowPopup = true
|
||||
DEBUG_LOG("이미지 로드 실패: \(error)")
|
||||
}
|
||||
@@ -94,24 +94,24 @@ struct CreatorCommunityModifyView: View {
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "777777"))
|
||||
|
||||
Text("등록할 이미지가 없으면 이미지 없이 게시글만 등록 하셔도 됩니다.")
|
||||
Text(I18n.Explorer.imageOptionalNotice)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "777777"))
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.top, 24)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("내용")
|
||||
Text(I18n.Explorer.contentTitle)
|
||||
.appFont(size: 16.7, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("\(viewModel.content.count)자")
|
||||
Text("\(viewModel.content.count)\(I18n.Explorer.contentCharacterUnit)")
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "ff5c49"))
|
||||
Text(" / 최대 500자")
|
||||
Text(I18n.Explorer.max500Chars)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "777777"))
|
||||
}
|
||||
@@ -128,14 +128,14 @@ struct CreatorCommunityModifyView: View {
|
||||
.padding(.top, 13.3)
|
||||
|
||||
VStack(spacing: 13.3) {
|
||||
Text("댓글 가능 여부")
|
||||
Text(I18n.Explorer.commentAvailability)
|
||||
.appFont(size: 16.7, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
HStack(spacing: 13.3) {
|
||||
SelectButtonView(
|
||||
title: "댓글 가능",
|
||||
title: I18n.CreateContent.commentAllowed,
|
||||
isChecked: viewModel.isAvailableComment
|
||||
) {
|
||||
if !viewModel.isAvailableComment {
|
||||
@@ -144,7 +144,7 @@ struct CreatorCommunityModifyView: View {
|
||||
}
|
||||
|
||||
SelectButtonView(
|
||||
title: "댓글 불가",
|
||||
title: I18n.CreateContent.commentNotAllowed,
|
||||
isChecked: !viewModel.isAvailableComment
|
||||
) {
|
||||
if viewModel.isAvailableComment {
|
||||
@@ -156,14 +156,14 @@ struct CreatorCommunityModifyView: View {
|
||||
.padding(.top, 26.7)
|
||||
|
||||
VStack(spacing: 13.3) {
|
||||
Text("연령 제한")
|
||||
Text(I18n.Explorer.ageRestriction)
|
||||
.appFont(size: 16.7, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
HStack(spacing: 13.3) {
|
||||
SelectButtonView(
|
||||
title: "전체 연령",
|
||||
title: I18n.CreateContent.allAges,
|
||||
isChecked: !viewModel.isAdult
|
||||
) {
|
||||
if viewModel.isAdult {
|
||||
@@ -172,7 +172,7 @@ struct CreatorCommunityModifyView: View {
|
||||
}
|
||||
|
||||
SelectButtonView(
|
||||
title: "19세 이상",
|
||||
title: I18n.CreateContent.over19,
|
||||
isChecked: viewModel.isAdult
|
||||
) {
|
||||
if !viewModel.isAdult {
|
||||
@@ -187,7 +187,7 @@ struct CreatorCommunityModifyView: View {
|
||||
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 13.3) {
|
||||
Text("닫기")
|
||||
Text(I18n.Explorer.close)
|
||||
.appFont(size: 18.3, weight: .bold)
|
||||
.foregroundColor(Color(hex: "3BB9F1"))
|
||||
.frame(maxWidth: .infinity)
|
||||
@@ -203,7 +203,7 @@ struct CreatorCommunityModifyView: View {
|
||||
AppState.shared.back()
|
||||
}
|
||||
|
||||
Text("수정")
|
||||
Text(I18n.Explorer.modify)
|
||||
.appFont(size: 18.3, weight: .bold)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
@@ -24,7 +24,7 @@ final class CreatorCommunityModifyViewModel: ObservableObject {
|
||||
@Published var postImageUrl: String? = nil
|
||||
@Published private(set) var communityPost: GetCommunityPostListResponse?
|
||||
|
||||
var placeholder = "내용을 입력하세요"
|
||||
var placeholder = I18n.Explorer.inputContent
|
||||
var postId = 0
|
||||
|
||||
func getCommunityPostDetail(onFailure: (() -> Void)? = nil) {
|
||||
@@ -58,7 +58,7 @@ final class CreatorCommunityModifyViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
@@ -67,7 +67,7 @@ final class CreatorCommunityModifyViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
if let onFailure = onFailure {
|
||||
onFailure()
|
||||
@@ -126,7 +126,7 @@ final class CreatorCommunityModifyViewModel: ObservableObject {
|
||||
let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: responseData)
|
||||
|
||||
if decoded.success {
|
||||
self.errorMessage = "게시물이 수정되었습니다."
|
||||
self.errorMessage = I18n.Explorer.postUpdated
|
||||
self.isShowPopup = true
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
@@ -136,19 +136,19 @@ final class CreatorCommunityModifyViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
.store(in: &subscription)
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
self.isLoading = false
|
||||
}
|
||||
@@ -157,7 +157,7 @@ final class CreatorCommunityModifyViewModel: ObservableObject {
|
||||
|
||||
private func validateData() -> Bool {
|
||||
if content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty || content.count < 5 {
|
||||
errorMessage = "내용을 5자 이상 입력해 주세요."
|
||||
errorMessage = I18n.Explorer.minContentLength(5)
|
||||
isShowPopup = true
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ struct CreatorCommunityRecordingVoiceView: View {
|
||||
VStack {
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
Text("음성녹음")
|
||||
Text(I18n.Explorer.recordingTitle)
|
||||
.appFont(size: 18.3, weight: .bold)
|
||||
.foregroundColor(.white)
|
||||
|
||||
@@ -77,7 +77,7 @@ struct CreatorCommunityRecordingVoiceView: View {
|
||||
HStack(spacing: 0) {
|
||||
Spacer()
|
||||
|
||||
Text("삭제")
|
||||
Text(I18n.Common.delete)
|
||||
.appFont(size: 15.3, weight: .medium)
|
||||
.foregroundColor(Color.graybb.opacity(0))
|
||||
|
||||
@@ -100,7 +100,7 @@ struct CreatorCommunityRecordingVoiceView: View {
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("삭제")
|
||||
Text(I18n.Common.delete)
|
||||
.appFont(size: 15.3, weight: .medium)
|
||||
.foregroundColor(Color.graybb)
|
||||
.onTapGesture {
|
||||
@@ -114,7 +114,7 @@ struct CreatorCommunityRecordingVoiceView: View {
|
||||
.padding(.vertical, 52.3)
|
||||
|
||||
HStack(spacing: 13.3) {
|
||||
Text("다시 녹음")
|
||||
Text(I18n.Explorer.recordAgain)
|
||||
.appFont(size: 18.3, weight: .bold)
|
||||
.foregroundColor(Color.button)
|
||||
.frame(width: (proxy.size.width - 40) / 3, height: 50)
|
||||
@@ -130,7 +130,7 @@ struct CreatorCommunityRecordingVoiceView: View {
|
||||
soundManager.recordMode = .RECORD
|
||||
}
|
||||
|
||||
Text("녹음완료")
|
||||
Text(I18n.Explorer.recordingComplete)
|
||||
.appFont(size: 18.3, weight: .bold)
|
||||
.foregroundColor(.white)
|
||||
.frame(width: (proxy.size.width - 40) * 2 / 3, height: 50)
|
||||
@@ -143,7 +143,7 @@ struct CreatorCommunityRecordingVoiceView: View {
|
||||
self.fileName = tempFileName
|
||||
self.isShowing = false
|
||||
} catch {
|
||||
errorMessage = "녹음파일을 생성하지 못했습니다.\n다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
errorMessage = I18n.Explorer.recordingFileCreateFailed
|
||||
isShowPopup = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,14 +44,14 @@ class CreatorCommunitySoundManager: NSObject, ObservableObject {
|
||||
audioSession.requestRecordPermission() { [weak self] allowed in
|
||||
DispatchQueue.main.async {
|
||||
if !allowed {
|
||||
self?.errorMessage = "권한을 허용하지 않으시면 음성녹음을 하실 수 없습니다."
|
||||
self?.errorMessage = I18n.Explorer.recordingPermissionDenied
|
||||
self?.isShowPopup = true
|
||||
self?.onClose = true
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
errorMessage = "오류가 발생했습니다. 다시 시도해 주세요."
|
||||
errorMessage = I18n.Message.Voice.Sound.commonError
|
||||
isShowPopup = true
|
||||
onClose = true
|
||||
}
|
||||
@@ -84,7 +84,7 @@ class CreatorCommunitySoundManager: NSObject, ObservableObject {
|
||||
|
||||
startTimer()
|
||||
} catch {
|
||||
errorMessage = "오류가 발생했습니다. 다시 시도해 주세요."
|
||||
errorMessage = I18n.Message.Voice.Sound.commonError
|
||||
isShowPopup = true
|
||||
}
|
||||
isLoading = false
|
||||
@@ -117,7 +117,7 @@ class CreatorCommunitySoundManager: NSObject, ObservableObject {
|
||||
self.player?.delegate = self
|
||||
self.player?.prepareToPlay()
|
||||
} catch {
|
||||
self.errorMessage = "오류가 발생했습니다. 다시 시도해 주세요."
|
||||
self.errorMessage = I18n.Message.Voice.Sound.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
|
||||
@@ -142,7 +142,9 @@ class CreatorCommunitySoundManager: NSObject, ObservableObject {
|
||||
func deleteAudioFile() {
|
||||
do {
|
||||
try FileManager.default.removeItem(at: getAudioFileURL())
|
||||
} catch {}
|
||||
} catch {
|
||||
DEBUG_LOG("오디오 파일 삭제 실패: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func getAudioFileURL() -> URL {
|
||||
|
||||
@@ -19,7 +19,7 @@ struct CreatorCommunityWriteView: View {
|
||||
@State private var isImageLoading = false
|
||||
|
||||
@State private var isShowRecordingVoiceView = false
|
||||
@State private var fileName: String = "녹음"
|
||||
@State private var fileName: String = I18n.Explorer.recordingDefaultFileName
|
||||
|
||||
private let imagePreviewSize: CGFloat = 110
|
||||
|
||||
@@ -30,12 +30,12 @@ struct CreatorCommunityWriteView: View {
|
||||
GeometryReader { proxy in
|
||||
ZStack {
|
||||
VStack(spacing: 0) {
|
||||
DetailNavigationBar(title: "게시글 등록")
|
||||
DetailNavigationBar(title: I18n.Explorer.postWriteTitle)
|
||||
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 13.3) {
|
||||
Text("이미지")
|
||||
Text(I18n.Explorer.imageTitle)
|
||||
.appFont(size: 16.7, weight: .bold)
|
||||
.foregroundColor(Color.grayee)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
@@ -75,7 +75,7 @@ struct CreatorCommunityWriteView: View {
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color.gray77)
|
||||
|
||||
Text("등록할 이미지가 없으면 이미지 없이 게시글만 등록 하셔도 됩니다.")
|
||||
Text(I18n.Explorer.imageOptionalNotice)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color.gray77)
|
||||
}
|
||||
@@ -85,7 +85,7 @@ struct CreatorCommunityWriteView: View {
|
||||
if let _ = viewModel.postImageData {
|
||||
VStack(spacing: 13.3) {
|
||||
HStack(spacing: 0) {
|
||||
Text("오디오 녹음")
|
||||
Text(I18n.Explorer.audioRecordingTitle)
|
||||
.appFont(size: 16.7, weight: .bold)
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
@@ -107,7 +107,7 @@ struct CreatorCommunityWriteView: View {
|
||||
.onTapGesture { isShowRecordingVoiceView = true }
|
||||
|
||||
|
||||
Text("※ 오디오 녹음은 최대 3분입니다")
|
||||
Text(I18n.Explorer.audioRecordingMax3Minutes)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color.gray77)
|
||||
}
|
||||
@@ -115,16 +115,16 @@ struct CreatorCommunityWriteView: View {
|
||||
}
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("내용")
|
||||
Text(I18n.Explorer.contentTitle)
|
||||
.appFont(size: 16.7, weight: .bold)
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("\(viewModel.content.count)자")
|
||||
Text("\(viewModel.content.count)\(I18n.Explorer.contentCharacterUnit)")
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color.mainRed)
|
||||
Text(" / 최대 500자")
|
||||
Text(I18n.Explorer.max500Chars)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color.gray77)
|
||||
}
|
||||
@@ -141,14 +141,14 @@ struct CreatorCommunityWriteView: View {
|
||||
.padding(.top, 13.3)
|
||||
|
||||
VStack(spacing: 13.3) {
|
||||
Text("댓글 가능 여부")
|
||||
Text(I18n.Explorer.commentAvailability)
|
||||
.appFont(size: 16.7, weight: .bold)
|
||||
.foregroundColor(Color.grayee)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
HStack(spacing: 13.3) {
|
||||
SelectButtonView(
|
||||
title: "댓글 가능",
|
||||
title: I18n.CreateContent.commentAllowed,
|
||||
isChecked: viewModel.isAvailableComment
|
||||
) {
|
||||
if !viewModel.isAvailableComment {
|
||||
@@ -157,7 +157,7 @@ struct CreatorCommunityWriteView: View {
|
||||
}
|
||||
|
||||
SelectButtonView(
|
||||
title: "댓글 불가",
|
||||
title: I18n.CreateContent.commentNotAllowed,
|
||||
isChecked: !viewModel.isAvailableComment
|
||||
) {
|
||||
if viewModel.isAvailableComment {
|
||||
@@ -170,14 +170,14 @@ struct CreatorCommunityWriteView: View {
|
||||
|
||||
if UserDefaults.bool(forKey: .auth) {
|
||||
VStack(spacing: 13.3) {
|
||||
Text("연령 제한")
|
||||
Text(I18n.Explorer.ageRestriction)
|
||||
.appFont(size: 16.7, weight: .bold)
|
||||
.foregroundColor(Color.grayee)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
HStack(spacing: 13.3) {
|
||||
SelectButtonView(
|
||||
title: "전체 연령",
|
||||
title: I18n.CreateContent.allAges,
|
||||
isChecked: !viewModel.isAdult
|
||||
) {
|
||||
if viewModel.isAdult {
|
||||
@@ -186,7 +186,7 @@ struct CreatorCommunityWriteView: View {
|
||||
}
|
||||
|
||||
SelectButtonView(
|
||||
title: "19세 이상",
|
||||
title: I18n.CreateContent.over19,
|
||||
isChecked: viewModel.isAdult
|
||||
) {
|
||||
if !viewModel.isAdult {
|
||||
@@ -200,14 +200,14 @@ struct CreatorCommunityWriteView: View {
|
||||
|
||||
if let _ = viewModel.postImageData {
|
||||
VStack(spacing: 13.3) {
|
||||
Text("가격 설정")
|
||||
Text(I18n.Explorer.priceSetting)
|
||||
.appFont(size: 16.7, weight: .bold)
|
||||
.foregroundColor(Color.grayee)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
HStack(spacing: 13.3) {
|
||||
SelectButtonView(
|
||||
title: "무료",
|
||||
title: I18n.CreateContent.free,
|
||||
isChecked: viewModel.isPriceFree
|
||||
) {
|
||||
if !viewModel.isPriceFree {
|
||||
@@ -216,7 +216,7 @@ struct CreatorCommunityWriteView: View {
|
||||
}
|
||||
|
||||
SelectButtonView(
|
||||
title: "유료",
|
||||
title: I18n.CreateContent.paid,
|
||||
isChecked: !viewModel.isPriceFree
|
||||
) {
|
||||
if viewModel.isPriceFree {
|
||||
@@ -238,7 +238,7 @@ struct CreatorCommunityWriteView: View {
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("캔")
|
||||
Text(I18n.Explorer.canUnitCompact)
|
||||
.appFont(size: 14.7, weight: .medium)
|
||||
.foregroundColor(Color.button)
|
||||
}
|
||||
@@ -259,7 +259,7 @@ struct CreatorCommunityWriteView: View {
|
||||
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 13.3) {
|
||||
Text("닫기")
|
||||
Text(I18n.Explorer.close)
|
||||
.appFont(size: 18.3, weight: .bold)
|
||||
.foregroundColor(Color.button)
|
||||
.frame(maxWidth: .infinity)
|
||||
@@ -275,7 +275,7 @@ struct CreatorCommunityWriteView: View {
|
||||
AppState.shared.back()
|
||||
}
|
||||
|
||||
Text("등록")
|
||||
Text(I18n.Explorer.register)
|
||||
.appFont(size: 18.3, weight: .bold)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
@@ -47,7 +47,7 @@ final class CreatorCommunityWriteViewModel: ObservableObject {
|
||||
@Published var price = 0
|
||||
@Published var soundData: Data? = nil
|
||||
|
||||
var placeholder = "내용을 입력하세요"
|
||||
var placeholder = I18n.Explorer.inputContent
|
||||
|
||||
func setPostImage(_ image: UIImage) {
|
||||
postImage = image
|
||||
@@ -99,7 +99,7 @@ final class CreatorCommunityWriteViewModel: ObservableObject {
|
||||
case .failure(let error):
|
||||
ERROR_LOG(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} receiveValue: { [unowned self] response in
|
||||
@@ -111,7 +111,7 @@ final class CreatorCommunityWriteViewModel: ObservableObject {
|
||||
let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: responseData)
|
||||
|
||||
if decoded.success {
|
||||
self.errorMessage = "게시물이 등록되었습니다."
|
||||
self.errorMessage = I18n.Explorer.postCreated
|
||||
self.isShowPopup = true
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
@@ -121,19 +121,19 @@ final class CreatorCommunityWriteViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
.store(in: &subscription)
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
self.isLoading = false
|
||||
}
|
||||
@@ -142,13 +142,13 @@ final class CreatorCommunityWriteViewModel: ObservableObject {
|
||||
|
||||
private func validateData() -> Bool {
|
||||
if content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty || content.count < 5 {
|
||||
errorMessage = "내용을 5자 이상 입력해 주세요."
|
||||
errorMessage = I18n.Explorer.minContentLength(5)
|
||||
isShowPopup = true
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
if !isPriceFree && price < 5 {
|
||||
errorMessage = "최소금액은 5캔 입니다."
|
||||
errorMessage = I18n.Explorer.minPriceFiveCans
|
||||
isShowPopup = true
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@ struct UserProfileFanTalkAllView: View {
|
||||
GeometryReader { proxy in
|
||||
BaseView(isLoading: $viewModel.isLoading) {
|
||||
VStack(spacing: 0) {
|
||||
DetailNavigationBar(title: String(localized: "팬 Talk 전체보기"))
|
||||
DetailNavigationBar(title: I18n.Explorer.fanTalkAllTitle)
|
||||
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
HStack(spacing: 6.7) {
|
||||
Text("응원")
|
||||
Text(I18n.Explorer.cheerTitle)
|
||||
.appFont(size: 14.7, weight: .medium)
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
@@ -43,7 +43,7 @@ struct UserProfileFanTalkAllView: View {
|
||||
.padding(.top, 13.3)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
TextField("응원댓글을 입력하세요", text: $cheersContent)
|
||||
TextField(I18n.Explorer.cheerInputPlaceholder, text: $cheersContent)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
@@ -115,7 +115,7 @@ struct UserProfileFanTalkAllView: View {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text("응원이 없습니다.\n\n처음으로 응원을 해보세요!")
|
||||
Text(I18n.Explorer.cheerEmpty)
|
||||
.appFont(size: 13.3, weight: .light)
|
||||
.foregroundColor(Color.graybb)
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
@@ -69,7 +69,7 @@ struct UserProfileFanTalkCheersItemView: View {
|
||||
.foregroundColor(Color.button)
|
||||
)
|
||||
|
||||
Text("수정")
|
||||
Text(I18n.Explorer.modify)
|
||||
.appFont(size: 14, weight: .bold)
|
||||
.foregroundColor(Color.white)
|
||||
.padding(13.3)
|
||||
@@ -80,7 +80,7 @@ struct UserProfileFanTalkCheersItemView: View {
|
||||
isModeModify = false
|
||||
}
|
||||
|
||||
Text("취소")
|
||||
Text(I18n.Common.cancel)
|
||||
.appFont(size: 14, weight: .bold)
|
||||
.foregroundColor(Color.button)
|
||||
.padding(13.3)
|
||||
@@ -102,7 +102,7 @@ struct UserProfileFanTalkCheersItemView: View {
|
||||
|
||||
if isShowInputReply {
|
||||
HStack(spacing: 10) {
|
||||
TextField("응원댓글에 답글을 남겨보세요!", text: $replyContent)
|
||||
TextField(I18n.Explorer.cheerReplyPlaceholder, text: $replyContent)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.appFont(size: 14, weight: .medium)
|
||||
@@ -118,7 +118,7 @@ struct UserProfileFanTalkCheersItemView: View {
|
||||
.foregroundColor(Color.button)
|
||||
)
|
||||
|
||||
Text("등록")
|
||||
Text(I18n.Explorer.register)
|
||||
.appFont(size: 14, weight: .bold)
|
||||
.foregroundColor(Color.white)
|
||||
.padding(13.3)
|
||||
@@ -136,7 +136,7 @@ struct UserProfileFanTalkCheersItemView: View {
|
||||
} else {
|
||||
if cheersItem.replyList.count <= 0 {
|
||||
if userId == UserDefaults.int(forKey: .userId) {
|
||||
Text("답글쓰기")
|
||||
Text(I18n.Explorer.replyWrite)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(Color.button)
|
||||
.padding(.top, 18.3)
|
||||
@@ -164,7 +164,7 @@ struct UserProfileFanTalkCheersItemView: View {
|
||||
.foregroundColor(Color.gray52)
|
||||
|
||||
if userId == UserDefaults.int(forKey: .userId) {
|
||||
Text("답글 수정")
|
||||
Text(I18n.Explorer.replyEdit)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(Color.button)
|
||||
.onTapGesture {
|
||||
@@ -196,7 +196,7 @@ struct UserProfileFanTalkCheersItemView: View {
|
||||
if isShowPopupMenu {
|
||||
VStack(spacing: 10) {
|
||||
if cheersItem.memberId != UserDefaults.int(forKey: .userId) {
|
||||
Text("신고하기")
|
||||
Text(I18n.Explorer.reportAction)
|
||||
.appFont(size: 14, weight: .medium)
|
||||
.foregroundColor(Color.gray77)
|
||||
.onTapGesture {
|
||||
@@ -206,7 +206,7 @@ struct UserProfileFanTalkCheersItemView: View {
|
||||
}
|
||||
|
||||
if cheersItem.memberId == UserDefaults.int(forKey: .userId) {
|
||||
Text("수정")
|
||||
Text(I18n.Explorer.edit)
|
||||
.appFont(size: 14, weight: .medium)
|
||||
.foregroundColor(Color.gray77)
|
||||
.onTapGesture {
|
||||
@@ -219,7 +219,7 @@ struct UserProfileFanTalkCheersItemView: View {
|
||||
if userId == UserDefaults.int(forKey: .userId) ||
|
||||
cheersItem.memberId == UserDefaults.int(forKey: .userId)
|
||||
{
|
||||
Text("삭제")
|
||||
Text(I18n.Common.delete)
|
||||
.appFont(size: 14, weight: .medium)
|
||||
.foregroundColor(Color.gray77)
|
||||
.onTapGesture {
|
||||
|
||||
@@ -26,13 +26,13 @@ struct UserProfileFanTalkView: View {
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
Text("팬 Talk")
|
||||
Text(I18n.Explorer.fanTalkTitle)
|
||||
.appFont(size: 26, weight: .bold)
|
||||
.foregroundColor(Color.white)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("전체보기")
|
||||
Text(I18n.Common.viewAll)
|
||||
.appFont(size: 14, weight: .light)
|
||||
.foregroundColor(Color(hex: "78909C"))
|
||||
.onTapGesture {
|
||||
@@ -43,7 +43,7 @@ struct UserProfileFanTalkView: View {
|
||||
|
||||
VStack(alignment: .leading, spacing: 20) {
|
||||
HStack(spacing: 6.7) {
|
||||
Text("응원")
|
||||
Text(I18n.Explorer.cheerTitle)
|
||||
.appFont(size: 16, weight: .medium)
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
@@ -53,7 +53,7 @@ struct UserProfileFanTalkView: View {
|
||||
}
|
||||
|
||||
HStack(spacing: 0) {
|
||||
TextField("응원댓글을 입력하세요", text: $cheersContent)
|
||||
TextField(I18n.Explorer.cheerInputPlaceholder, text: $cheersContent)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.appFont(size: 14, weight: .medium)
|
||||
@@ -111,7 +111,7 @@ struct UserProfileFanTalkView: View {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text("응원이 없습니다.\n\n처음으로 응원을 해보세요!")
|
||||
Text(I18n.Explorer.cheerEmpty)
|
||||
.appFont(size: 13.3, weight: .light)
|
||||
.foregroundColor(Color.graybb)
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
@@ -70,7 +70,7 @@ final class UserProfileFanTalkViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
if let errorPopup = errorPopup {
|
||||
@@ -80,7 +80,7 @@ final class UserProfileFanTalkViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
if let errorPopup = errorPopup {
|
||||
errorPopup(self.errorMessage)
|
||||
} else {
|
||||
@@ -95,9 +95,9 @@ final class UserProfileFanTalkViewModel: ObservableObject {
|
||||
func writeCheersReply(parentCheersId: Int, creatorId: Int, cheersReplyContent: String) {
|
||||
if cheersReplyContent.trimmingCharacters(in: .whitespaces).isEmpty {
|
||||
if let errorPopup = errorPopup {
|
||||
errorPopup("내용을 입력하세요")
|
||||
errorPopup(I18n.Explorer.inputContent)
|
||||
} else {
|
||||
errorMessage = "내용을 입력하세요"
|
||||
errorMessage = I18n.Explorer.inputContent
|
||||
isShowPopup = true
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ final class UserProfileFanTalkViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
if let errorPopup = errorPopup {
|
||||
@@ -147,7 +147,7 @@ final class UserProfileFanTalkViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
if let errorPopup = errorPopup {
|
||||
errorPopup(self.errorMessage)
|
||||
} else {
|
||||
@@ -161,9 +161,9 @@ final class UserProfileFanTalkViewModel: ObservableObject {
|
||||
func writeCheers(creatorId: Int, cheersContent: String) {
|
||||
if cheersContent.trimmingCharacters(in: .whitespaces).isEmpty {
|
||||
if let errorPopup = errorPopup {
|
||||
errorPopup("내용을 입력하세요")
|
||||
errorPopup(I18n.Explorer.inputContent)
|
||||
} else {
|
||||
errorMessage = "내용을 입력하세요"
|
||||
errorMessage = I18n.Explorer.inputContent
|
||||
isShowPopup = true
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ final class UserProfileFanTalkViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
if let errorPopup = errorPopup {
|
||||
@@ -213,7 +213,7 @@ final class UserProfileFanTalkViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
if let errorPopup = errorPopup {
|
||||
errorPopup(self.errorMessage)
|
||||
} else {
|
||||
@@ -227,18 +227,18 @@ final class UserProfileFanTalkViewModel: ObservableObject {
|
||||
func modifyCheers(cheersId: Int, creatorId: Int, cheersContent: String? = nil, isActive: Bool? = nil) {
|
||||
if cheersContent == nil && isActive == nil {
|
||||
if let errorPopup = errorPopup {
|
||||
errorPopup("변경사항이 없습니다.")
|
||||
errorPopup(I18n.Explorer.noChanges)
|
||||
} else {
|
||||
errorMessage = "변경사항이 없습니다."
|
||||
errorMessage = I18n.Explorer.noChanges
|
||||
isShowPopup = true
|
||||
}
|
||||
}
|
||||
|
||||
if let cheersContent = cheersContent, cheersContent.trimmingCharacters(in: .whitespaces).isEmpty {
|
||||
if let errorPopup = errorPopup {
|
||||
errorPopup("내용을 입력하세요")
|
||||
errorPopup(I18n.Explorer.inputContent)
|
||||
} else {
|
||||
errorMessage = "내용을 입력하세요"
|
||||
errorMessage = I18n.Explorer.inputContent
|
||||
isShowPopup = true
|
||||
}
|
||||
|
||||
@@ -278,20 +278,20 @@ final class UserProfileFanTalkViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
.store(in: &subscription)
|
||||
}
|
||||
|
||||
func report(type: ReportType, reason: String = "프로필 신고") {
|
||||
func report(type: ReportType, reason: String = I18n.Dialog.MemberProfile.reportProfile) {
|
||||
isLoading = true
|
||||
|
||||
let request = ReportRequest(type: type, reason: reason, reportedMemberId: nil, cheersId: reportCheersId > 0 && type == .CHEERS ? reportCheersId : nil, audioContentId: nil)
|
||||
@@ -316,12 +316,12 @@ final class UserProfileFanTalkViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ struct FollowerListView: View {
|
||||
var body: some View {
|
||||
BaseView(isLoading: $viewModel.isLoading) {
|
||||
VStack(spacing: 0) {
|
||||
DetailNavigationBar(title: String(localized: "팔로워 리스트"))
|
||||
DetailNavigationBar(title: I18n.MemberChannel.followersList)
|
||||
|
||||
HStack(spacing: 4) {
|
||||
Text("전체")
|
||||
Text(I18n.Category.all)
|
||||
.appFont(size: 18.3, weight: .bold)
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@ struct UserProfileSeriesView: View {
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 13.3) {
|
||||
HStack(spacing: 0) {
|
||||
Text("시리즈")
|
||||
Text(I18n.Explorer.seriesTitle)
|
||||
.appFont(size: 26, weight: .bold)
|
||||
.foregroundColor(Color.white)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("전체보기")
|
||||
Text(I18n.Common.viewAll)
|
||||
.appFont(size: 14, weight: .light)
|
||||
.foregroundColor(Color(hex: "78909C"))
|
||||
.onTapGesture {
|
||||
|
||||
@@ -14,28 +14,28 @@ struct UserProfileActivitySummaryView: View {
|
||||
var body: some View {
|
||||
HStack(spacing: 0) {
|
||||
ActivitySummaryItemView(
|
||||
title: "라이브\n횟수",
|
||||
title: I18n.Explorer.activityLiveCount,
|
||||
count: String(format: "%d", item.liveCount)
|
||||
)
|
||||
|
||||
ActivitySummaryDividerView()
|
||||
|
||||
ActivitySummaryItemView(
|
||||
title: "라이브\n시간",
|
||||
title: I18n.Explorer.activityLiveTime,
|
||||
count: String(format: "%d", item.liveTime)
|
||||
)
|
||||
|
||||
ActivitySummaryDividerView()
|
||||
|
||||
ActivitySummaryItemView(
|
||||
title: "라이브\n참여자",
|
||||
title: I18n.Explorer.activityLiveParticipants,
|
||||
count: String(format: "%d", item.liveContributorCount)
|
||||
)
|
||||
|
||||
ActivitySummaryDividerView()
|
||||
|
||||
ActivitySummaryItemView(
|
||||
title: "등록\n콘텐츠",
|
||||
title: I18n.Explorer.activityRegisteredContent,
|
||||
count: String(format: "%d", item.contentCount)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,13 +24,13 @@ struct UserProfileContentView: View {
|
||||
var body: some View {
|
||||
VStack(spacing: 21) {
|
||||
HStack(spacing: 0) {
|
||||
Text(userId == UserDefaults.int(forKey: .userId) ? "내 콘텐츠" : "콘텐츠")
|
||||
Text(userId == UserDefaults.int(forKey: .userId) ? I18n.Explorer.myContent : I18n.Explorer.content)
|
||||
.appFont(size: 26, weight: .bold)
|
||||
.foregroundColor(Color.white)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("전체보기")
|
||||
Text(I18n.Common.viewAll)
|
||||
.appFont(size: 14, weight: .light)
|
||||
.foregroundColor(Color(hex: "78909C"))
|
||||
.onTapGesture {
|
||||
@@ -39,7 +39,7 @@ struct UserProfileContentView: View {
|
||||
}
|
||||
|
||||
if userId == UserDefaults.int(forKey: .userId) {
|
||||
Text("새로운 콘텐츠 등록하기")
|
||||
Text(I18n.Explorer.createNewContent)
|
||||
.appFont(size: 16, weight: .bold)
|
||||
.foregroundColor(Color.grayee)
|
||||
.padding(.vertical, 17)
|
||||
@@ -73,7 +73,7 @@ struct UserProfileContentView: View {
|
||||
VStack(spacing: 8) {
|
||||
// 상단 정보 (계산된 % 보유중, 정보 아이콘, 개수)
|
||||
HStack {
|
||||
Text(ownedContentCount > 0 ? "\(Int(round(Double(ownedContentCount) / Double(totalContentCount) * 100)))% 보유중" : "소장 중인 작품이 없어요!")
|
||||
Text(ownedContentCount > 0 ? I18n.Explorer.ownedPercentage(Int(round(Double(ownedContentCount) / Double(totalContentCount) * 100))) : I18n.Explorer.noOwnedContent)
|
||||
.appFont(size: 18, weight: .bold)
|
||||
.foregroundColor(.white)
|
||||
|
||||
@@ -88,7 +88,7 @@ struct UserProfileContentView: View {
|
||||
.appFont(size: 16, weight: .regular)
|
||||
.foregroundColor(.white)
|
||||
|
||||
Text("\(totalContentCount)개")
|
||||
Text(I18n.Explorer.totalContentCount(totalContentCount))
|
||||
.appFont(size: 16, weight: .regular)
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
|
||||
@@ -16,14 +16,14 @@ struct UserProfileDonationAllView: View {
|
||||
var body: some View {
|
||||
BaseView(isLoading: $viewModel.isLoading) {
|
||||
VStack(spacing: 0) {
|
||||
DetailNavigationBar(title: String(localized: "후원랭킹 전체보기"))
|
||||
DetailNavigationBar(title: I18n.Explorer.donationRankingAllTitle)
|
||||
|
||||
if userId == UserDefaults.int(forKey: .userId) {
|
||||
VStack(spacing: 10.7) {
|
||||
HStack(spacing: 10) {
|
||||
Spacer()
|
||||
|
||||
Text("채널에 후원랭킹 활성화")
|
||||
Text(I18n.Explorer.donationRankActivation)
|
||||
.appFont(size: 16, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
@@ -38,7 +38,7 @@ struct UserProfileDonationAllView: View {
|
||||
HStack(spacing: 0) {
|
||||
Spacer()
|
||||
|
||||
Text("※ 비활성화하면 채널 내 후원랭킹이 표시되지 않으며,\n라이브 중에도 후원랭킹에 따른 뱃지가 반영되지 않습니다.")
|
||||
Text(I18n.Explorer.donationRankActivationNotice)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(Color(hex: "555555"))
|
||||
.multilineTextAlignment(.trailing)
|
||||
@@ -79,7 +79,7 @@ struct UserProfileDonationAllView: View {
|
||||
|
||||
VStack(spacing: 13.3) {
|
||||
HStack(spacing: 0) {
|
||||
Text("오늘")
|
||||
Text(I18n.Explorer.today)
|
||||
.appFont(size: 12, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
@@ -89,13 +89,13 @@ struct UserProfileDonationAllView: View {
|
||||
.appFont(size: 12, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Text(" 캔")
|
||||
Text(I18n.Explorer.canUnitWithSpace)
|
||||
.appFont(size: 12, weight: .light)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
}
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("지난주")
|
||||
Text(I18n.Explorer.lastWeek)
|
||||
.appFont(size: 12, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
@@ -105,13 +105,13 @@ struct UserProfileDonationAllView: View {
|
||||
.appFont(size: 12, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Text(" 캔")
|
||||
Text(I18n.Explorer.canUnitWithSpace)
|
||||
.appFont(size: 12, weight: .light)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
}
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("이번 달 어제까지")
|
||||
Text(I18n.Explorer.thisMonthUntilYesterday)
|
||||
.appFont(size: 12, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
@@ -121,7 +121,7 @@ struct UserProfileDonationAllView: View {
|
||||
.appFont(size: 12, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Text(" 캔")
|
||||
Text(I18n.Explorer.canUnitWithSpace)
|
||||
.appFont(size: 12, weight: .light)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
}
|
||||
@@ -153,7 +153,7 @@ struct UserProfileDonationAllView: View {
|
||||
}
|
||||
|
||||
HStack(alignment: .center, spacing: 0) {
|
||||
Text("전체")
|
||||
Text(I18n.MemberChannel.totalLabel)
|
||||
.appFont(size: 14.7, weight: .medium)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
@@ -162,7 +162,7 @@ struct UserProfileDonationAllView: View {
|
||||
.foregroundColor(Color(hex: "80d8ff"))
|
||||
.padding(.leading, 6.7)
|
||||
|
||||
Text("개")
|
||||
Text(I18n.MemberChannel.countUnit)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(Color(hex: "777777"))
|
||||
|
||||
@@ -253,7 +253,7 @@ struct UserProfileDonationAllItemView: View {
|
||||
Spacer()
|
||||
|
||||
if let donationCan = item.donationCan, donationCan > 0, withDonationCan {
|
||||
Text("\(donationCan) 캔")
|
||||
Text(I18n.Explorer.canWithSpace(donationCan))
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
}
|
||||
|
||||
@@ -86,13 +86,13 @@ final class UserProfileDonationAllViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
@@ -144,13 +144,13 @@ final class UserProfileDonationAllViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
@@ -189,13 +189,13 @@ final class UserProfileDonationAllViewModel: ObservableObject {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
} else {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
}
|
||||
|
||||
self.isShowPopup = true
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
|
||||
self.errorMessage = I18n.Common.commonError
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,13 @@ struct UserProfileDonationView: View {
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 14) {
|
||||
HStack(spacing: 0) {
|
||||
Text("후원랭킹")
|
||||
Text(I18n.Explorer.donationRankingTitle)
|
||||
.appFont(size: 26, weight: .bold)
|
||||
.foregroundColor(Color.white)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("전체보기")
|
||||
Text(I18n.Common.viewAll)
|
||||
.appFont(size: 14, weight: .light)
|
||||
.foregroundColor(Color(hex: "78909C"))
|
||||
.onTapGesture {
|
||||
|
||||
@@ -13,7 +13,7 @@ struct UserProfileIntroduceView: View {
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 16.7) {
|
||||
Text("채널 소개")
|
||||
Text(I18n.Explorer.channelIntroduceTitle)
|
||||
.appFont(size: 16.7, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ struct UserProfileLiveView: View {
|
||||
.clipShape(Circle())
|
||||
} else {
|
||||
VStack(spacing: 0) {
|
||||
Text("\(dateDic["month"] ?? "")월")
|
||||
Text(I18n.Explorer.month(dateDic["month"] ?? ""))
|
||||
.appFont(size: 14, weight: .bold)
|
||||
.foregroundColor(.white)
|
||||
.padding(.vertical, 6)
|
||||
@@ -102,7 +102,7 @@ struct UserProfileLiveView: View {
|
||||
}
|
||||
|
||||
if item.isReservation {
|
||||
Text("예약완료")
|
||||
Text(I18n.Explorer.reservationDone)
|
||||
.appFont(size: 12, weight: .bold)
|
||||
.foregroundColor(Color.white)
|
||||
.padding(4)
|
||||
@@ -125,7 +125,7 @@ struct UserProfileLiveView: View {
|
||||
.background(Color(hex: "3b5ff1"))
|
||||
.cornerRadius(4)
|
||||
} else {
|
||||
Text("무료")
|
||||
Text(I18n.CreateContent.free)
|
||||
.appFont(size: 14, weight: .regular)
|
||||
.foregroundColor(Color(hex: "#263238"))
|
||||
.padding(4)
|
||||
|
||||
@@ -32,7 +32,7 @@ final class UserProfileViewModel: ObservableObject {
|
||||
@Published var passwordDialogConfirmAction: (String) -> Void = { _ in }
|
||||
@Published var isShowPasswordDialog = false
|
||||
|
||||
@Published var navigationTitle = "채널"
|
||||
@Published var navigationTitle = I18n.Explorer.channel
|
||||
|
||||
@Published private(set) var creatorProfile: GetCreatorProfileResponse?
|
||||
@Published private(set) var creatorDetail: GetCreatorDetailResponse?
|
||||
@@ -516,7 +516,7 @@ final class UserProfileViewModel: ObservableObject {
|
||||
|
||||
if decoded.success {
|
||||
getCreatorProfile(userId: userId)
|
||||
self.errorMessage = "차단이 해제 되었습니다."
|
||||
self.errorMessage = I18n.MemberChannel.userUnblocked
|
||||
} else {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
@@ -534,7 +534,7 @@ final class UserProfileViewModel: ObservableObject {
|
||||
.store(in: &subscription)
|
||||
}
|
||||
|
||||
func report(type: ReportType, userId: Int? = nil, reason: String = "프로필 신고") {
|
||||
func report(type: ReportType, userId: Int? = nil, reason: String = I18n.Dialog.MemberProfile.reportProfile) {
|
||||
isLoading = true
|
||||
|
||||
let request = ReportRequest(type: type, reason: reason, reportedMemberId: userId, cheersId: cheersId > 0 && type == .CHEERS ? cheersId : nil, audioContentId: nil)
|
||||
|
||||
@@ -2651,6 +2651,328 @@ If you block this user, the following features will be restricted.
|
||||
}
|
||||
}
|
||||
|
||||
enum Explorer {
|
||||
static var channel: String {
|
||||
pick(ko: "채널", en: "Channel", ja: "チャンネル")
|
||||
}
|
||||
|
||||
static var searchChannelPlaceholder: String {
|
||||
pick(ko: "채널명을 입력해 보세요", en: "Search channel name", ja: "チャンネル名を入力してください")
|
||||
}
|
||||
|
||||
static var searchEmptyResult: String {
|
||||
pick(ko: "검색 결과가 없습니다.", en: "No search results.", ja: "検索結果がありません。")
|
||||
}
|
||||
|
||||
static var rankingWeeklyUpdateNotice: String {
|
||||
pick(ko: "※ 인기 크리에이터의 순위는 매주 업데이트됩니다.", en: "※ Popular creator rankings are updated weekly.", ja: "※ 人気クリエイターのランキングは毎週更新されます。")
|
||||
}
|
||||
|
||||
static var communityTitle: String {
|
||||
pick(ko: "커뮤니티", en: "Community", ja: "コミュニティ")
|
||||
}
|
||||
|
||||
static var viewMore: String {
|
||||
pick(ko: "더보기", en: "More", ja: "もっと見る")
|
||||
}
|
||||
|
||||
static var secretComment: String {
|
||||
pick(ko: "비밀댓글", en: "Secret comment", ja: "秘密コメント")
|
||||
}
|
||||
|
||||
static var commentInputPlaceholder: String {
|
||||
pick(ko: "댓글을 입력해 보세요.", en: "Enter a comment.", ja: "コメントを入力してください。")
|
||||
}
|
||||
|
||||
static var replyTitle: String {
|
||||
pick(ko: "답글", en: "Replies", ja: "返信")
|
||||
}
|
||||
|
||||
static var replyWrite: String {
|
||||
pick(ko: "답글 쓰기", en: "Write reply", ja: "返信を書く")
|
||||
}
|
||||
|
||||
static func replyCount(_ count: Int) -> String {
|
||||
pick(ko: "답글 \(count)개", en: "\(count) replies", ja: "返信\(count)件")
|
||||
}
|
||||
|
||||
static var edit: String {
|
||||
pick(ko: "수정", en: "Edit", ja: "編集")
|
||||
}
|
||||
|
||||
static var report: String {
|
||||
pick(ko: "신고", en: "Report", ja: "通報")
|
||||
}
|
||||
|
||||
static var reportAction: String {
|
||||
pick(ko: "신고하기", en: "Report", ja: "通報する")
|
||||
}
|
||||
|
||||
static var noChanges: String {
|
||||
pick(ko: "변경사항이 없습니다.", en: "No changes.", ja: "変更事項がありません。")
|
||||
}
|
||||
|
||||
static var inputContent: String {
|
||||
pick(ko: "내용을 입력하세요", en: "Enter content.", ja: "内容を入力してください。")
|
||||
}
|
||||
|
||||
static var inputContentWithPeriod: String {
|
||||
pick(ko: "내용을 입력하세요.", en: "Enter content.", ja: "内容を入力してください。")
|
||||
}
|
||||
|
||||
static func minContentLength(_ count: Int) -> String {
|
||||
pick(ko: "내용을 \(count)자 이상 입력해 주세요.", en: "Please enter at least \(count) characters.", ja: "内容を\(count)文字以上入力してください。")
|
||||
}
|
||||
|
||||
static var deleted: String {
|
||||
pick(ko: "삭제되었습니다", en: "Deleted.", ja: "削除されました。")
|
||||
}
|
||||
|
||||
static var imageLoadFailed: String {
|
||||
pick(ko: "이미지를 로드하지 못했습니다.", en: "Could not load the image.", ja: "画像を読み込めませんでした。")
|
||||
}
|
||||
|
||||
static var postCreated: String {
|
||||
pick(ko: "게시물이 등록되었습니다.", en: "Post has been created.", ja: "投稿が登録されました。")
|
||||
}
|
||||
|
||||
static var postUpdated: String {
|
||||
pick(ko: "게시물이 수정되었습니다.", en: "Post has been updated.", ja: "投稿が修正されました。")
|
||||
}
|
||||
|
||||
static var minPriceFiveCans: String {
|
||||
pick(ko: "최소금액은 5캔 입니다.", en: "The minimum price is 5 cans.", ja: "最低金額は5canです。")
|
||||
}
|
||||
|
||||
static var pinRelease: String {
|
||||
pick(ko: "고정 해제", en: "Unpin", ja: "固定解除")
|
||||
}
|
||||
|
||||
static var pinToTop: String {
|
||||
pick(ko: "최상단에 고정", en: "Pin to top", ja: "最上部に固定")
|
||||
}
|
||||
|
||||
static func viewPostWithCans(_ can: Int) -> String {
|
||||
pick(ko: "\(can)캔으로 게시글 보기", en: "View post with \(can) cans", ja: "\(can)canで投稿を見る")
|
||||
}
|
||||
|
||||
static var postRegister: String {
|
||||
pick(ko: "게시물 등록", en: "Create post", ja: "投稿登録")
|
||||
}
|
||||
|
||||
static var postRegisterDescription: String {
|
||||
pick(ko: "게시 후에 게시물이 여기에 표시되고\n커뮤니티에 공개됩니다.", en: "After posting, your post appears here\nand is published to the community.", ja: "投稿後、ここに表示され\nコミュニティに公開されます。")
|
||||
}
|
||||
|
||||
static var postWriteTitle: String {
|
||||
pick(ko: "게시글 등록", en: "Create post", ja: "投稿登録")
|
||||
}
|
||||
|
||||
static var postModifyTitle: String {
|
||||
pick(ko: "게시글 수정", en: "Edit post", ja: "投稿修正")
|
||||
}
|
||||
|
||||
static var imageTitle: String {
|
||||
pick(ko: "이미지", en: "Image", ja: "画像")
|
||||
}
|
||||
|
||||
static var imageOptionalNotice: String {
|
||||
pick(ko: "등록할 이미지가 없으면 이미지 없이 게시글만 등록 하셔도 됩니다.", en: "If there is no image to upload, you can post without an image.", ja: "登録する画像がない場合、画像なしで投稿できます。")
|
||||
}
|
||||
|
||||
static var contentTitle: String {
|
||||
pick(ko: "내용", en: "Content", ja: "内容")
|
||||
}
|
||||
|
||||
static var contentCharacterUnit: String {
|
||||
pick(ko: "자", en: "", ja: "文字")
|
||||
}
|
||||
|
||||
static var max500Chars: String {
|
||||
pick(ko: " / 최대 500자", en: " / up to 500 chars", ja: " / 最大500文字")
|
||||
}
|
||||
|
||||
static var commentAvailability: String {
|
||||
pick(ko: "댓글 가능 여부", en: "Comment availability", ja: "コメント可否")
|
||||
}
|
||||
|
||||
static var ageRestriction: String {
|
||||
pick(ko: "연령 제한", en: "Age restriction", ja: "年齢制限")
|
||||
}
|
||||
|
||||
static var priceSetting: String {
|
||||
pick(ko: "가격 설정", en: "Price setting", ja: "価格設定")
|
||||
}
|
||||
|
||||
static var close: String {
|
||||
pick(ko: "닫기", en: "Close", ja: "閉じる")
|
||||
}
|
||||
|
||||
static var register: String {
|
||||
pick(ko: "등록", en: "Register", ja: "登録")
|
||||
}
|
||||
|
||||
static var modify: String {
|
||||
pick(ko: "수정", en: "Edit", ja: "編集")
|
||||
}
|
||||
|
||||
static var recordingDefaultFileName: String {
|
||||
pick(ko: "녹음", en: "Recording", ja: "録音")
|
||||
}
|
||||
|
||||
static var recordingTitle: String {
|
||||
pick(ko: "음성녹음", en: "Voice recording", ja: "音声録音")
|
||||
}
|
||||
|
||||
static var recordAgain: String {
|
||||
pick(ko: "다시 녹음", en: "Record again", ja: "再録音")
|
||||
}
|
||||
|
||||
static var recordingComplete: String {
|
||||
pick(ko: "녹음완료", en: "Done recording", ja: "録音完了")
|
||||
}
|
||||
|
||||
static var recordingPermissionDenied: String {
|
||||
pick(ko: "권한을 허용하지 않으시면 음성녹음을 하실 수 없습니다.", en: "Voice recording is unavailable without permission.", ja: "権限を許可しないと音声録音を利用できません。")
|
||||
}
|
||||
|
||||
static var recordingFileCreateFailed: String {
|
||||
pick(ko: "녹음파일을 생성하지 못했습니다.\n다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다.", en: "Could not create the recording file.\nPlease try again.\nIf the issue persists, contact customer support.", ja: "録音ファイルを作成できませんでした。\nもう一度お試しください。\n問題が続く場合はカスタマーサポートにお問い合わせください。")
|
||||
}
|
||||
|
||||
static var audioRecordingTitle: String {
|
||||
pick(ko: "오디오 녹음", en: "Audio recording", ja: "オーディオ録音")
|
||||
}
|
||||
|
||||
static var audioRecordingMax3Minutes: String {
|
||||
pick(ko: "※ 오디오 녹음은 최대 3분입니다", en: "※ Audio recording is limited to 3 minutes.", ja: "※ オーディオ録音は最大3分です。")
|
||||
}
|
||||
|
||||
static var fanTalkTitle: String {
|
||||
pick(ko: "팬 Talk", en: "Fan Talk", ja: "ファントーク")
|
||||
}
|
||||
|
||||
static var fanTalkAllTitle: String {
|
||||
pick(ko: "팬 Talk 전체보기", en: "All Fan Talk", ja: "ファントーク一覧")
|
||||
}
|
||||
|
||||
static var cheerTitle: String {
|
||||
pick(ko: "응원", en: "Cheer", ja: "応援")
|
||||
}
|
||||
|
||||
static var cheerInputPlaceholder: String {
|
||||
pick(ko: "응원댓글을 입력하세요", en: "Enter a cheer comment", ja: "応援コメントを入力してください")
|
||||
}
|
||||
|
||||
static var cheerEmpty: String {
|
||||
pick(ko: "응원이 없습니다.\n\n처음으로 응원을 해보세요!", en: "No cheers yet.\n\nBe the first to cheer!", ja: "応援がありません。\n\n最初の応援をしてみましょう!")
|
||||
}
|
||||
|
||||
static var cheerReplyPlaceholder: String {
|
||||
pick(ko: "응원댓글에 답글을 남겨보세요!", en: "Leave a reply to this cheer!", ja: "応援コメントに返信してみましょう!")
|
||||
}
|
||||
|
||||
static var replyEdit: String {
|
||||
pick(ko: "답글 수정", en: "Edit reply", ja: "返信を編集")
|
||||
}
|
||||
|
||||
static var seriesTitle: String {
|
||||
pick(ko: "시리즈", en: "Series", ja: "シリーズ")
|
||||
}
|
||||
|
||||
static var channelIntroduceTitle: String {
|
||||
pick(ko: "채널 소개", en: "Channel intro", ja: "チャンネル紹介")
|
||||
}
|
||||
|
||||
static var donationRankingTitle: String {
|
||||
pick(ko: "후원랭킹", en: "Donation ranking", ja: "後援ランキング")
|
||||
}
|
||||
|
||||
static var donationRankingAllTitle: String {
|
||||
pick(ko: "후원랭킹 전체보기", en: "All donation rankings", ja: "後援ランキング一覧")
|
||||
}
|
||||
|
||||
static var donationRankActivation: String {
|
||||
pick(ko: "채널에 후원랭킹 활성화", en: "Enable donation ranking on channel", ja: "チャンネルで後援ランキングを有効化")
|
||||
}
|
||||
|
||||
static var donationRankActivationNotice: String {
|
||||
pick(ko: "※ 비활성화하면 채널 내 후원랭킹이 표시되지 않으며,\n라이브 중에도 후원랭킹에 따른 뱃지가 반영되지 않습니다.", en: "※ If disabled, donation ranking is hidden in your channel, and ranking badges are not reflected during live.", ja: "※ 無効にするとチャンネル内に後援ランキングが表示されず、ライブ中のランキングバッジも反映されません。")
|
||||
}
|
||||
|
||||
static var today: String {
|
||||
pick(ko: "오늘", en: "Today", ja: "今日")
|
||||
}
|
||||
|
||||
static var lastWeek: String {
|
||||
pick(ko: "지난주", en: "Last week", ja: "先週")
|
||||
}
|
||||
|
||||
static var thisMonthUntilYesterday: String {
|
||||
pick(ko: "이번 달 어제까지", en: "This month until yesterday", ja: "今月(昨日まで)")
|
||||
}
|
||||
|
||||
static var canUnitWithSpace: String {
|
||||
pick(ko: " 캔", en: " cans", ja: " can")
|
||||
}
|
||||
|
||||
static var canUnitCompact: String {
|
||||
pick(ko: "캔", en: "cans", ja: "can")
|
||||
}
|
||||
|
||||
static func canWithSpace(_ can: Int) -> String {
|
||||
pick(ko: "\(can) 캔", en: "\(can) cans", ja: "\(can)can")
|
||||
}
|
||||
|
||||
static var myContent: String {
|
||||
pick(ko: "내 콘텐츠", en: "My content", ja: "マイコンテンツ")
|
||||
}
|
||||
|
||||
static var content: String {
|
||||
pick(ko: "콘텐츠", en: "Content", ja: "コンテンツ")
|
||||
}
|
||||
|
||||
static var createNewContent: String {
|
||||
pick(ko: "새로운 콘텐츠 등록하기", en: "Create new content", ja: "新しいコンテンツを登録")
|
||||
}
|
||||
|
||||
static func ownedPercentage(_ percentage: Int) -> String {
|
||||
pick(ko: "\(percentage)% 보유중", en: "\(percentage)% owned", ja: "\(percentage)%保有中")
|
||||
}
|
||||
|
||||
static var noOwnedContent: String {
|
||||
pick(ko: "소장 중인 작품이 없어요!", en: "No owned works yet!", ja: "所蔵中の作品がありません!")
|
||||
}
|
||||
|
||||
static func totalContentCount(_ count: Int) -> String {
|
||||
pick(ko: "\(count)개", en: "\(count)", ja: "\(count)件")
|
||||
}
|
||||
|
||||
static func month(_ value: String) -> String {
|
||||
pick(ko: "\(value)월", en: "\(value)", ja: "\(value)月")
|
||||
}
|
||||
|
||||
static var reservationDone: String {
|
||||
pick(ko: "예약완료", en: "Reserved", ja: "予約完了")
|
||||
}
|
||||
|
||||
static var activityLiveCount: String {
|
||||
pick(ko: "라이브\n횟수", en: "Live\ncount", ja: "ライブ\n回数")
|
||||
}
|
||||
|
||||
static var activityLiveTime: String {
|
||||
pick(ko: "라이브\n시간", en: "Live\ntime", ja: "ライブ\n時間")
|
||||
}
|
||||
|
||||
static var activityLiveParticipants: String {
|
||||
pick(ko: "라이브\n참여자", en: "Live\nparticipants", ja: "ライブ\n参加者")
|
||||
}
|
||||
|
||||
static var activityRegisteredContent: String {
|
||||
pick(ko: "등록\n콘텐츠", en: "Registered\ncontent", ja: "登録\nコンテンツ")
|
||||
}
|
||||
}
|
||||
|
||||
enum Dialog {
|
||||
enum ApplyAuditionComplete {
|
||||
static var thankYouDescription: String {
|
||||
|
||||
@@ -249,52 +249,52 @@
|
||||
|
||||
### Explorer (40)
|
||||
#### Group 1 (1-10)
|
||||
- [ ] `SodaLive/Sources/Explorer/ExplorerSectionView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/ExplorerView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/ExplorerViewModel.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/ChannelDonation/ChannelDonationAllView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/ChannelDonation/ChannelDonationItemView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentItemView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentListView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentListViewModel.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentReplyView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentReplyViewModel.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/ExplorerSectionView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/ExplorerView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/ExplorerViewModel.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/ChannelDonation/ChannelDonationAllView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/ChannelDonation/ChannelDonationItemView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentItemView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentListView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentListViewModel.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentReplyView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentReplyViewModel.swift`
|
||||
|
||||
#### Group 2 (11-20)
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllItemLockView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllViewModel.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityMenuView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Player/CreatorCommunityMediaPlayerManager.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/CreatorCommunityItemView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/CreatorCommunityMoreItemView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/CreatorCommunityNoPostsItemView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/Modify/CreatorCommunityModifyView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllItemLockView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllViewModel.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityMenuView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Player/CreatorCommunityMediaPlayerManager.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/CreatorCommunityItemView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/CreatorCommunityMoreItemView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/CreatorCommunityNoPostsItemView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/Modify/CreatorCommunityModifyView.swift`
|
||||
|
||||
#### Group 3 (21-30)
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/Modify/CreatorCommunityModifyViewModel.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/Write/CreatorCommunityRecordingVoiceView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/Write/CreatorCommunitySoundManager.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/Write/CreatorCommunityWriteView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/Write/CreatorCommunityWriteViewModel.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/FanTalk/UserProfileFanTalkAllView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/FanTalk/UserProfileFanTalkCheersItemView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/FanTalk/UserProfileFanTalkView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/FanTalk/UserProfileFanTalkViewModel.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/FollowerList/FollowerListView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/Modify/CreatorCommunityModifyViewModel.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/Write/CreatorCommunityRecordingVoiceView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/Write/CreatorCommunitySoundManager.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/Write/CreatorCommunityWriteView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/CreatorCommunity/Write/CreatorCommunityWriteViewModel.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/FanTalk/UserProfileFanTalkAllView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/FanTalk/UserProfileFanTalkCheersItemView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/FanTalk/UserProfileFanTalkView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/FanTalk/UserProfileFanTalkViewModel.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/FollowerList/FollowerListView.swift`
|
||||
|
||||
#### Group 4 (31-40)
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/Series/UserProfileSeriesView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/UserProfileActivitySummaryView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/UserProfileContentView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/UserProfileDonationAllView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/UserProfileDonationAllViewModel.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/UserProfileDonationView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/UserProfileIntroduceView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/UserProfileLiveView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/UserProfileView.swift`
|
||||
- [ ] `SodaLive/Sources/Explorer/Profile/UserProfileViewModel.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/Series/UserProfileSeriesView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/UserProfileActivitySummaryView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/UserProfileContentView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/UserProfileDonationAllView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/UserProfileDonationAllViewModel.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/UserProfileDonationView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/UserProfileIntroduceView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/UserProfileLiveView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/UserProfileView.swift`
|
||||
- [x] `SodaLive/Sources/Explorer/Profile/UserProfileViewModel.swift`
|
||||
|
||||
### Follow (1)
|
||||
- [x] `SodaLive/Sources/Follow/FollowCreatorView.swift`
|
||||
@@ -951,3 +951,27 @@
|
||||
- 빌드 검증: `SodaLive`, `SodaLive-dev` Debug 빌드 모두 오류 없이 완료(경고만 존재).
|
||||
- 테스트 검증: 두 스킴 모두 `Scheme ... is not currently configured for the test action.`로 test action 미구성 확인(코드 실패 아님, 스킴 제약).
|
||||
- LSP 진단 참고: 단일 파일 진단 시 `No such module 'Moya'`가 보고되나, SourceKit 단독 해석 한계이며 실제 `xcodebuild` 컴파일은 통과했다.
|
||||
|
||||
### 20차 구현 (Explorer 모듈 Group 1~4, 40개 파일 처리, 2026-04-01)
|
||||
- 무엇/왜/어떻게:
|
||||
- 무엇: `변경 대상 파일 전체 목록`의 `Explorer` Group 1~4(40개 파일)를 전수 점검하고, 런타임 사용자 노출 하드코딩 문구를 `I18n.*`로 치환했다.
|
||||
- 왜: Explorer(탐색/프로필/팬톡/크리에이터 커뮤니티) 구간에서 하드코딩 문구와 직접 로컬라이제이션 API(`String(localized:)`)가 혼재되어 `I18n.swift` 단일 접근 원칙과 충돌했기 때문이다.
|
||||
- 어떻게: Explorer 대상 파일을 선별해 하드코딩/직접 API 사용을 재탐지하고, `I18n.swift`에 `I18n.Explorer` 네임스페이스를 추가한 뒤 호출부를 치환했다. 공통 문구는 `I18n.Common`으로 통합 재사용했다.
|
||||
- 실행 명령/도구:
|
||||
- `lsp_diagnostics(filePath=SodaLive/Sources/Explorer, extension=.swift, severity=all)`
|
||||
- `lsp_diagnostics(filePath=SodaLive/Sources/I18n/I18n.swift, severity=all)`
|
||||
- `grep("String\\(localized:|NSLocalizedString\\(|LocalizedStringKey\\(", include=*.swift, path=SodaLive/Sources/Explorer)`
|
||||
- `grep("\"[^\"]*[가-힣][^\"]*\"", include=*.swift, path=SodaLive/Sources/Explorer)`
|
||||
- `git diff --name-only -- "SodaLive/Sources/Explorer"`
|
||||
- `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`
|
||||
- 결과:
|
||||
- Explorer Group 1~4 체크박스 40개 `- [x]` 완료 상태를 유지/확인했다.
|
||||
- 실치환 파일은 총 37개였고, 나머지 3개(`ChannelDonationAllView.swift` 등)는 런타임 사용자 노출 하드코딩이 없어 점검만 수행했다.
|
||||
- `String(localized:)`/`NSLocalizedString`/`LocalizedStringKey`의 Explorer 직접 사용은 0건으로 확인했다.
|
||||
- Explorer 잔여 한글 리터럴은 Preview 샘플 데이터 및 `DEBUG_LOG` 메시지(비사용자 노출)만 존재함을 재확인했다.
|
||||
- 빌드 검증: `SodaLive`, `SodaLive-dev` Debug 빌드 모두 성공(`** BUILD SUCCEEDED **`).
|
||||
- 테스트 검증: 두 스킴 모두 `Scheme ... is not currently configured for the test action.`로 test action 미구성 확인(코드 실패 아님, 스킴 제약).
|
||||
- LSP 진단 참고: SourceKit 단독 해석에서 외부 모듈/프로젝트 심볼(`Moya`, `Kingfisher`, `I18n` 등) 미해결 오류가 보고되었으나, 동일 변경셋은 `xcodebuild` 실컴파일 통과로 검증했다.
|
||||
|
||||
Reference in New Issue
Block a user