Content Security Policy with FluentUI-React-Electron-Forge - electron

With index.html :
<html>
<head>
<meta charset="UTF-8">
<meta
http-equiv="Content-Security-Policy" content-src='static2.sharepointonline.com';
script-src-elem 'static2.sharepointonline.com';
img-src 'static2.sharepointonline.com';
style-src 'static2.sharepointonline.com';
font-src 'https://static2.sharepointonline.com;
connect-src https: http:"
>
</head>
<body>
<div id="app" style="height: 100%;" style-src="../../assets/fonts/" 'self' data:></div>
</body>
</html>
In index.tsx :
import { initializeIcons } from "#fluentui/react/lib/Icons"
initializeIcons("https://static2.sharepointonline.com/files/fabric/assets/icons/", { disableWarnings: true })
I get this message:
Refused to load the font '' because it violates the following Content Security Policy directive: "default-src 'self' 'unsafe-inline'
data:". Note that 'font-src' was not explicitly set, so 'default-src' is used as a fallback.
"#fluentui/react": "^8.80.0"
"react": "^18.1.0"
node: v16.15.1
O.S. : Ubuntu 20.04
Update 1)
I've found in the Electron docs this suggestions:
https://www.electronjs.org/docs/v14-x-y/tutorial/security#csp-http-header
I then added this snippet into main :
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
'Content-Security-Policy': ['default-src \'none\'', 'script-src-elem \'static2.sharepointonline.com\'']
}
})
})
But I get this errors:
Refused to load the script 'http://localhost:3000/main_window/index.js' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'script-src-elem' was not explicitly set, so 'default-src' is used as a fallback.
Refused to load the script 'http://localhost:3000/main_window/index.js' because it violates the following Content Security Policy directive: "script-src-elem 'static2.sharepointonline.com'
Update 2):
Now in index.html :
<meta
http-equiv="Content-Security-Policy" content-src=static2.sharepointonline.com;
script-src-elem static2.sharepointonline.com;
img-src static2.sharepointonline.com;
style-src static2.sharepointonline.com;
font-src https://static2.sharepointonline.com;
connect-src https: http:"
>
Here: https://content-security-policy.com/#source_list
I read : * : Wildcard, allows any URL except data: blob: filesystem: schemes.
So... I tried to put in main:
session.defaultSession.webRequest.onHeadersReceived((details,
callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
'Content-Security-Policy': ['default-src \'*\'', 'style-src-
attr \'*\'', 'script-src-elem \'*\'' ]
}
})
})
the previous error disappear but the app doesnt work and I get these two errors, which I tried, without succeeding, to solve :
Update 3)
As in https://webpack.js.org/guides/csp/#examples I tried to set __webpack_nonce__ in webpack.main.config.js (I'm using Electron Forge ) .
I've put in this way:
const rules = require('./webpack.rules');
const plugins = require('./webpack.plugins');
rules.push({
test: /\.ts$/,
use: [{ loader: 'ts-loader' }],
});
module.exports = {
/**
* This is the main entry point for your application, it's the
first file
* that runs in the main process.
*/
entry: {
main: './src/main/index.ts',
},
__webpack_nonce__ =
'c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=',
// Put your normal webpack config below here
module: {
//rules: require('./webpack.rules'),
rules,
},
plugins: plugins,
resolve: {
extensions: ['.js', '.ts', '.jsx', '.tsx', '.css', '.json'],
fallback: {
fs: false,
'stream': require.resolve('stream-browserify'),
'buffer': require.resolve('buffer'),
'util': require.resolve('util'),
'assert': require.resolve('assert'),
'http': require.resolve('stream-http'),
'url': require.resolve('url'),
'https': require.resolve('https-browserify'),
'os': require.resolve('os-browserify'),
'path': require.resolve('path-browserify')
},
},
};
In index.html :
session.defaultSession.webRequest.onHeadersReceived((details,
callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
//'Content-Security-Policy': ['default-src \'*\'', 'style-src-attr \'*\'', 'script-src-elem \'*\'' ]
'Content-Security-Policy0: [
'default-src \'nonce-c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=\'',
'style-src-attr \'nonce-c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=\'',
'script-src-elem \'c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=\''
]
}
})
})
But I get
An unhandled error has occurred inside Forge:
Invalid shorthand property initializer
/home/raphy/FPlayground/webpack.main.config.js:18
__webpack_nonce__ =
'c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=',
SyntaxError: Invalid shorthand property initializer
Update 4)
Now... I'm having a real strange error and situation.
With in main:
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
'Content-Security-Policy': [
'default-src \'nonce-c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=\'',
'style-src-attr \'nonce-c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=\'',
'script-src-elem \'c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=\''
]
}
})
in webpack.plugins.js :
new webpack.LoaderOptionsPlugin({
options: {
__webpack_nonce__ : 'c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=',
},
}),
and in index.html :
<meta http-equiv="Content-Security-Policy"
content-src 'nonce-c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=';
script-src-elem 'nonce-c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=';
img-src 'nonce-c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=';
style-src 'nonce-c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=';
font-src 'nonce-c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM=';
connect-src https: http:"
>
Where to specify Content-Security-Policy? In package.json as suggested here: React Electron App - React Leaftlet Content Security Policy errors ? or in webpack.plugins.js ?
How to make it work?

I spent quite few hours in this hurdle...
Bu, now, with in package.json :
"plugins": [
[
"#electron-forge/plugin-webpack",
{
"mainConfig": "./webpack.main.config.js",
"devContentSecurityPolicy": "default-src 'none'; script-src 'unsafe-eval'; script-src-elem 'self'; img-src *; style-src 'self' 'unsafe-inline'; font-src 'self' https://static2.sharepointonline.com/files/fabric/assets/icons/; connect-src 'self';",
./src/app/index.html :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="app" style="height: 100%;" style-src="../../assets/fonts/" 'self' data:></div>
</body>
</html>
and commented __webpack_nonce__' option in webpack.plugin.js'
it seems working fine
I have to thank #spender for having highlighted some errors I made

Related

SwaggerUIBundle : Specify base url

I need to test a api where :
API Url
http://api.mydomain.loc:20109/v1/
API Definition URL
http://api.mydomain.loc:20109/v1/swagger/swagger.json
The API definition is :
{
"openapi": "3.0.1",
"info": {
"title": "***",
"description": "***",
"version": "v1"
},
"servers": [
{
"url": "/v1/path1/path2"
}
],
"/ressource1": {
"get": {
"responses": {
"200": {
"description": "Success"
}
}
}
},
...
}
I follow this part unpkg in the documentation to start a local Swagger UI. I create the file "swagger-ui.html" with this content :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="description"
content="SwaggerIU"
/>
<title>SwaggerUI</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist#4.5.0/swagger-ui.css" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist#4.5.0/swagger-ui-bundle.js" crossorigin></script>
<script>
window.onload = () => {
window.ui = SwaggerUIBundle({
url: 'http://api.mydomain.loc:20109/v1/swagger/swagger.json',
dom_id: '#swagger-ui',
});
};
</script>
</body>
</html>
When I open the page, the API definition is correctly loaded and Swagger UI displayed. But when I try out the endpoint "ressource1", Swagger UI call "http://api.mydomain.loc:20109/v1/path1/path2/ressource1". In my case, I want to call "http://api.mydomain.loc:20109/v1/ressource1".
How override the base path in Swagger UI with unpkg?
Here's another solution that uses a plugin with rootInjects. The main idea is the same as in #vernou's answer - update the OpenAPI definition dynamically.
<!-- index.html -->
<script>
const UrlMutatorPlugin = (system) => ({
rootInjects: {
setServer: (server) => {
const jsonSpec = system.getState().toJSON().spec.json;
const servers = [{url: server}];
const newJsonSpec = Object.assign({}, jsonSpec, { servers });
return system.specActions.updateJsonSpec(newJsonSpec);
}
}
});
window.onload = function() {
const ui = SwaggerUIBundle({
url: "http://api.mydomain.loc:20109/v1/swagger/swagger.json",
...
// Add UrlMutatorPlugin to the plugins list
plugins: [
SwaggerUIBundle.plugins.DownloadUrl,
UrlMutatorPlugin
],
// This will set appropriate data when Swagger UI is ready
onComplete: () => {
window.ui.setServer("http://api.mydomain.loc:20109/v1")
}
});
window.ui = ui;
};
</script>
Swagger UI has the parameter spec :
spec : A JavaScript object describing the OpenAPI definition. When used, the url parameter will not be parsed. This is useful for testing manually-generated definitions without hosting them.
The solution is to load manually the api definition, edit the definition and pass the edited definition to Swagger UI.
Example for json OpenApi Specification :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="description"
content="SwaggerIU"
/>
<title>SwaggerUI</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist#4.5.0/swagger-ui.css" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist#4.5.0/swagger-ui-bundle.js" crossorigin></script>
<script>
const swaggerUrl = "http://api.mydomain.loc:20109/v1/swagger/swagger.json"
const apiUrl = "http://api.mydomain.loc:20109/v1/"
window.onload = () => {
let swaggerJson = fetch(swaggerUrl).then(r => r.json().then(j => {
j.servers[0].url = apiUrl;
window.ui = SwaggerUIBundle({
spec: j,
dom_id: '#swagger-ui',
});
}));
};
</script>
</body>
</html>
Example for yaml OpenApi Specification :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="description"
content="SwaggerIU"
/>
<title>SwaggerUI</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist#4.15.5/swagger-ui.css" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist#4.15.5/swagger-ui-bundle.js" crossorigin></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.js" crossorigin></script>
<script>
const swaggerUrl = "http://api.mydomain.loc:20109/v1/swagger/swagger.yaml"
const apiUrl = "http://api.mydomain.loc:20109/v1/"
window.onload = () => {
let swaggerJson = fetch(swaggerUrl).then(r => r.text().then(t => {
let j = jsyaml.load(t);
j.servers[0].url = apiUrl;
window.ui = SwaggerUIBundle({
spec: j,
dom_id: '#swagger-ui',
});
}));
};
</script>
</body>
</html>
You can copy this code and just edit the value in swaggerUrl and apiUrl.

How can I troubleshoot why electron-builder isn't creating a working production package

My app builds fine on local, but when I try to create a production version, I'm having trouble. I'm not very well versed in either electron or electron-builder, so this could definitely be something simple I'm missing.
My project packages successfully, and when I open it from Finder (I'm on a mac) the window launches properly, but nothing renders; this is the result:
Previously (with different mucking around) I've had an error 'not allowed to access local file:' and then gives me a directory path.
Here is my package.json:
"main": "public/electron.js",
"name": "storyweaver-dm",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.3.2",
"#testing-library/user-event": "^7.1.2",
"axios": "^0.19.2",
"concurrently": "^5.1.0",
"electron-is-dev": "^1.1.0",
"nodemon": "^2.0.4",
"react": "^16.13.0",
"react-beautiful-dnd": "^13.0.0",
"react-dom": "^16.13.0",
"react-hook-form": "^6.1.2",
"react-scripts": "3.4.0",
"react-select": "^3.1.0",
"recoil": "0.0.10",
"sqlite3": "^5.0.0",
"styled-components": "^5.0.1",
"wait-on": "^4.0.1"
},
"devDependencies": {
"#rescripts/cli": "^0.0.13",
"#rescripts/rescript-env": "^0.0.11",
"electron": "^8.1.1",
"electron-builder": "^22.4.1",
"electron-devtools-installer": "^2.2.4",
"typescript": "^3.8.3"
},
"homepage": "./",
"scripts": {
"build": "rescripts build",
"eject": "react-scripts eject",
"electron-dev": "concurrently \"BROWSER=none yarn start\" \"wait-on http://localhost:4203 && electron .\"",
"dev": "concurrently \"BROWSER=none npm start\" \"wait-on http://localhost:4203 && electron .\"",
"electron-pack": "electron-builder build -mw",
"postinstall": "electron-builder install-app-deps",
"preelectron-pack": "npm install",
"start": "PORT=4203 rescripts start",
"test": "rescripts test"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"rescripts": [
"env"
],
"author": {
"name": "Jamie Sauve and other wonderful people",
"email": "jamiesauve#zohomail.com"
},
"build": {
"appId": "com.my-website.my-app",
"productName": "StoryWeaver DM",
"copyright": "Copyright © 2019 ${author}",
"mac": {
"icon": "./assets.icon.icns",
"category": "public.app-category.utilities"
},
"files": [
"public/**/*",
"build/**/*",
"node_modules/**/*",
"pseudoServer/**/*",
"./public/electron.js"
],
"directories": {
"buildResources": "assets"
}
}
}
and here is my electron.js (I renamed this - this is my main Electron process):
const electron = require('electron');
const app = electron.app;
const ipcMain = electron.ipcMain;
const BrowserWindow = electron.BrowserWindow;
// const { default: installExtension, REACT_DEVELOPER_TOOLS } = require('electron-devtools-installer');
const path = require('path');
const isDev = require('electron-is-dev');
process.env['APP_PATH'] = app.getAppPath();
const directory = isDev ? process.cwd() : process.env.APP_PATH;
const databaseApi = require(path.join(directory, './pseudoServer/api/controller/routes'))
ipcMain.handle('dbRequest', async (event, request) => {
const response = await databaseApi(request)
return response
})
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: false,
webSecurity: false,
/**
* import native Node modules explicitly in this file; something about Create-React-App and webpack mess
* with Electron's ability to provide these directly.
* See the comment by HemalR here: https://github.com/electron/electron/issues/9920
*/
preload: __dirname + '/preload.js'
},
});
mainWindow.maximize();
mainWindow.loadURL(isDev ? 'http://localhost:4203' : `file:///${__dirname}/public/index.html`)
if (isDev) {
// Open the DevTools.
//BrowserWindow.addDevToolsExtension('<location to your react chrome extension>');
mainWindow.webContents.openDevTools();
// installExtension(REACT_DEVELOPER_TOOLS)
// .then((name) => console.log(`Added Extension: ${name}`))
// .catch((err) => console.log('An error occurred: ', err));
}
mainWindow.on('closed', () => mainWindow = null);
}
app.on('ready', createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (mainWindow === null) {
createWindow();
}
});
and this is my index.html:
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<!-- see https://github.com/electron/electron/issues/19775 for the line below -->
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' http://* 'unsafe-inline'; script-src 'self' http://* 'unsafe-inline'" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<base href="./" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>StoryWeaver DM</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
How can I get this app packaging properly in production?
The /pseudoServer directory might be an odd pattern - I'm using a sqlite3 database, and created a 'server' (really just called from the electron main process) to access it. I'm not sure if this actually counts as a backend or not in Electron.
My project is at https://github.com/jamiesauve/StoryWeaver-DM if these two files don't provide enough information.

how to configure service worker in react project ( npx create-react-app)?

I'm creating a pwa with reactJS but I can't get google lighthouse to recognize it as such. I created the project with npx create-react-app and these are the configuration files to get the service workers works:
registerServiceWorker.js
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
export default function register() {
console.log("register", process.env.PUBLIC_URL)
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
return;
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
console.log(swUrl)
if (isLocalhost) {
// This is running on localhost. Lets check if a service worker still exists or not.
checkValidServiceWorker(swUrl);
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit'
);
});
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl);
}
});
}
}
function registerValidSW(swUrl) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log('New content is available; please refresh.');
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl)
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
console.log("registerValidSW", swUrl)
registerValidSW(swUrl);
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}
index.js
import React from "react";
import ReactDOM from "react-dom";
import { createBrowserHistory } from "history";
import { Route, Switch, Redirect, HashRouter } from "react-router-dom";
import { Provider } from "react-redux";
import AuthLayout from "layouts/Auth.jsx";
import RtlLayout from "layouts/RTL.jsx";
import AdminLayout from "layouts/Admin.jsx";
import { store } from "helpers/store.js";
import LoginPage from "views/Pages/LoginPage.jsx";
import "assets/scss/material-dashboard-pro-react.scss?v=1.5.0";
import { PrivateRoute } from "./components/PrivateRoute/PrivateRoute";
import PDVDetails from "./views/Pages/PDVDetails";
import RegisterUserClientPage from "./views/Pages/RegisterUserClientPage";
import { createMuiTheme, MuiThemeProvider } from "#material-ui/core/styles";
import registerServiceWorker from './registerServiceWorker';
//import { App } from './App';
const hist = createBrowserHistory();
const theme = createMuiTheme({
overrides: {
MuiTableCell: {
root: {
textAlign: 'center'
}
}
}
});
ReactDOM.render(
<MuiThemeProvider theme={theme}>
<Provider store={store}>
<HashRouter history={hist}>
<Switch>
{/* <Route path="/admin/PDVDetails/:id" component={PDVDetails} /> */}
{/* <Route path="/auth/Login-Page" component={LoginPage}/>
<Route path="/auth/Register-user-client/:id" component={RegisterUserClientPage}/> */}
<Route path="/auth" component={AuthLayout} />
<PrivateRoute path="/admin" component={AdminLayout} />
<Redirect from="/" to="/admin/dashboard" />
</Switch>
</HashRouter>
</Provider>
</MuiThemeProvider>,
document.getElementById("root")
);
registerServiceWorker();
service-worker.js
/**
* The workboxSW.precacheAndRoute() method efficiently caches and responds to
* requests for URLs in the manifest.
* See
*/
// Precarga la app
importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.5.0/workbox-sw.js');
if (workbox) {
console.log(`Yay! Workbox is loaded 🎉`);
workbox.precaching.precacheAndRoute([]);
} else {
console.log(`Boo! Workbox didn't load 😬`);
}
// self.__precacheManifest = [].concat(self.__precacheManifest || [])
// workbox.precaching.suppressWarnings()
// workbox.precaching.precacheAndRoute(self.__precacheManifest, {})
// App Shell
workbox.routing.registerNavigationRoute('/index.html')
console.log("service worker js")
// La API usa Stale While Revalidate para mayor velocidad
workbox.routing.registerRoute(/^https?:\/\/mi.app.com\/api\/.*/,
workbox.strategies.staleWhileRevalidate(),
'POST')
// // Last fuentes van con Cache First y vencen al mes
// workbox.routing.registerRoute(/^https:\/\/fonts.(?:googleapis|gstatic).com\/(.*)/,
// workbox.strategies.cacheFirst({
// cacheName: 'google-fonts-cache',
// plugins: [
// new workbox.expiration.Plugin({
// maxAgeSeconds: 30 * 24 * 60 * 60
// })
// ]
// }),
// 'GET')
// Todo lo demás usa Network First
workbox.routing.registerRoute(/^https?.*/,
workbox.strategies.networkFirst(), 'GET')
manifest.json
{
"short_name": "ComercialPWA",
"name": "Comercial VEGA PWA",
"icons": [
{
"src": "icon.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "/",
"scope": "/",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff",
"related_applications": [],
"prefer_related_applications": false
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="theme-color" content="#000000" />
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="shortcut icon" href="%PUBLIC_URL%/icon.png" />
<link rel="apple-touch-icon" href="/icon.png" />
<meta name="apple-mobile-web-app-title" content="ComercialPWA" />
<meta name="apple-mobile-web-app-capable" content="no" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<link
rel="apple-touch-icon"
sizes="76x76"
href="%PUBLIC_URL%/apple-icon.png"
/>
<link
rel="stylesheet"
href="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css"
/>
<script src="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"></script>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/jvectormap/2.0.4/jquery-jvectormap.css"
type="text/css"
media="screen"
/>
<link
rel="stylesheet"
href="//cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css"
type="text/css"
media="screen"
/>
<!-- Fonts and icons -->
<link
href="https://use.fontawesome.com/releases/v5.0.7/css/all.css"
rel="stylesheet"
/>
<link
rel="stylesheet"
type="text/css"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons"
/>
<link
href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet"
/>
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Vive una experiencia única con Novaventa</title>
</head>
<body>
<noscript> You need to enable JavaScript to run this app. </noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
package.json
{
"name": "material-dashboard-pro-react",
"version": "1.5.0",
"private": true,
"dependencies": {
"#date-io/date-fns": "^1.3.13",
"#material-ui/core": "^4.9.5",
"#material-ui/icons": "3.0.2",
"#material-ui/pickers": "^3.2.10",
"chartist": "0.10.1",
"dashboard": "0.0.1",
"date-fns": "^2.10.0",
"history": "4.7.2",
"immutability-helper": "^3.0.1",
"material": "^0.4.3",
"moment": "^2.24.0",
"moment-timezone": "^0.5.27",
"node-sass": "^4.12.0",
"nouislider": "13.1.0",
"perfect-scrollbar": "1.4.0",
"react": "^16.13.0",
"react-big-calendar": "0.20.3",
"react-bootstrap-sweetalert": "4.4.1",
"react-chartist": "0.13.3",
"react-csv": "^1.1.1",
"react-datetime": "2.16.3",
"react-dnd": "^7.0.2",
"react-dnd-html5-backend": "^7.0.2",
"react-dom": "^16.8.1",
"react-google-maps": "9.4.5",
"react-jvectormap": "0.0.6",
"react-moment": "^0.9.7",
"react-number-format": "^4.3.0",
"react-redux": "^7.1.0",
"react-responsive-carousel": "^3.1.51",
"react-router-dom": "4.3.1",
"react-scripts": "^2.1.8",
"react-swipeable-views": "0.13.1",
"react-table": "6.9.2",
"react-tag-input": "^6.4.2",
"react-tagsinput": "3.19.0",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"serve": "^9.1.0"
},
"scripts": {
"dev": "react-scripts start",
"start": "serve ./build -s -p 5000",
"copy": "copyfiles -u 1 src/**/**/* src/**/* src/* build",
"build": "npm run copy && workbox injectManifest workbox-config.js",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"deploy": "npm run build",
"lint:check": "eslint . --ext=js,jsx; exit 0",
"lint:fix": "eslint . --ext=js,jsx --fix; exit 0",
"install:clean": "rm -rf node_modules/ && rm -rf package-lock.json && npm install && npm start",
"compile-sass": "node-sass src/assets/scss/material-dashboard-pro-react.scss src/assets/css/material-dashboard-pro-react.css",
"minify-sass": "node-sass src/assets/scss/material-dashboard-pro-react.scss src/assets/css/material-dashboard-pro-react.min.css --output-style compressed",
"map-sass": "node-sass src/assets/scss/material-dashboard-pro-react.scss src/assets/css/material-dashboard-pro-react.css --source-map true"
},
"optionalDependencies": {
"#types/googlemaps": "3.30.16",
"#types/markerclustererplus": "2.1.33",
"ajv": "6.9.1",
"prettier": "1.16.4"
},
"devDependencies": {
"eslint-config-prettier": "4.0.0",
"eslint-plugin-prettier": "3.0.1",
"redux-devtools": "^3.5.0",
"remote-redux-devtools": "^0.5.16",
"copyfiles": "^1.2.0",
"workbox-cli": "^3.5.0"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
these are screenshots from the google inspector:
manifest
service-worker
the page has the ssl certificate configured too and this is the report generated by google lighthouse:
Google lighthouse report
What is missing to solve these problems?

ui-router not working in cordova angular ios build

I have a problem while loading views using ui-router in cordova ios build. I'm using cordova angular in my application. The ui-router working fine in android build but while i'm running the app using cordova emulate ios the views not getting loaded.
here is my code looks like,
index.html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Awesome material design app</title>
<link rel="stylesheet" href="node_modules/angular-material/angular-material.css">
<link rel="stylesheet" href="lib/ionic/css/ionicons.min.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/ngPercentDisplay.css">
<script src="node_modules/angular/angular.js"></script>
<script src="lib/angular-ui-router.min.js"></script>
<script src="node_modules/angular-aria/angular-aria.js"></script>
<script src="node_modules/angular-animate/angular-animate.js"> </script>
<script src="node_modules/angular-material/angular-material.js"></script>
<script src="node_modules/angular-local-storage/dist/angular-local-storage.js"></script>
<script src="lib/angular-touch.min.js"></script>
<script src="js/ng-cordova.min.js"></script>
<script src="cordova.js"></script>
<script src="js/index.js"></script>
<script src="js/controller.js"></script>
<script src="js/router.js"></script>
</head>
<body ng-app="YourApp">
<div layout="column">
<ng-include src="'templates/partials/sidebar.html'" style="top:0px" ng-if ="lang =='ENGLISH'"></ng-include>
<ng-include src="'templates/partials/sidebar-right.html'" style="top:0px" ng-if ="lang =='ARABIC'"></ng-include>
<div ui-view></div>
</div>
</body>
</html>
The router.js file looks like below
app.config(['$urlRouterProvider', '$stateProvider','$compileProvider', function($urlRouterProvider, $stateProvider,$compileProvider) {
$urlRouterProvider.otherwise('/signup');
$stateProvider.state('signup', {
url:'/signup',
templateUrl: 'templates/sign-up.html',
controller: 'signupCtrl'
});
}]);
The index.js file looks like
var app = {
// Application Constructor
initialize: function() {
this.bindEvents();
},
// Bind Event Listeners
//
// Bind any events that are required on startup. Common events are:
// 'load', 'deviceready', 'offline', and 'online'.
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
// deviceready Event Handler
//
// The scope of 'this' is the event. In order to call the 'receivedEvent'
// function, we must explicitly call 'app.receivedEvent(...);'
onDeviceReady: function() {
app.receivedEvent('deviceready');
},
// Update DOM on a Received Event
receivedEvent: function(id) {
var parentElement = document.getElementById(id);
var listeningElement = parentElement.querySelector('.listening');
var receivedElement = parentElement.querySelector('.received');
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
console.log('Received Event: ' + id);
}
};
app.initialize();
controller.js looks like below,
'use strict';
var app = angular.module( 'YourApp', [ 'ngMaterial','ui.router']);
app.controller('myCtrl',['$scope',function ($scope) {
$scope.detail={};
$scope.detail.name="MyApp";
$scope.detail.desc="welcome to my app!";
}]);
Please help me if any one knows about this issue. Thanks in advance.

Barcode Scanner Issue in Cordova 3

I'm using the Barcode Scanner plugin with Cordova, and the camera keep freezing when I navigate through my app.
It throws the following warning in XCode :
Warning: Attempt to present <CDVbcsViewController> on <MainViewController> while a presentation is in progress!
Do you have any ideas how I could solve this issue ?
edit:
Maybe it has something to do with Backbone as I'm browsing the app. The Barcode scan goes well when i'm on the homepage, but as soon as I change the page, it's freezing and I got the warning.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
<link rel="stylesheet" type="text/css" href="css/main.css" />
<title>Project</title>
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="cordova.js"></script>
<script data-main="js/main" src="js/lib/require.js"></script>
</body>
</html>
plugin_cordova.js
cordova.define('cordova/plugin_list', function(require, exports, module) {
module.exports = [
{
"file": "plugins/com.phonegap.plugins.barcodescanner/www/barcodescanner.js",
"id": "com.phonegap.plugins.barcodescanner.BarcodeScanner",
"clobbers": [
"cordova.plugins.barcodeScanner"
]
}
]
});
my backbone view
define(['jquery','underscore','backbone'], function($, _, Backbone){
var myView = Backbone.View.extend({
initialize: function(){
/* ... */
},
render: function(ev){
/* ... */
}
startScan: function(e){
e.preventDefault();
cordova.plugins.barcodeScanner.scan(this.scanSuccess,this.scanError);
},
scanSuccess: function(response){
alert("We got a barcode\n" +
"Result: " + response.text + "\n" +
"Format: " + response.format + "\n" +
"Cancelled: " + response.cancelled);
},
scanError: function(error){
alert('Error: '+error);
},
});
return myView;
});
Thanks!
I also faced the similar warning recently. After some investigation, triggering the barcode scanner more than once at the same time will have this problem. This could be due to multiple times binding of the button that trigger scanner.

Resources