mirror of
https://github.com/vector-im/hydrogen-web.git
synced 2024-12-23 11:35:04 +01:00
use error view (model) in call view (model)
This commit is contained in:
parent
64d6db556a
commit
4070d422cd
@ -29,6 +29,10 @@ export class ErrorViewModel extends ViewModel<Options> {
|
|||||||
return this.getOption("error")?.message;
|
return this.getOption("error")?.message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get error(): Error {
|
||||||
|
return this.getOption("error");
|
||||||
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.getOption("onClose")();
|
this.getOption("onClose")();
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import {getStreamVideoTrack, getStreamAudioTrack} from "../../../matrix/calls/co
|
|||||||
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar";
|
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar";
|
||||||
import {EventObservableValue} from "../../../observable/value/EventObservableValue";
|
import {EventObservableValue} from "../../../observable/value/EventObservableValue";
|
||||||
import {ObservableValueMap} from "../../../observable/map/ObservableValueMap";
|
import {ObservableValueMap} from "../../../observable/map/ObservableValueMap";
|
||||||
|
import { ErrorViewModel } from "../../ErrorViewModel";
|
||||||
import type {Room} from "../../../matrix/room/Room";
|
import type {Room} from "../../../matrix/room/Room";
|
||||||
import type {GroupCall} from "../../../matrix/calls/group/GroupCall";
|
import type {GroupCall} from "../../../matrix/calls/group/GroupCall";
|
||||||
import type {Member} from "../../../matrix/calls/group/Member";
|
import type {Member} from "../../../matrix/calls/group/Member";
|
||||||
@ -28,14 +29,17 @@ import type {BaseObservableList} from "../../../observable/list/BaseObservableLi
|
|||||||
import type {BaseObservableValue} from "../../../observable/value/BaseObservableValue";
|
import type {BaseObservableValue} from "../../../observable/value/BaseObservableValue";
|
||||||
import type {Stream} from "../../../platform/types/MediaDevices";
|
import type {Stream} from "../../../platform/types/MediaDevices";
|
||||||
import type {MediaRepository} from "../../../matrix/net/MediaRepository";
|
import type {MediaRepository} from "../../../matrix/net/MediaRepository";
|
||||||
|
import type { Session } from "../../../matrix/Session";
|
||||||
|
|
||||||
type Options = BaseOptions & {
|
type Options = BaseOptions & {
|
||||||
call: GroupCall,
|
call: GroupCall,
|
||||||
room: Room,
|
room: Room,
|
||||||
|
session: Session
|
||||||
};
|
};
|
||||||
|
|
||||||
export class CallViewModel extends ViewModel<Options> {
|
export class CallViewModel extends ViewModel<Options> {
|
||||||
public readonly memberViewModels: BaseObservableList<IStreamViewModel>;
|
public readonly memberViewModels: BaseObservableList<IStreamViewModel>;
|
||||||
|
private _errorViewModel?: ErrorViewModel;
|
||||||
|
|
||||||
constructor(options: Options) {
|
constructor(options: Options) {
|
||||||
super(options);
|
super(options);
|
||||||
@ -88,8 +92,8 @@ export class CallViewModel extends ViewModel<Options> {
|
|||||||
return this.call.id;
|
return this.call.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
get error(): string | undefined {
|
get errorViewModel(): ErrorViewModel | undefined {
|
||||||
return this.call.error?.message;
|
return this._errorViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private get call(): GroupCall {
|
private get call(): GroupCall {
|
||||||
@ -97,12 +101,19 @@ export class CallViewModel extends ViewModel<Options> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onUpdate() {
|
private onUpdate() {
|
||||||
|
if (this.call.error) {
|
||||||
|
this._reportError(this.call.error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async hangup() {
|
async hangup() {
|
||||||
|
try {
|
||||||
if (this.call.hasJoined) {
|
if (this.call.hasJoined) {
|
||||||
await this.call.leave();
|
await this.call.leave();
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this._reportError(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async toggleCamera() {
|
async toggleCamera() {
|
||||||
@ -125,7 +136,6 @@ export class CallViewModel extends ViewModel<Options> {
|
|||||||
// unmute but no track?
|
// unmute but no track?
|
||||||
if (muteSettings.microphone && !getStreamAudioTrack(localMedia.userMedia)) {
|
if (muteSettings.microphone && !getStreamAudioTrack(localMedia.userMedia)) {
|
||||||
const stream = await this.platform.mediaDevices.getMediaTracks(true, !muteSettings.camera);
|
const stream = await this.platform.mediaDevices.getMediaTracks(true, !muteSettings.camera);
|
||||||
console.log("got tracks", Array.from(stream.getTracks()).map((t: MediaStreamTrack) => { return {kind: t.kind, id: t.id};}))
|
|
||||||
await this.call.setMedia(localMedia.withUserMedia(stream));
|
await this.call.setMedia(localMedia.withUserMedia(stream));
|
||||||
} else {
|
} else {
|
||||||
await this.call.setMuted(muteSettings.toggleMicrophone());
|
await this.call.setMuted(muteSettings.toggleMicrophone());
|
||||||
@ -133,6 +143,21 @@ export class CallViewModel extends ViewModel<Options> {
|
|||||||
this.emitChange();
|
this.emitChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _reportError(error: Error) {
|
||||||
|
if (this._errorViewModel?.error === error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.disposeTracked(this._errorViewModel);
|
||||||
|
this._errorViewModel = new ErrorViewModel(this.childOptions({
|
||||||
|
error,
|
||||||
|
onClose: () => {
|
||||||
|
this._errorViewModel = this.disposeTracked(this._errorViewModel);
|
||||||
|
this.emitChange("errorViewModel");
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
this.emitChange("errorViewModel");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OwnMemberViewModel extends ViewModel<Options> implements IStreamViewModel {
|
class OwnMemberViewModel extends ViewModel<Options> implements IStreamViewModel {
|
||||||
@ -151,7 +176,7 @@ class OwnMemberViewModel extends ViewModel<Options> implements IStreamViewModel
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
get error(): string | undefined {
|
get errorViewModel(): ErrorViewModel | undefined {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,22 +232,25 @@ class OwnMemberViewModel extends ViewModel<Options> implements IStreamViewModel
|
|||||||
|
|
||||||
type MemberOptions = BaseOptions & {
|
type MemberOptions = BaseOptions & {
|
||||||
member: Member,
|
member: Member,
|
||||||
mediaRepository: MediaRepository
|
mediaRepository: MediaRepository,
|
||||||
|
session: Session
|
||||||
};
|
};
|
||||||
|
|
||||||
export class CallMemberViewModel extends ViewModel<MemberOptions> implements IStreamViewModel {
|
export class CallMemberViewModel extends ViewModel<MemberOptions> implements IStreamViewModel {
|
||||||
|
private _errorViewModel?: ErrorViewModel;
|
||||||
|
|
||||||
get stream(): Stream | undefined {
|
get stream(): Stream | undefined {
|
||||||
return this.member.remoteMedia?.userMedia;
|
return this.member.remoteMedia?.userMedia;
|
||||||
}
|
}
|
||||||
|
|
||||||
get error(): string | undefined {
|
|
||||||
return this.member.error?.message;
|
|
||||||
}
|
|
||||||
|
|
||||||
private get member(): Member {
|
private get member(): Member {
|
||||||
return this.getOption("member");
|
return this.getOption("member");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get errorViewModel(): ErrorViewModel | undefined {
|
||||||
|
return this._errorViewModel;
|
||||||
|
}
|
||||||
|
|
||||||
get isCameraMuted(): boolean {
|
get isCameraMuted(): boolean {
|
||||||
return this.member.remoteMuteSettings?.camera ?? true;
|
return this.member.remoteMuteSettings?.camera ?? true;
|
||||||
}
|
}
|
||||||
@ -250,7 +278,23 @@ export class CallMemberViewModel extends ViewModel<MemberOptions> implements ISt
|
|||||||
}
|
}
|
||||||
|
|
||||||
onUpdate() {
|
onUpdate() {
|
||||||
|
this.mapMemberSyncErrorIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private mapMemberSyncErrorIfNeeded() {
|
||||||
|
if (this.member.error && (!this._errorViewModel || this._errorViewModel.error !== this.member.error)) {
|
||||||
|
this.disposeTracked(this._errorViewModel);
|
||||||
|
this._errorViewModel = this.track(new ErrorViewModel(this.childOptions({
|
||||||
|
error: this.member.error,
|
||||||
|
onClose: () => {
|
||||||
|
this._errorViewModel = this.disposeTracked(this._errorViewModel);
|
||||||
|
this.emitChange("errorViewModel");
|
||||||
|
},
|
||||||
|
})));
|
||||||
|
this.emitChange("errorViewModel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
compare(other: OwnMemberViewModel | CallMemberViewModel): number {
|
compare(other: OwnMemberViewModel | CallMemberViewModel): number {
|
||||||
if (other instanceof OwnMemberViewModel) {
|
if (other instanceof OwnMemberViewModel) {
|
||||||
return -other.compare(this);
|
return -other.compare(this);
|
||||||
@ -268,5 +312,5 @@ export interface IStreamViewModel extends AvatarSource, ViewModel {
|
|||||||
get stream(): Stream | undefined;
|
get stream(): Stream | undefined;
|
||||||
get isCameraMuted(): boolean;
|
get isCameraMuted(): boolean;
|
||||||
get isMicrophoneMuted(): boolean;
|
get isMicrophoneMuted(): boolean;
|
||||||
get error(): string | undefined;
|
get errorViewModel(): ErrorViewModel | undefined;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import {ListView} from "../../general/ListView";
|
|||||||
import {classNames} from "../../general/html";
|
import {classNames} from "../../general/html";
|
||||||
import {Stream} from "../../../../types/MediaDevices";
|
import {Stream} from "../../../../types/MediaDevices";
|
||||||
import type {CallViewModel, CallMemberViewModel, IStreamViewModel} from "../../../../../domain/session/room/CallViewModel";
|
import type {CallViewModel, CallMemberViewModel, IStreamViewModel} from "../../../../../domain/session/room/CallViewModel";
|
||||||
|
import { ErrorView } from "../../general/ErrorView";
|
||||||
|
|
||||||
export class CallView extends TemplateView<CallViewModel> {
|
export class CallView extends TemplateView<CallViewModel> {
|
||||||
private resizeObserver?: ResizeObserver;
|
private resizeObserver?: ResizeObserver;
|
||||||
@ -44,8 +45,8 @@ export class CallView extends TemplateView<CallViewModel> {
|
|||||||
}, onClick: disableTargetCallback(() => vm.toggleCamera())}),
|
}, onClick: disableTargetCallback(() => vm.toggleCamera())}),
|
||||||
t.button({className: "CallView_hangup", onClick: disableTargetCallback(() => vm.hangup())}),
|
t.button({className: "CallView_hangup", onClick: disableTargetCallback(() => vm.hangup())}),
|
||||||
]),
|
]),
|
||||||
t.if(vm => !!vm.error, t => {
|
t.if(vm => !!vm.errorViewModel, t => {
|
||||||
return t.div({className: "CallView_error"}, vm => vm.error);
|
return t.div({className: "CallView_error"}, t.view(new ErrorView(vm.errorViewModel!)));
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -116,8 +117,8 @@ class StreamView extends TemplateView<IStreamViewModel> {
|
|||||||
cameraMuted: vm => vm.isCameraMuted,
|
cameraMuted: vm => vm.isCameraMuted,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
t.if(vm => !!vm.error, t => {
|
t.if(vm => !!vm.errorViewModel, t => {
|
||||||
return t.div({className: "StreamView_error"}, vm => vm.error);
|
return t.div({className: "StreamView_error"}, t.view(new ErrorView(vm.errorViewModel!)));
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user