라이브룸 V2V 번역 자막 기능을 추가한다
라이브룸에서 진행자 언어와 기기 언어가 다를 때 자막 토글을 제공한다. 룸 정보 응답에 V2V 워커 토큰과 진행자 언어 코드를 포함한다. Agora V2V 에이전트 참여와 종료 API 연동을 추가한다
This commit is contained in:
@@ -17,7 +17,9 @@ struct LiveRoomInfoGuestView: View {
|
||||
let isOnNotice: Bool
|
||||
let isOnMenuPan: Bool
|
||||
let isOnSignature: Bool
|
||||
let isOnV2VCaption: Bool
|
||||
let isShowMenuPanButton: Bool
|
||||
let isShowV2VCaptionButton: Bool
|
||||
|
||||
let creatorId: Int
|
||||
let creatorNickname: String
|
||||
@@ -37,6 +39,7 @@ struct LiveRoomInfoGuestView: View {
|
||||
let onClickTotalHeart: () -> Void
|
||||
let onClickTotalDonation: () -> Void
|
||||
let onClickChangeListener: () -> Void
|
||||
let onClickToggleV2VCaption: () -> Void
|
||||
let onClickToggleSignature: () -> Void
|
||||
|
||||
var body: some View {
|
||||
@@ -62,6 +65,20 @@ struct LiveRoomInfoGuestView: View {
|
||||
strokeCornerRadius: 5.3
|
||||
) { onClickChangeListener() }
|
||||
}
|
||||
|
||||
if isShowV2VCaptionButton {
|
||||
LiveRoomOverlayStrokeTextToggleButton(
|
||||
isOn: isOnV2VCaption,
|
||||
onText: I18n.LiveRoom.captionOn,
|
||||
onTextColor: Color.button,
|
||||
onStrokeColor: Color.button,
|
||||
offText: I18n.LiveRoom.captionOff,
|
||||
offTextColor: Color.graybb,
|
||||
offStrokeColor: Color.graybb,
|
||||
strokeWidth: 1,
|
||||
strokeCornerRadius: 5.3
|
||||
) { onClickToggleV2VCaption() }
|
||||
}
|
||||
|
||||
LiveRoomOverlayStrokeTextToggleButton(
|
||||
isOn: isOnSignature,
|
||||
@@ -222,7 +239,9 @@ struct LiveRoomInfoGuestView_Previews: PreviewProvider {
|
||||
isOnNotice: false,
|
||||
isOnMenuPan: false,
|
||||
isOnSignature: false,
|
||||
isOnV2VCaption: false,
|
||||
isShowMenuPanButton: false,
|
||||
isShowV2VCaptionButton: true,
|
||||
creatorId: 1,
|
||||
creatorNickname: "도화",
|
||||
creatorProfileUrl: "https://cf.sodalive.net/profile/26/26-profile-ddf78b4d-0300-4c50-9c84-5d8a95fd5fe2-4892-1705256364320",
|
||||
@@ -258,6 +277,7 @@ struct LiveRoomInfoGuestView_Previews: PreviewProvider {
|
||||
onClickTotalHeart: {},
|
||||
onClickTotalDonation: {},
|
||||
onClickChangeListener: {},
|
||||
onClickToggleV2VCaption: {},
|
||||
onClickToggleSignature: {}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -95,7 +95,9 @@ struct LiveRoomViewV2: View {
|
||||
isOnNotice: viewModel.isShowNotice,
|
||||
isOnMenuPan: viewModel.isShowMenuPan,
|
||||
isOnSignature: viewModel.isSignatureOn,
|
||||
isOnV2VCaption: viewModel.isV2VCaptionOn,
|
||||
isShowMenuPanButton: !liveRoomInfo.menuPan.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty,
|
||||
isShowV2VCaptionButton: viewModel.isV2VAvailable,
|
||||
creatorId: liveRoomInfo.creatorId,
|
||||
creatorNickname: liveRoomInfo.creatorNickname,
|
||||
creatorProfileUrl: liveRoomInfo.creatorProfileUrl,
|
||||
@@ -132,6 +134,9 @@ struct LiveRoomViewV2: View {
|
||||
onClickChangeListener: {
|
||||
viewModel.setListener()
|
||||
},
|
||||
onClickToggleV2VCaption: {
|
||||
viewModel.toggleV2VCaption()
|
||||
},
|
||||
onClickToggleSignature: {
|
||||
viewModel.isSignatureOn.toggle()
|
||||
}
|
||||
@@ -182,7 +187,7 @@ struct LiveRoomViewV2: View {
|
||||
.onPreferenceChange(ScrollOffsetKey.self) {
|
||||
viewModel.setOffset($0)
|
||||
}
|
||||
.padding(.bottom, 70)
|
||||
.padding(.bottom, v2vCaptionBottomInset)
|
||||
}
|
||||
.padding(.top, 16)
|
||||
|
||||
@@ -308,6 +313,19 @@ struct LiveRoomViewV2: View {
|
||||
}
|
||||
.padding(.trailing, 13.3)
|
||||
|
||||
if isV2VCaptionVisible {
|
||||
Text(viewModel.v2vCaptionText)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
.lineLimit(2)
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 10)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
.background(Color.black.opacity(0.75))
|
||||
.cornerRadius(10)
|
||||
.padding(.horizontal, 13.3)
|
||||
}
|
||||
|
||||
LiveRoomInputChatView {
|
||||
viewModel.sendMessage(chatMessage: $0) {
|
||||
viewModel.isShowingNewChat = false
|
||||
@@ -316,6 +334,7 @@ struct LiveRoomViewV2: View {
|
||||
|
||||
return true
|
||||
}
|
||||
.padding(.top, isV2VCaptionVisible ? -13.3 : 0)
|
||||
.padding(.bottom, 10)
|
||||
}
|
||||
|
||||
@@ -323,7 +342,7 @@ struct LiveRoomViewV2: View {
|
||||
LiveRoomNewChatView{
|
||||
viewModel.isShowingNewChat = false
|
||||
proxy.scrollTo(viewModel.messages.count - 1, anchor: .center)
|
||||
}.padding(.bottom, 70)
|
||||
}.padding(.bottom, v2vCaptionBottomInset)
|
||||
}
|
||||
|
||||
if viewModel.isSignatureOn && viewModel.signatureImageUrl.trimmingCharacters(in: .whitespacesAndNewlines).count > 0 {
|
||||
@@ -474,6 +493,7 @@ struct LiveRoomViewV2: View {
|
||||
.onDisappear {
|
||||
UIApplication.shared.isIdleTimerDisabled = false
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
viewModel.stopV2VTranslationIfJoined()
|
||||
viewModel.stopPeriodicPlaybackValidation()
|
||||
}
|
||||
|
||||
@@ -744,6 +764,10 @@ struct LiveRoomViewV2: View {
|
||||
if viewModel.isLoading && viewModel.liveRoomInfo == nil {
|
||||
LoadingView()
|
||||
}
|
||||
|
||||
if viewModel.isV2VLoading {
|
||||
LoadingView()
|
||||
}
|
||||
}
|
||||
.overlay(alignment: .center) {
|
||||
ZStack {
|
||||
@@ -916,6 +940,17 @@ struct LiveRoomViewV2: View {
|
||||
}
|
||||
}
|
||||
|
||||
private extension LiveRoomViewV2 {
|
||||
var isV2VCaptionVisible: Bool {
|
||||
viewModel.isV2VCaptionOn &&
|
||||
!viewModel.v2vCaptionText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
||||
}
|
||||
|
||||
var v2vCaptionBottomInset: CGFloat {
|
||||
isV2VCaptionVisible ? 120 : 70
|
||||
}
|
||||
}
|
||||
|
||||
struct LiveRoomViewV2_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
LiveRoomViewV2()
|
||||
|
||||
Reference in New Issue
Block a user