|
26 | 26 | @if (ActiveTab == GoLiveStudioTab.Stream) |
27 | 27 | { |
28 | 28 | <div class="gl-tab-content active"> |
| 29 | + <div class="gl-info-section" |
| 30 | + data-test="@UiTestIds.GoLive.LocalRecordingControls"> |
| 31 | + <span class="gl-info-label">Local recording</span> |
| 32 | + <div class="gl-local-rec-grid"> |
| 33 | + <button type="button" |
| 34 | + class="gl-local-rec-btn @(IsRecordingActive ? "active" : null)" |
| 35 | + disabled="@(!CanControlLocalRecording)" |
| 36 | + data-state="@LocalRecordingState" |
| 37 | + data-test="@UiTestIds.GoLive.LocalRecordingVideoButton" |
| 38 | + @onclick="ToggleLocalRecording"> |
| 39 | + <UiIcon Kind="UiIconKind.Video" Size="13" /> |
| 40 | + <strong>Video</strong> |
| 41 | + <span>@LocalRecordingVideoStatus</span> |
| 42 | + </button> |
| 43 | + <button type="button" |
| 44 | + class="gl-local-rec-btn @(IsRecordingActive ? "active" : null)" |
| 45 | + disabled="@(!CanControlLocalRecording || !HasPrimaryMicrophone)" |
| 46 | + data-state="@(HasPrimaryMicrophone ? LocalRecordingState : UnavailableStateValue)" |
| 47 | + data-test="@UiTestIds.GoLive.LocalRecordingAudioButton" |
| 48 | + @onclick="ToggleLocalRecording"> |
| 49 | + <UiIcon Kind="UiIconKind.Microphone" Size="13" /> |
| 50 | + <strong>Audio</strong> |
| 51 | + <span>@LocalRecordingAudioStatus</span> |
| 52 | + </button> |
| 53 | + </div> |
| 54 | + <p class="gl-local-rec-copy" |
| 55 | + data-test="@UiTestIds.GoLive.LocalRecordingStatus">@LocalRecordingDetail</p> |
| 56 | + </div> |
| 57 | + |
29 | 58 | <div class="gl-info-section"> |
30 | 59 | <span class="gl-info-label">@Text(GoLiveText.Sidebar.DestinationsLabel)</span> |
31 | 60 | <div class="gl-dest-list"> |
|
229 | 258 | private const string ActiveMeterStateValue = "active"; |
230 | 259 | private const string DisabledStateValue = "false"; |
231 | 260 | private const string EnabledStateValue = "true"; |
| 261 | + private const string RecordingStateValue = "recording"; |
| 262 | + private const string StoppedStateValue = "stopped"; |
| 263 | + private const string UnavailableStateValue = "unavailable"; |
232 | 264 |
|
233 | 265 | [Parameter] public GoLiveStudioTab ActiveTab { get; set; } |
234 | 266 | [Parameter] public IReadOnlyList<GoLiveAudioChannelViewModel> AudioChannels { get; set; } = []; |
| 267 | + [Parameter] public bool CanControlLocalRecording { get; set; } |
235 | 268 | [Parameter] public EventCallback CreateRoom { get; set; } |
236 | 269 | [Parameter] public bool CueArmed { get; set; } |
237 | 270 | [Parameter] public IReadOnlyList<GoLiveDestinationSummaryViewModel> Destinations { get; set; } = []; |
238 | 271 | [Parameter] public bool IsRoomActive { get; set; } |
| 272 | + [Parameter] public bool IsRecordingActive { get; set; } |
| 273 | + [Parameter] public bool HasPrimaryMicrophone { get; set; } |
239 | 274 | [Parameter] public bool MuteAllGuests { get; set; } |
240 | 275 | [Parameter] public IReadOnlyList<GoLiveRoomParticipantViewModel> Participants { get; set; } = []; |
241 | 276 | [Parameter] public string RoomCode { get; set; } = string.Empty; |
|
244 | 279 | [Parameter] public EventCallback SendCue { get; set; } |
245 | 280 | [Parameter] public IReadOnlyList<GoLiveMetricViewModel> StatusMetrics { get; set; } = []; |
246 | 281 | [Parameter] public EventCallback<string> ToggleDestination { get; set; } |
| 282 | + [Parameter] public EventCallback ToggleLocalRecording { get; set; } |
247 | 283 | [Parameter] public EventCallback ToggleMuteAllGuests { get; set; } |
248 | 284 | [Parameter] public EventCallback ToggleTalkback { get; set; } |
249 | 285 | [Parameter] public bool TalkbackEnabled { get; set; } |
|
252 | 288 | private bool _muteAllGuests => MuteAllGuests; |
253 | 289 | private bool _talkbackEnabled => TalkbackEnabled; |
254 | 290 |
|
| 291 | + private string LocalRecordingState => |
| 292 | + !CanControlLocalRecording |
| 293 | + ? UnavailableStateValue |
| 294 | + : IsRecordingActive |
| 295 | + ? RecordingStateValue |
| 296 | + : StoppedStateValue; |
| 297 | + |
| 298 | + private string LocalRecordingVideoStatus => |
| 299 | + !CanControlLocalRecording |
| 300 | + ? "Unavailable" |
| 301 | + : IsRecordingActive |
| 302 | + ? "Recording" |
| 303 | + : "Stopped"; |
| 304 | + |
| 305 | + private string LocalRecordingAudioStatus => |
| 306 | + !HasPrimaryMicrophone |
| 307 | + ? "Unavailable" |
| 308 | + : IsRecordingActive |
| 309 | + ? "Recording" |
| 310 | + : "Stopped"; |
| 311 | + |
| 312 | + private string LocalRecordingDetail => |
| 313 | + !CanControlLocalRecording |
| 314 | + ? "Camera permission or a local source is required." |
| 315 | + : "Browser-local audio/video export. No stream or cloud upload."; |
| 316 | + |
255 | 317 | private string Text(string key) => Localizer[key]; |
256 | 318 | } |
0 commit comments