MediaStreamRecorder is not a constructor - javascript

I'm new to Angular6 and I'm trying to use MediaStreamRecorder. I'm definitely doing something wrong when defining MediaStreamRecorder because I keep getting the error TypeError: msr__WEBPACK_IMPORTED_MODULE_4__.MediaStreamRecorder is not a constructor. Not sure how or where should I declare and define MediaStreamRecorder. Can you help me with this, please?
I have installed msr module, and my code looks like this:
import { Component,ViewChild, OnInit, Inject } from '#angular/core';
import { LinksService } from 'demo/_services/links.service';
import { Http,Response,Headers } from '#angular/http';
import { MediaStreamRecorder} from 'msr';
import { RecordRTC } from 'recordrtc';
#Component({
selector: 'demo-ceva',
templateUrl: './ceva.component.html',
styleUrls: ['./ceva.component.css'],
providers: [
{
provide: SpeechRecognitionLang,
useValue: 'en-US',
},
SpeechRecognitionService,
],
})
export class CevaComponent {
public navigator: any;
public MediaStreamRecorder: any;
constructor( private http: Http, private service: SpeechRecognitionService, private links: LinksService ) {
this.record = () => {
var browser = <any>navigator;
var obj = { audio: true, video:false };
browser.getUserMedia = (browser.getUserMedia || browser.webkitGetUserMedia || browser.mozGetUserMedia || browser.msGetUserMedia);
browser.mediaDevices.getUserMedia(obj).then(stream => {
var source = window.URL.createObjectURL(stream);
var config= { ... }
var recorder = new MediaStreamRecorder(stream, config);
recorder.record();
recorder.stop(function(blob) {
var blob = recorder.blob;
console.log(blob);
});
});
});

As the answer to this post suggested, the solution to me was that in typings.d.ts file to add the following declarations:
declare interface MediaRecorderErrorEvent extends Event {
name: string;
}
declare interface MediaRecorderDataAvailableEvent extends Event {
data : any;
}
interface MediaRecorderEventMap {
'dataavailable': MediaRecorderDataAvailableEvent;
'error': MediaRecorderErrorEvent ;
'pause': Event;
'resume': Event;
'start': Event;
'stop': Event;
'warning': MediaRecorderErrorEvent ;
}
declare class MediaRecorder extends EventTarget {
readonly mimeType: string;
// readonly MimeType: 'audio/wav';
readonly state: 'inactive' | 'recording' | 'paused';
readonly stream: MediaStream;
ignoreMutedMedia: boolean;
videoBitsPerSecond: number;
audioBitsPerSecond: number;
ondataavailable: (event : MediaRecorderDataAvailableEvent) => void;
onerror: (event: MediaRecorderErrorEvent) => void;
onpause: () => void;
onresume: () => void;
onstart: () => void;
onstop: () => void;
constructor(stream: MediaStream);
start();
stop();
resume();
pause();
isTypeSupported(type: string): boolean;
requestData();
addEventListener<K extends keyof MediaRecorderEventMap>(type: K, listener: (this: MediaStream, ev: MediaRecorderEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof MediaRecorderEventMap>(type: K, listener: (this: MediaStream, ev: MediaRecorderEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
And in my component, I was able to use var mediaRecorder = new MediaRecorder(stream); without any other declarations. Thank you, #firegloves , for the link to this post and thank you, #Tiberiu C. for the answer! It was really helpful.

npm install -D #types/dom-mediacapture-record

I had the same issue with pure JS and React and removing the following line "fixed" the problem:
window.MediaRecorder = require('audio-recorder-polyfill');

Related

HMS Core location Kit TypeError: Cannot read properties of undefined (reading 'getFusedLocationProviderClient') - Ionic/Capacitor - VueJS

I'm trying to implement HMS Core location kit into my vue ionic app.
I import HMSLocation and declare it, but when I try to use the getFusedLocationProviderClient function I get
TypeError: Cannot read properties of undefined (reading 'getFusedLocationProviderClient')
import { HMSLocation } from "#hmscore/ionic-native-hms-location/ngx";
export default {
data() {
return {
hmsLocation: null,
fusedClient: null,
locationResult: null,
};
},
mounted() {
this.getLocation();
},
methods: {
async getLocation() {
this.hmsLocation = new HMSLocation();
console.log(this.hmsLocation);
this.fusedClient = this.hmsLocation.getFusedLocationProviderClient();
this.locationResult = await this.fusedClient.getLastLocation;
},
},
.....
console.log(this.hmsLocation); returns
node_modules/#hmscore/ionic-native-hms-location/ngx
import { IonicNativePlugin } from '#ionic-native/core';
export declare class HMSLocation extends IonicNativePlugin {
getGeofenceService(): GeofenceService;
getGeocoderService(language: string, country?: string): GeocoderService;
getFusedLocationProviderClient(): FusedLocationService;
getActivityIdentificationService(): ActivityIdentificationService;
addListener(event: Events, callback: (data: LocationResult | [] | ActivityConversionResponse | ActivityIdentificationResponse) => void): any;
disableLogger(): Promise<void>;
enableLogger(): Promise<void>;
}
export declare class BackgroundManager {
private constructor();
static notify(notificationId: number, notification: string): void;
static makeToast(text: string, duration: number): void;
}
export interface FusedLocationService {
disableBackgroundLocation(): Promise<void>;
enableBackgroundLocation(notificationId: number, notification: string): Promise<void>;
checkLocationSettings(request: LocationSettingsRequest): Promise<LocationSettingsStates>;
flushLocations(): Promise<void>;
getLastLocation(): Promise<Location>;
getLastLocationWithAddress(request: LocationRequest): Promise<HWLocation>;
getLocationAvailability(): Promise<boolean>;
getNavigationContextState(requestType: NavigationRequestConstants): Promise<NavigationResult>;
removeLocationUpdates(requestCode: number, type: RequestType): Promise<boolean>;
requestLocationUpdates(requestCode: number, request: LocationRequest, callback?: (locationResult: LocationResult) => void): Promise<boolean>;
requestLocationUpdatesEx(requestCode: number, request: LocationRequest): Promise<boolean>;
setMockLocation(latLng: LatLng): Promise<void>;
setMockMode(mode: boolean): Promise<void>;
setLogConfig(logConfigSettings: LogConfigSettings): Promise<void>;
getLogConfig(): Promise<LogConfigSettings>;
}

Display an array of data from function in Angular

My goal is to display a cross or a check according to the vote.result data from the polls.
I had to use Angular only few times and I feel pretty lost honestly.
TS file (angular) :
#Component({
selector: 'app-deck-card',
templateUrl: './deck-card.component.html',
styleUrls: ['./deck-card.component.scss'],
})
export class DeckCardComponent implements OnInit {
#Input() isAnim: boolean;
#Input() inGame: boolean;
#Input() editMode: boolean;
#Input() readOnly: boolean;
#Input() deckIsBase: boolean;
#Input() card: CardDto;
#Input() polls: PollDto[];
#Input() isSearch: boolean;
#Input() isImport: boolean;
#Input() idDeck: number;
#Input() editRight: boolean;
#Output() changeVote = new EventEmitter<number>();
#Output() deleteEvent = new EventEmitter<number>();
#Output() duplicateEvent = new EventEmitter<CardDto>();
#Output() importEvent = new EventEmitter<CardDto>();
#Output() sharedToCommunityEvent = new EventEmitter<CardDto>();
safeIcon: SafeUrl | string;
votes: VoteDto[];
constructor(private readonly authState: AuthState,
private sanitizer: DomSanitizer) {
}
ngOnInit(): void {
this.safeIcon = this.sanitizer.bypassSecurityTrustUrl(this.card?.theme?.icon);
this.votes = this.polls?.find(p => p.card.id === this.card?.id)?.votes;
}
/**
* Emit the card ID to delete the card
* #return void
*/
deleteCard(): void {
this.deleteEvent.emit(this.card.id);
}
showTheResult(): string {
console.log(this.polls);
console.log(this.votes);
this.polls?.forEach(vote => {
if (vote.voted && vote.result == false) {
// display a mat-icon cross
console.log(vote)
return '<mat-icon>clear</mat-icon>'
} else if (vote.voted && vote.result == true) {
// display a mat-icon check
console.log(vote)
return '<mat-icon>done</mat-icon>'
}
});
return '';
}
}
My 2 console.log in showTheResult() are always undefined.
So, obviously, the console log in the if condition are never reached.
HTML file :
<div class="card-body" [class.card-body-readOnly]="readOnly">
<p class="main-text" [class.readOnly]="readOnly" [class.short]="inGame && isAnim"
[class.long]="!editMode && !isAnim">{{card?.text}}</p>
<p>{{showTheResult()}}</p>
<p>DISPLAY HERE THE MAT-ICON</p>
<span *ngIf="isAnim || editMode" class="sub-text">#{{card?.id}}</span>
</div>
can someone show me the way ?
The DTOs look like this:
export interface PollDto {
id: number;
result: boolean;
voted: boolean;
priority: number;
card: CardDto;
votes: VoteDto[];
}
export interface VoteDto {
participantId: number;
participantName?: string;
pollId: number;
result: boolean;
}
since your this.polls is an #Input(), you don't know if this variable is actually loaded when you reach ngOnInit lifecycle.
When working with #Input data, if you want to catch the moment data is loaded, you should watch the changes :
https://ultimatecourses.com/blog/detect-input-property-changes-ngonchanges-setters
ngOnChanges(changes: SimpleChanges) {
console.log(changes);
}
This way, you will see if ever your data are loaded, if not, that means the problem is in the parent container component.
Also, a quick note : I don't think you should return HTML in your
method, you probably want to handle this another way, with a directive
or something, this would not be a good practice.
Cheers ! :)

Typescript: es6 import type definition (.d.ts) from node_modules subfolder

I have a npm package that has the following type definitions (simplified):
./node_modules/ag-grid-react/main.d.ts
export declare class AgGridReact extends Component<AgGridReactProps, {}> {}
./node_modules/ag-grid-react/lib/agGridReact.d.ts
export declare class AgGridReact extends Component<AgGridReactProps, {}> {
gridOptions: GridOptions;
api: GridApi | null;
columnApi: ColumnApi;
}
I am using the component in my react component like this:
import { AgGridReact } from 'ag-grid-react'
const HelpRequests= () => {
const grid = useRef<AgGridReact>(null)
if (grid.current) console.log(grid.current.columnApi)
return (<AgGridReact ref={grid}/>)
}
The Problem:
Typescript does complain that there is no columnApi. It seems it sadly picks the wrong type from the main.d.ts
I found that I can import the type from the agGridReact.d.ts directly and use it like this:
import {AgGridReact as AgGridReactType} from 'ag-grid-react/lib/agGridReact'
...
const grid = useRef<AgGridReactType>(null)
Question:
Is this the correct way to address this issue? Will typescript be smart enough not to import the ./node_modules/ag-grid-react/lib/agGridReact.ts file which could cause my bundle size to go up?
I've searched a lot but could not find anything about importing types only from node_modules subfolders.
I will try to answer this:
Let's assume there is an xyz library and it has these files:
xyz/lib/main.ts:
export const test = 1000
and
xyz/main.ts:
export * from './lib/main.ts'
export const test = 'foo bar'
And I would like to use xyz in my app.ts, and I am aware of only its main.ts file as I think it is the main file which exports everything from library. So I am most likely to do:
app.ts:
import { test } from './xyz/main'
console.debug(test) // it will print 'foo bar'
Now, somebody goes and comment this line in the library:
xyz/main.ts:
export * from './lib/main.ts'
// export const test = 'foo bar'
Now, what will be printed by my app.ts? It will print 1000.
The same thing is happening there with ag-grid-react. It (ag-grid-react/main.d.ts) is overriding the apparently correct (better) class declaration present in ag-grid-react/lib/agGridReact.d.ts. And it is perfectly fine to import from inner path.
main.d.ts:
export * from './lib/agGridReact'; // it is exporting from innner path too
export declare class AgGridColumn extends Component<AgGridColumnProps | AgGridColumnGroupProps, {}> { // and overriding here at the same time
}
agGridReact.d.ts:
export declare class AgGridReact extends Component<AgGridReactProps, {}> {
props: any;
state: any;
static propTypes: any;
gridOptions: GridOptions;
changeDetectionService: ChangeDetectionService;
api: GridApi | null;
columnApi: ColumnApi;
portals: ReactPortal[];
hasPendingPortalUpdate: boolean;
destroyed: boolean;
protected eGridDiv: HTMLElement;
private static MAX_COMPONENT_CREATION_TIME;
constructor(props: any, state: any);
render(): React.ReactElement<any, string | ((props: any) => React.ReactElement<any, string | any | (new (props: any) => React.Component<any, any, any>)>) | (new (props: any) => React.Component<any, any, any>)>;
createStyleForDiv(): any;
componentDidMount(): void;
waitForInstance(reactComponent: ReactComponent, resolve: (value: any) => void, runningTime?: number): void;
mountReactPortal(portal: ReactPortal, reactComponent: ReactComponent, resolve: (value: any) => void): void;
batchUpdate(callback?: any): any;
destroyPortal(portal: ReactPortal): void;
private getStrategyTypeForProp;
shouldComponentUpdate(nextProps: any): boolean;
componentDidUpdate(prevProps: any): void;
processPropsChanges(prevProps: any, nextProps: any): void;
private extractDeclarativeColDefChanges;
private extractGridPropertyChanges;
componentWillUnmount(): void;
isDisableStaticMarkup(): boolean;
}
I can't exactly say why ag-grid did this. I found this looking at the typing files. I may be incorrect too.

Cannot find module '#angular/core

I want to implement chart in my angular app. So I used ChartJs. I implemented method to show chart but problem in its gives an error when compiling.
My base-chart.directive.d.ts file as follows.
import { OnDestroy, OnChanges, OnInit, EventEmitter, ElementRef, SimpleChanges, DoCheck } from '#angular/core';
import * as chartJs from 'chart.js';
import { Color } from './color';
import { ThemeService } from './theme.service';
export declare type SingleDataSet = (number[] | chartJs.ChartPoint[]);
export declare type MultiDataSet = (number[] | chartJs.ChartPoint[])[];
export declare type SingleOrMultiDataSet = SingleDataSet | MultiDataSet;
export declare type PluginServiceGlobalRegistrationAndOptions = chartJs.PluginServiceGlobalRegistration & chartJs.PluginServiceRegistrationOptions;
export declare type SingleLineLabel = string;
export declare type MultiLineLabel = string[];
export declare type Label = SingleLineLabel | MultiLineLabel;
export declare class BaseChartDirective implements OnDestroy, OnChanges, OnInit, OnDestroy, DoCheck {
private element;
private themeService;
data: SingleOrMultiDataSet;
datasets: chartJs.ChartDataSets[];
labels: Label[];
options: chartJs.ChartOptions;
chartType: chartJs.ChartType;
colors: Color[];
legend: boolean;
plugins: PluginServiceGlobalRegistrationAndOptions[];
chartClick: EventEmitter<{
event?: MouseEvent;
active?: {}[];
}>;
chartHover: EventEmitter<{
event: MouseEvent;
active: {}[];
}>;
ctx: string;
chart: Chart;
private old;
private subs;
/**
* Register a plugin.
*/
static registerPlugin(plugin: PluginServiceGlobalRegistrationAndOptions): void;
static unregisterPlugin(plugin: PluginServiceGlobalRegistrationAndOptions): void;
constructor(element: ElementRef, themeService: ThemeService);
ngOnInit(): void;
private themeChanged;
ngDoCheck(): void;
copyLabel(a: Label): Label;
labelsEqual(a: Label, b: Label): boolean;
copyColor(a: Color): Color;
colorsEqual(a: Color, b: Color): boolean;
updateColors(): void;
ngOnChanges(changes: SimpleChanges): void;
ngOnDestroy(): void;
update(duration?: any, lazy?: any): {};
hideDataset(index: number, hidden: boolean): void;
isDatasetHidden(index: number): boolean;
toBase64Image(): string;
getChartConfiguration(): chartJs.ChartConfiguration;
getChartBuilder(ctx: string): Chart;
smartMerge(options: any, overrides: any, level?: number): any;
private isMultiLineLabel;
private joinLabel;
private propagateDatasetsToData;
private propagateDataToDatasets;
private isMultiDataSet;
private getDatasets;
private refresh;
}
I have already followed instruction which mentioned here
But my problem as it is. Please help. My ChartJs version is:ng2-charts#2.2.3 and angular version 8.
Try npm cache clean --force and then run npm install ng2-charts#2.3.2 --save to re install ng chart.

pipe operator not behaving as expected RXJS

Please look at my component below the purpose to is to listen on changes to an input, which it does and then emit the value to the parent component. I created a pipe to only emit every so often and therby minimize the calls to the api, for some reason even though I can see through various console.log statements that it goes in the pipe, it emits the value on every change. What is it that I am missing:
import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output, KeyValueDiffers, DoCheck, KeyValueDiffer} from '#angular/core';
import {BehaviorSubject, Observable, of} from "rxjs";
import {debounceTime, distinctUntilChanged, map, skip, switchMap, takeUntil, tap} from "rxjs/operators";
#Component({
selector: 'core-ui-typeahead-filter',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './typeahead-filter.component.html',
})
export class TypeaheadFilterComponent implements DoCheck {
#Input() id: string;
#Input() name: string;
#Input() caption: string;
#Input() placeholder: string;
#Input() cssClass: string;
#Input() cssStyle: string;
#Input() function: any;
#Input() data: Observable<string[]>;
differ: any;
detectChange: string = '';
// term$ = new BehaviorSubject<string>('');
text$ = new Observable<string>();
#Output() onTypeahead: EventEmitter<any> = new EventEmitter<any>();
#Output() onSelect: EventEmitter<any> = new EventEmitter<any>();
constructor(private differs: KeyValueDiffers) {
this.differ = this.differs.find({}).create();
}
handleTypeahead = (text$: Observable<string>) =>
text$.pipe(
distinctUntilChanged(),
debounceTime(500),
).subscribe((value) => {
this.onTypeahead.emit(of(value))
})
handleSelectItem(item) {
this.onSelect.emit(item);
}
ngDoCheck() {
const change = this.differ.diff(this);
if (change) {
change.forEachChangedItem(item => {
if (item.key === 'detectChange'){
console.log('item changed', item)
this.text$ = of(item.currentValue);
this.handleTypeahead(this.text$);
}
});
}
}
}
More background: There is an ngModel on the input linked to detectChange when it changes then the ngDoCheck is called and executes. Everything is done in observables so in the parent I can subscribe to the incoming events.
EDIT -------------------------------------------------------------------
Tried the following solution based on my understanding of #ggradnig answer, sadly it skips over my pipe something seems wrong with it, really not sure what:
handleTypeahead = (text$: Observable<string>) => {
this.test.subscribe(this.text$);
this.test.pipe(
distinctUntilChanged(),
debounceTime(500),
// switchMap(value => text$)
).subscribe((value) => {
tap(console.log('im inside the subscription',value))
this.onTypeahead.emit(value)
})
}
handleSelectItem(item) {
this.onSelect.emit(item);
}
ngDoCheck() {
const change = this.differ.diff(this);
if (change) {
change.forEachChangedItem(item => {
if (item.key === 'detectChange'){
console.log('item changed', item)
this.text$ = of(item.currentValue);
this.handleTypeahead(this.test);
}
});
}
}
}
You can do the following -
export class TypeaheadFilterComponent implements DoCheck {
#Input() id: string;
#Input() name: string;
#Input() caption: string;
#Input() placeholder: string;
#Input() cssClass: string;
#Input() cssStyle: string;
#Input() function: any;
#Input() data: Observable<string[]>;
differ: any;
detectChange: string = '';
// term$ = new BehaviorSubject<string>('');
text$ = new BehaviorSubject<string>('');
serachTerm$: Observable<string>;
#Output() onTypeahead: EventEmitter<any> = new EventEmitter<any>();
#Output() onSelect: EventEmitter<any> = new EventEmitter<any>();
constructor(private differs: KeyValueDiffers) {
this.differ = this.differs.find({}).create();
}
// handleTypeahead = (text$: Observable<string>) =>
// text$.pipe(
// distinctUntilChanged(),
// debounceTime(500),
// ).subscribe((value) => {
// this.onTypeahead.emit(of(value))
// })
ngOnInit() {
this.serachTerm$ = this.text$
.pipe(
distinctUntilChanged(),
debounceTime(500),
//filter(), //use filter operator if your logic wants to ignore certain string like empty/null
tap(s => this.onTypeahead.emit(s))
);
}
handleSelectItem(item) {
this.onSelect.emit(item);
}
ngDoCheck() {
const change = this.differ.diff(this);
if (change) {
change.forEachChangedItem(item => {
if (item.key === 'detectChange'){
console.log('item changed', item)
this.text$.next(item.currentValue);
}
});
}
}
}
Now, at the bottom of your template put the following line -
<ng-container *ngIf="searchTerm$ | async"></ng-container>
Having this line will keep your component code free form managing the subscription [i.e. need not to subscribe/unsubscribe]; async pipe will take care of it.

Categories

Resources