PDFjs not working in safari, blank page. How to solve issue? - reactjs

I'm using pdfjs-dist "^2.16.105" to import pdf files into fabric as fabric.Images in my React Application. According to the http://fabricjs.com/import-pdf example, this all works in Chrome, Firefox, but does not work in Safari. I'm testing in Safari version 14.1.2. Here's the error in the console when loading react app.
SyntaxError: Unexpected private name #ensureObj. Cannot parse class method with private
name.
I have read that safari versions before 14.5 does not support private classes. How can this problem be solved?
In Safari React application doesn't start, I only see a blank screen.
This is my code
import * as PDFJS from "pdfjs-dist";
import * as pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";
PDFJS.GlobalWorkerOptions.workerSrc = pdfjsWorker;
...
PDFJS.getDocument({
data: pdfData,
}).promise.then((a) => {
a.getPage(1).then((page) => {
let viewport = page.getViewport({ scale: window.devicePixelRatio });
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
canvas.height = viewport.height;
canvas.width = viewport.width;
const render_context = {
canvasContext: context,
viewport: viewport,
};
const renderTask = page.render(render_context);
renderTask.promise.then(() => {
const canvasImage = new fabric.Image(canvas, {});
renderCanvasImg(canvasImage);
});
});
});

One possibility is to downgrade pdf-dist library to v2.4.456 since the version v2.13.216 introduced #ensureObj - private fields ES2022 feature (see build/pdf.js).
package.json:
{
dependencies: {
"pdfjs-dist": "v2.4.456",
...
}
...
}
Second possibility would be to use some transpiler (etc. Babel) to downgrade the ES version.

Related

I am using React Native Expo And need to do live background location tracking

React Native Expo: Background Location has not been configured. To enable it, add location to UIBackgroundModes in Info.plistfile
I am using expo-location and trying to do background location tracking.
my app.json under IOS includes this
"infoPlist": { "UIBackgroundModes": [ "location", "fetch" ],
I am calling the startLocationUpdatesAsync function as such
` useEffect(() => {
var appLocation = undefined;
const startLocationTracking = async () => {
var opts = {
accuracy: Location.Accuracy.BestForNavigation,
distanceInterval: 1, //meters
};
appLocation = await Location.watchPositionAsync(opts, (location) => {
dispatch(setCurrentLocation(location.coords));
sendLocationToAPI(location);
});
const backgroundLocation = await Location.startLocationUpdatesAsync("background-location")
}`
I end up getting this error
Unhandled promise rejection: Error: Background Location has not been configured. To enable it, add locationtoUIBackgroundModes in Info.plist file.
I Do not know how to get rid of this, but I think I may have to expo eject and switch to cli. If anyone can help so I can avoid this it would be really helpful.

Webview context doesn't show up anymore when testing using Appium

I am creating an automation test using Appium and webdriverio:
const wdio = require("webdriverio");
const opts = {
path: "/wd/hub",
port: 4723,
capabilities: {
platformName: "Android",
platformVersion: "11",
deviceName: "Android Emulator",
app: "/path/to/myapk.apk",
automationName: "UiAutomator2",
autoGrantPermissions: true
}
};
async function main() {
const driver = await wdio.remote(opts);
const contexts = await driver.getContexts();
console.log("Contexts:", contexts);
await driver.deleteSession();
}
main();
The problem
When running tests I could see that I used to have two contexts:
NATIVE_APP
WEBVIEW_chrome (or similar, I do not remember exactly the value here)
I then made a change which switched contexts to the webview, there I got an error about the chrome driver not being found. That is when I installed it: npm install "appium-chromedriver".
I do not know if this is what made everything go babanas, but since then, everytime I test, I can only see the native context, no more webview context :(
More info
It is important to point out that I have modified my Android app to include this:
#Override
public void onCreate() {
super.onCreate();
WebView.setWebContentsDebuggingEnabled(true);
}
I can also start chrome://inspect and see the webview is there and even inspect it. But when running tests, the driver cannot see the webview context.
Why? How to fix this?
Turns out that I need to wait for a webview to show up in the app, so this works:
async function main() {
const driver = await wdio.remote(opts);
// Wait a few seconds so the webview properly loads
await new Promise(resolve => setTimeout(resolve, 5000));
const contexts = await driver.getContexts();
console.log("Contexts:", contexts);
await driver.deleteSession();
}

angular 9.1 and babylon 4.1 loading gltf issue

Day 1 on babylon.js. I have cloned this repository for angular 9.1 and babylon 4.1 starter kit. I am able to run the project.
Next step is that I wanted to load the gltf model for which I have installed the package babylonjs-loaders and used the library but getting error that path to model 404.
Code:
import { WindowRefService } from './../services/window-ref.service';
import {ElementRef, Injectable, NgZone} from '#angular/core';
import {
Engine,
FreeCamera,
Scene,
Light,
Mesh,
Color3,
Color4,
Vector3,
HemisphericLight,
StandardMaterial,
Texture,
DynamicTexture
} from 'babylonjs';
import 'babylonjs-materials';
import 'babylonjs-loaders';
#Injectable({ providedIn: 'root' })
export class EngineService {
private canvas: HTMLCanvasElement;
private engine: BABYLON.Engine;
private camera: BABYLON.FreeCamera;
private scene: BABYLON.Scene;
private light: BABYLON.Light;
private sphere: Mesh;
public constructor(
private ngZone: NgZone,
private windowRef: WindowRefService
) {}
public animate(): void {
// We have to run this outside angular zones,
// because it could trigger heavy changeDetection cycles.
this.ngZone.runOutsideAngular(() => {
const rendererLoopCallback = () => {
this.scene.render();
};
if (this.windowRef.document.readyState !== 'loading') {
this.engine.runRenderLoop(rendererLoopCallback);
} else {
this.windowRef.window.addEventListener('DOMContentLoaded', () => {
this.engine.runRenderLoop(rendererLoopCallback);
});
}
this.windowRef.window.addEventListener('resize', () => {
this.engine.resize();
});
});
}
public loadScene(canvas: ElementRef<HTMLCanvasElement>): void {
// The first step is to get the reference of the canvas element from our HTML document
this.canvas = canvas.nativeElement;
// Then, load the Babylon 3D engine:
this.engine = new BABYLON.Engine(this.canvas, true);
// create a basic BJS Scene object
this.scene = new BABYLON.Scene(this.engine);
this.scene.clearColor = new Color4(0, 0, 0, 0);
// create a FreeCamera, and set its position to (x:5, y:10, z:-20 )
this.camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(5, 10, -20), this.scene);
// target the camera to scene origin
this.camera.setTarget(BABYLON.Vector3.Zero());
// attach the camera to the canvas
this.camera.attachControl(this.canvas, false);
// create a basic light, aiming 0,1,0 - meaning, to the sky
this.light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), this.scene);
BABYLON.SceneLoader.Append("./", "bmw.gltf", this.scene, function (scene) {
// do something with the scene
});
}
}
I have googled on similar question but did not reach to any conclusion. I might be missing something basic. I have kept the gltf on the same directory as ts file and path is proper. I have tested with putting png image on same path and able to see it in network tab of chrome dev tool with 200 status.
Please help guys. I am guessing the way i am importing babylonjs-loaders is the culprit here.
error screenshot:
Your bmw.gltf file should be located in your assets folder.
this means that you will have to load the files from there.
BABYLON.SceneLoader.Append("/assets", "bmw.gltf"

FBXLoader can't find version number of fbx file

I'm trying to load a .fbx file, the loader.load function throws the following error:
THREE.FBXLoader: Cannot find the version number for the file given.
I don't know how to solve this problem. How can I check in the fbx file if it has a version number?
Below you can find the react component that I've written. When I test the app, I see only a black canvas.
I tried two different files, but have the same error for both files.
export default class myComponent extends Component {
componentDidMount() {
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
2000
);
camera.position.set(2, 18, 28);
const scene = new THREE.Scene();
const light = new THREE.HemisphereLight(0xffffff, 0x444444);
light.position.set(0, 1, 0);
scene.add(light);
const gridHelper = new THREE.GridHelper(28, 28, 0x303030, 0x303030);
scene.add(gridHelper);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
this.model.appendChild(renderer.domElement);
const loader = new FBXLoader();
let model = new THREE.Object3D();
loader.load(
'./3DModels/MHT.fbx',
function(object) {
model = object.scene;
scene.add(model);
},
undefined,
function(e) {
console.log(e);
}
);
renderer.render(scene, camera);
}
render() {
return <div ref={ref => (this.model = ref)} />;
}
}
FBXLoader throws this error: THREE.FBXLoader: Cannot find the version number for the file given.
loader.load('./3DModels/MHT.fbx', function(object) {
...
})
instead:
const path = require(./3DModels/MHT.fbx);//写在类的外面
loader.load(path, function(object) {
...
})
I have meeted the same problem just now, you can try to debug like this:
I find the reason that my project use Mockjs which make XMLHttpRequest become MockXMLHttpRequest:
// relative code in three.js:
request.addEventListener( 'load', function ( event ) {
// if you use Mockjs, this become MockXMLHttpRequest but not XMLHttpRequest
// this.response not is ArrayBuffer ,there is the bug.
var response = this.response;
var callbacks = loading[ url ];
Here just my case which maybe help you.
Are you hosting your files in your src folder or public folder?
You should be keeping the fbx files in public folder.
The loader scans the document and parses the text to find what it needs to load. Case with working in react is this will trigger before the DOM is rendered, so it basicaly can't the version because it sees no file.
I worked it out while trying to "debug" the loader code. It turned out it was me :)
Another fbx thing is you should always use the latest loader plugin. Under this link you will find both the link to the original plugin and the example how to convert it to React module.
Hope this helps.
I had exactly the same error coming up on a ThreeJS RPG game hosted on Heroku. I eventually found a simple solution which worked for me and am posting here for any other poor soul who runs into to this issue.
The issue for me was that when I was downloading the FBX file from mixamo I was downloading just the FBX.binary file. **You need to download the fbx file with the version number **. So I just downloaded the FBX animation as FBX 7.4 and it worked. See image.
Hope this helps someone save the stupid number of hours I wasted on this...
download fbx 7.4 or 6.1

Koa.js serve React, api url also render with React page in Chrome

I'm using koa-static to serve static file with root url localhost:3000/, and koa-router to serve RESTful api, like localhost:3000/api/account/login
Make a fakeBuild folder contain only one file index.html. All work fine. root url and api url show correct content.
// serve static file
const serve = require('koa-static')
const staticPath = path.join(__dirname,'..','Client','poker','fakeBuild')
log(staticPath)
app.use(serve(staticPath))
// router
const router = require('./router/Index.js')(app)
Then I try to connect Koa with React
I use yarn build to build React static files, React project is created by create-react-app, not modified.
Then I change the koa-static's target to build folder, just one line changed
const staticPath = path.join(__dirname,'..','Client','poker','build')
Then access localhost:3000/, chrome show React start page, works
Then access localhost:3000/api/account/login, chrome show React start page, what??
Use postman check localhost:3000/api/account/login, it response what I put in router, fine.
So I can use apis, just ignore chrome's result?
It must be React and Chrome doing something extra. I try to remove service-worker.js in React build folder, api url render correctly in chrome.
So anyone can give some documents or explain to help me understand what react done, to keep all the url render it.
And why my api localhost:3000/api/account/login not require service-worker.js (just return some text in response body), also got the js worked. Just because koa-static served the file?
====
Update: my router code, And project available on here
router/Index.js
const Router = require('koa-router');
const R = (app)=>{
const router = new Router();
const api = require('./Api.js');
router.use('/api', api.routes(), api.allowedMethods())
app.use(router.routes())
.use(router.allowedMethods());
};
module.exports = R;
router/Api.js
const Router = require('koa-router')
const log = require('../helper/Utils').log;
module.exports = (function () {
const Api = new Router();
Api.get('/account/login', async (ctx, next)=>{
log("hello");
ctx.status = 200;
ctx.body = `login`
});
Api.get('/account/register', async (ctx, next)=>{
ctx.status = 200;
ctx.body = `register`
});
return Api;
})();

Resources