mirror of
https://github.com/vector-im/element-call.git
synced 2024-11-15 00:04:59 +08:00
Merge remote-tracking branch 'upstream/livekit' into refactor/replace-jest-with-vitest
This commit is contained in:
commit
d266432427
4
.github/workflows/publish.yaml
vendored
4
.github/workflows/publish.yaml
vendored
@ -26,7 +26,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Log in to container registry
|
- name: Log in to container registry
|
||||||
uses: docker/login-action@3d58c274f17dffee475a5520cbe67f0a882c4dbb
|
uses: docker/login-action@83a00bc1ab5ded6580f31df1c49e6aaa932d840d
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.REGISTRY }}
|
registry: ${{ env.REGISTRY }}
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
@ -54,7 +54,7 @@ jobs:
|
|||||||
tar --numeric-owner --transform "s/dist/element-call-${TARBALL_VERSION}/" -cvzf element-call-${TARBALL_VERSION}.tar.gz dist
|
tar --numeric-owner --transform "s/dist/element-call-${TARBALL_VERSION}/" -cvzf element-call-${TARBALL_VERSION}.tar.gz dist
|
||||||
|
|
||||||
- name: Upload
|
- name: Upload
|
||||||
uses: actions/upload-artifact@4c0ff1c489dca52fedb26375d7d8fe7bd9233f19
|
uses: actions/upload-artifact@ef09cdac3e2d3e60d8ccadda691f4f1cec5035cb
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
with:
|
with:
|
||||||
|
@ -100,9 +100,8 @@
|
|||||||
"@types/request": "^2.48.8",
|
"@types/request": "^2.48.8",
|
||||||
"@types/sdp-transform": "^2.4.5",
|
"@types/sdp-transform": "^2.4.5",
|
||||||
"@types/uuid": "9",
|
"@types/uuid": "9",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.1.0",
|
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||||
"@typescript-eslint/parser": "^6.1.0",
|
"@typescript-eslint/parser": "^7.0.0",
|
||||||
"@vitest/coverage-v8": "^1.2.2",
|
|
||||||
"babel-loader": "^9.0.0",
|
"babel-loader": "^9.0.0",
|
||||||
"babel-plugin-transform-vite-meta-env": "^1.0.3",
|
"babel-plugin-transform-vite-meta-env": "^1.0.3",
|
||||||
"eslint": "^8.14.0",
|
"eslint": "^8.14.0",
|
||||||
|
@ -143,6 +143,7 @@
|
|||||||
"unmute_microphone_button_label": "Unmute microphone",
|
"unmute_microphone_button_label": "Unmute microphone",
|
||||||
"version": "Version: {{version}}",
|
"version": "Version: {{version}}",
|
||||||
"video_tile": {
|
"video_tile": {
|
||||||
|
"change_fit_contain": "Crop to fit",
|
||||||
"exit_full_screen": "Exit full screen",
|
"exit_full_screen": "Exit full screen",
|
||||||
"full_screen": "Full screen",
|
"full_screen": "Full screen",
|
||||||
"mute_for_me": "Mute for me",
|
"mute_for_me": "Mute for me",
|
||||||
|
@ -41,6 +41,8 @@ export const RoomAuthView: FC = () => {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
(e) => {
|
(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
const data = new FormData(e.target);
|
const data = new FormData(e.target);
|
||||||
const dataForDisplayName = data.get("displayName");
|
const dataForDisplayName = data.get("displayName");
|
||||||
const displayName =
|
const displayName =
|
||||||
|
@ -167,6 +167,12 @@ export class UserMediaTileViewModel extends BaseTileViewModel {
|
|||||||
*/
|
*/
|
||||||
public readonly videoEnabled: StateObservable<boolean>;
|
public readonly videoEnabled: StateObservable<boolean>;
|
||||||
|
|
||||||
|
private readonly _cropVideo = new BehaviorSubject(true);
|
||||||
|
/**
|
||||||
|
* Whether the tile video should be contained inside the tile or be cropped to fit.
|
||||||
|
*/
|
||||||
|
public readonly cropVideo = state(this._cropVideo);
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
id: string,
|
id: string,
|
||||||
member: RoomMember | undefined,
|
member: RoomMember | undefined,
|
||||||
@ -205,6 +211,10 @@ export class UserMediaTileViewModel extends BaseTileViewModel {
|
|||||||
this._locallyMuted.next(!this._locallyMuted.value);
|
this._locallyMuted.next(!this._locallyMuted.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public toggleFitContain(): void {
|
||||||
|
this._cropVideo.next(!this._cropVideo.value);
|
||||||
|
}
|
||||||
|
|
||||||
public setLocalVolume(value: number): void {
|
public setLocalVolume(value: number): void {
|
||||||
this._localVolume.next(value);
|
this._localVolume.next(value);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ borders don't support gradients */
|
|||||||
.videoTile video {
|
.videoTile video {
|
||||||
inline-size: 100%;
|
inline-size: 100%;
|
||||||
block-size: 100%;
|
block-size: 100%;
|
||||||
object-fit: cover;
|
object-fit: contain;
|
||||||
background-color: var(--cpd-color-bg-subtle-primary);
|
background-color: var(--cpd-color-bg-subtle-primary);
|
||||||
/* This transform is a no-op, but it forces Firefox to use a different
|
/* This transform is a no-op, but it forces Firefox to use a different
|
||||||
rendering path, one that actually clips the corners of <video> elements into
|
rendering path, one that actually clips the corners of <video> elements into
|
||||||
@ -89,6 +89,10 @@ borders don't support gradients */
|
|||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.videoTile.cropVideo video {
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
.videoTile.videoMuted video {
|
.videoTile.videoMuted video {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -206,9 +206,16 @@ const UserMediaTile = subscribe<UserMediaTileProps, HTMLDivElement>(
|
|||||||
const mirror = useStateObservable(vm.mirror);
|
const mirror = useStateObservable(vm.mirror);
|
||||||
const speaking = useStateObservable(vm.speaking);
|
const speaking = useStateObservable(vm.speaking);
|
||||||
const locallyMuted = useStateObservable(vm.locallyMuted);
|
const locallyMuted = useStateObservable(vm.locallyMuted);
|
||||||
|
const cropVideo = useStateObservable(vm.cropVideo);
|
||||||
const localVolume = useStateObservable(vm.localVolume);
|
const localVolume = useStateObservable(vm.localVolume);
|
||||||
const onChangeMute = useCallback(() => vm.toggleLocallyMuted(), [vm]);
|
const onChangeMute = useCallback(() => vm.toggleLocallyMuted(), [vm]);
|
||||||
|
const onChangeFitContain = useCallback(() => vm.toggleFitContain(), [vm]);
|
||||||
const onSelectMute = useCallback((e: Event) => e.preventDefault(), []);
|
const onSelectMute = useCallback((e: Event) => e.preventDefault(), []);
|
||||||
|
const onSelectFitContain = useCallback(
|
||||||
|
(e: Event) => e.preventDefault(),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
const onChangeLocalVolume = useCallback(
|
const onChangeLocalVolume = useCallback(
|
||||||
(v: number) => vm.setLocalVolume(v),
|
(v: number) => vm.setLocalVolume(v),
|
||||||
[vm],
|
[vm],
|
||||||
@ -225,6 +232,13 @@ const UserMediaTile = subscribe<UserMediaTileProps, HTMLDivElement>(
|
|||||||
label={t("common.profile")}
|
label={t("common.profile")}
|
||||||
onSelect={onOpenProfile}
|
onSelect={onOpenProfile}
|
||||||
/>
|
/>
|
||||||
|
<ToggleMenuItem
|
||||||
|
Icon={ExpandIcon}
|
||||||
|
label={t("video_tile.change_fit_contain")}
|
||||||
|
checked={cropVideo}
|
||||||
|
onChange={onChangeFitContain}
|
||||||
|
onSelect={onSelectFitContain}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@ -235,6 +249,13 @@ const UserMediaTile = subscribe<UserMediaTileProps, HTMLDivElement>(
|
|||||||
onChange={onChangeMute}
|
onChange={onChangeMute}
|
||||||
onSelect={onSelectMute}
|
onSelect={onSelectMute}
|
||||||
/>
|
/>
|
||||||
|
<ToggleMenuItem
|
||||||
|
Icon={ExpandIcon}
|
||||||
|
label={t("video_tile.change_fit_contain")}
|
||||||
|
checked={cropVideo}
|
||||||
|
onChange={onChangeFitContain}
|
||||||
|
onSelect={onSelectFitContain}
|
||||||
|
/>
|
||||||
{/* TODO: Figure out how to make this slider keyboard accessible */}
|
{/* TODO: Figure out how to make this slider keyboard accessible */}
|
||||||
<MenuItem as="div" Icon={VolumeIcon} label={null} onSelect={null}>
|
<MenuItem as="div" Icon={VolumeIcon} label={null} onSelect={null}>
|
||||||
<Slider
|
<Slider
|
||||||
@ -257,6 +278,7 @@ const UserMediaTile = subscribe<UserMediaTileProps, HTMLDivElement>(
|
|||||||
className={classNames(className, {
|
className={classNames(className, {
|
||||||
[styles.mirror]: mirror,
|
[styles.mirror]: mirror,
|
||||||
[styles.speaking]: showSpeakingIndicator && speaking,
|
[styles.speaking]: showSpeakingIndicator && speaking,
|
||||||
|
[styles.cropVideo]: cropVideo,
|
||||||
})}
|
})}
|
||||||
style={style}
|
style={style}
|
||||||
targetWidth={targetWidth}
|
targetWidth={targetWidth}
|
||||||
|
Loading…
Reference in New Issue
Block a user