feat: update broadcasting button logic and improve pre-join styles

ov-components_modernization
Carlos Santos 2025-12-11 18:31:20 +01:00
parent 53927b05a7
commit 68e9398b06
2 changed files with 350 additions and 357 deletions

View File

@ -71,22 +71,6 @@
[(ngModel)]="broadcastUrl" [(ngModel)]="broadcastUrl"
id="broadcast-url-input" id="broadcast-url-input"
/> />
<button
mat-icon-button
@if (broadcastingStatus !== broadcastingStatusEnum.STARTED) {
id="broadcasting-btn"
[disabled]="
!broadcastUrl ||
broadcastingStatus === broadcastingStatusEnum.STARTING ||
broadcastingStatus === broadcastingStatusEnum.STOPPING
"
(click)="startBroadcasting()"
matTooltip="{{ 'PANEL.STREAMING.START' | translate }}"
}
>
<mat-icon>play_circle</mat-icon>
</button>
@if (broadcastingStatus === broadcastingStatusEnum.STARTED) { @if (broadcastingStatus === broadcastingStatusEnum.STARTED) {
<button <button
mat-icon-button mat-icon-button
@ -96,6 +80,20 @@
> >
<mat-icon>stop_circle</mat-icon> <mat-icon>stop_circle</mat-icon>
</button> </button>
} @else {
<button
mat-icon-button
id="broadcasting-btn"
[disabled]="
!broadcastUrl ||
broadcastingStatus === broadcastingStatusEnum.STARTING ||
broadcastingStatus === broadcastingStatusEnum.STOPPING
"
(click)="startBroadcasting()"
matTooltip="{{ 'PANEL.STREAMING.START' | translate }}"
>
<mat-icon>play_circle</mat-icon>
</button>
} }
</div> </div>

View File

@ -2,291 +2,289 @@
display: block; display: block;
width: 100%; width: 100%;
height: 100%; height: 100%;
}
.prejoin-container { .prejoin-container {
min-height: 100vh; min-height: 100vh;
background: var(--ov-background-color); background: var(--ov-background-color);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
box-sizing: border-box;
position: relative;
transition: all 0.3s ease;
&.name-error {
.prejoin-main {
min-height: fit-content;
}
}
.prejoin-content {
width: 100%;
max-width: 520px;
margin: 0 auto;
.prejoin-main {
width: 100%;
background: var(--ov-surface-color, #ffffff);
border-radius: var(--ov-surface-radius);
overflow: hidden;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
animation: fadeIn 0.3s ease-out;
transform: translateZ(0);
}
}
// Top Language Toolbar
.top-toolbar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
display: flex;
justify-content: flex-end;
padding: 20px 24px;
background: transparent;
}
// Loading State
.loading-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 20px; background-color: var(--ov-background-color, #f5f5f5);
box-sizing: border-box; z-index: 1000;
position: relative;
transition: all 0.3s ease;
&.name-error { .loading-content {
.prejoin-main {
min-height: fit-content;
}
}
.prejoin-content {
width: 100%;
max-width: 520px;
margin: 0 auto;
.prejoin-main {
width: 100%;
background: var(--ov-surface-color, #ffffff);
border-radius: var(--ov-surface-radius);
overflow: hidden;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
animation: fadeIn 0.3s ease-out;
transform: translateZ(0);
}
}
// Top Language Toolbar
.top-toolbar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
display: flex;
justify-content: flex-end;
padding: 20px 24px;
background: transparent;
}
// Loading State
.loading-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex; display: flex;
flex-direction: column;
align-items: center; align-items: center;
justify-content: center; gap: 16px;
background-color: var(--ov-background-color, #f5f5f5);
z-index: 1000;
.loading-content { .loading-text {
display: flex; color: var(--ov-text-primary-color, #333);
flex-direction: column; font-size: 16px;
align-items: center; font-weight: 500;
gap: 16px; }
.loading-text { .mat-mdc-progress-spinner {
color: var(--ov-text-primary-color, #333); --mat-progress-spinner-active-indicator-color: var(--ov-secondary-action-color, #4285f4);
font-size: 16px;
font-weight: 500;
}
.mat-mdc-progress-spinner {
--mat-progress-spinner-active-indicator-color: var(--ov-secondary-action-color, #4285f4);
}
} }
} }
}
// Video Preview Section // Video Preview Section
.video-preview-section { .video-preview-section {
.video-preview-container { .video-preview-container {
position: relative; position: relative;
width: 100%;
aspect-ratio: 4/3;
border-radius: var(--ov-surface-radius) var(--ov-surface-radius) 0 0;
overflow: hidden;
background: var(--ov-video-background, var(--ov-primary-action-color));
.video-frame {
width: 100%; width: 100%;
aspect-ratio: 4/3; height: 100%;
border-radius: var(--ov-surface-radius) var(--ov-surface-radius) 0 0; position: relative;
overflow: hidden;
background: var(--ov-video-background, var(--ov-primary-action-color));
.video-frame { ::ng-deep .video-element {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: relative; object-fit: cover;
display: block;
::ng-deep .video-element { video {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
display: block; border-radius: 0;
video {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 0;
}
}
}
.video-overlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 16px;
z-index: 9999;
display: flex;
justify-content: center;
align-items: flex-end;
.device-controls {
display: flex;
gap: 12px;
}
.background-control {
position: absolute;
bottom: 16px;
left: 16px;
.background-button {
width: 48px;
height: 48px;
min-width: 48px;
min-height: 48px;
background: var(--ov-primary-action-color);
color: var(--ov-text-primary-color);
border-radius: 16px;
padding: 0;
&.mat-mdc-button-disabled {
background: var(--ov-disabled-background);
color: var(--ov-text-disabled-color);
cursor: not-allowed;
&:hover {
transform: none;
}
}
mat-icon {
font-size: 22px;
width: 22px;
height: 22px;
opacity: 0.9;
transition: opacity 0.2s ease;
margin: 0;
}
}
} }
} }
} }
}
.vb-container { .video-overlay {
height: fit-content; position: absolute;
overflow: hidden; bottom: 0;
} left: 0;
right: 0;
padding: 16px;
z-index: 9999;
display: flex;
justify-content: center;
align-items: flex-end;
// Configuration Section .device-controls {
.configuration-section { display: flex;
display: flex; gap: 12px;
padding: 24px; }
gap: 10px;
flex-flow: column;
.input-section { .background-control {
::ng-deep .name-input { position: absolute;
.mat-mdc-form-field { bottom: 16px;
width: 100%; left: 16px;
.mat-mdc-text-field-wrapper { .background-button {
border-radius: var(--ov-surface-radius); width: 48px;
border: 1px solid var(--ov-border-color, #e0e0e0); height: 48px;
transition: all 0.2s ease; min-width: 48px;
min-height: 48px;
background: var(--ov-primary-action-color);
color: var(--ov-text-primary-color);
border-radius: 16px;
padding: 0;
&.mat-mdc-button-disabled {
background: var(--ov-disabled-background);
color: var(--ov-text-disabled-color);
cursor: not-allowed;
&:hover { &:hover {
border-color: var(--ov-primary-action-color, #4285f4); transform: none;
}
&.mdc-text-field--focused {
border-color: var(--ov-primary-action-color, #4285f4);
box-shadow: 0 0 0 3px rgba(66, 133, 244, 0.1);
} }
} }
.mat-mdc-form-field-subscript-wrapper { mat-icon {
display: none; font-size: 22px;
width: 22px;
height: 22px;
opacity: 0.9;
transition: opacity 0.2s ease;
margin: 0;
} }
input {
font-size: 16px;
font-weight: 500;
color: var(--ov-text-surface-color, #666);
padding: 16px;
&::placeholder {
color: var(--ov-text-surface-color, #666);
font-weight: 400;
}
}
}
}
}
.error-message {
display: flex;
align-items: center;
gap: 8px;
padding: 12px 16px;
background-color: rgba(244, 67, 54, 0.08);
border: 1px solid rgba(244, 67, 54, 0.2);
border-radius: var(--ov-surface-radius);
color: var(--ov-error-color, #d32f2f);
.error-icon {
font-size: 18px;
width: 18px;
height: 18px;
}
.error-text {
font-size: 14px;
font-weight: 500;
}
}
.join-section {
.join-button {
width: 100%;
height: 56px;
background: var(--ov-primary-action-color);
color: var(--ov-text-primary-color);
border-radius: var(--ov-surface-radius);
font-size: 16px;
font-weight: 600;
letter-spacing: 0.5px;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
&:hover:not([disabled]) {
background: color-mix(in srgb, var(--ov-primary-action-color), var(--ov-secondary-action-color) 10%);
transform: translateY(-1px);
}
&:active:not([disabled]) {
transform: translateY(0);
}
&[disabled] {
background: var(--ov-disabled-color, #ccc);
color: var(--ov-disabled-text-color, #999);
cursor: not-allowed;
box-shadow: none;
}
.join-icon {
font-size: 20px;
width: 20px;
height: 20px;
} }
} }
} }
} }
} }
.vb-container {
height: fit-content;
overflow: hidden;
}
// Configuration Section
.configuration-section {
display: flex;
padding: 24px;
gap: 10px;
flex-flow: column;
.input-section {
::ng-deep .name-input {
.mat-mdc-form-field {
width: 100%;
.mat-mdc-text-field-wrapper {
border-radius: var(--ov-surface-radius);
border: 1px solid var(--ov-border-color, #e0e0e0);
transition: all 0.2s ease;
&:hover {
border-color: var(--ov-primary-action-color, #4285f4);
}
&.mdc-text-field--focused {
border-color: var(--ov-primary-action-color, #4285f4);
box-shadow: 0 0 0 3px rgba(66, 133, 244, 0.1);
}
}
.mat-mdc-form-field-subscript-wrapper {
display: none;
}
input {
font-size: 16px;
font-weight: 500;
color: var(--ov-text-surface-color, #666);
padding: 16px;
&::placeholder {
color: var(--ov-text-surface-color, #666);
font-weight: 400;
}
}
}
}
}
.error-message {
display: flex;
align-items: center;
gap: 8px;
padding: 12px 16px;
background-color: rgba(244, 67, 54, 0.08);
border: 1px solid rgba(244, 67, 54, 0.2);
border-radius: var(--ov-surface-radius);
color: var(--ov-error-color, #d32f2f);
.error-icon {
font-size: 18px;
width: 18px;
height: 18px;
}
.error-text {
font-size: 14px;
font-weight: 500;
}
}
.join-section {
.join-button {
width: 100%;
height: 56px;
background: var(--ov-primary-action-color);
color: var(--ov-text-primary-color);
border-radius: var(--ov-surface-radius);
font-size: 16px;
font-weight: 600;
letter-spacing: 0.5px;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
&:hover:not([disabled]) {
background: color-mix(in srgb, var(--ov-primary-action-color), var(--ov-secondary-action-color) 10%);
transform: translateY(-1px);
}
&:active:not([disabled]) {
transform: translateY(0);
}
&[disabled] {
background: var(--ov-disabled-color, #ccc);
color: var(--ov-disabled-text-color, #999);
cursor: not-allowed;
box-shadow: none;
}
.join-icon {
font-size: 20px;
width: 20px;
height: 20px;
}
}
}
}
// Mobile Layout Optimization // Mobile Layout Optimization
.prejoin-container.mobile { &.mobile {
all: unset;
padding: 0; padding: 0;
display: content;
height: 100vh;
min-height: 100vh; min-height: 100vh;
height: 100vh;
max-height: 100vh; max-height: 100vh;
overflow: hidden; overflow: hidden;
@ -303,7 +301,6 @@
flex-direction: column; flex-direction: column;
.video-preview-section { .video-preview-section {
// Video takes all remaining space
flex: 1 1 auto; flex: 1 1 auto;
min-height: 0; min-height: 0;
overflow: hidden; overflow: hidden;
@ -321,7 +318,6 @@
gap: 16px; gap: 16px;
background: var(--ov-surface-color, #ffffff); background: var(--ov-surface-color, #ffffff);
// Ensure content is displayed in column
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -332,7 +328,6 @@
} }
.vb-container { .vb-container {
// Virtual background panel - also adapts to content
flex: 0 0 auto; flex: 0 0 auto;
max-height: 60vh; max-height: 60vh;
overflow-y: auto; overflow-y: auto;
@ -341,109 +336,109 @@
} }
} }
} }
}
@keyframes slideInFromRight { // Responsive Design for Desktop/Tablet
from { @media (max-width: 640px) and (min-height: 640px) {
opacity: 0; .prejoin-container:not(.mobile) {
transform: translateX(20px); padding: 16px;
}
to {
opacity: 1;
transform: translateX(0);
}
}
// Responsive Design for Desktop/Tablet .prejoin-content {
@media (max-width: 640px) and (min-height: 640px) { max-width: 100%;
.prejoin-container:not(.mobile) {
padding: 16px;
.prejoin-content { .prejoin-main {
max-width: 100%; border-radius: var(--ov-surface-radius);
.prejoin-main {
border-radius: var(--ov-surface-radius);
}
}
.configuration-section {
padding: 20px;
gap: 16px;
}
.top-toolbar {
padding: 16px 20px;
} }
} }
}
@media (max-width: 480px) and (min-height: 640px) { .configuration-section {
.prejoin-container:not(.mobile) { padding: 20px;
padding: 12px; gap: 16px;
.configuration-section {
padding: 16px;
}
.video-overlay .device-controls {
gap: 8px;
::ng-deep .device-selector .mat-mdc-icon-button {
width: 44px;
height: 44px;
mat-icon {
font-size: 18px;
}
}
}
.top-toolbar {
padding: 12px 16px;
}
}
}
// Short screens - optimize for horizontal space
@media (max-height: 640px) and (min-width: 640px) {
.prejoin-container:not(.mobile) {
align-items: flex-start;
padding-top: 60px; // Space for top toolbar
.video-preview-section .video-preview-container {
aspect-ratio: 16/9; // Wider aspect ratio for short screens
}
}
}
// Dark theme support
@media (prefers-color-scheme: dark) {
.prejoin-container {
background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%);
} }
.prejoin-main { .top-toolbar {
background: #2d2d2d; padding: 16px 20px;
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.3),
0 2px 8px rgba(0, 0, 0, 0.2);
}
.configuration-section .input-section ::ng-deep .name-input .participant-name-input-container .input-wrapper {
background-color: #3a3a3a;
border-color: #555;
}
}
// Animation keyframes
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
} }
} }
} }
@media (max-width: 480px) and (min-height: 640px) {
.prejoin-container:not(.mobile) {
padding: 12px;
.configuration-section {
padding: 16px;
}
.video-overlay .device-controls {
gap: 8px;
::ng-deep .device-selector .mat-mdc-icon-button {
width: 44px;
height: 44px;
mat-icon {
font-size: 18px;
}
}
}
.top-toolbar {
padding: 12px 16px;
}
}
}
// Short screens - optimize for horizontal space
@media (max-height: 640px) and (min-width: 640px) {
.prejoin-container:not(.mobile) {
align-items: flex-start;
padding-top: 60px;
.video-preview-section .video-preview-container {
aspect-ratio: 16/9;
}
}
}
// Dark theme support
@media (prefers-color-scheme: dark) {
.prejoin-container {
background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%);
}
.prejoin-main {
background: #2d2d2d;
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.3),
0 2px 8px rgba(0, 0, 0, 0.2);
}
.configuration-section .input-section ::ng-deep .name-input .participant-name-input-container .input-wrapper {
background-color: #3a3a3a;
border-color: #555;
}
}
// Animation keyframes
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideInFromRight {
from {
opacity: 0;
transform: translateX(20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}