From 0b246d6978d86e6cb9ad0c32875c455f882a4da0 Mon Sep 17 00:00:00 2001 From: tancik Date: Thu, 14 Jul 2022 16:58:09 +0000 Subject: [PATCH] Prettified Code! --- .../viewer/app/src/ExtensibleObjectLoader.js | 450 +++++++++--------- pyrad/viewer/app/src/SceneNode.js | 232 ++++----- pyrad/viewer/app/src/index.js | 4 +- pyrad/viewer/app/src/serviceWorker.js | 214 ++++----- pyrad/viewer/app/src/setupTests.js | 2 +- pyrad/viewer/app/src/utils.js | 4 +- 6 files changed, 453 insertions(+), 453 deletions(-) diff --git a/pyrad/viewer/app/src/ExtensibleObjectLoader.js b/pyrad/viewer/app/src/ExtensibleObjectLoader.js index 97076364f..01346a452 100644 --- a/pyrad/viewer/app/src/ExtensibleObjectLoader.js +++ b/pyrad/viewer/app/src/ExtensibleObjectLoader.js @@ -12,38 +12,38 @@ import * as BufferGeometryUtils from "three/examples/jsm/utils/BufferGeometryUti // * A new merged `BufferGeometry` if the input contains meshes // * empty `BufferGeometry` otherwise function merge_geometries(object, preserve_materials = false) { - let materials = []; - let geometries = []; - let root_transform = object.matrix.clone(); + let materials = []; + let geometries = []; + let root_transform = object.matrix.clone(); - function collectGeometries(node, parent_transform) { - let transform = parent_transform.clone().multiply(node.matrix); - if (node.type === "Mesh") { - node.geometry.applyMatrix(transform); - geometries.push(node.geometry); - materials.push(node.material); - } - for (let child of node.children) { - collectGeometries(child, transform); - } + function collectGeometries(node, parent_transform) { + let transform = parent_transform.clone().multiply(node.matrix); + if (node.type === "Mesh") { + node.geometry.applyMatrix(transform); + geometries.push(node.geometry); + materials.push(node.material); } + for (let child of node.children) { + collectGeometries(child, transform); + } + } - collectGeometries(object, root_transform); - let result = null; - if (geometries.length === 1) { - result = geometries[0]; - if (preserve_materials) { - result.material = materials[0]; - } - } else if (geometries.length > 1) { - result = BufferGeometryUtils.mergeBufferGeometries(geometries, true); - if (preserve_materials) { - result.material = materials; - } - } else { - result = new THREE.BufferGeometry(); + collectGeometries(object, root_transform); + let result = null; + if (geometries.length === 1) { + result = geometries[0]; + if (preserve_materials) { + result.material = materials[0]; } - return result; + } else if (geometries.length > 1) { + result = BufferGeometryUtils.mergeBufferGeometries(geometries, true); + if (preserve_materials) { + result.material = materials; + } + } else { + result = new THREE.BufferGeometry(); + } + return result; } // Handler for special texture types that we want to support @@ -53,28 +53,28 @@ function merge_geometries(object, preserve_materials = false) { // * A new `THREE.Texture` if that json represents a special texture // * `null` otherwise function handle_special_texture(json) { - if (json.type === "_text") { - let canvas = document.createElement("canvas"); - // canvas width and height should be in the power of 2; otherwise although - // the page usually loads successfully, WebGL does complain/warn - canvas.width = 256; - canvas.height = 256; - let ctx = canvas.getContext("2d"); - ctx.textAlign = "center"; - let font_size = json.font_size; - // auto-resing the font_size to fit in the canvas - ctx.font = font_size + "px " + json.font_face; - while (ctx.measureText(json.text).width > canvas.width) { - font_size--; - ctx.font = font_size + "px " + json.font_face; - } - ctx.fillText(json.text, canvas.width / 2, canvas.height / 2); - let canvas_texture = new THREE.CanvasTexture(canvas); - canvas_texture.uuid = json.uuid; - return canvas_texture; - } else { - return null; + if (json.type === "_text") { + let canvas = document.createElement("canvas"); + // canvas width and height should be in the power of 2; otherwise although + // the page usually loads successfully, WebGL does complain/warn + canvas.width = 256; + canvas.height = 256; + let ctx = canvas.getContext("2d"); + ctx.textAlign = "center"; + let font_size = json.font_size; + // auto-resing the font_size to fit in the canvas + ctx.font = font_size + "px " + json.font_face; + while (ctx.measureText(json.text).width > canvas.width) { + font_size--; + ctx.font = font_size + "px " + json.font_face; } + ctx.fillText(json.text, canvas.width / 2, canvas.height / 2); + let canvas_texture = new THREE.CanvasTexture(canvas); + canvas_texture.uuid = json.uuid; + return canvas_texture; + } else { + return null; + } } // Handler for special geometry types that we want to support @@ -84,41 +84,41 @@ function handle_special_texture(json) { // * A new `THREE.Mesh` if that json represents a special geometry // * `null` otherwise function handle_special_geometry(geom) { - if (geom.type === "_meshfile") { - console.warn( - "_meshfile is deprecated. Please use _meshfile_geometry for geometries and _meshfile_object for objects with geometry and material" - ); - geom.type = "_meshfile_geometry"; + if (geom.type === "_meshfile") { + console.warn( + "_meshfile is deprecated. Please use _meshfile_geometry for geometries and _meshfile_object for objects with geometry and material" + ); + geom.type = "_meshfile_geometry"; + } + if (geom.type === "_meshfile_geometry") { + if (geom.format === "obj") { + let loader = new OBJLoader(); + let obj = loader.parse(geom.data + "\n"); + let loaded_geom = merge_geometries(obj); + loaded_geom.uuid = geom.uuid; + return loaded_geom; + } else if (geom.format === "dae") { + let loader = new ColladaLoader(); + let obj = loader.parse(geom.data); + let result = merge_geometries(obj.scene); + result.uuid = geom.uuid; + return result; + } else if (geom.format === "stl") { + let loader = new STLLoader(); + let loaded_geom = loader.parse(geom.data.buffer); + loaded_geom.uuid = geom.uuid; + return loaded_geom; + } else if (geom.format === "ply") { + let loader = new PLYLoader(); + let loaded_geom = loader.parse(geom.data.buffer); + loaded_geom.uuid = geom.uuid; + return loaded_geom; + } else { + console.error("Unsupported mesh type:", geom); + return null; } - if (geom.type === "_meshfile_geometry") { - if (geom.format === "obj") { - let loader = new OBJLoader(); - let obj = loader.parse(geom.data + "\n"); - let loaded_geom = merge_geometries(obj); - loaded_geom.uuid = geom.uuid; - return loaded_geom; - } else if (geom.format === "dae") { - let loader = new ColladaLoader(); - let obj = loader.parse(geom.data); - let result = merge_geometries(obj.scene); - result.uuid = geom.uuid; - return result; - } else if (geom.format === "stl") { - let loader = new STLLoader(); - let loaded_geom = loader.parse(geom.data.buffer); - loaded_geom.uuid = geom.uuid; - return loaded_geom; - } else if (geom.format === "ply") { - let loader = new PLYLoader(); - let loaded_geom = loader.parse(geom.data.buffer); - loaded_geom.uuid = geom.uuid; - return loaded_geom; - } else { - console.error("Unsupported mesh type:", geom); - return null; - } - } - return null; + } + return null; } // The ExtensibleObjectLoader extends the THREE.ObjectLoader @@ -135,148 +135,148 @@ function handle_special_geometry(geom) { // * Converting "_text" textures into text by drawing the // requested text onto a canvas. export class ExtensibleObjectLoader extends THREE.ObjectLoader { - delegate(special_handler, base_handler, json, additional_objects) { - let result = {}; - if (json === undefined) { - return result; + delegate(special_handler, base_handler, json, additional_objects) { + let result = {}; + if (json === undefined) { + return result; + } + let remaining_json = []; + for (let data of json) { + let x = special_handler(data); + if (x !== null) { + result[x.uuid] = x; + } else { + remaining_json.push(data); + } + } + return Object.assign( + result, + base_handler(remaining_json, additional_objects) + ); + } + + parseTextures(json, images) { + return this.delegate( + handle_special_texture, + super.parseTextures, + json, + images + ); + } + + parseGeometries(json, shapes) { + return this.delegate( + handle_special_geometry, + super.parseGeometries, + json, + shapes + ); + } + + parseObject(json, geometries, materials) { + if (json.type === "_meshfile_object") { + let geometry; + let material; + let manager = new THREE.LoadingManager(); + let path = + json.url === undefined + ? undefined + : THREE.LoaderUtils.extractUrlBase(json.url); + manager.setURLModifier((url) => { + if (json.resources[url] !== undefined) { + return json.resources[url]; } - let remaining_json = []; - for (let data of json) { - let x = special_handler(data); - if (x !== null) { - result[x.uuid] = x; - } else { - remaining_json.push(data); - } + return url; + }); + if (json.format === "obj") { + let loader = new OBJLoader(manager); + if (json.mtl_library) { + let mtl_loader = new MTLLoader(manager); + let mtl_parse_result = mtl_loader.parse(json.mtl_library + "\n", ""); + let materials = + MtlObjBridge.addMaterialsFromMtlLoader(mtl_parse_result); + loader.setMaterials(materials); + this.onTextureLoad(); } - return Object.assign( - result, - base_handler(remaining_json, additional_objects) - ); + let obj = loader.parse(json.data + "\n", path); + geometry = merge_geometries(obj, true); + geometry.uuid = json.uuid; + material = geometry.material; + } else if (json.format === "dae") { + let loader = new ColladaLoader(manager); + loader.onTextureLoad = this.onTextureLoad; + let obj = loader.parse(json.data, path); + geometry = merge_geometries(obj.scene, true); + geometry.uuid = json.uuid; + material = geometry.material; + } else if (json.format === "stl") { + let loader = new STLLoader(); + geometry = loader.parse(json.data.buffer, path); + geometry.uuid = json.uuid; + material = geometry.material; + } else { + console.error("Unsupported mesh type:", json); + return null; + } + let object = new THREE.Mesh(geometry, material); + + // Copied from ObjectLoader + object.uuid = json.uuid; + + if (json.name !== undefined) object.name = json.name; + + if (json.matrix !== undefined) { + object.matrix.fromArray(json.matrix); + + if (json.matrixAutoUpdate !== undefined) + object.matrixAutoUpdate = json.matrixAutoUpdate; + if (object.matrixAutoUpdate) + object.matrix.decompose( + object.position, + object.quaternion, + object.scale + ); + } else { + if (json.position !== undefined) + object.position.fromArray(json.position); + if (json.rotation !== undefined) + object.rotation.fromArray(json.rotation); + if (json.quaternion !== undefined) + object.quaternion.fromArray(json.quaternion); + if (json.scale !== undefined) object.scale.fromArray(json.scale); + } + + if (json.castShadow !== undefined) object.castShadow = json.castShadow; + if (json.receiveShadow !== undefined) + object.receiveShadow = json.receiveShadow; + + if (json.shadow) { + if (json.shadow.bias !== undefined) + object.shadow.bias = json.shadow.bias; + if (json.shadow.radius !== undefined) + object.shadow.radius = json.shadow.radius; + if (json.shadow.mapSize !== undefined) + object.shadow.mapSize.fromArray(json.shadow.mapSize); + if (json.shadow.camera !== undefined) + object.shadow.camera = this.parseObject(json.shadow.camera); + } + + if (json.visible !== undefined) object.visible = json.visible; + if (json.frustumCulled !== undefined) + object.frustumCulled = json.frustumCulled; + if (json.renderOrder !== undefined) object.renderOrder = json.renderOrder; + if (json.userjson !== undefined) object.userjson = json.userData; + if (json.layers !== undefined) object.layers.mask = json.layers; + + return object; + } else if (json.type === "CameraHelper") { + console.log("processing CameraHelper"); + console.log(json); + console.log(geometries); + console.log(materials); + return super.parseObject(json, geometries, materials); + } else { + return super.parseObject(json, geometries, materials); } - - parseTextures(json, images) { - return this.delegate( - handle_special_texture, - super.parseTextures, - json, - images - ); - } - - parseGeometries(json, shapes) { - return this.delegate( - handle_special_geometry, - super.parseGeometries, - json, - shapes - ); - } - - parseObject(json, geometries, materials) { - if (json.type === "_meshfile_object") { - let geometry; - let material; - let manager = new THREE.LoadingManager(); - let path = - json.url === undefined ? - undefined : - THREE.LoaderUtils.extractUrlBase(json.url); - manager.setURLModifier((url) => { - if (json.resources[url] !== undefined) { - return json.resources[url]; - } - return url; - }); - if (json.format === "obj") { - let loader = new OBJLoader(manager); - if (json.mtl_library) { - let mtl_loader = new MTLLoader(manager); - let mtl_parse_result = mtl_loader.parse(json.mtl_library + "\n", ""); - let materials = - MtlObjBridge.addMaterialsFromMtlLoader(mtl_parse_result); - loader.setMaterials(materials); - this.onTextureLoad(); - } - let obj = loader.parse(json.data + "\n", path); - geometry = merge_geometries(obj, true); - geometry.uuid = json.uuid; - material = geometry.material; - } else if (json.format === "dae") { - let loader = new ColladaLoader(manager); - loader.onTextureLoad = this.onTextureLoad; - let obj = loader.parse(json.data, path); - geometry = merge_geometries(obj.scene, true); - geometry.uuid = json.uuid; - material = geometry.material; - } else if (json.format === "stl") { - let loader = new STLLoader(); - geometry = loader.parse(json.data.buffer, path); - geometry.uuid = json.uuid; - material = geometry.material; - } else { - console.error("Unsupported mesh type:", json); - return null; - } - let object = new THREE.Mesh(geometry, material); - - // Copied from ObjectLoader - object.uuid = json.uuid; - - if (json.name !== undefined) object.name = json.name; - - if (json.matrix !== undefined) { - object.matrix.fromArray(json.matrix); - - if (json.matrixAutoUpdate !== undefined) - object.matrixAutoUpdate = json.matrixAutoUpdate; - if (object.matrixAutoUpdate) - object.matrix.decompose( - object.position, - object.quaternion, - object.scale - ); - } else { - if (json.position !== undefined) - object.position.fromArray(json.position); - if (json.rotation !== undefined) - object.rotation.fromArray(json.rotation); - if (json.quaternion !== undefined) - object.quaternion.fromArray(json.quaternion); - if (json.scale !== undefined) object.scale.fromArray(json.scale); - } - - if (json.castShadow !== undefined) object.castShadow = json.castShadow; - if (json.receiveShadow !== undefined) - object.receiveShadow = json.receiveShadow; - - if (json.shadow) { - if (json.shadow.bias !== undefined) - object.shadow.bias = json.shadow.bias; - if (json.shadow.radius !== undefined) - object.shadow.radius = json.shadow.radius; - if (json.shadow.mapSize !== undefined) - object.shadow.mapSize.fromArray(json.shadow.mapSize); - if (json.shadow.camera !== undefined) - object.shadow.camera = this.parseObject(json.shadow.camera); - } - - if (json.visible !== undefined) object.visible = json.visible; - if (json.frustumCulled !== undefined) - object.frustumCulled = json.frustumCulled; - if (json.renderOrder !== undefined) object.renderOrder = json.renderOrder; - if (json.userjson !== undefined) object.userjson = json.userData; - if (json.layers !== undefined) object.layers.mask = json.layers; - - return object; - } else if (json.type === "CameraHelper") { - console.log("processing CameraHelper"); - console.log(json); - console.log(geometries); - console.log(materials); - return super.parseObject(json, geometries, materials); - } else { - return super.parseObject(json, geometries, materials); - } - } -} \ No newline at end of file + } +} diff --git a/pyrad/viewer/app/src/SceneNode.js b/pyrad/viewer/app/src/SceneNode.js index 4f24ce31c..293def860 100644 --- a/pyrad/viewer/app/src/SceneNode.js +++ b/pyrad/viewer/app/src/SceneNode.js @@ -3,142 +3,142 @@ import * as THREE from "three"; const dat = require("dat.gui"); function remove_folders(gui) { - for (let name of Object.keys(gui.__folders)) { - let folder = gui.__folders[name]; - remove_folders(folder); - dat.dom.dom.unbind(window, "resize", folder.__resizeHandler); - gui.removeFolder(folder); - } + for (let name of Object.keys(gui.__folders)) { + let folder = gui.__folders[name]; + remove_folders(folder); + dat.dom.dom.unbind(window, "resize", folder.__resizeHandler); + gui.removeFolder(folder); + } } function dispose(object) { - if (!object) { - return; - } - if (object.geometry) { - object.geometry.dispose(); - } - if (object.material) { - if (Array.isArray(object.material)) { - for (let material of object.material) { - if (material.map) { - material.map.dispose(); - } - material.dispose(); - } - } else { - if (object.material.map) { - object.material.map.dispose(); - } - object.material.dispose(); + if (!object) { + return; + } + if (object.geometry) { + object.geometry.dispose(); + } + if (object.material) { + if (Array.isArray(object.material)) { + for (let material of object.material) { + if (material.map) { + material.map.dispose(); } + material.dispose(); + } + } else { + if (object.material.map) { + object.material.map.dispose(); + } + object.material.dispose(); } + } } export class SceneNode { - constructor(object, folder) { - this.object = object; - this.folder = folder; - this.children = {}; - this.create_controls(); - for (let c of this.object.children) { - this.add_child(c); - } + constructor(object, folder) { + this.object = object; + this.folder = folder; + this.children = {}; + this.create_controls(); + for (let c of this.object.children) { + this.add_child(c); } + } - add_child(object) { - let f = this.folder.addFolder(object.name); - let node = new SceneNode(object, f); - this.children[object.name] = node; - return node; - } + add_child(object) { + let f = this.folder.addFolder(object.name); + let node = new SceneNode(object, f); + this.children[object.name] = node; + return node; + } - create_child(name) { - let obj = new THREE.Group(); - obj.name = name; - this.object.add(obj); - return this.add_child(obj); - } + create_child(name) { + let obj = new THREE.Group(); + obj.name = name; + this.object.add(obj); + return this.add_child(obj); + } - find(path) { - if (path.length == 0) { - return this; - } else { - let name = path[0]; - let child = this.children[name]; - if (child === undefined) { - child = this.create_child(name); - } - return child.find(path.slice(1)); - } + find(path) { + if (path.length == 0) { + return this; + } else { + let name = path[0]; + let child = this.children[name]; + if (child === undefined) { + child = this.create_child(name); + } + return child.find(path.slice(1)); } + } - create_controls() { - if (this.vis_controller !== undefined) { - this.folder.domElement.removeChild(this.vis_controller.domElement); - } - this.vis_controller = new dat.controllers.BooleanController( - this.object, - "visible" - ); - this.folder.domElement.prepend(this.vis_controller.domElement); - this.vis_controller.domElement.style.height = "0"; - this.vis_controller.domElement.style.float = "right"; + create_controls() { + if (this.vis_controller !== undefined) { + this.folder.domElement.removeChild(this.vis_controller.domElement); } + this.vis_controller = new dat.controllers.BooleanController( + this.object, + "visible" + ); + this.folder.domElement.prepend(this.vis_controller.domElement); + this.vis_controller.domElement.style.height = "0"; + this.vis_controller.domElement.style.float = "right"; + } - set_property(property, value) { - if (property === "position") { - this.object.position.set(value[0], value[1], value[2]); - } else if (property === "quaternion") { - this.object.quaternion.set(value[0], value[1], value[2], value[3]); - } else if (property === "scale") { - this.object.scale.set(value[0], value[1], value[2]); - } else { - this.object[property] = value; - } - this.vis_controller.updateDisplay(); + set_property(property, value) { + if (property === "position") { + this.object.position.set(value[0], value[1], value[2]); + } else if (property === "quaternion") { + this.object.quaternion.set(value[0], value[1], value[2], value[3]); + } else if (property === "scale") { + this.object.scale.set(value[0], value[1], value[2]); + } else { + this.object[property] = value; } + this.vis_controller.updateDisplay(); + } - set_transform(matrix) { - let mat = new THREE.Matrix4(); - mat.fromArray(matrix); - mat.decompose( - this.object.position, - this.object.quaternion, - this.object.scale - ); - } + set_transform(matrix) { + let mat = new THREE.Matrix4(); + mat.fromArray(matrix); + mat.decompose( + this.object.position, + this.object.quaternion, + this.object.scale + ); + } - set_object(object) { - let parent = this.object.parent; - this.dispose_recursive(); - this.object.parent.remove(this.object); - this.object = object; - parent.add(object); - this.create_controls(); - } + set_object(object) { + let parent = this.object.parent; + this.dispose_recursive(); + this.object.parent.remove(this.object); + this.object = object; + parent.add(object); + this.create_controls(); + } - dispose_recursive() { - for (let name of Object.keys(this.children)) { - this.children[name].dispose_recursive(); - } - dispose(this.object); + dispose_recursive() { + for (let name of Object.keys(this.children)) { + this.children[name].dispose_recursive(); } + dispose(this.object); + } - delete(path) { - if (path.length == 0) { - console.error("Can't delete an empty path"); - } else { - let parent = this.find(path.slice(0, path.length - 1)); - let name = path[path.length - 1]; - let child = parent.children[name]; - if (child !== undefined) { - child.dispose_recursive(); - parent.object.remove(child.object); - remove_folders(child.folder); - parent.folder.removeFolder(child.folder); - delete parent.children[name]; - } - } + delete(path) { + if (path.length == 0) { + console.error("Can't delete an empty path"); + } else { + let parent = this.find(path.slice(0, path.length - 1)); + let name = path[path.length - 1]; + let child = parent.children[name]; + if (child !== undefined) { + child.dispose_recursive(); + parent.object.remove(child.object); + remove_folders(child.folder); + parent.folder.removeFolder(child.folder); + delete parent.children[name]; + } } -} \ No newline at end of file + } +} diff --git a/pyrad/viewer/app/src/index.js b/pyrad/viewer/app/src/index.js index 0413f29d8..8ad97d50b 100644 --- a/pyrad/viewer/app/src/index.js +++ b/pyrad/viewer/app/src/index.js @@ -5,9 +5,9 @@ import * as serviceWorker from "./serviceWorker"; import { Viewer } from "./Viewer"; const root = ReactDOM.createRoot(document.getElementById("root")); -root.render( < Viewer / > ); +root.render(); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://bit.ly/CRA-PWA -serviceWorker.unregister(); \ No newline at end of file +serviceWorker.unregister(); diff --git a/pyrad/viewer/app/src/serviceWorker.js b/pyrad/viewer/app/src/serviceWorker.js index a756f090f..c7cd6663d 100644 --- a/pyrad/viewer/app/src/serviceWorker.js +++ b/pyrad/viewer/app/src/serviceWorker.js @@ -11,131 +11,131 @@ // opt-in, read https://bit.ly/CRA-PWA const isLocalhost = Boolean( - window.location.hostname === "localhost" || + window.location.hostname === "localhost" || // [::1] is the IPv6 localhost address. window.location.hostname === "[::1]" || // 127.0.0.0/8 are considered localhost for IPv4. window.location.hostname.match( - /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ ) ); export function register(config) { - 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.href); - 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/facebook/create-react-app/issues/2374 - return; - } - - window.addEventListener("load", () => { - const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; - - if (isLocalhost) { - // This is running on localhost. Let's check if a service worker still exists or not. - checkValidServiceWorker(swUrl, config); - - // 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 https://bit.ly/CRA-PWA" - ); - }); - } else { - // Is not localhost. Just register service worker - registerValidSW(swUrl, config); - } - }); + 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.href); + 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/facebook/create-react-app/issues/2374 + return; } + + window.addEventListener("load", () => { + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + + if (isLocalhost) { + // This is running on localhost. Let's check if a service worker still exists or not. + checkValidServiceWorker(swUrl, config); + + // 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 https://bit.ly/CRA-PWA" + ); + }); + } else { + // Is not localhost. Just register service worker + registerValidSW(swUrl, config); + } + }); + } } function registerValidSW(swUrl, config) { - navigator.serviceWorker - .register(swUrl) - .then((registration) => { - registration.onupdatefound = () => { - const installingWorker = registration.installing; - if (installingWorker == null) { - return; - } - installingWorker.onstatechange = () => { - if (installingWorker.state === "installed") { - if (navigator.serviceWorker.controller) { - // At this point, the updated precached content has been fetched, - // but the previous service worker will still serve the older - // content until all client tabs are closed. - console.log( - "New content is available and will be used when all " + - "tabs for this page are closed. See https://bit.ly/CRA-PWA." - ); + navigator.serviceWorker + .register(swUrl) + .then((registration) => { + registration.onupdatefound = () => { + const installingWorker = registration.installing; + if (installingWorker == null) { + return; + } + installingWorker.onstatechange = () => { + if (installingWorker.state === "installed") { + if (navigator.serviceWorker.controller) { + // At this point, the updated precached content has been fetched, + // but the previous service worker will still serve the older + // content until all client tabs are closed. + console.log( + "New content is available and will be used when all " + + "tabs for this page are closed. See https://bit.ly/CRA-PWA." + ); - // Execute callback - if (config && config.onUpdate) { - config.onUpdate(registration); - } - } 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."); + // Execute callback + if (config && config.onUpdate) { + config.onUpdate(registration); + } + } 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."); - // Execute callback - if (config && config.onSuccess) { - config.onSuccess(registration); - } - } - } - }; - }; - }) - .catch((error) => { - console.error("Error during service worker registration:", error); - }); + // Execute callback + if (config && config.onSuccess) { + config.onSuccess(registration); + } + } + } + }; + }; + }) + .catch((error) => { + console.error("Error during service worker registration:", error); + }); } function checkValidServiceWorker(swUrl, config) { - // Check if the service worker can be found. If it can't reload the page. - fetch(swUrl, { - headers: { "Service-Worker": "script" }, - }) - .then((response) => { - // Ensure service worker exists, and that we really are getting a JS file. - const contentType = response.headers.get("content-type"); - if ( - response.status === 404 || - (contentType != null && contentType.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. - registerValidSW(swUrl, config); - } - }) - .catch(() => { - console.log( - "No internet connection found. App is running in offline mode." - ); + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl, { + headers: { "Service-Worker": "script" }, + }) + .then((response) => { + // Ensure service worker exists, and that we really are getting a JS file. + const contentType = response.headers.get("content-type"); + if ( + response.status === 404 || + (contentType != null && contentType.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. + registerValidSW(swUrl, config); + } + }) + .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(); - }) - .catch((error) => { - console.error(error.message); - }); - } -} \ No newline at end of file + if ("serviceWorker" in navigator) { + navigator.serviceWorker.ready + .then((registration) => { + registration.unregister(); + }) + .catch((error) => { + console.error(error.message); + }); + } +} diff --git a/pyrad/viewer/app/src/setupTests.js b/pyrad/viewer/app/src/setupTests.js index 9b1d6d0a7..5fdf00169 100644 --- a/pyrad/viewer/app/src/setupTests.js +++ b/pyrad/viewer/app/src/setupTests.js @@ -2,4 +2,4 @@ // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom -import "@testing-library/jest-dom/extend-expect"; \ No newline at end of file +import "@testing-library/jest-dom/extend-expect"; diff --git a/pyrad/viewer/app/src/utils.js b/pyrad/viewer/app/src/utils.js index 13a5cae47..98fd4938b 100644 --- a/pyrad/viewer/app/src/utils.js +++ b/pyrad/viewer/app/src/utils.js @@ -1,3 +1,3 @@ export function split_path(path_str) { - return path_str.split("/").filter((x) => x.length > 0); -} \ No newline at end of file + return path_str.split("/").filter((x) => x.length > 0); +}