I have this class:
export default class CallManager{
static instance = null
calls = []
static getInstance() {
if (CallManager.instance == null) {
CallManager.instance = new CallManager()
}
return this.instance;
}
addCall(callUUID, data){
this.calls.push({
callId : callUUID,
data: data
})
}
removeCall(callUUID){
this.calls = this.calls.filter(c => c.callId != callUUID)
}
getAllCall(){
return this.calls
}
}
When ios app killed + get incoming call (with RNCallKeep), I'm using this class to store new call like this:
RNCallKeep.addEventListener('didDisplayIncomingCall', ({ error, callUUID, handle, localizedCallerName, hasVideo, fromPushKit, payload }) => {
// you might want to do following things when receiving this event:
// - Start playing ringback if it is an outgoing call
console.log('didDisplayIncomingCall', error, callUUID, handle, localizedCallerName, hasVideo, fromPushKit, payload)
try {
CallManager.getInstance().addCall(callUUID, { ...payload})
} catch (error) {
console.log('didDisplayIncomingCall error', error)
RNCallKeep.endCall(callUUID)
}
})
const answerCall = ({callUUID}) => {
console.log(`[answerCall] ${callUUID}`)
RNCallKeep.answerIncomingCall(callUUID)
const callData = CallManager.getInstance().getAllCall().find(c => c.callId.toString().toUpperCase() === callUUID.toString().toUpperCase())
....
}
But after debug, i got getAllCall return empty. Can someone help?
Related
I tried my best to write a custom directive in Apollo Server Express to validate two input type fields.
But the code even works but the recording of the mutation already occurs.
I appreciate if anyone can help me fix any error in the code below.
This is just sample code, I need to test the value in two fields at the same time.
const { SchemaDirectiveVisitor } = require('apollo-server');
const { GraphQLScalarType, GraphQLNonNull, defaultFieldResolver } = require('graphql');
class RegexDirective extends SchemaDirectiveVisitor {
visitInputFieldDefinition(field) {
this.wrapType(field);
}
visitFieldDefinition(field) {
this.wrapType(field);
}
wrapType(field) {
const { resolve = defaultFieldResolver } = field;
field.resolve = async function (source, args, context, info) {
if (info.operation.operation === 'mutation') {
if (source[field.name] === 'error') {
throw new Error(`Find error: ${field.name}`);
}
}
return await resolve.call(this, source, args, context, info);
};
if (
field.type instanceof GraphQLNonNull
&& field.type.ofType instanceof GraphQLScalarType
) {
field.type = new GraphQLNonNull(
new RegexType(field.type.ofType),
);
} else if (field.type instanceof GraphQLScalarType) {
field.type = new RegexType(field.type);
} else {
// throw new Error(`Not a scalar type: ${field.type}`);
}
}
}
class RegexType extends GraphQLScalarType {
constructor(type) {
super({
name: 'RegexScalar',
serialize(value) {
return type.serialize(value);
},
parseValue(value) {
return type.parseValue(value);
},
parseLiteral(ast) {
const result = type.parseLiteral(ast);
return result;
},
});
}
}
module.exports = RegexDirective;
I've got NestJS application which interact with YoutubeAPI and load videos from it.
One particular method is important and it's loadVideos from below. Method it self has multiple asyncs inside and I need to work with videoIdMap property once everything is finished
private loadVideos(
playListId: string,
channel: Channel,
nextPageToken: string,
stopLoadingOnVideoId: string,
) {
const baseUrl = YoutubeService.VIDEO_URL_SNIPPET_BY_ID + playListId;
const response = this.httpService
.get(nextPageToken ? baseUrl + '&pageToken=' + nextPageToken : baseUrl)
.pipe(map((response) => response.data));
response.subscribe((data) => {
data.items.forEach((item) => {
if (stopLoadingOnVideoId && item.snippet.resourceId.videoId === stopLoadingOnVideoId) {
return;
}
this.prepareVideoEntity(item.snippet, channel).then((partialVideo) =>
this.videoService.create(partialVideo).then((video) => {
this.videoIdMap[video.youtubeId] = video.id;
}),
);
});
if (data.nextPageToken) {
this.loadVideos(
playListId,
channel,
data.nextPageToken,
stopLoadingOnVideoId,
);
}
});
}
Ideal solution for me would be to make loadVideos async somehow so I can later do:
public methodWhichCallLoadVideos(): void {
await loadVideos(playListId, channel, null, stopLoadingOnVideoId)
// My code which have to be executed right after videos are loaded
}
Every solution I tried out end up with this.videoIdMap to be empty object or with compilation issue so any idea is more than welcome.
You could switch to promises instead of Observables, thus turning the method into an async one that recurs as long as data has a nextPageToken:
private async loadVideos(
playListId: string,
channel: Channel,
nextPageToken: string,
stopLoadingOnVideoId: string,
) {
const baseUrl = YoutubeService.VIDEO_URL_SNIPPET_BY_ID + playListId;
const response = await this.httpService
.get(nextPageToken ? url + '&pageToken=' + nextPageToken : url).toPromise();
const { data } = response;
for (const item of data.items) {
if (stopLoadingOnVideoId && item.snippet.resourceId.videoId === stopLoadingOnVideoId) {
continue;
}
const partialVideo = await this.prepareVideoEntity(item.snippet, channel);
const video = await this.videoService.create(partialVideo)
this.videoIdMap[video.youtubeId] = video.id;
}
if (data.nextPageToken) {
await this.loadVideos(
playListId,
channel,
data.nextPageToken,
stopLoadingOnVideoId,
);
}
}
In your caller you can then simply await loadVideos(...):
private async initVideoIdMap(...) {
await this.loadVideos(...);
// this.videoIdMap should be correctly populated at this point
}
The given class has a method which returns a cached stream but that stream can be triggered by another private hot stream which makes the cached stream emits a new value.
The class
export class SomeClass {
private cache: Observable<number>;
private trigger$ = new Subject();
private multiply = 1;
constructor(private num: number) {}
getNumber(): Observable<number> {
return (
this.cache ||
(this.cache = concat(of(void 0), this.trigger$).pipe(
switchMap(() => of(this.num * this.multiply++)),
shareReplay(1)
))
);
}
trigger(): void {
this.trigger$.next();
}
}
Example: https://stackblitz.com/edit/rxjs-gpyc46?file=index.ts
What is the way to test it?
This try is failed
it("trigger updates", () => {
testScheduler.run(({ expectObservable }) => {
const num$ = someClass.getNumber();
expectObservable(num$).toBe("a", { a: 3 });
someClass.trigger();
expectObservable(num$).toBe("a", { a: 6 });
someClass.trigger();
expectObservable(num$).toBe("a", { a: 9 });
});
});
Example: https://stackblitz.com/edit/rxjs-test-tricky-flow?file=src%2Fsome-class.spec.ts
UPD: so the problem here that seems it is not possible to mock the trigger$ property.
It would look like this
it("trigger updates", () => {
testScheduler.run(({ hot, expectObservable }) => {
spyOnProperty(someClass, 'trigger$', 'get').and.returnValue(hot('^--b--c'));
const num$ = someClass.getNumber();
expectObservable(num$).toBe("a--b--c", { a: 3, b: 6, c: 9 });
});
});
But the trigger$ property must be changed this way
get trigger$() {
return new Subject();
}
Example: https://stackblitz.com/edit/rxjs-test-tricky-flow-x2arxf?file=src%2Fsome-class.ts
I'm trying to bind the data from api which is written in .net core with angular api using ng for i getting the value properly but when i use the check input field my console is full on unstoppable errors
I have tried many examples from stackoverflow non them worked for me
export class UsermanagementComponent {
userDetailsList: any = [];
public userList: any= [];
departmentuser: any = {};
public searchTxt:any;
isActive: boolean = false;
checkuserstatus: boolean;
constructor(private router: Router, private http: HttpClient, private
toastr: ToastrService, private appComponent: AppComponent) {
this.userList
}
private jwtHelper: JwtHelperService = new JwtHelperService();
ngOnInit() {
this.appComponent.startSpinner();
this.getuser();
;
}
edituser(userList: any) {
localStorage.setItem("userList", JSON.stringify(userList));
console.log(userList);
this.router.navigate(["/landingpage/edituser"], userList);
}
lockUnlockUser(userList: any) {
console.log(userList);
this.http.post(environment.apiUrl + "Account/LockUserAccount", userList,
{
}).subscribe(data => {
this.appComponent.stopSpinner();
this.router.navigate(["/landingpage/usermanagement"]);
this.userList = data;
this.checkuserstatus = this.userList.lockoutEnabled;
console.log(this.checkuserstatus);
if (this.checkuserstatus == true) {
let toast = this.toastr.success(MessageVariable.UserLocked);
alert(toast);
} else if (this.checkuserstatus == false) {
let toast = this.toastr.info(MessageVariable.UserUnLocked);
alert(toast);
}
}, (err) => {
this.toastr.error(MessageVariable.ErrorMsg);
});
}
getuser() {
this.appComponent.startSpinner();
var userId = localStorage.getItem('userid');
console.log(userId);
this.http.get(environment.apiUrl + "Account/GetUser", {
}).subscribe(data => {
this.appComponent.stopSpinner();
this.userList = data;
console.log(this.userList);
}, (err) => {
this.toastr.error(MessageVariable.ErrorMsg);
});
}
}
UsermanagementComponent.html:22 ERROR Error: Error trying to diff '[object Object]'. Only arrays and iterables are allowed
at
I have a two way bound object in a custom element. Its two way bound to the parent.
The parent, client.ts, does a fetch for the client data based on a clientDetails class.
The child here is the Address custom element.
When the client form is populated with a client so is the address component via the bind.
In the address.ts (child here) I have initialized the two way bind as so:
#bindable({ defaultBindingMode: bindingMode.twoWay }) address = new AddressDetails;
AddressDetails is as follows:
import { Serializable } from "../../../../services/serializable/Serializable"
import { AddressLocation } from "./addressLocation"
export class AddressDetails implements Serializable<AddressDetails> {
address1: string;
address2: string;
addressLocation: AddressLocation;
deserialize(input) {
//console.log("INPUT: ", input)
this.address1 = input.address1;
this.address2 = input.address2;
if (input.addressLocation) {
this.addressLocation = new AddressLocation;
this.addressLocation.deserialize(input.addressLocation);
}
return this;
}
}
When a client is requested for edit it all works so if a client is populated then so is the address component.
My problem is that I am getting errors wherever I try and set a value thats part of the bind object. that is, If I want to set the stateShortName as per:
this.address.addressLocation.stateShortName = this.companyStateShortName;
I get the error:
address.ts:72 Uncaught (in promise) TypeError: Cannot set property 'stateShortName' of undefined
As it states this.address.addressLocation.stateShortName is undefined.
This caused me to check if I could console.log the value of this.address in a "created" function as well as "bind" and "attached".
So even though I have bound this object, initialized at the start as AddressDetails it always comes up as undefined even when all the fields show values it still errors as "undefined".
Even though I have initialized this object from the start no matter where I try and access this two way bound object I cant because its "undefined"
Why cant I access it??
..and how do I access "this.address" or any of its members so I can, say, set one of the object's members to a value??
Below is the whole class for the "address.ts" for context. I get an error any time I try and access or set this.address in this class.
import { HttpClient } from "aurelia-fetch-client";
import { bindable, bindingMode, autoinject, inject, NewInstance, PLATFORM } from "aurelia-framework";
import { Router, activationStrategy } from "aurelia-router";
import {
ValidationControllerFactory,
ValidationController,
ValidationRules
} from "aurelia-validation";
import { BootstrapFormRenderer } from "../../../../services/bootstrapFormRenderer/bootstrapFormRenderer";
import { AuthService } from "../../../../services/auth/auth-service"
import { AddressDetails } from "../address/addressDetails"
import { AddressLocation } from "./addressLocation"
#autoinject
export class Address {
#bindable({ defaultBindingMode: bindingMode.twoWay }) address = new AddressDetails;
postcode: string;
states = Array();
companyStateShortName: string;
constructor(
private authService: AuthService) {
this.getStateData();
}
created(owningView, myView) {
console.log("CONSTRUCTOR ADDRESS: ", typeof this.address, this.address);
}
bind(bindingContext, overrideContext) {
if (this.address.addressLocation.postcode === "undefined") {//we want it to match
setTimeout(50);//wait 50 millisecnds then recheck
return;
}
console.log("BIND ADDRESS: ", this.address);
}
attached() {
console.log("ATTACHED ADDRESS: ", this.address);
}
// Single fetch for poplulating the states and obtaining the default state.
getStateData() {
const headers = this.authService.header();
let stateDropdown = fetch("/api/selectData/GetStatesAndCompanyStateId", {
method: "GET",
headers
})
.then(response => response.json())
.then(data => {
for (const key in data.stateDropDownList) {
this.states[key] = data.stateDropDownList[key].stateShortName;
}
console.log("ADDRESS get state data: ", this.address);
console.log("data: ", data)
this.companyStateShortName = data.companyStateShortName;
console.log("StateShortName: ", this.companyStateShortName)
})
.then(() => {
//if (typeof this.address.addressLocation != "undefined") {
//this.address = new AddressDetails;
//this.address.addressLocation = new AddressLocation;
//debugger;
console.log("this.address.addressLocation: ", typeof this.address, this.address)
this.address.addressLocation.stateShortName = this.companyStateShortName;
//}
});
return stateDropdown;
}
// Fetch for async suburb dropdown.
async getSuburbData(filter: string, limit: number) {
const headers = this.authService.header();
if (this.address) {
}
else {
console.log('undefined')
}
const queryStringValues = {
query: filter,
stateShortName: this.companyStateShortName
};
const queryString = "?" + Object.keys(queryStringValues)
.filter(key => typeof queryStringValues[key] !== "undefined" && queryStringValues[key] !== null)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(queryStringValues[key])}`)
.join("&");
console.log("queryStringValue; ", queryString)
//console.log("initial suburb", this.address.addressLocation.suburb);
let suburbLookup = await fetch("/api/selectData/QuerySuburbs" + queryString, {
method: "GET",
headers: headers
})
.then(response => {
return response.json();
})
.then(addressLocation => filter.length > 0 ? addressLocation.filter(item => item.suburb.toLowerCase().indexOf(filter.toLowerCase()) > -1) : addressLocation)
.then(addressLocation => limit ? addressLocation.splice(0, limit) : addressLocation); // Not really needed - its done on the server.
//.then(suburbs => console.log("Suburbs: ", suburbs));
//this.postCode = this.address.postcode;
console.log("suburbLookup", suburbLookup);
return suburbLookup
}
suburbSelected(item) {
//debugger;
//console.log("BEFORE ASSIGNMENT OF SUBURB NAME: ", item, item.postcode, this.address.addressLocation.postcode)
if (this.address.addressLocation != null && item != null) {
console.log("2 changed suburb", this.address.addressLocation.suburb);
//this.address.addressLocation.suburb = item.name
var test = item.postcode;
//this.address.addressLocation.postcode = item.postcode;
//this.address.addressLocation.addressLocationId = item.addressLocationId;
} else {
// this.address.addressLocation.postcode = "-";
}
console.log("AFTER ASSIGNMENT OF SUBURB NAME: ", item, this.address)
}
}
class StateDropdownAndCompanyState {
companyStateShortName: string;
stateDropdownList: StateDropdown[];
}
class StateDropdown {
stateId: number;
stateShortName: string;
stateName: string;
stateLabel: string;
}
class suburbQuery {
query: string;
stateShortName: string;
}