Integrate DeepAR Shoes try-on SDK with react - reactjs

I am trying to implement DeepAR SDK for shoe try-on in my react app but when I try to instantiate DeepAR class I got a weird error:
Uncaught (in promise) RuntimeError: Aborted(both async and sync fetching of the wasm failed). Build with -sASSERTIONS for more info.
at q2 (deepar.esm.js:1:676382)
at Q2 (deepar.esm.js:1:676689)
at deepar.esm.js:1:755786
I tried to put those files in public folder, and inside src but it didn't work.
const deepar = new DeepAR({
canvas,
licenseKey: import.meta.env.VITE_DEEPAR_SDK_KEY,
deeparWasmPath: "../lib/wasm/deepar.wasm",
footTrackingConfig: {
poseEstimationWasmPath: "../lib/wasm/libxzimgPoseEstimation.wasm",
detectorPath: iosDetected
? "../lib/models/foot/foot-detector-ios.bin"
: "../lib/models/foot/foot-detector-android.bin",
trackerPath: iosDetected
? "../lib/models/foot/foot-tracker-ios.bin"
: "../lib/models/foot/foot-tracker-android.bin",
objPath: "../lib/models/foot/foot-model.obj",
},
callbacks: {
onInitialize: () => {
deepar.startVideo();
// deepar.switchEffect(0, "mask", "/effects/Shoe_PBR");
},
onCameraPermissionAsked: () => console.log("onCameraPermissionAsked"),
onCameraPermissionGranted: () => console.log("onCameraPermissionGranted"),
onCameraPermissionDenied: () => console.log("onCameraPermissionDenied"),
onVideoStarted: () => console.log("onVideoStarted"),
onError: (error) => console.log("onError", error),
},
});

Related

Agora screen sharing in electron with react, Gives permission denied

I am building an electron-react app with Agora for calls. I am trying to implement the screen sharing feature.
As described in the following documentation I tried requesting screen sharing.
https://docs.agora.io/en/video/screensharing_web_ng?platform=Web#screen-sharing-on-electron
But I am getting the following error
AgoraRTCError PERMISSION_DENIED: NotAllowedError: Permission denied
I tried invoking the same function AgoraRTC.createScreenVideoTrack in react and electron but the result was the same.
How do I get permission to share the screen in electron with agora?
After some research, I found the electron way of doing it.
First I request to share the screen.
const turnScreenSharingOn = async () => {
const sources = await window.electron.media.getDesktopSources();
setScreenSources(sources);
setScreenSharePopupVisible(true);
};
window.electron.media.getDesktopSources() is a electron preload function that fetches the screen sources.
getDesktopSources: async () =>
await desktopCapturer
.getSources({
types: ['window', 'screen'],
})
.then((sources) =>
sources.map((source) => ({
id: source.id,
name: source.name,
appIconUrl: source?.appIcon?.toDataURL(),
thumbnailUrl: source?.thumbnail
?.resize({ height: 160 })
.toDataURL(),
}))
)
Once I have the sources I show the popup from which I choose the source and pass the source id to the next function.
const onScreenChoose = async (sourceId: string, cb?: () => void) => {
const stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: sourceId,
},
} as MediaTrackConstraints,
});
const track = stream.getVideoTracks()[0];
const screenTrack = AgoraRTC.createCustomVideoTrack({
mediaStreamTrack: track,
});
window.agora.screenTrack?.setEnabled(false);
window.agora.screenTrack = screenTrack;
setScreenTrack(screenTrack);
await screenShareClient.publish(screenTrack);
setScreenSharePopupVisible(false);
cb?.();
};

jest mockReturnValueOnce is not a function

I have a custom hook that returns true or false by checking if the view is a mobile or a desktop view.
I'm trying to write a test for a page that uses this hook. I tried as following
import { useIsMobile } from '../../../../hooks/useIsMobile';
jest.mock('../../../../hooks/useIsMobile');
describe('Form', () => {
beforeEach(jest.resetAllMocks);
it('should render the correct header style for deliver to label in desktop view', () => {
(useIsMobile as jest.Mock).mockReturnValueOnce(false);
const delivery_label = screen.getByTestId('label1');
expect(delivery_label.tagName).toEqual('H3');
});
it('should render the correct header style for deliver to label in mobile view', () => {
(useIsMobile as jest.Mock).mockReturnValueOnce(true);
const delivery_label = screen.getByTestId('label1');
expect(delivery_label.tagName).toEqual('H4');
});
}
But I'm getting this error
TypeError: _useIsMobile.useIsMobile.mockReturnValueOnce is not a function
What does this mean and how can i fix this?

How do you mock isPlatform from #ionic/core

Have a React Ionic app where I need to determine if the app is running on an iOS device. I've done that by importing isPlatform.
import { isPlatform } from "#ionic/core";
const isIOS = isPlatform("ios");
I've tried the following and when isPlatform is called it still returns false.
jest.mock("#ionic/core", () => ({
isPlatform: () => {
return true;
}
}));
How do I mock isPlatform in my unit test using jest so it returns true?
Figured it out. I needed to mock ionic/core in order for it to work.
jest.mock("#ionic/core");
import * as Ionic from '#ionic/core';
(Ionic as any).isPlatform = jest.fn(() => true);
If component only uses isFlatform in #ionic/core you can mock one function isFlatform:
jest.mock("#ionic/core", () => ({
isPlatform: () => true,
}));
but when component use another function and you only want to mock isFlatform you can use:
jest.mock("#ionic/core", () => ({
...jest.requireActual("#ionic/core"),
isPlatform: () => true,
}));
Similar to the previous responses but using a slightly more flexible approach to be able to mock the result based on what we want to test in each scenario. In our app we're using Angular but this approach should be working as well for React.
The idea is to define a mockIsPlatform() function:
// Note: on our app, we're importing the `isPlatform` helper method
// from `#ionic/angular` but that's not really important.
let mockIsPlatform: (key: string) => boolean;
jest.mock('#ionic/angular', () => ({
...(jest.requireActual('#ionic/angular') as object),
isPlatform: (key: string) => mockIsPlatform(key),
}));
Our service has some methods that use the isPlatform() method behind the scenes:
public isIos(): boolean {
return isPlatform('ios');
}
public isAndroid(): boolean {
return isPlatform('android');
}
So we can now test those methods like this:
test('detect platform', () => {
// Simulate ios platform
mockIsPlatform = (key) => key === 'ios';
expect(myServiceInstance.isIos()).toBeTruthy();
expect(myServiceInstance.isAndroid()).toBeFalsy();
// Simulate android platform
mockIsPlatform = (key) => key === 'android';
expect(myServiceInstance.isIos()).toBeFalsy();
expect(myServiceInstance.isAndroid()).toBeTruthy();
})

How to refresh powerbi-client-react component once token has expired?

I am testing a react web app where I can display reports from Power BI. I am using powerbi-client-react to embed the reports. However, I face an issue when I load the component with an expired token, I get this error: Content not available screenshot.
So whenever that happens, I catch it with the error event handler, get a new token and update the powerbi report accessToken. However, it doesn't seem to reload/refresh the embed when I set the new accessToken in react. It only displays the screenshot above.
Error log screenshot.
Is there a way to force refresh the embed component with the new access token? or is my approach not correct? Any mistakes pointer would be appreciated.
import React from 'react';
import {models} from 'powerbi-client';
import {PowerBIEmbed} from 'powerbi-client-react';
// Bootstrap config
let embedConfigTest = {
type: 'report', // Supported types: report, dashboard, tile, visual and qna
id: reportId,
embedUrl: powerBIEmbedURL,
accessToken: null,
tokenType: models.TokenType.Embed,
pageView: 'fitToWidth',
settings: {
panes: {
filters: {
expanded: false,
visible: false,
},
},
background: models.BackgroundType.Transparent,
},
};
const PowerBiReport = ({graphName, ...props}) => {
let [embedToken, setEmbedToken] = React.useState();
let [embedConfig, setEmbedConfig] = React.useState(embedConfigTest);
React.useEffect(
() => {
setEmbedToken(EXPIRED_TOKEN);
setEmbedConfig({
...embedConfig,
accessToken: EXPIRED_TOKEN, // Initiate with known expired token
});
},
[graphName]
);
const changeSettings = (newToken) => {
setEmbedConfig({
...embedConfig,
accessToken: newToken,
});
};
// Map of event handlers to be applied to the embedding report
const eventHandlersMap = new Map([
[
'loaded',
function() {
console.log('Report has loaded');
},
],
[
'rendered',
function() {
console.log('Report has rendered');
},
],
[
'error',
async function(event, embed) {
if (event) {
console.error(event.detail);
console.log(embed);
// Simulate getting a new token and update
setEmbedToken(NEW_TOKEN);
changeSettings(NEW_TOKEN);
}
},
],
]);
return (
<PowerBIEmbed
embedConfig={embedConfig}
eventHandlers={eventHandlersMap}
cssClassName={'report-style-class'}
/>
);
};
export default PowerBiReport;
Thanks #vtCode. Here is a sample but the refresh can only happen in 15 secs interval.
import { PowerBIEmbed } from "powerbi-client-react";
export default function PowerBiContainer({ embeddedToken }) {
const [report, setReport] = useState(null);
useEffect(() => {
if (report == null) return;
report.refresh();
}, [report, embeddedToken]);
return (
<PowerBIEmbed
embedConfig={{ ...embedConfig, accessToken: embeddedToken }}
getEmbeddedComponent={(embeddedReport) => setReport(embeddedReport)};
/>
);
}
Alternatively, you can add the React "key" attribute which remounts the component when embededToken changes
<PowerBIEmbed key={embeddedToken}
embedConfig={{ ...embedConfig, accessToken: embeddedToken }}
/>
I ended up solving this issue, although not so beautiful.
I checked the powerbi-client wiki as it has dependency on it and found out that you could use embed.reload() in the embed object I get from the error function.
For some reason (I could not find out why), the error handler gets triggered twice, so to avoid refreshing the token twice, I had to create a dialog notifying the user that the token had expired and whenever that dialog is closed, I reload the powerbi report.
Exact wiki reference:
Overriding Error Experience
Reload a report
Update embed token

Web-worker issue: Uncaught DOMException: Failed to execute 'postMessage' on 'Worker

I have a barchart made with chartjs in a React app. It works well, but the data parsing could be handled by a web worker so as to speed up the page loading.
I have declared my web worker in a useEffect function:
let data = React.useRef([]);
useEffect(() => {
const dataWorker: Worker = new Worker("./worker.ts");
dataWorker.postMessage({
msg: "formatData",
data: { series, theme, range },
});
dataWorker.onmessage = (e: MessageEvent) => {
if (e && e.data) {
data.current = e.data;
}
};
}, [range, series, theme]);
And the webworker is defined in a separate file worker.ts:
self.onmessage = async (e) => {
if (e && e.data && e.data.msg === "formatData") {
const { sortedSeries, theme, range } = e.data;
// eslint-disable-next-line react-hooks/rules-of-hooks
const data = useFormatData(sortedSeries, theme, range);
self.postMessage(data);
}
};
function useFormatData(series, theme, range) {
return useMemo(() => {
// do stuff
};
}, [range, sortedSeries, theme]);
}
The worker makes the page crash with the following error:
Uncaught DOMException: Failed to execute 'postMessage' on 'Worker: function (number) {
var b = number % 10,
output =
toInt((number...... } could not be cloned.
How to fix this?
I recently saw this issue when I was passing an object to the web worker that contained a function that I was not aware of.
By the looks of your error, it could be the case for you as well in regards to series, theme, or range being passed to the worker.
There is a good explanation of alternatives explained in this SO Answer. To summarize, it mentions passing only the the serializable data to the worker and then adding back the functions (if necessary) on the webworker side.

Resources